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