]> SALOME platform Git repositories - tools/siman.git/blob - Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java
Salome HOME
Compare method signature and DocToCompareDTO are added.
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / StudyServiceImpl.java
1 /*****************************************************************************
2  * Company         OPEN CASCADE
3  * Application     SIMAN
4  * File            Id: 
5  * Creation date   02.10.2012
6  * @author         Author: Maria KRUCHININA
7  * @version        Revision: 
8  *****************************************************************************/
9
10 package org.splat.service;
11
12 import java.io.IOException;
13 import java.text.DecimalFormat;
14 import java.text.SimpleDateFormat;
15 import java.util.Calendar;
16 import java.util.Collections;
17 import java.util.Date;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22
23 import org.hibernate.criterion.Restrictions;
24 import org.splat.dal.bo.kernel.Relation;
25 import org.splat.dal.bo.kernel.User;
26 import org.splat.dal.bo.som.ActorRelation;
27 import org.splat.dal.bo.som.ContributorRelation;
28 import org.splat.dal.bo.som.DescriptionAttribute;
29 import org.splat.dal.bo.som.DocumentType;
30 import org.splat.dal.bo.som.IDBuilder;
31 import org.splat.dal.bo.som.KnowledgeElement;
32 import org.splat.dal.bo.som.ProgressState;
33 import org.splat.dal.bo.som.Publication;
34 import org.splat.dal.bo.som.Scenario;
35 import org.splat.dal.bo.som.SimulationContext;
36 import org.splat.dal.bo.som.Study;
37 import org.splat.dal.bo.som.Study.Properties;
38 import org.splat.dal.bo.som.ValidationCycle;
39 import org.splat.dal.bo.som.ValidationCycle.Actor;
40 import org.splat.dal.bo.som.ValidationCycleRelation;
41 import org.splat.dal.bo.som.ValidationStep;
42 import org.splat.dal.bo.som.Visibility;
43 import org.splat.dal.dao.som.DescriptionAttributeDAO;
44 import org.splat.dal.dao.som.DocumentDAO;
45 import org.splat.dal.dao.som.IDBuilderDAO;
46 import org.splat.dal.dao.som.PublicationDAO;
47 import org.splat.dal.dao.som.ScenarioDAO;
48 import org.splat.dal.dao.som.StudyDAO;
49 import org.splat.dal.dao.som.ValidationCycleDAO;
50 import org.splat.exception.InvalidParameterException;
51 import org.splat.kernel.InvalidPropertyException;
52 import org.splat.kernel.MissedPropertyException;
53 import org.splat.kernel.MultiplyDefinedException;
54 import org.splat.log.AppLogger;
55 import org.splat.service.dto.DocToCompareDTO;
56 import org.splat.service.technical.IndexService;
57 import org.splat.service.technical.ProjectSettingsService;
58 import org.splat.service.technical.ProjectSettingsServiceImpl;
59 import org.splat.service.technical.RepositoryService;
60 import org.splat.som.Revision;
61 import org.springframework.transaction.annotation.Transactional;
62
63
64 /**
65  * This class defines all methods for creation, modification the study.
66  * 
67  * @author Maria KRUCHININA
68  * 
69  */
70 public class StudyServiceImpl implements StudyService {
71
72         /**
73          * logger for the service.
74          */
75         public final static AppLogger LOG = AppLogger
76                         .getLogger(StudyServiceImpl.class);
77
78         /**
79          * Injected index service.
80          */
81         private IndexService _indexService;
82
83         /**
84          * Injected step service.
85          */
86         private StepService _stepService;
87
88         /**
89          * Injected project service.
90          */
91         private ProjectSettingsService _projectSettings;
92
93         /**
94          * Injected project element service.
95          */
96         private ProjectElementService _projectElementService;
97
98         /**
99          * Injected study DAO.
100          */
101         private StudyDAO _studyDAO;
102
103         /**
104          * Injected scenario DAO.
105          */
106         private ScenarioDAO _scenarioDAO;
107
108         /**
109          * Injected validation cycle DAO.
110          */
111         private ValidationCycleDAO _validationCycleDAO;
112
113         /**
114          * Injected IDBuilder DAO.
115          */
116         private IDBuilderDAO _iDBuilderDAO;
117
118         /**
119          * Injected document type service.
120          */
121         private DocumentTypeService _documentTypeService;
122
123         /**
124          * Injected user service.
125          */
126         private UserService _userService;
127
128         /**
129          * Injected publication DAO.
130          */
131         private PublicationDAO _publicationDAO;
132
133         /**
134          * Injected repository service.
135          */
136         private RepositoryService _repositoryService;
137
138         /**
139          * Injected document DAO.
140          */
141         private DocumentDAO _documentDAO;
142
143         /**
144          * Injected description attribute DAO.
145          */
146         private DescriptionAttributeDAO _descriptionAttributeDAO;
147
148         /**
149          * {@inheritDoc}
150          * 
151          * @see org.splat.service.StudyService#selectStudy(long)
152          */
153         @Override
154         @Transactional
155         public Study selectStudy(final long index) {
156                 Study result = getStudyDAO().get(index);
157                 loadWorkflow(result);
158                 return result;
159         }
160
161         /**
162          * Get study by its reference.
163          * 
164          * @param refid
165          *            the study reference
166          * @return found study or null
167          */
168         @Transactional(readOnly = true)
169         public Study selectStudy(final String refid) {
170                 Study result = getStudyDAO().findByCriteria(
171                                 Restrictions.eq("sid", refid));
172                 loadWorkflow(result);
173                 return result;
174         }
175
176         /**
177          * {@inheritDoc}
178          * 
179          * @see org.splat.service.StudyService#createStudy(org.splat.dal.bo.som.Study.Properties)
180          */
181         @Override
182         @Transactional
183         public Study createStudy(final Study.Properties sprop)
184                         throws MissedPropertyException, InvalidPropertyException,
185                         MultiplyDefinedException {
186                 sprop.setReference(getProjectSettings().getReferencePattern());
187                 Study study = new Study(sprop);
188
189                 buildReference(study);
190                 getStudyDAO().create(study);
191                 try {
192                         IndexService lucin = getIndex();
193                         lucin.add(study);
194                 } catch (IOException error) {
195                         LOG.error("Unable to index the study '" + study.getIndex()
196                                         + "', reason:", error);
197                         // Continue and try to index later
198                 }
199                 return study;
200         }
201
202         /**
203          * {@inheritDoc}
204          * 
205          * @see org.splat.service.StudyService#addProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext.Properties)
206          */
207         @Override
208         @Transactional
209         public SimulationContext addProjectContext(final Study aStudy,
210                         final SimulationContext.Properties cprop)
211                         throws MissedPropertyException, InvalidPropertyException,
212                         MultiplyDefinedException {
213                 SimulationContext added = getStepService().addSimulationContext(
214                                 getProjectElementService().getFirstStep(aStudy), cprop);
215                 update(aStudy);
216                 return added;
217         }
218
219         /**
220          * {@inheritDoc}
221          * 
222          * @see org.splat.service.StudyService#addProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext)
223          */
224         @Override
225         @Transactional
226         public SimulationContext addProjectContext(final Study aStudy,
227                         final SimulationContext context) {
228                 SimulationContext added = getStepService().addSimulationContext(
229                                 getProjectElementService().getFirstStep(aStudy), context);
230                 update(aStudy);
231                 return added;
232         }
233
234         /**
235          * {@inheritDoc}
236          * 
237          * @see org.splat.service.StudyService#addContributor(org.splat.dal.bo.som.Study, org.splat.dal.bo.kernel.User)
238          */
239         @Override
240         public boolean addContributor(final Study aStudy, final User user) {
241                 List<User> contributor = getModifiableContributors(aStudy); // Initializes contributor
242                 for (Iterator<User> i = contributor.iterator(); i.hasNext();) {
243                         User present = i.next();
244                         if (present.equals(user)) {
245                                 return false;
246                         }
247                 }
248                 boolean absent = getModifiableActors(aStudy).add(user); // User may already be a reviewer or an approver
249
250                 aStudy.addRelation(new ContributorRelation(aStudy, user));
251                 if (absent) {
252                         update(aStudy); // Else, useless to re-index the study
253                 }
254                 contributor.add(user);
255                 return true;
256         }
257
258         /**
259          * Moves this study from the Public to the Reference area of the repository. For being moved to the Reference area, the study must
260          * previously be approved.
261          * 
262          * @param aStudy
263          *            the study to move
264          * @return true if the move succeeded.
265          * @see #moveToPublic()
266          * @see #isPublic()
267          * @see Publication#approve(Date)
268          */
269         @Override
270         public boolean moveToReference(final Study aStudy) {
271                 if (aStudy.getProgressState() != ProgressState.APPROVED) {
272                         return false;
273                 }
274                 if (aStudy.getVisibility() != Visibility.PUBLIC) {
275                         return false;
276                 }
277
278                 aStudy.setVisibility(Visibility.REFERENCE);
279                 if (update(aStudy)) {
280                         return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
281                 }
282                 return false;
283         }
284
285         /**
286          * {@inheritDoc}
287          * 
288          * @see org.splat.service.StudyService#update(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Study.Properties)
289          */
290         @Override
291         public boolean update(final Study aStudy, final Properties sprop)
292                         throws InvalidPropertyException {
293                 if (sprop.getTitle() != null) {
294                         aStudy.setTitle(sprop.getTitle());
295                 }
296                 if (sprop.getSummary() != null) {
297                         aStudy.setAttribute(new DescriptionAttribute(aStudy, sprop
298                                         .getSummary()));
299                 }
300                 // TODO: To be completed
301                 return update(aStudy);
302         }
303
304         /**
305          * Check if the document is published in the study.
306          * 
307          * @param aStudy
308          *            the study
309          * @param doc
310          *            the document
311          * @return true if the document is published in the study
312          */
313 /*      private boolean publishes(final Study aStudy, final Document doc) {
314                 if (!aStudy.publishes(doc)) {
315                         Scenario[] scene = aStudy.getScenarii();
316                         for (int i = 0; i < scene.length; i++) {
317                                 if (scene[i].publishes(doc)) {
318                                         return true;
319                                 }
320                         }
321                 }
322                 return false;
323         }
324 */
325         /**
326          * {@inheritDoc}
327          * 
328          * @see org.splat.service.StudyService#removeContributor(org.splat.dal.bo.som.Study, org.splat.dal.bo.kernel.User[])
329          */
330         @Override
331         public boolean removeContributor(final Study aStudy, final User... users) {
332                 List<User> contributor = getModifiableContributors(aStudy); // Initializes contributor
333                 Boolean done = false;
334                 for (int i = 0; i < users.length; i++) {
335                         User user = users[i];
336                         for (Iterator<User> j = contributor.iterator(); j.hasNext();) {
337                                 User present = j.next();
338                                 if (!present.equals(user)) {
339                                         continue;
340                                 }
341
342                                 aStudy.removeRelation(ContributorRelation.class, user);
343                                 j.remove(); // Updates the contributor shortcut
344                                 done = true;
345                                 break;
346                         }
347                 }
348                 if (done) {
349                         update(aStudy);
350                 }
351                 return done;
352         }
353
354         /**
355          * {@inheritDoc}
356          * 
357          * @see org.splat.service.StudyService#removeProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext)
358          */
359         @Override
360         public boolean removeProjectContext(final Study aStudy,
361                         final SimulationContext context) {
362                 boolean done = getStepService().removeSimulationContext(
363                                 getProjectElementService().getFirstStep(aStudy), context);
364                 update(aStudy);
365                 return done;
366         }
367
368         /**
369          * {@inheritDoc}
370          * 
371          * @see org.splat.service.StudyService#setValidationCycle(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.DocumentType,
372          *      org.splat.dal.bo.som.ValidationCycle.Properties)
373          */
374         @Override
375         @Transactional
376         public void setValidationCycle(final Study aStudyDTO, final DocumentType type,
377                         final ValidationCycle.Properties vprop) {
378                 Map<String, ValidationCycle> validactor = aStudyDTO.getValidationCycles();
379                 if (validactor == null) {
380                         setShortCuts(aStudyDTO); // Initializes validactor and actor
381                 }
382
383                 Study aStudy = selectStudy(aStudyDTO.getIndex());
384                 
385                 String cname = type.getName();
386                 ValidationCycle cycle = validactor.get(cname);
387
388                 if (cycle != null && cycle.isAssigned()) {
389                         resetActors(cycle, vprop);
390                 } else {
391                         try {
392                                 cycle = new ValidationCycle(aStudy, vprop.setDocumentType(type));
393
394                                 getValidationCycleDAO().create(cycle); // RKV
395
396                                 ValidationCycleRelation link = cycle.getContext();
397                                 aStudy.addRelation(link);
398                                 aStudyDTO.getAllRelations().add(link); // RKV
399
400                                 validactor.put(cname, link.getTo()); // Replaces the cycle if exists as default,
401                         } catch (Exception error) {
402                                 LOG.error("Unable to re-index Knowledge Elements, reason:",
403                                                 error);
404                                 return;
405                         }
406                 }
407                 resetActorsShortCut(aStudyDTO);
408                 update(aStudy); // Re-index the study, just in case
409         }
410
411         /**
412          * Demotes this study from In-Check to In-Draft then In-Work states. This function is called internally when demoting the final result
413          * document of the study.
414          * 
415          * @param aStudy
416          *            a study to demote
417          * @return true if the demotion succeeded.
418          */
419         @Override
420         public boolean demote(final Study aStudy) {
421                 if (aStudy.getProgressState() == ProgressState.inCHECK) {
422                         aStudy.setProgressState(ProgressState.inDRAFT);
423                 } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
424                         aStudy.setProgressState(ProgressState.inWORK);
425                 } else {
426                         return false;
427                 }
428                 return update(aStudy);
429         }
430
431         /**
432          * {@inheritDoc}
433          * 
434          * @see org.splat.service.StudyService#generateLocalIndex(org.splat.dal.bo.som.Study)
435          */
436         @Override
437         @Transactional
438         public int generateLocalIndex(final Study aStudy) {
439                 aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1);
440                 return aStudy.getLastLocalIndex();
441         }
442
443         /**
444          * Promotes this study from In-Work to In-Draft then In-Check and APPROVED states. This function is called internally when promoting the
445          * final result document of the study.
446          * 
447          * @param aStudy
448          *            a study to promote
449          * @return true if the demotion succeeded.
450          */
451         @Override
452         @Transactional
453         public boolean promote(final Study aStudy) {
454                 if (aStudy.getProgressState() == ProgressState.inWORK) {
455                         aStudy.setProgressState(ProgressState.inDRAFT);
456                 } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
457                         aStudy.setProgressState(ProgressState.inCHECK);
458                         Revision myvers = new Revision(aStudy.getVersion());
459                         if (myvers.isMinor()) {
460                                 aStudy.setVersion(myvers.incrementAs(aStudy.getProgressState())
461                                                 .toString());
462                         }
463                 } else if (aStudy.getProgressState() == ProgressState.inCHECK) {
464                         aStudy.setProgressState(ProgressState.APPROVED);
465                 } else {
466                         return false;
467                 }
468
469                 return update(aStudy);
470         }
471
472         /**
473          * Moves this study from the Private to the Public area of the repository.
474          * 
475          * @param aStudy
476          *            a study to move
477          * @return true if the move succeeded.
478          * @see #isPublic()
479          */
480         @Override
481         @Transactional
482         public boolean moveToPublic(final Study aStudy) {
483                 boolean isOk = false;
484                 if (aStudy.getVisibility() == Visibility.PRIVATE) {
485                         aStudy.setVisibility(Visibility.PUBLIC);
486                         if (update(aStudy)) {
487                                 isOk = updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
488                         }
489                 }
490                 return isOk;
491         }
492         
493         /**
494          * Moves this study from the Public to the Private area of the repository.
495          * 
496          * @param aStudy
497          *            a study to move
498          * @return true if the move succeeded.
499          */
500         @Override
501         @Transactional
502         public boolean moveToPrivate(final Study aStudy) {
503                 boolean isOk = false;
504                 if (aStudy.getVisibility() == Visibility.PUBLIC) {
505                         aStudy.setVisibility(Visibility.PRIVATE);
506                         if (update(aStudy)) {
507                                 isOk = updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
508                         }
509                 }
510                 return isOk;
511         }
512
513         /**
514          * Update a study in the database.
515          * 
516          * @param aStudy
517          *            the study to update
518          * @return true if the study is updated successfully
519          */
520         @Transactional
521         private boolean update(final Study aStudy) {
522                 boolean isOk = false;
523                 try {
524                         getStudyDAO().merge(aStudy); // Update of relational base
525                         setShortCuts(aStudy); // RKV: initialize transient actors set
526                         getIndex().update(aStudy); // Update of Lucene index
527                         isOk = true;
528                 } catch (Exception e) {
529                         LOG.error("STD-000001", e, aStudy.getIndex(), e.getMessage());
530                 }
531                 return isOk;
532         }
533
534         /**
535          * Build reference for the study. The reference of the study is stored as a new reference pattern (IDBuilder).
536          * 
537          * @param aStudy
538          *            the study
539          * @return true if reference building is succeded
540          */
541         @Transactional
542         private boolean buildReference(final Study aStudy) {
543                 String pattern = aStudy.getReference(); // The study being supposed just created, its reference is the reference pattern
544                 IDBuilder tool = selectIDBuilder(aStudy.getDate());
545                 if (tool == null) {
546                         tool = new IDBuilder(aStudy.getDate());
547                         getIDBuilderDAO().create(tool);
548                 }
549                 aStudy.setReference(buildReference(tool, pattern, aStudy));
550                 return true;
551         }
552
553         /**
554          * Build reference for the study. The reference of the study is stored as a new reference pattern (IDBuilder).
555          * 
556          * @param aBuilder
557          *            the id builder
558          * @param study
559          *            the study
560          * @param pattern
561          *            the reference pattern
562          * @return true if reference building is succeded
563          */
564         @Transactional
565         public String buildReference(final IDBuilder aBuilder,
566                         final String pattern, final Study study) {
567                 char[] format = pattern.toCharArray();
568                 char[] ref = new char[80]; // Better evaluate the length of the generated string
569                 int next = aBuilder.getBase() + 1;
570
571                 int count = 0;
572                 for (int i = 0; i < format.length; i++) {
573
574                         // Insertion of attribute values
575                         if (format[i] == '%') {
576                                 i += 1;
577
578                                 if (format[i] == 'y') { // Insertion of year in format 2 (e.g. 09) or 4 (e.g. 2009) digits
579                                         int n = i;
580                                         while (format[i] == 'y') {
581                                                 i += 1;
582                                                 if (i == format.length) {
583                                                         break;
584                                                 }
585                                         }
586                                         SimpleDateFormat tostring = new SimpleDateFormat("yyyy"); //RKV: NOPMD: TODO: Use locale here?
587                                         String year = tostring.format(study.getDate());
588                                         year = year.substring(4 - (i - n), 4); // 4-(i-n) must be equal to either 0 or 2
589                                         for (int j = 0; j < year.length(); j++) {
590                                                 ref[count] = year.charAt(j);
591                                                 count += 1;
592                                         }
593                                         i -= 1; // Back to the last 'y' character
594                                 } else if (format[i] == '0') { // Insertion of the index
595                                         int n = i;
596                                         while (format[i] == '0') {
597                                                 i += 1;
598                                                 if (i == format.length) {
599                                                         break;
600                                                 }
601                                         }
602                                         DecimalFormat tostring = new DecimalFormat(pattern
603                                                         .substring(n, i));
604                                         String number = tostring.format(next);
605                                         for (int j = 0; j < number.length(); j++) {
606                                                 ref[count] = number.charAt(j);
607                                                 count += 1;
608                                         }
609                                         i -= 1; // Back to the last '0' character
610                                 }
611                                 // Keep the character
612                         } else {
613                                 ref[count] = format[i];
614                                 count += 1;
615                         }
616                 }
617                 // Incrementation of the number of study
618                 aBuilder.setBase(next);
619                 getIDBuilderDAO().update(aBuilder);
620                 return String.copyValueOf(ref, 0, count);
621         }
622
623         /**
624          * Find an id builder by date.
625          * 
626          * @param date
627          *            the date
628          * @return found id builder
629          */
630         private IDBuilder selectIDBuilder(final Date date) {
631                 Calendar aDate = Calendar.getInstance();
632                 aDate.setTime(date);
633                 return getIDBuilderDAO().findByCriteria(
634                                 Restrictions.eq("cycle", aDate.get(Calendar.YEAR)));
635         }
636
637         /**
638          * Fill transient collection ModifiableActors of the study.
639          * 
640          * @param aStudy
641          *            the study
642          */
643         private void resetActorsShortCut(final Study aStudy) {
644                 getModifiableActors(aStudy).clear();
645                 // Get all actors involved in validation cycles
646                 for (Iterator<ValidationCycle> i = aStudy.getValidationCycles()
647                                 .values().iterator(); i.hasNext();) {
648                         ValidationCycle cycle = i.next();
649                         User[] user = cycle.getAllActors();
650                         for (int j = 0; j < user.length; j++) {
651                                 getModifiableActors(aStudy).add(user[j]);
652                         }
653                 }
654                 // Get all other actors
655                 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
656                                 .hasNext();) {
657                         Relation link = i.next();
658                         Class<?> kindof = link.getClass().getSuperclass();
659                         if (!kindof.equals(ActorRelation.class)) {
660                                 continue;
661                         }
662                         getModifiableActors(aStudy).add(((ActorRelation) link).getTo());
663                 }
664         }
665
666         /**
667          * Update lucene index for the study knowledge elements.
668          * 
669          * @param aStudy
670          *            the study
671          * @return true if reindexing succeeded
672          */
673         private boolean updateKnowledgeElementsIndex(final Study aStudy) {
674                 boolean isOk = false;
675                 try {
676                         IndexService lucin = getIndex();
677
678                         for (Iterator<Scenario> i = aStudy.getScenariiList().iterator(); i
679                                         .hasNext();) {
680                                 Scenario scene = i.next();
681                                 for (Iterator<KnowledgeElement> j = scene
682                                                 .getAllKnowledgeElements().iterator(); j.hasNext();) {
683                                         KnowledgeElement kelm = j.next();
684                                         lucin.update(kelm);
685                                 }
686                         }
687                         isOk = true;
688                 } catch (Exception error) {
689                         LOG.error("Unable to re-index Knowledge Elements, reason:",
690                                         error);
691                 }
692                 return isOk;
693         }
694
695         /**
696          * Get lucene index service. Create a lucene index if it does not exist.
697          * 
698          * @return index service
699          * @throws IOException
700          *             if error occurs during lucene index creation
701          */
702         private IndexService getIndex() throws IOException {
703                 IndexService lucin = getIndexService();
704                 if (!lucin.exists()) {
705                         lucin.create(); // Happens when re-indexing all studies
706                 }
707                 return lucin;
708         }
709
710         /**
711          * Create a new validation cycle for documents of the given study.
712          * 
713          * @param from
714          *            the study
715          * @param cycle
716          *            the cycle description
717          * @return the new validation cycle
718          */
719         protected ValidationCycle createValidationCycle(
720                         final Study from,
721                         final ProjectSettingsServiceImpl.ProjectSettingsValidationCycle cycle) {
722                 Actor[] actype = cycle.getActorTypes();
723                 User.Properties uprop = new User.Properties();
724
725                 ValidationCycle aValidationCycle = new ValidationCycle();
726                 aValidationCycle.setDocumentType(getDocumentTypeService().selectType(
727                                 cycle.getName())); // Null in case of default validation cycle
728                 // context = new ValidationCycleRelation(from, vprop);
729                 // RKV aValidationCycle.context = null; // Validation cycle defined in the workflow
730                 for (int i = 0; i < actype.length; i++) {
731                         User actor = null;
732                         if (actype[i] != null) {
733                                 try {
734                                         if (actype[i] == Actor.manager) {
735                                                 actor = from.getAuthor();
736                                         } else if (actype[i] == Actor.Nx1) {
737                                                 List<User> manager = getUserService().selectUsersWhere(
738                                                                 uprop.setOrganizationName("Nx1"));
739                                                 if (manager.size() == 1) {
740                                                         actor = manager.get(0);
741                                                 }
742                                         } else if (actype[i] == Actor.Nx2) {
743                                                 List<User> manager = getUserService().selectUsersWhere(
744                                                                 uprop.setOrganizationName("Nx2"));
745                                                 if (manager.size() == 1) {
746                                                         actor = manager.get(0);
747                                                 }
748                                         } else { /* Actor.customer */
749                                                 actor = from.getAuthor();
750                                                 // TODO: Get the customer of the study, if exists
751                                         }
752                                 } catch (Exception e) { // Should not happen
753                                         actor = null;
754                                 }
755                         }
756                         if (i == 0) {
757                                 aValidationCycle.setReviewer(actor);
758                         } else if (i == 1) {
759                                 aValidationCycle.setApprover(actor);
760                         } else if (i == 2) {
761                                 aValidationCycle.setSignatory(actor);
762                         }
763                 }
764                 return aValidationCycle;
765         }
766
767         /**
768          * Remove a validation step from the validation cycle.
769          * 
770          * @param aValidationCycle
771          *            the validation cycle
772          * @param step
773          *            the validation step to remove
774          */
775         @Transactional
776         protected void remove(final ValidationCycle aValidationCycle,
777                         final ValidationStep step) {
778                 if (step == ValidationStep.REVIEW) {
779                         aValidationCycle.setReviewer(null);
780                 } else if (step == ValidationStep.APPROVAL) {
781                         aValidationCycle.setApprover(null);
782                 } else if (step == ValidationStep.ACCEPTANCE
783                                 || step == ValidationStep.REFUSAL) {
784                         aValidationCycle.setSignatory(null);
785                 }
786                 if (aValidationCycle.isSaved()) {
787                         getValidationCycleDAO().update(aValidationCycle);
788                 }
789         }
790
791         /**
792          * Reset actors for the validation cycle.
793          * 
794          * @param aValidationCycle
795          *            the validation cycle to update
796          * @param vprop
797          *            new validation cycle properties containing new actors
798          */
799         @Transactional
800         public void resetActors(final ValidationCycle aValidationCycle,
801                         final ValidationCycle.Properties vprop) {
802                 aValidationCycle.setPublisher(vprop.getPublisher()); // May be null
803                 aValidationCycle.setReviewer(vprop.getReviewer()); // May be null
804                 aValidationCycle.setApprover(vprop.getApprover()); // May be null
805                 aValidationCycle.setSignatory(vprop.getSignatory()); // May be null
806                 if (aValidationCycle.isSaved()) {
807                         getValidationCycleDAO().merge(aValidationCycle);
808                 }
809         }
810
811         /**
812          * Set actor for the given validation cycle and validation step.
813          * 
814          * @param aValidationCycle
815          *            the validation cycle
816          * @param step
817          *            the validation step
818          * @param actor
819          *            the actor to set
820          */
821         @Transactional
822         protected void setActor(final ValidationCycle aValidationCycle,
823                         final ValidationStep step, final User actor) {
824                 if (step == ValidationStep.PROMOTION) {
825                         aValidationCycle.setPublisher(actor);
826                 } else if (step == ValidationStep.REVIEW) {
827                         aValidationCycle.setReviewer(actor);
828                 } else if (step == ValidationStep.APPROVAL) {
829                         aValidationCycle.setApprover(actor);
830                 } else if (step == ValidationStep.ACCEPTANCE
831                                 || step == ValidationStep.REFUSAL) {
832                         aValidationCycle.setSignatory(actor);
833                 }
834                 if (aValidationCycle.isSaved()) {
835                         getValidationCycleDAO().update(aValidationCycle);
836                 }
837         }
838
839         /**
840          * Returns all actors of this study other than the author, including contributors, reviewers and approvers.
841          * 
842          * @param aStudy
843          *            the study
844          * @return the actors of this study
845          * @see #hasActor(User)
846          */
847         public Set<User> getActors(final Study aStudy) {
848                 if (aStudy.getActor() == null) {
849                         setShortCuts(aStudy);
850                 }
851                 return Collections.unmodifiableSet(aStudy.getActor());
852         }
853
854         /**
855          * Returns all actors of this study other than the author, including contributors, reviewers and approvers.
856          * 
857          * @param aStudy
858          *            the study
859          * @return the modifiable set of actors of this study
860          * @see #hasActor(User)
861          */
862         public Set<User> getModifiableActors(final Study aStudy) {
863                 if (aStudy.getActor() == null) {
864                         setShortCuts(aStudy);
865                 }
866                 return aStudy.getActor();
867         }
868
869         /**
870          * Returns unmodifiable initialized transient list of contributors of this study.
871          * 
872          * @param aStudy
873          *            the study
874          * @return the unmodifiable not null transient list of contributors of this study
875          */
876         @Override
877         public List<User> getContributors(final Study aStudy) {
878                 if (aStudy.getContributor() == null) {
879                         setShortCuts(aStudy);
880                 }
881                 return Collections.unmodifiableList(aStudy.getContributor()); // May be empty
882         }
883
884         /**
885          * Returns modifiable initialized transient list of contributors of this study.
886          * 
887          * @param aStudy
888          *            the study
889          * @return the modifiable not null transient list of contributors of this study
890          */
891         public List<User> getModifiableContributors(final Study aStudy) {
892                 if (aStudy.getContributor() == null) {
893                         setShortCuts(aStudy);
894                 }
895                 return aStudy.getContributor(); // May be empty
896         }
897
898         /**
899          * Returns the validation cycle of the given document type.
900          * 
901          * @param aStudy
902          *            the study
903          * @param type
904          *            the document type being subject of validation
905          * @return the validation cycle of the document, or null if not defined.
906          */
907         @Override
908         public ValidationCycle getValidationCycleOf(final Study aStudy,
909                         final DocumentType type) {
910                 if (aStudy.getValidationCycles() == null || aStudy.getValidationCycles().isEmpty()) {
911                         setShortCuts(aStudy);
912                 }
913                 ValidationCycle result = aStudy.getValidationCycles().get(
914                                 type.getName());
915                 if (result == null) {
916                         if (type.isStepResult()) {
917                                 result = aStudy.getValidationCycles().get("default"); // "default" validation cycle defined in the configuration, if exist
918                         }
919                         if (result == null) {
920                                 result = aStudy.getValidationCycles().get("built-in");
921                         }
922                 }
923                 return result;
924         }
925
926         /**
927          * Checks if the given user is actor of this study. Actors include contributors, reviewers and approvers.
928          * 
929          * @param aStudy
930          *            the study
931          * @param user
932          *            the user to look for
933          * @return true if the given user is actor of this study.
934          * @see #getActors()
935          */
936         @Override
937         public boolean hasActor(final Study aStudy, final User user) {
938                 if (user == null) {
939                         return false;
940                 }
941                 for (Iterator<User> i = getActors(aStudy).iterator(); i.hasNext();) {
942                         User involved = i.next();
943                         if (involved.equals(user)) {
944                                 return true;
945                         }
946                 }
947                 return false;
948         }
949
950         /**
951          * Checks if the given user participates to this study. The Study staff includes the author and contributors.
952          * 
953          * @param aStudy
954          *            the study
955          * @param user
956          *            the user to look for
957          * @return true if the given user is actor of this study.
958          * @see #getContributors()
959          */
960         @Override
961         public boolean isStaffedBy(final Study aStudy, final User user) {
962                 if (user == null) {
963                         return false;
964                 }
965                 if (aStudy == null) {
966                         return false;
967                 }
968                 if (aStudy.getAuthor() == null) {
969                         return false;
970                 }
971                 if (aStudy.getAuthor().equals(user)) {
972                         return true;
973                 }
974                 for (Iterator<User> i = getContributors(aStudy).iterator(); i.hasNext();) {
975                         if (i.next().equals(user)) {
976                                 return true;
977                         }
978                 }
979                 return false;
980         }
981
982         /**
983          * Initialize shortcuts of the study as its transient collections.
984          * 
985          * @param aStudy
986          *            the study
987          */
988         @Override
989         public void loadWorkflow(final Study aStudy) {
990                 setShortCuts(aStudy);
991         }
992
993         /**
994          * Initialize shortcuts of the study as its transient collections.
995          * 
996          * @param aStudy
997          *            the study
998          */
999         public void setShortCuts(final Study aStudy) {
1000                 aStudy.getContributor().clear();
1001                 aStudy.getValidationCycles().clear();
1002                 aStudy.getActor().clear();
1003
1004                 // Get the contributors
1005                 for (Iterator<Relation> i = aStudy.getRelations(
1006                                 ContributorRelation.class).iterator(); i.hasNext();) {
1007                         ContributorRelation link = (ContributorRelation) i.next();
1008                         aStudy.getContributor().add(link.getTo());
1009                 }
1010                 // Get the validation cycles specific to this study
1011                 for (Iterator<Relation> i = aStudy.getRelations(
1012                                 ValidationCycleRelation.class).iterator(); i.hasNext();) {
1013                         ValidationCycleRelation link = (ValidationCycleRelation) i.next();
1014                         aStudy.getValidationCycles().put(link.getDocumentType().getName(),
1015                                         link.getTo()); // The associated document type is necessarily not null in this
1016                         // context
1017                 }
1018                 // Get the validation cycles coming from the configured workflow and not overridden in this study
1019                 for (Iterator<ProjectSettingsServiceImpl.ProjectSettingsValidationCycle> i = getProjectSettings()
1020                                 .getAllValidationCycles().iterator(); i.hasNext();) {
1021                         ProjectSettingsServiceImpl.ProjectSettingsValidationCycle cycle = i
1022                                         .next();
1023                         String type = cycle.getName();
1024                         if (!aStudy.getValidationCycles().containsKey(type)) {
1025                                 aStudy.getValidationCycles().put(type,
1026                                                 createValidationCycle(aStudy, cycle));
1027                         }
1028                 }
1029                 // Get all corresponding actors
1030                 for (Iterator<ValidationCycle> i = aStudy.getValidationCycles()
1031                                 .values().iterator(); i.hasNext();) {
1032                         ValidationCycle cycle = i.next();
1033                         User[] user = cycle.getAllActors();
1034                         for (int j = 0; j < user.length; j++) {
1035                                 aStudy.getActor().add(user[j]);
1036                         }
1037                 }
1038                 // Get all other actors
1039                 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
1040                                 .hasNext();) {
1041                         Relation link = i.next();
1042                         Class<?> kindof = link.getClass().getSuperclass();
1043                         if (!kindof.equals(ActorRelation.class)) {
1044                                 continue;
1045                         }
1046                         aStudy.getActor().add(((ActorRelation) link).getTo());
1047                 }
1048         }
1049         
1050         /**
1051          * 
1052          * {@inheritDoc}
1053          * @see org.splat.service.StudyService#markStudyAsReference(org.splat.dal.bo.som.Study)
1054          */
1055         @Override
1056         @Transactional
1057         public void markStudyAsReference (final Study aStudy) {
1058                 
1059                 aStudy.setMarkreference(1);
1060                 aStudy.setProgressState(ProgressState.TEMPLATE);
1061                 getStudyDAO().merge(aStudy);
1062         }
1063         
1064         /**
1065          * 
1066          * {@inheritDoc}
1067          * @see org.splat.service.StudyService#removeStudyAsReference(org.splat.dal.bo.som.Study)
1068          */
1069         @Override
1070         @Transactional
1071         public void removeStudyAsReference(final Study aStudy) {
1072                 
1073                 aStudy.setMarkreference(0);
1074                 aStudy.setProgressState(ProgressState.APPROVED);
1075                 getStudyDAO().merge(aStudy);
1076         }
1077         
1078         
1079         /** 
1080          * {@inheritDoc}
1081          * @see org.splat.service.StudyService#getDescription(java.lang.Long)
1082          */
1083         @Override
1084         @Transactional(readOnly = true)
1085         public String getDescription(final Long studyId) throws InvalidParameterException {
1086                 if(studyId == null) {
1087                         throw new InvalidParameterException("studyId", "null");
1088                 }
1089                 Study study = _studyDAO.get(studyId);
1090                 if(study == null) {
1091                         throw new InvalidParameterException("studyId", studyId.toString());
1092                 }
1093                 return study.getDescription();
1094         }
1095         
1096         
1097         /** 
1098          * {@inheritDoc}
1099          * @see org.splat.service.StudyService#setDescription(java.lang.Long, java.lang.String)
1100          */
1101         @Override
1102         @Transactional
1103         public void setDescription(final Long studyId, final String descriptionText) 
1104                         throws InvalidParameterException {
1105                 if(studyId == null) {
1106                         throw new InvalidParameterException("studyId", "null");
1107                 }
1108                 Study study = _studyDAO.get(studyId);
1109                 if(study == null) {
1110                         throw new InvalidParameterException("studyId", studyId.toString());
1111                 }
1112                 study.setAttribute(new DescriptionAttribute(study, descriptionText));
1113         }
1114         
1115         /** 
1116          * {@inheritDoc}
1117          * @see org.splat.service.StudyService#removeStudyDescription(java.lang.Long)
1118          */
1119         @Override
1120         @Transactional
1121         public boolean removeDescription(final Long studyId) throws InvalidParameterException {
1122                 if(studyId == null) {
1123                         throw new InvalidParameterException("studyId", String.valueOf(studyId));
1124                 }
1125                 Study study = _studyDAO.get(studyId);
1126                 if(study == null) {
1127                         throw new InvalidParameterException("studyId", String.valueOf(studyId));
1128                 }
1129                 return study.removeAttribute(study.getAttribute(DescriptionAttribute.class));
1130         }
1131         
1132         @Override
1133         public String compare (final List<DocToCompareDTO> docsList) {
1134                 return "Result file path";
1135         }
1136
1137         /**
1138          * Get project settings.
1139          * 
1140          * @return Project settings service
1141          */
1142         private ProjectSettingsService getProjectSettings() {
1143                 return _projectSettings;
1144         }
1145
1146         /**
1147          * Set project settings service.
1148          * 
1149          * @param projectSettingsService
1150          *            project settings service
1151          */
1152         public void setProjectSettings(
1153                         final ProjectSettingsService projectSettingsService) {
1154                 _projectSettings = projectSettingsService;
1155         }
1156
1157         /**
1158          * Get the projectElementService.
1159          * 
1160          * @return the projectElementService
1161          */
1162         public ProjectElementService getProjectElementService() {
1163                 return _projectElementService;
1164         }
1165
1166         /**
1167          * Set the projectElementService.
1168          * 
1169          * @param projectElementService
1170          *            the projectElementService to set
1171          */
1172         public void setProjectElementService(
1173                         final ProjectElementService projectElementService) {
1174                 _projectElementService = projectElementService;
1175         }
1176
1177         /**
1178          * Get the stepService.
1179          * 
1180          * @return the stepService
1181          */
1182         public StepService getStepService() {
1183                 return _stepService;
1184         }
1185
1186         /**
1187          * Set the stepService.
1188          * 
1189          * @param stepService
1190          *            the stepService to set
1191          */
1192         public void setStepService(final StepService stepService) {
1193                 _stepService = stepService;
1194         }
1195
1196         /**
1197          * Get the indexService.
1198          * 
1199          * @return the indexService
1200          */
1201         public IndexService getIndexService() {
1202                 return _indexService;
1203         }
1204
1205         /**
1206          * Set the indexService.
1207          * 
1208          * @param indexService
1209          *            the indexService to set
1210          */
1211         public void setIndexService(final IndexService indexService) {
1212                 _indexService = indexService;
1213         }
1214
1215         /**
1216          * Get the studyDAO.
1217          * 
1218          * @return the studyDAO
1219          */
1220         public StudyDAO getStudyDAO() {
1221                 return _studyDAO;
1222         }
1223
1224         /**
1225          * Set the studyDAO.
1226          * 
1227          * @param studyDAO
1228          *            the studyDAO to set
1229          */
1230         public void setStudyDAO(final StudyDAO studyDAO) {
1231                 _studyDAO = studyDAO;
1232         }
1233
1234         /**
1235          * Get the iDBuilderDAO.
1236          * 
1237          * @return the iDBuilderDAO
1238          */
1239         public IDBuilderDAO getIDBuilderDAO() {
1240                 return _iDBuilderDAO;
1241         }
1242
1243         /**
1244          * Set the iDBuilderDAO.
1245          * 
1246          * @param builderDAO
1247          *            the iDBuilderDAO to set
1248          */
1249         public void setIDBuilderDAO(final IDBuilderDAO builderDAO) {
1250                 _iDBuilderDAO = builderDAO;
1251         }
1252
1253         /**
1254          * Get the scenarioDAO.
1255          * 
1256          * @return the scenarioDAO
1257          */
1258         public ScenarioDAO getScenarioDAO() {
1259                 return _scenarioDAO;
1260         }
1261
1262         /**
1263          * Set the scenarioDAO.
1264          * 
1265          * @param scenarioDAO
1266          *            the scenarioDAO to set
1267          */
1268         public void setScenarioDAO(final ScenarioDAO scenarioDAO) {
1269                 _scenarioDAO = scenarioDAO;
1270         }
1271
1272         /**
1273          * Get the validationCycleDAO.
1274          * 
1275          * @return the validationCycleDAO
1276          */
1277         public ValidationCycleDAO getValidationCycleDAO() {
1278                 return _validationCycleDAO;
1279         }
1280
1281         /**
1282          * Set the validationCycleDAO.
1283          * 
1284          * @param validationCycleDAO
1285          *            the validationCycleDAO to set
1286          */
1287         public void setValidationCycleDAO(
1288                         final ValidationCycleDAO validationCycleDAO) {
1289                 _validationCycleDAO = validationCycleDAO;
1290         }
1291
1292         /**
1293          * Get the documentTypeService.
1294          * 
1295          * @return the documentTypeService
1296          */
1297         public DocumentTypeService getDocumentTypeService() {
1298                 return _documentTypeService;
1299         }
1300
1301         /**
1302          * Set the documentTypeService.
1303          * 
1304          * @param documentTypeService
1305          *            the documentTypeService to set
1306          */
1307         public void setDocumentTypeService(
1308                         final DocumentTypeService documentTypeService) {
1309                 _documentTypeService = documentTypeService;
1310         }
1311
1312         /**
1313          * Get the userService.
1314          * 
1315          * @return the userService
1316          */
1317         public UserService getUserService() {
1318                 return _userService;
1319         }
1320
1321         /**
1322          * Set the userService.
1323          * 
1324          * @param userService
1325          *            the userService to set
1326          */
1327         public void setUserService(final UserService userService) {
1328                 _userService = userService;
1329         }
1330         
1331         /**
1332          * Get the publicationDAO.
1333          * @return the publicationDAO
1334          */
1335         public PublicationDAO getPublicationDAO() {
1336                 return _publicationDAO;
1337         }
1338
1339         /**
1340          * Set the publicationDAO.
1341          * @param publicationDAO the publicationDAO to set
1342          */
1343         public void setPublicationDAO(final PublicationDAO publicationDAO) {
1344                 _publicationDAO = publicationDAO;
1345         }
1346
1347         /**
1348          * Get the repositoryService.
1349          * @return the repositoryService
1350          */
1351         public RepositoryService getRepositoryService() {
1352                 return _repositoryService;
1353         }
1354
1355         /**
1356          * Set the repositoryService.
1357          * @param repositoryService the repositoryService to set
1358          */
1359         public void setRepositoryService(final RepositoryService repositoryService) {
1360                 _repositoryService = repositoryService;
1361         }
1362
1363         /**
1364          * Get the documentDAO.
1365          * @return the documentDAO
1366          */
1367         public DocumentDAO getDocumentDAO() {
1368                 return _documentDAO;
1369         }
1370
1371         /**
1372          * Set the documentDAO.
1373          * @param documentDAO the documentDAO to set
1374          */
1375         public void setDocumentDAO(final DocumentDAO documentDAO) {
1376                 _documentDAO = documentDAO;
1377         }
1378
1379         /**
1380          * Get the descriptionAttributeDAO.
1381          * @return the descriptionAttributeDAO
1382          */
1383         public DescriptionAttributeDAO getDescriptionAttributeDAO() {
1384                 return _descriptionAttributeDAO;
1385         }
1386
1387         /**
1388          * Set the descriptionAttributeDAO.
1389          * @param descriptionAttributeDAO the descriptionAttributeDAO to set
1390          */
1391         public void setDescriptionAttributeDAO(
1392                         final DescriptionAttributeDAO descriptionAttributeDAO) {
1393                 _descriptionAttributeDAO = descriptionAttributeDAO;
1394         }
1395 }