Salome HOME
small correction.
[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.awt.Graphics2D;
13 import java.io.File;
14 import java.io.FileNotFoundException;
15 import java.io.FileOutputStream;
16 import java.io.IOException;
17 import java.text.DecimalFormat;
18 import java.text.SimpleDateFormat;
19 import java.util.ArrayList;
20 import java.util.Calendar;
21 import java.util.Collections;
22 import java.util.Date;
23 import java.util.HashMap;
24 import java.util.HashSet;
25 import java.util.Iterator;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Scanner;
29 import java.util.Set;
30
31 import org.apache.lucene.index.IndexWriter;
32 import org.apache.lucene.store.FSDirectory;
33 import org.hibernate.Criteria;
34 import org.hibernate.Hibernate;
35 import org.hibernate.criterion.DetachedCriteria;
36 import org.hibernate.criterion.Restrictions;
37 import org.hibernate.proxy.HibernateProxy;
38 import org.jfree.chart.ChartFactory;
39 import org.jfree.chart.JFreeChart;
40 import org.jfree.chart.plot.PlotOrientation;
41 import org.jfree.data.xy.XYSeries;
42 import org.jfree.data.xy.XYSeriesCollection;
43 import org.splat.common.properties.MessageKeyEnum;
44 import org.splat.dal.bo.kernel.Relation;
45 import org.splat.dal.bo.kernel.User;
46 import org.splat.dal.bo.som.ActorRelation;
47 import org.splat.dal.bo.som.ContributorRelation;
48 import org.splat.dal.bo.som.DescriptionAttribute;
49 import org.splat.dal.bo.som.DocumentType;
50 import org.splat.dal.bo.som.IDBuilder;
51 import org.splat.dal.bo.som.ProgressState;
52 import org.splat.dal.bo.som.ProjectElement;
53 import org.splat.dal.bo.som.Publication;
54 import org.splat.dal.bo.som.Scenario;
55 import org.splat.dal.bo.som.SimulationContext;
56 import org.splat.dal.bo.som.Study;
57 import org.splat.dal.bo.som.Study.Properties;
58 import org.splat.dal.bo.som.ValidationCycle;
59 import org.splat.dal.bo.som.ValidationCycle.Actor;
60 import org.splat.dal.bo.som.ValidationCycleRelation;
61 import org.splat.dal.bo.som.ValidationStep;
62 import org.splat.dal.bo.som.Visibility;
63 import org.splat.dal.dao.som.DescriptionAttributeDAO;
64 import org.splat.dal.dao.som.DocumentDAO;
65 import org.splat.dal.dao.som.IDBuilderDAO;
66 import org.splat.dal.dao.som.PublicationDAO;
67 import org.splat.dal.dao.som.ScenarioDAO;
68 import org.splat.dal.dao.som.StudyDAO;
69 import org.splat.dal.dao.som.UsedByRelationDAO;
70 import org.splat.dal.dao.som.ValidationCycleDAO;
71 import org.splat.exception.IncompatibleDataException;
72 import org.splat.exception.InvalidParameterException;
73 import org.splat.kernel.InvalidPropertyException;
74 import org.splat.kernel.MismatchException;
75 import org.splat.kernel.MissedPropertyException;
76 import org.splat.kernel.MultiplyDefinedException;
77 import org.splat.log.AppLogger;
78 import org.splat.service.dto.DocToCompareDTO;
79 import org.splat.service.dto.DocumentDTO;
80 import org.splat.service.dto.StudyFacadeDTO;
81 import org.splat.service.technical.IndexService;
82 import org.splat.service.technical.ProjectSettingsService;
83 import org.splat.service.technical.ProjectSettingsService.Step;
84 import org.splat.service.technical.ProjectSettingsServiceImpl;
85 import org.splat.service.technical.RepositoryService;
86 import org.splat.som.Revision;
87 import org.springframework.transaction.annotation.Transactional;
88
89 import com.lowagie.text.Document;
90 import com.lowagie.text.DocumentException;
91 import com.lowagie.text.Rectangle;
92 import com.lowagie.text.pdf.DefaultFontMapper;
93 import com.lowagie.text.pdf.PdfContentByte;
94 import com.lowagie.text.pdf.PdfTemplate;
95 import com.lowagie.text.pdf.PdfWriter;
96
97 /**
98  * This class defines all methods for creation, modification the study.
99  * 
100  * @author Maria KRUCHININA
101  * 
102  */
103 public class StudyServiceImpl implements StudyService {
104
105         /**
106          * logger for the service.
107          */
108         public final static AppLogger LOG = AppLogger
109                         .getLogger(StudyServiceImpl.class);
110         /**
111          * "studyId" parameter name.
112          */
113         public final static String PARAM_STUDY_ID = "studyId";
114
115         /**
116          * Injected index service.
117          */
118         private IndexService _indexService;
119
120         /**
121          * Injected step service.
122          */
123         private StepService _stepService;
124
125         /**
126          * Injected project service.
127          */
128         private ProjectSettingsService _projectSettings;
129
130         /**
131          * Injected project element service.
132          */
133         private ProjectElementService _projectElementService;
134
135         /**
136          * Injected study DAO.
137          */
138         private StudyDAO _studyDAO;
139
140         /**
141          * Injected usedBy relations DAO.
142          */
143         private UsedByRelationDAO _usedByRelationDAO;
144
145         /**
146          * Injected scenario DAO.
147          */
148         private ScenarioDAO _scenarioDAO;
149
150         /**
151          * Injected validation cycle DAO.
152          */
153         private ValidationCycleDAO _validationCycleDAO;
154
155         /**
156          * Injected IDBuilder DAO.
157          */
158         private IDBuilderDAO _iDBuilderDAO;
159
160         /**
161          * Injected document type service.
162          */
163         private DocumentTypeService _documentTypeService;
164
165         /**
166          * Injected user service.
167          */
168         private UserService _userService;
169
170         /**
171          * Injected publication DAO.
172          */
173         private PublicationDAO _publicationDAO;
174
175         /**
176          * Injected repository service.
177          */
178         private RepositoryService _repositoryService;
179
180         /**
181          * Injected document DAO.
182          */
183         private DocumentDAO _documentDAO;
184
185         /**
186          * Injected description attribute DAO.
187          */
188         private DescriptionAttributeDAO _descriptionAttributeDAO;
189
190         /**
191          * {@inheritDoc}
192          * 
193          * @see org.splat.service.StudyService#selectStudy(long)
194          */
195         @Transactional
196         public Study selectStudy(final long index) {
197                 Study result = getStudyDAO().get(index);
198                 loadWorkflow(result);
199                 return result;
200         }
201
202         /**
203          * {@inheritDoc}
204          * 
205          * @see org.splat.service.StudyService#removeStudy(long)
206          */
207         @Transactional
208         public void removeStudy(final Long index) {
209                 Study study = getStudyDAO().get(index);
210                 Set<org.splat.dal.bo.som.Document> docums = new HashSet<org.splat.dal.bo.som.Document>();
211                 if (study != null) {
212                         // Select all documents published in the study and study's scenarios.
213                         DetachedCriteria query = DetachedCriteria.forClass(
214                                         Publication.class, "pub");
215                         query
216                                         .createCriteria("pub.owner", "projelem",
217                                                         Criteria.INNER_JOIN)
218                                         .createAlias("projelem.owner", "study", Criteria.LEFT_JOIN)
219                                         .add(
220                                                         Restrictions
221                                                                         .or(Restrictions.eq("projelem.rid", index),
222                                                                                         Restrictions.eq("study.rid", index)))
223                                         .setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);
224
225                         if (LOG.isDebugEnabled()) {
226                                 LOG.debug("Find study documents: " + query.toString());
227                         }
228                         for (Publication pub : getPublicationDAO().getFilteredList(query)) {
229                                 docums.add(pub.value());
230                                 // Find also all previous versions of the document
231                                 for (org.splat.dal.bo.som.Document prev = pub.value()
232                                                 .getPreviousVersion(); prev != null; prev = prev
233                                                 .getPreviousVersion()) {
234                                         docums.add(prev);
235                                 }
236                         }
237
238                         // Delete the study with its relations, scenarios and publications
239                         getStudyDAO().delete(study);
240
241                         // Remove all relations of study documents
242                         for (org.splat.dal.bo.som.Document doc : docums) {
243                                 LOG.debug("Found doc: " + doc.getTitle() + " [" + doc.getReference() + "]" + " [" + doc.getRid() + "]");
244                                 doc.getAllRelations().clear();
245                         }
246                         getDocumentDAO().flush();
247
248                         // Remove all documents of the study
249                         for (org.splat.dal.bo.som.Document doc : docums) {
250                                 LOG.debug("Remove doc: " + doc.getTitle() + " [" + doc.getReference() + "]" + " [" + doc.getRid() + "]");
251                                 getDocumentDAO().delete(doc);
252                         }
253                 }
254         }
255
256         /**
257          * Get study by its reference.
258          * 
259          * @param refid
260          *            the study reference
261          * @return found study or null
262          */
263         @Transactional(readOnly = true)
264         public Study selectStudy(final String refid) {
265                 Study result = getStudyDAO().findByCriteria(
266                                 Restrictions.eq("sid", refid));
267                 loadWorkflow(result);
268                 return result;
269         }
270
271         /**
272          * {@inheritDoc}
273          * 
274          * @see org.splat.service.StudyService#createStudy(org.splat.dal.bo.som.Study.Properties)
275          */
276         @Transactional
277         public Study createStudy(final Study.Properties sprop)
278                         throws MissedPropertyException, InvalidPropertyException,
279                         MultiplyDefinedException {
280                 sprop.setReference(getProjectSettings().getReferencePattern());
281                 Study study = new Study(sprop);
282
283                 buildReference(study);
284                 getStudyDAO().create(study);
285                 // try {
286                 // IndexService lucin = getIndex();
287                 // lucin.add(study);
288                 // } catch (IOException error) {
289                 // LOG.error("Unable to index the study '" + study.getIndex()
290                 // + "', reason:", error);
291                 // // Continue and try to index later
292                 // }
293                 return study;
294         }
295
296         /**
297          * {@inheritDoc}
298          * 
299          * @see org.splat.service.StudyService#addProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext.Properties)
300          */
301         @Transactional
302         public SimulationContext addProjectContext(final Study aStudy,
303                         final SimulationContext.Properties cprop)
304                         throws MissedPropertyException, InvalidPropertyException,
305                         MultiplyDefinedException {
306                 SimulationContext added = getStepService().addSimulationContext(
307                                 getProjectElementService().getFirstStep(aStudy), cprop);
308                 update(aStudy);
309                 return added;
310         }
311
312         /**
313          * {@inheritDoc}
314          * 
315          * @see org.splat.service.StudyService#addProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext)
316          */
317         @Transactional
318         public SimulationContext addProjectContext(final Study aStudy,
319                         final SimulationContext context) {
320                 SimulationContext added = getStepService().addSimulationContext(
321                                 getProjectElementService().getFirstStep(aStudy), context);
322                 update(aStudy);
323                 return added;
324         }
325
326         /**
327          * {@inheritDoc}
328          * 
329          * @see org.splat.service.StudyService#addContributor(org.splat.dal.bo.som.Study, org.splat.dal.bo.kernel.User)
330          */
331         @Transactional
332         public boolean addContributor(final Study aStudy, final User user) {
333                 List<User> contributor = getModifiableContributors(aStudy); // Initializes contributor
334                 for (Iterator<User> i = contributor.iterator(); i.hasNext();) {
335                         User present = i.next();
336                         if (present.equals(user)) {
337                                 return false;
338                         }
339                 }
340                 boolean absent = getModifiableActors(aStudy).add(user); // User may already be a reviewer or an approver
341
342                 aStudy.addRelation(new ContributorRelation(aStudy, user));
343                 if (absent) {
344                         update(aStudy); // Else, useless to re-index the study
345                 }
346                 return true;
347         }
348
349         /**
350          * Moves this study from the Public to the Reference area of the repository. For being moved to the Reference area, the study must
351          * previously be approved.
352          * 
353          * @param aStudy
354          *            the study to move
355          * @return true if the move succeeded.
356          * @see #moveToPublic()
357          * @see #isPublic()
358          * @see Publication#approve(Date)
359          */
360         public boolean moveToReference(final Study aStudy) {
361                 if (aStudy.getProgressState() != ProgressState.APPROVED) {
362                         return false;
363                 }
364                 if (aStudy.getVisibility() != Visibility.PUBLIC) {
365                         return false;
366                 }
367
368                 aStudy.setVisibility(Visibility.REFERENCE);
369                 if (update(aStudy)) {
370                         return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
371                 }
372                 return false;
373         }
374
375         /**
376          * {@inheritDoc}
377          * 
378          * @see org.splat.service.StudyService#update(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Study.Properties)
379          */
380         public boolean update(final Study aStudy, final Properties sprop)
381                         throws InvalidPropertyException {
382                 if (sprop.getTitle() != null) {
383                         aStudy.setTitle(sprop.getTitle());
384                 }
385                 if (sprop.getSummary() != null) {
386                         aStudy.setAttribute(new DescriptionAttribute(aStudy, sprop
387                                         .getSummary()));
388                 }
389                 // TODO: To be completed
390                 return update(aStudy);
391         }
392
393         /**
394          * Check if the document is published in the study.
395          * 
396          * @param aStudy
397          *            the study
398          * @param doc
399          *            the document
400          * @return true if the document is published in the study
401          */
402 /*      private boolean publishes(final Study aStudy, final Document doc) {
403                 if (!aStudy.publishes(doc)) {
404                         Scenario[] scene = aStudy.getScenarii();
405                         for (int i = 0; i < scene.length; i++) {
406                                 if (scene[i].publishes(doc)) {
407                                         return true;
408                                 }
409                         }
410                 }
411                 return false;
412         }
413          */
414         /**
415          * {@inheritDoc}
416          * 
417          * @see org.splat.service.StudyService#removeContributor(org.splat.dal.bo.som.Study, org.splat.dal.bo.kernel.User[])
418          */
419         @Transactional
420         public boolean removeContributor(final Study aStudy, final User... users) {
421                 List<User> contributor = getModifiableContributors(aStudy); // Initializes contributor
422                 Boolean done = false;
423                 for (int i = 0; i < users.length; i++) {
424                         User user = users[i];
425                         for (Iterator<User> j = contributor.iterator(); j.hasNext();) {
426                                 User present = j.next();
427                                 if (!present.equals(user)) {
428                                         continue;
429                                 }
430
431                                 aStudy.removeRelation(ContributorRelation.class, user);
432                                 j.remove(); // Updates the contributor shortcut
433                                 done = true;
434                                 break;
435                         }
436                 }
437                 if (done) {
438                         update(aStudy);
439                 }
440                 return done;
441         }
442
443         /**
444          * {@inheritDoc}
445          * 
446          * @see org.splat.service.StudyService#removeProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext)
447          */
448         public boolean removeProjectContext(final Study aStudy,
449                         final SimulationContext context) {
450                 boolean done = getStepService().removeSimulationContext(
451                                 getProjectElementService().getFirstStep(aStudy), context);
452                 update(aStudy);
453                 return done;
454         }
455
456         /**
457          * {@inheritDoc}
458          * 
459          * @see org.splat.service.StudyService#setValidationCycle(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.DocumentType,
460          *      org.splat.dal.bo.som.ValidationCycle.Properties)
461          */
462         @Transactional
463         public void setValidationCycle(final Study aStudyDTO,
464                         final DocumentType type, final ValidationCycle.Properties vprop) {
465                 Map<String, ValidationCycle> validactor = aStudyDTO
466                                 .getValidationCycles();
467                 if (validactor == null) {
468                         setShortCuts(aStudyDTO); // Initializes validactor and actor
469                 }
470
471                 Study aStudy = selectStudy(aStudyDTO.getIndex());
472
473                 String cname = type.getName();
474                 ValidationCycle cycle = validactor.get(cname);
475
476                 if (cycle != null && cycle.isAssigned()) {
477                         resetActors(cycle, vprop);
478                 } else {
479                         try {
480                                 cycle = new ValidationCycle(aStudy, vprop.setDocumentType(type));
481
482                                 getValidationCycleDAO().create(cycle); // RKV
483
484                                 ValidationCycleRelation link = cycle.getContext();
485                                 aStudy.addRelation(link);
486                                 aStudyDTO.getAllRelations().add(link); // RKV
487
488                                 validactor.put(cname, link.getTo()); // Replaces the cycle if exists as default,
489                         } catch (Exception error) {
490                                 LOG.error("Unable to re-index Knowledge Elements, reason:",
491                                                 error);
492                                 return;
493                         }
494                 }
495                 resetActorsShortCut(aStudyDTO);
496                 update(aStudy); // Re-index the study, just in case
497         }
498
499         /**
500          * Demotes this study from In-Check to In-Draft then In-Work states. This function is called internally when demoting the final result
501          * document of the study.
502          * 
503          * @param aStudy
504          *            a study to demote
505          * @return true if the demotion succeeded.
506          */
507         public boolean demote(final Study aStudy) {
508                 if (aStudy.getProgressState() == ProgressState.inCHECK) {
509                         aStudy.setProgressState(ProgressState.inDRAFT);
510                 } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
511                         aStudy.setProgressState(ProgressState.inWORK);
512                 } else {
513                         return false;
514                 }
515                 return update(aStudy);
516         }
517
518         /**
519          * {@inheritDoc}
520          * 
521          * @see org.splat.service.StudyService#generateLocalIndex(org.splat.dal.bo.som.Study)
522          */
523         @Transactional
524         public int generateLocalIndex(final Study aStudy) {
525                 aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1);
526                 return aStudy.getLastLocalIndex();
527         }
528
529         /**
530          * Promotes this study from In-Work to In-Draft then In-Check and APPROVED states. This function is called internally when promoting the
531          * final result document of the study.
532          * 
533          * @param aStudy
534          *            a study to promote
535          * @return true if the demotion succeeded.
536          */
537         @Transactional
538         public boolean promote(final Study aStudy) {
539                 if (aStudy.getProgressState() == ProgressState.inWORK) {
540                         aStudy.setProgressState(ProgressState.inDRAFT);
541                 } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
542                         aStudy.setProgressState(ProgressState.inCHECK);
543                         Revision myvers = new Revision(aStudy.getVersion());
544                         if (myvers.isMinor()) {
545                                 aStudy.setVersion(myvers.incrementAs(aStudy.getProgressState())
546                                                 .toString());
547                         }
548                 } else if (aStudy.getProgressState() == ProgressState.inCHECK) {
549                         aStudy.setProgressState(ProgressState.APPROVED);
550                 } else {
551                         return false;
552                 }
553
554                 return update(aStudy);
555         }
556
557         /**
558          * Moves this study from the Private to the Public area of the repository.
559          * 
560          * @param aStudy
561          *            a study to move
562          * @return true if the move succeeded.
563          * @see #isPublic()
564          */
565         @Transactional
566         public boolean moveToPublic(final Study aStudy) {
567                 boolean isOk = false;
568                 if (aStudy.getVisibility() == Visibility.PRIVATE) {
569                         aStudy.setVisibility(Visibility.PUBLIC);
570                         if (update(aStudy)) {
571                                 isOk = updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
572                         }
573                 }
574                 return isOk;
575         }
576
577         /**
578          * Moves this study from the Public to the Private area of the repository.
579          * 
580          * @param aStudy
581          *            a study to move
582          * @return true if the move succeeded.
583          */
584         @Transactional
585         public boolean moveToPrivate(final Study aStudy) {
586                 boolean isOk = false;
587                 if (aStudy.getVisibility() == Visibility.PUBLIC) {
588                         aStudy.setVisibility(Visibility.PRIVATE);
589                         if (update(aStudy)) {
590                                 isOk = updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
591                         }
592                 }
593                 return isOk;
594         }
595
596         /**
597          * Update a study in the database.
598          * 
599          * @param aStudy
600          *            the study to update
601          * @return true if the study is updated successfully
602          */
603         @Transactional
604         private boolean update(final Study aStudy) {
605                 boolean isOk = false;
606                 try {
607                         getStudyDAO().merge(aStudy); // Update of relational base
608                         setShortCuts(aStudy); // RKV: initialize transient actors set
609                         // RKV: getIndex().update(aStudy); // Update of Lucene index
610                         isOk = true;
611                 } catch (Exception e) {
612                         LOG.error("STD-000001", e, aStudy.getIndex(), e.getMessage());
613                 }
614                 return isOk;
615         }
616
617         /**
618          * Build reference for the study. The reference of the study is stored as a new reference pattern (IDBuilder).
619          * 
620          * @param aStudy
621          *            the study
622          * @return true if reference building is succeded
623          */
624         @Transactional
625         private boolean buildReference(final Study aStudy) {
626                 String pattern = aStudy.getReference(); // The study being supposed just created, its reference is the reference pattern
627                 IDBuilder tool = selectIDBuilder(aStudy.getDate());
628                 if (tool == null) {
629                         tool = new IDBuilder(aStudy.getDate());
630                         getIDBuilderDAO().create(tool);
631                 }
632                 aStudy.setReference(buildReference(tool, pattern, aStudy));
633                 return true;
634         }
635
636         /**
637          * Build reference for the study. The reference of the study is stored as a new reference pattern (IDBuilder).
638          * 
639          * @param aBuilder
640          *            the id builder
641          * @param study
642          *            the study
643          * @param pattern
644          *            the reference pattern
645          * @return true if reference building is succeded
646          */
647         @Transactional
648         public String buildReference(final IDBuilder aBuilder,
649                         final String pattern, final Study study) {
650                 char[] format = pattern.toCharArray();
651                 char[] ref = new char[80]; // Better evaluate the length of the generated string
652                 int next = aBuilder.getBase() + 1;
653
654                 int count = 0;
655                 for (int i = 0; i < format.length; i++) {
656
657                         // Insertion of attribute values
658                         if (format[i] == '%') {
659                                 i += 1;
660
661                                 if (format[i] == 'y') { // Insertion of year in format 2 (e.g. 09) or 4 (e.g. 2009) digits
662                                         int n = i;
663                                         while (format[i] == 'y') {
664                                                 i += 1;
665                                                 if (i == format.length) {
666                                                         break;
667                                                 }
668                                         }
669                                         SimpleDateFormat tostring = new SimpleDateFormat("yyyy"); // RKV: NOPMD: TODO: Use locale here?
670                                         String year = tostring.format(study.getDate());
671                                         year = year.substring(4 - (i - n), 4); // 4-(i-n) must be equal to either 0 or 2
672                                         for (int j = 0; j < year.length(); j++) {
673                                                 ref[count] = year.charAt(j);
674                                                 count += 1;
675                                         }
676                                         i -= 1; // Back to the last 'y' character
677                                 } else if (format[i] == '0') { // Insertion of the index
678                                         int n = i;
679                                         while (format[i] == '0') {
680                                                 i += 1;
681                                                 if (i == format.length) {
682                                                         break;
683                                                 }
684                                         }
685                                         DecimalFormat tostring = new DecimalFormat(pattern
686                                                         .substring(n, i));
687                                         String number = tostring.format(next);
688                                         for (int j = 0; j < number.length(); j++) {
689                                                 ref[count] = number.charAt(j);
690                                                 count += 1;
691                                         }
692                                         i -= 1; // Back to the last '0' character
693                                 }
694                                 // Keep the character
695                         } else {
696                                 ref[count] = format[i];
697                                 count += 1;
698                         }
699                 }
700                 // Incrementation of the number of study
701                 aBuilder.setBase(next);
702                 getIDBuilderDAO().update(aBuilder);
703                 return String.copyValueOf(ref, 0, count);
704         }
705
706         /**
707          * Find an id builder by date.
708          * 
709          * @param date
710          *            the date
711          * @return found id builder
712          */
713         private IDBuilder selectIDBuilder(final Date date) {
714                 Calendar aDate = Calendar.getInstance();
715                 aDate.setTime(date);
716                 return getIDBuilderDAO().findByCriteria(
717                                 Restrictions.eq("cycle", aDate.get(Calendar.YEAR)));
718         }
719
720         /**
721          * Fill transient collection ModifiableActors of the study.
722          * 
723          * @param aStudy
724          *            the study
725          */
726         private void resetActorsShortCut(final Study aStudy) {
727                 getModifiableActors(aStudy).clear();
728                 // Get all actors involved in validation cycles
729                 for (Iterator<ValidationCycle> i = aStudy.getValidationCycles()
730                                 .values().iterator(); i.hasNext();) {
731                         ValidationCycle cycle = i.next();
732                         User[] user = cycle.getAllActors();
733                         for (int j = 0; j < user.length; j++) {
734                                 getModifiableActors(aStudy).add(user[j]);
735                         }
736                 }
737                 // Get all other actors
738                 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
739                                 .hasNext();) {
740                         Relation link = i.next();
741                         Class<?> kindof = link.getClass().getSuperclass();
742                         if (!kindof.equals(ActorRelation.class)) {
743                                 continue;
744                         }
745                         getModifiableActors(aStudy).add(((ActorRelation) link).getTo());
746                 }
747         }
748
749         /**
750          * Update lucene index for the study knowledge elements.
751          * 
752          * @param aStudy
753          *            the study
754          * @return true if reindexing succeeded
755          */
756         private boolean updateKnowledgeElementsIndex(final Study aStudy) {
757                 // boolean isOk = false;
758                 // try {
759                 // IndexService lucin = getIndex();
760                 //
761                 // for (Iterator<Scenario> i = aStudy.getScenariiList().iterator(); i
762                 // .hasNext();) {
763                 // Scenario scene = i.next();
764                 // for (Iterator<KnowledgeElement> j = scene
765                 // .getAllKnowledgeElements().iterator(); j.hasNext();) {
766                 // KnowledgeElement kelm = j.next();
767                 // lucin.update(kelm);
768                 // }
769                 // }
770                 // isOk = true;
771                 // } catch (Exception error) {
772                 // LOG.error("Unable to re-index Knowledge Elements, reason:",
773                 // error);
774                 // }
775                 // return isOk;
776                 return true;
777         }
778
779         /**
780          * Get lucene index service. Create a lucene index if it does not exist.
781          * 
782          * @return index service
783          * @throws IOException
784          *             if error occurs during lucene index creation
785          */
786         private IndexService getIndex() throws IOException {
787                 IndexService lucin = getIndexService();
788                 if (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
789                                 .getRepositoryIndexDirectory()))) {
790                         IndexWriter.unlock(FSDirectory.open(getRepositoryService()
791                                         .getRepositoryIndexDirectory()));
792                 }
793                 if (!lucin.exists()) {
794                         lucin.create(); // Happens when re-indexing all studies
795                 }
796                 return lucin;
797         }
798
799         /**
800          * Create a new validation cycle for documents of the given study.
801          * 
802          * @param from
803          *            the study
804          * @param cycle
805          *            the cycle description
806          * @return the new validation cycle
807          */
808         protected ValidationCycle createValidationCycle(
809                         final Study from,
810                         final ProjectSettingsServiceImpl.ProjectSettingsValidationCycle cycle) {
811                 Actor[] actype = cycle.getActorTypes();
812                 User.Properties uprop = new User.Properties();
813
814                 ValidationCycle aValidationCycle = new ValidationCycle();
815                 aValidationCycle.setDocumentType(getDocumentTypeService().selectType(
816                                 cycle.getName())); // Null in case of default validation cycle
817                 // context = new ValidationCycleRelation(from, vprop);
818                 // RKV aValidationCycle.context = null; // Validation cycle defined in the workflow
819                 for (int i = 0; i < actype.length; i++) {
820                         User actor = null;
821                         if (actype[i] != null) {
822                                 try {
823                                         if (actype[i] == Actor.manager) {
824                                                 actor = from.getAuthor();
825                                         } else if (actype[i] == Actor.Nx1) {
826                                                 List<User> manager = getUserService().selectUsersWhere(
827                                                                 uprop.setOrganizationName("Nx1"));
828                                                 if (manager.size() == 1) {
829                                                         actor = manager.get(0);
830                                                 }
831                                         } else if (actype[i] == Actor.Nx2) {
832                                                 List<User> manager = getUserService().selectUsersWhere(
833                                                                 uprop.setOrganizationName("Nx2"));
834                                                 if (manager.size() == 1) {
835                                                         actor = manager.get(0);
836                                                 }
837                                         } else { /* Actor.customer */
838                                                 actor = from.getAuthor();
839                                                 // TODO: Get the customer of the study, if exists
840                                         }
841                                 } catch (Exception e) { // Should not happen
842                                         actor = null;
843                                 }
844                         }
845                         if (i == 0) {
846                                 aValidationCycle.setReviewer(actor);
847                         } else if (i == 1) {
848                                 aValidationCycle.setApprover(actor);
849                         } else if (i == 2) {
850                                 aValidationCycle.setSignatory(actor);
851                         }
852                 }
853                 return aValidationCycle;
854         }
855
856         /**
857          * Remove a validation step from the validation cycle.
858          * 
859          * @param aValidationCycle
860          *            the validation cycle
861          * @param step
862          *            the validation step to remove
863          */
864         @Transactional
865         protected void remove(final ValidationCycle aValidationCycle,
866                         final ValidationStep step) {
867                 if (step == ValidationStep.REVIEW) {
868                         aValidationCycle.setReviewer(null);
869                 } else if (step == ValidationStep.APPROVAL) {
870                         aValidationCycle.setApprover(null);
871                 } else if (step == ValidationStep.ACCEPTANCE
872                                 || step == ValidationStep.REFUSAL) {
873                         aValidationCycle.setSignatory(null);
874                 }
875                 if (aValidationCycle.isSaved()) {
876                         getValidationCycleDAO().update(aValidationCycle);
877                 }
878         }
879
880         /**
881          * Reset actors for the validation cycle.
882          * 
883          * @param aValidationCycle
884          *            the validation cycle to update
885          * @param vprop
886          *            new validation cycle properties containing new actors
887          */
888         @Transactional
889         public void resetActors(final ValidationCycle aValidationCycle,
890                         final ValidationCycle.Properties vprop) {
891                 aValidationCycle.setPublisher(vprop.getPublisher()); // May be null
892                 aValidationCycle.setReviewer(vprop.getReviewer()); // May be null
893                 aValidationCycle.setApprover(vprop.getApprover()); // May be null
894                 aValidationCycle.setSignatory(vprop.getSignatory()); // May be null
895                 if (aValidationCycle.isSaved()) {
896                         getValidationCycleDAO().merge(aValidationCycle);
897                 }
898         }
899
900         /**
901          * Set actor for the given validation cycle and validation step.
902          * 
903          * @param aValidationCycle
904          *            the validation cycle
905          * @param step
906          *            the validation step
907          * @param actor
908          *            the actor to set
909          */
910         @Transactional
911         protected void setActor(final ValidationCycle aValidationCycle,
912                         final ValidationStep step, final User actor) {
913                 if (step == ValidationStep.PROMOTION) {
914                         aValidationCycle.setPublisher(actor);
915                 } else if (step == ValidationStep.REVIEW) {
916                         aValidationCycle.setReviewer(actor);
917                 } else if (step == ValidationStep.APPROVAL) {
918                         aValidationCycle.setApprover(actor);
919                 } else if (step == ValidationStep.ACCEPTANCE
920                                 || step == ValidationStep.REFUSAL) {
921                         aValidationCycle.setSignatory(actor);
922                 }
923                 if (aValidationCycle.isSaved()) {
924                         getValidationCycleDAO().update(aValidationCycle);
925                 }
926         }
927
928         /**
929          * Returns all actors of this study other than the author, including contributors, reviewers and approvers.
930          * 
931          * @param aStudy
932          *            the study
933          * @return the actors of this study
934          * @see #hasActor(User)
935          */
936         public Set<User> getActors(final Study aStudy) {
937                 if (aStudy.getActor() == null) {
938                         setShortCuts(aStudy);
939                 }
940                 return Collections.unmodifiableSet(aStudy.getActor());
941         }
942
943         /**
944          * Returns all actors of this study other than the author, including contributors, reviewers and approvers.
945          * 
946          * @param aStudy
947          *            the study
948          * @return the modifiable set of actors of this study
949          * @see #hasActor(User)
950          */
951         public Set<User> getModifiableActors(final Study aStudy) {
952                 if (aStudy.getActor() == null) {
953                         setShortCuts(aStudy);
954                 }
955                 return aStudy.getActor();
956         }
957
958         /**
959          * Returns unmodifiable initialized transient list of contributors of this study.
960          * 
961          * @param aStudy
962          *            the study
963          * @return the unmodifiable not null transient list of contributors of this study
964          */
965         public List<User> getContributors(final Study aStudy) {
966                 if (aStudy.getContributor() == null) {
967                         setShortCuts(aStudy);
968                 }
969                 return Collections.unmodifiableList(aStudy.getContributor()); // May be empty
970         }
971
972         /**
973          * Returns modifiable initialized transient list of contributors of this study.
974          * 
975          * @param aStudy
976          *            the study
977          * @return the modifiable not null transient list of contributors of this study
978          */
979         public List<User> getModifiableContributors(final Study aStudy) {
980                 if (aStudy.getContributor() == null) {
981                         setShortCuts(aStudy);
982                 }
983                 return aStudy.getContributor(); // May be empty
984         }
985
986         /**
987          * Returns the validation cycle of the given document type.
988          * 
989          * @param aStudy
990          *            the study
991          * @param type
992          *            the document type being subject of validation
993          * @return the validation cycle of the document, or null if not defined.
994          */
995         public ValidationCycle getValidationCycleOf(final Study aStudy,
996                         final DocumentType type) {
997                 if (aStudy.getValidationCycles() == null
998                                 || aStudy.getValidationCycles().isEmpty()) {
999                         setShortCuts(aStudy);
1000                 }
1001                 ValidationCycle result = aStudy.getValidationCycles().get(
1002                                 type.getName());
1003                 if (result == null) {
1004                         if (type.isStepResult()) {
1005                                 result = aStudy.getValidationCycles().get("default"); // "default" validation cycle defined in the configuration, if exist
1006                         }
1007                         if (result == null) {
1008                                 result = aStudy.getValidationCycles().get("built-in");
1009                         }
1010                 }
1011                 return result;
1012         }
1013
1014         /**
1015          * Checks if the given user is actor of this study. Actors include contributors, reviewers and approvers.
1016          * 
1017          * @param aStudy
1018          *            the study
1019          * @param user
1020          *            the user to look for
1021          * @return true if the given user is actor of this study.
1022          * @see #getActors()
1023          */
1024         public boolean hasActor(final Study aStudy, final User user) {
1025                 if (user == null) {
1026                         return false;
1027                 }
1028                 for (Iterator<User> i = getActors(aStudy).iterator(); i.hasNext();) {
1029                         User involved = i.next();
1030                         if (involved.equals(user)) {
1031                                 return true;
1032                         }
1033                 }
1034                 return false;
1035         }
1036
1037         /**
1038          * Checks if the given user participates to this study. The Study staff includes the author and contributors.
1039          * 
1040          * @param aStudy
1041          *            the study
1042          * @param user
1043          *            the user to look for
1044          * @return true if the given user is actor of this study.
1045          * @see #getContributors()
1046          */
1047         public boolean isStaffedBy(final Study aStudy, final User user) {
1048                 if (user == null) {
1049                         return false;
1050                 }
1051                 if (aStudy == null) {
1052                         return false;
1053                 }
1054                 if (aStudy.getAuthor() == null) {
1055                         return false;
1056                 }
1057                 if (aStudy.getAuthor().equals(user)) {
1058                         return true;
1059                 }
1060                 for (Iterator<User> i = getContributors(aStudy).iterator(); i.hasNext();) {
1061                         if (i.next().equals(user)) {
1062                                 return true;
1063                         }
1064                 }
1065                 return false;
1066         }
1067
1068         /**
1069          * Initialize shortcuts of the study as its transient collections.
1070          * 
1071          * @param aStudy
1072          *            the study
1073          */
1074         public void loadWorkflow(final Study aStudy) {
1075                 setShortCuts(aStudy);
1076         }
1077
1078         /**
1079          * Initialize shortcuts of the study as its transient collections.
1080          * 
1081          * @param aStudy
1082          *            the study
1083          */
1084         public void setShortCuts(final Study aStudy) {
1085                 aStudy.getContributor().clear();
1086                 aStudy.getValidationCycles().clear();
1087                 aStudy.getActor().clear();
1088
1089                 // Get the contributors
1090                 for (Iterator<Relation> i = aStudy.getRelations(
1091                                 ContributorRelation.class).iterator(); i.hasNext();) {
1092                         ContributorRelation link = (ContributorRelation) i.next();
1093                         aStudy.getContributor().add(link.getTo());
1094                 }
1095                 // Get the validation cycles specific to this study
1096                 for (Iterator<Relation> i = aStudy.getRelations(
1097                                 ValidationCycleRelation.class).iterator(); i.hasNext();) {
1098                         ValidationCycleRelation link = (ValidationCycleRelation) i.next();
1099                         aStudy.getValidationCycles().put(link.getDocumentType().getName(),
1100                                         link.getTo()); // The associated document type is necessarily not null in this
1101                         // context
1102                 }
1103                 // Get the validation cycles coming from the configured workflow and not overridden in this study
1104                 for (Iterator<ProjectSettingsServiceImpl.ProjectSettingsValidationCycle> i = getProjectSettings()
1105                                 .getAllValidationCycles().iterator(); i.hasNext();) {
1106                         ProjectSettingsServiceImpl.ProjectSettingsValidationCycle cycle = i
1107                                         .next();
1108                         String type = cycle.getName();
1109                         if (!aStudy.getValidationCycles().containsKey(type)) {
1110                                 aStudy.getValidationCycles().put(type,
1111                                                 createValidationCycle(aStudy, cycle));
1112                         }
1113                 }
1114                 // Get all corresponding actors
1115                 for (Iterator<ValidationCycle> i = aStudy.getValidationCycles()
1116                                 .values().iterator(); i.hasNext();) {
1117                         ValidationCycle cycle = i.next();
1118                         User[] user = cycle.getAllActors();
1119                         for (int j = 0; j < user.length; j++) {
1120                                 aStudy.getActor().add(user[j]);
1121                         }
1122                 }
1123                 // Get all other actors
1124                 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
1125                                 .hasNext();) {
1126                         Relation link = i.next();
1127                         Class<?> kindof = link.getClass().getSuperclass();
1128                         if (!kindof.equals(ActorRelation.class)) {
1129                                 continue;
1130                         }
1131                         aStudy.getActor().add(((ActorRelation) link).getTo());
1132                 }
1133         }
1134
1135         /**
1136          * 
1137          * {@inheritDoc}
1138          * 
1139          * @see org.splat.service.StudyService#markStudyAsReference(org.splat.dal.bo.som.Study)
1140          */
1141         @Override
1142         @Transactional
1143         public void markStudyAsReference(final Study aStudy) {
1144
1145                 aStudy.setMarkreference(1);
1146                 aStudy.setProgressState(ProgressState.TEMPLATE);
1147                 getStudyDAO().merge(aStudy);
1148         }
1149
1150         /**
1151          * 
1152          * {@inheritDoc}
1153          * 
1154          * @see org.splat.service.StudyService#removeStudyAsReference(org.splat.dal.bo.som.Study)
1155          */
1156         @Override
1157         @Transactional
1158         public void removeStudyAsReference(final Study aStudy) {
1159
1160                 aStudy.setMarkreference(0);
1161                 aStudy.setProgressState(ProgressState.APPROVED);
1162                 getStudyDAO().merge(aStudy);
1163         }
1164
1165         /**
1166          * {@inheritDoc}
1167          * 
1168          * @see org.splat.service.StudyService#getDescription(java.lang.Long)
1169          */
1170         @Override
1171         @Transactional(readOnly = true)
1172         public String getDescription(final Long studyId)
1173                         throws InvalidParameterException {
1174                 if (studyId == null) {
1175                         throw new InvalidParameterException(PARAM_STUDY_ID, "null");
1176                 }
1177                 Study study = _studyDAO.get(studyId);
1178                 if (study == null) {
1179                         throw new InvalidParameterException(PARAM_STUDY_ID, studyId.toString());
1180                 }
1181                 return study.getDescription();
1182         }
1183
1184         /**
1185          * {@inheritDoc}
1186          * 
1187          * @see org.splat.service.StudyService#setDescription(java.lang.Long, java.lang.String)
1188          */
1189         @Override
1190         @Transactional
1191         public void setDescription(final Long studyId, final String descriptionText)
1192                         throws InvalidParameterException {
1193                 if (studyId == null) {
1194                         throw new InvalidParameterException(PARAM_STUDY_ID, "null");
1195                 }
1196                 Study study = _studyDAO.get(studyId);
1197                 if (study == null) {
1198                         throw new InvalidParameterException(PARAM_STUDY_ID, studyId.toString());
1199                 }
1200                 study.setAttribute(new DescriptionAttribute(study, descriptionText));
1201         }
1202
1203         /**
1204          * {@inheritDoc}
1205          * 
1206          * @see org.splat.service.StudyService#removeStudyDescription(java.lang.Long)
1207          */
1208         @Override
1209         @Transactional
1210         public boolean removeDescription(final Long studyId)
1211                         throws InvalidParameterException {
1212                 if (studyId == null) {
1213                         throw new InvalidParameterException(PARAM_STUDY_ID, String
1214                                         .valueOf(studyId));
1215                 }
1216                 Study study = _studyDAO.get(studyId);
1217                 if (study == null) {
1218                         throw new InvalidParameterException(PARAM_STUDY_ID, String
1219                                         .valueOf(studyId));
1220                 }
1221                 return study.removeAttribute(study
1222                                 .getAttribute(DescriptionAttribute.class));
1223         }
1224
1225         /**
1226          * 
1227          * {@inheritDoc}
1228          * 
1229          * @see org.splat.service.StudyService#compare(java.util.List)
1230          */
1231         @Override
1232         public String compare(final List<DocToCompareDTO> docsList,
1233                         final String userName) throws IncompatibleDataException {
1234
1235                 String axis1Name = "";
1236                 String axis2Name = "";
1237                 String chartTitle = "";
1238                 String resultPath = "";
1239
1240                 XYSeriesCollection dataset = new XYSeriesCollection();
1241
1242                 Iterator<DocToCompareDTO> docListIter = docsList.iterator();
1243
1244                 for (; docListIter.hasNext();) {
1245
1246                         DocToCompareDTO docDTO = docListIter.next();
1247                         String pathToFile = docDTO.getPathToFile();
1248                         File compDocFile = new File(pathToFile);
1249
1250                         resultPath = pathToFile.substring(0, pathToFile.indexOf("vault"))
1251                                         + "downloads" + File.separator + userName + File.separator
1252                                         + "ComparisonResult.pdf";
1253
1254                         XYSeries series = new XYSeries("Study: " + docDTO.getStudyTitle() + " Scenario: " + docDTO.getScenarioTitle() + " Document: " + docDTO.getDocumentTitle());
1255
1256                         // read the file and get points information.
1257                         try {
1258                                 Scanner input = new Scanner(compDocFile);
1259
1260                                 //get the title of the chart.
1261                                 if (input.hasNext()) {
1262                                         chartTitle = input.nextLine();
1263                                 }
1264                                 
1265                                 // get the name of the axis.
1266                                 if (input.hasNext()) {
1267                                         String[] tokens = input.nextLine().split(",");
1268
1269                                         if (tokens.length < 2) {
1270                                                 throw new IncompatibleDataException(
1271                                                                 MessageKeyEnum.IDT_000001.toString());
1272                                         }
1273
1274                                         if ("".equals(axis1Name)) {
1275                                                 axis1Name = tokens[0];
1276                                         } else if (!axis1Name.equals(tokens[0])) {
1277                                                 LOG.debug("Axis must be the same for all documents");
1278                                                 throw new IncompatibleDataException(
1279                                                                 MessageKeyEnum.IDT_000001.toString());
1280                                         }
1281
1282                                         if ("".equals(axis2Name)) {
1283                                                 axis2Name = tokens[1];
1284                                         } else if (!axis2Name.equals(tokens[1])) {
1285                                                 LOG.debug("Axis must be the same for all documents");
1286                                                 throw new IncompatibleDataException(
1287                                                                 MessageKeyEnum.IDT_000001.toString());
1288                                         }
1289                                 }
1290
1291                                 // Get the XY points series.
1292                                 while (input.hasNext()) {
1293
1294                                         String currentString = input.nextLine();
1295
1296                                         if (!("".equals(currentString))) {
1297                                                 String[] tokens = currentString.split(" ");
1298                                                 series.add(Double.valueOf(tokens[0]), Double
1299                                                                 .valueOf(tokens[1]));
1300                                         }
1301
1302                                 } // while
1303
1304                                 dataset.addSeries(series);
1305
1306                         } catch (FileNotFoundException e) {
1307                                 LOG.error("Sorry, the file is not found.", e);
1308                         }
1309                 } // for
1310
1311                 JFreeChart chart = ChartFactory.createXYLineChart(
1312                                 chartTitle, // Title
1313                                 axis1Name, // x-axis Label
1314                                 axis2Name, // y-axis Label
1315                                 dataset, // Dataset
1316                                 PlotOrientation.VERTICAL, // Plot Orientation
1317                                 true, // Show Legend
1318                                 true, // Use tooltips
1319                                 false // Configure chart to generate URLs?
1320                                 );
1321
1322                 // export to PDF - file.
1323                 int x = 500;
1324                 int y = 300;
1325                 Rectangle pagesize = new Rectangle(x, y);
1326                 Document document = new Document(pagesize, 50, 50, 50, 50);
1327                 PdfWriter writer;
1328                 try {
1329                         File resFile = new File(resultPath);
1330                         File resFolder = new File(resultPath.substring(0, resultPath
1331                                         .lastIndexOf(File.separator)));
1332                         resFolder.mkdirs();
1333                         writer = PdfWriter.getInstance(document, new FileOutputStream(
1334                                         resFile));
1335
1336                         document.open();
1337                         PdfContentByte cb = writer.getDirectContent();
1338                         PdfTemplate tp = cb.createTemplate(x, y);
1339                         Graphics2D g2 = tp.createGraphics(x, y, new DefaultFontMapper());
1340                         chart.draw(g2, new java.awt.Rectangle(x, y));
1341                         g2.dispose();
1342                         cb.addTemplate(tp, 0, 0);
1343                         document.close();
1344
1345                 } catch (FileNotFoundException e) {
1346                         LOG.error("Sorry, the file is not found.", e);
1347                 } catch (DocumentException e) {
1348                         LOG.error("Sorry, the DocumentException is thrown.", e);
1349                 }
1350
1351                 return resultPath;
1352         }
1353
1354         /**
1355          * Get project settings.
1356          * 
1357          * @return Project settings service
1358          */
1359         private ProjectSettingsService getProjectSettings() {
1360                 return _projectSettings;
1361         }
1362
1363         /**
1364          * Set project settings service.
1365          * 
1366          * @param projectSettingsService
1367          *            project settings service
1368          */
1369         public void setProjectSettings(
1370                         final ProjectSettingsService projectSettingsService) {
1371                 _projectSettings = projectSettingsService;
1372         }
1373
1374         /**
1375          * Get the projectElementService.
1376          * 
1377          * @return the projectElementService
1378          */
1379         public ProjectElementService getProjectElementService() {
1380                 return _projectElementService;
1381         }
1382
1383         /**
1384          * Set the projectElementService.
1385          * 
1386          * @param projectElementService
1387          *            the projectElementService to set
1388          */
1389         public void setProjectElementService(
1390                         final ProjectElementService projectElementService) {
1391                 _projectElementService = projectElementService;
1392         }
1393
1394         /**
1395          * Get the stepService.
1396          * 
1397          * @return the stepService
1398          */
1399         public StepService getStepService() {
1400                 return _stepService;
1401         }
1402
1403         /**
1404          * Set the stepService.
1405          * 
1406          * @param stepService
1407          *            the stepService to set
1408          */
1409         public void setStepService(final StepService stepService) {
1410                 _stepService = stepService;
1411         }
1412
1413         /**
1414          * Get the indexService.
1415          * 
1416          * @return the indexService
1417          */
1418         public IndexService getIndexService() {
1419                 return _indexService;
1420         }
1421
1422         /**
1423          * Set the indexService.
1424          * 
1425          * @param indexService
1426          *            the indexService to set
1427          */
1428         public void setIndexService(final IndexService indexService) {
1429                 _indexService = indexService;
1430         }
1431
1432         /**
1433          * Get the studyDAO.
1434          * 
1435          * @return the studyDAO
1436          */
1437         public StudyDAO getStudyDAO() {
1438                 return _studyDAO;
1439         }
1440
1441         /**
1442          * Set the studyDAO.
1443          * 
1444          * @param studyDAO
1445          *            the studyDAO to set
1446          */
1447         public void setStudyDAO(final StudyDAO studyDAO) {
1448                 _studyDAO = studyDAO;
1449         }
1450
1451         /**
1452          * Get the iDBuilderDAO.
1453          * 
1454          * @return the iDBuilderDAO
1455          */
1456         public IDBuilderDAO getIDBuilderDAO() {
1457                 return _iDBuilderDAO;
1458         }
1459
1460         /**
1461          * Set the iDBuilderDAO.
1462          * 
1463          * @param builderDAO
1464          *            the iDBuilderDAO to set
1465          */
1466         public void setIDBuilderDAO(final IDBuilderDAO builderDAO) {
1467                 _iDBuilderDAO = builderDAO;
1468         }
1469
1470         /**
1471          * Get the scenarioDAO.
1472          * 
1473          * @return the scenarioDAO
1474          */
1475         public ScenarioDAO getScenarioDAO() {
1476                 return _scenarioDAO;
1477         }
1478
1479         /**
1480          * Set the scenarioDAO.
1481          * 
1482          * @param scenarioDAO
1483          *            the scenarioDAO to set
1484          */
1485         public void setScenarioDAO(final ScenarioDAO scenarioDAO) {
1486                 _scenarioDAO = scenarioDAO;
1487         }
1488
1489         /**
1490          * Get the validationCycleDAO.
1491          * 
1492          * @return the validationCycleDAO
1493          */
1494         public ValidationCycleDAO getValidationCycleDAO() {
1495                 return _validationCycleDAO;
1496         }
1497
1498         /**
1499          * Set the validationCycleDAO.
1500          * 
1501          * @param validationCycleDAO
1502          *            the validationCycleDAO to set
1503          */
1504         public void setValidationCycleDAO(
1505                         final ValidationCycleDAO validationCycleDAO) {
1506                 _validationCycleDAO = validationCycleDAO;
1507         }
1508
1509         /**
1510          * Get the documentTypeService.
1511          * 
1512          * @return the documentTypeService
1513          */
1514         public DocumentTypeService getDocumentTypeService() {
1515                 return _documentTypeService;
1516         }
1517
1518         /**
1519          * Set the documentTypeService.
1520          * 
1521          * @param documentTypeService
1522          *            the documentTypeService to set
1523          */
1524         public void setDocumentTypeService(
1525                         final DocumentTypeService documentTypeService) {
1526                 _documentTypeService = documentTypeService;
1527         }
1528
1529         /**
1530          * Get the userService.
1531          * 
1532          * @return the userService
1533          */
1534         public UserService getUserService() {
1535                 return _userService;
1536         }
1537
1538         /**
1539          * Set the userService.
1540          * 
1541          * @param userService
1542          *            the userService to set
1543          */
1544         public void setUserService(final UserService userService) {
1545                 _userService = userService;
1546         }
1547
1548         /**
1549          * {@inheritDoc}
1550          * 
1551          * @see org.splat.service.StudyService#getComparableStudies()
1552          */
1553         @Transactional(readOnly = true)
1554         public List<StudyFacadeDTO> getComparableStudies(final long userId) throws MismatchException {
1555                 //retrieve the number of the "Analyze the results" step 
1556                 List<Step> allSteps = _projectSettings.getAllSteps();
1557                 Step theAnalyzeStep = null;
1558                 for(Step step : allSteps) {
1559                         if(step.getKey().equals("postprocessing")) {
1560                                 theAnalyzeStep = step;
1561                         }
1562                 }
1563                 if(theAnalyzeStep == null) {    //TODO: throw some other exception
1564                         throw new MismatchException("no step with key 'postprocessing' found." +
1565                                         "Probably, customization settings have been changed.");
1566                 }
1567
1568                 List<Publication> publications = _publicationDAO.getFilteredList("mydoc",
1569                                 Restrictions.eq("step", Integer.valueOf(theAnalyzeStep.getNumber())));
1570
1571                 //split retrieved publications into groups by studies and scenarios
1572                 Map<Study, List<ProjectElement>> studyMap = new HashMap<Study, List<ProjectElement>>();
1573                 Map<ProjectElement, List<Publication>> scenarioMap = 
1574                                 new HashMap<ProjectElement, List<Publication>>();
1575                 
1576                 for(Publication publication : publications) {                   
1577                         //filter out publications corresponding to a document of given step which is not a _result_ document
1578                         if(!publication.value().getType().isResultOf(theAnalyzeStep)
1579                                         || !"srd".equals(publication.getSourceFile().getFormat())) {
1580                                 continue;
1581                         }
1582                         
1583                         //check the study visibility to the user
1584                         if(!isStaffedBy(publication.getOwnerStudy(), _userService.selectUser(userId))
1585                                         && Visibility.PUBLIC.equals(publication.getOwnerStudy().getVisibility())) {
1586                                 continue;
1587                         }
1588         
1589                         Study study = publication.getOwnerStudy();
1590                         ProjectElement scenario = publication.getOwner();
1591                         
1592                         Hibernate.initialize(scenario);
1593                     if (scenario instanceof HibernateProxy) {
1594                         scenario = (ProjectElement) ((HibernateProxy) scenario).getHibernateLazyInitializer()
1595                                 .getImplementation();
1596                     }
1597                         
1598                         if(!(scenario instanceof Scenario)) {
1599                                 throw new MismatchException(
1600                                                 "publications from postprocessing step are supposed to have owner scenario");
1601                         }
1602
1603                         if(!studyMap.containsKey(study)) {
1604                                 studyMap.put(study, new ArrayList<ProjectElement>());
1605                         }
1606                         
1607                         if(!studyMap.get(study).contains(scenario)) {
1608                                 studyMap.get(study).add(scenario);
1609                         }
1610
1611                         if(!scenarioMap.containsKey(scenario)) {
1612                                 scenarioMap.put(scenario, new ArrayList<Publication>());
1613                         }
1614                         scenarioMap.get(scenario).add(publication);
1615                 }
1616                 
1617                 //Create the result DTOs
1618                 List<StudyFacadeDTO> result = new ArrayList<StudyFacadeDTO>();
1619                 for(Study study : studyMap.keySet()) {
1620                         
1621                         StudyFacadeDTO studyDTO = new StudyFacadeDTO();
1622                         studyDTO.setName(study.getTitle());
1623                         studyDTO.setScenarios(new ArrayList<StudyFacadeDTO.ScenarioDTO>());
1624                         result.add(studyDTO);
1625                         
1626                         for(ProjectElement scenario : studyMap.get(study)) {
1627                                 
1628                                 StudyFacadeDTO.ScenarioDTO scenarioDTO = new StudyFacadeDTO.ScenarioDTO();
1629                                 scenarioDTO.setName(scenario.getTitle());
1630                                 scenarioDTO.setDocs(new ArrayList<DocumentDTO>());
1631                                 studyDTO.getScenarios().add(scenarioDTO);
1632
1633                                 for(Publication publication : scenarioMap.get(scenario)) {
1634
1635                                         DocumentDTO documentDTO = new DocumentDTO();
1636                                         documentDTO.setId(publication.getIndex());
1637                                         documentDTO.setTitle(publication.value().getTitle());
1638                                         
1639                                         scenarioDTO.getDocs().add(documentDTO);
1640                                 }
1641                         }
1642                 }               
1643                 return result;
1644         }
1645         
1646         /**
1647          * Get the publicationDAO.
1648          * 
1649          * @return the publicationDAO
1650          */
1651         public PublicationDAO getPublicationDAO() {
1652                 return _publicationDAO;
1653         }
1654
1655         /**
1656          * Set the publicationDAO.
1657          * 
1658          * @param publicationDAO
1659          *            the publicationDAO to set
1660          */
1661         public void setPublicationDAO(final PublicationDAO publicationDAO) {
1662                 _publicationDAO = publicationDAO;
1663         }
1664
1665         /**
1666          * Get the repositoryService.
1667          * 
1668          * @return the repositoryService
1669          */
1670         public RepositoryService getRepositoryService() {
1671                 return _repositoryService;
1672         }
1673
1674         /**
1675          * Set the repositoryService.
1676          * 
1677          * @param repositoryService
1678          *            the repositoryService to set
1679          */
1680         public void setRepositoryService(final RepositoryService repositoryService) {
1681                 _repositoryService = repositoryService;
1682         }
1683
1684         /**
1685          * Get the documentDAO.
1686          * 
1687          * @return the documentDAO
1688          */
1689         public DocumentDAO getDocumentDAO() {
1690                 return _documentDAO;
1691         }
1692
1693         /**
1694          * Set the documentDAO.
1695          * 
1696          * @param documentDAO
1697          *            the documentDAO to set
1698          */
1699         public void setDocumentDAO(final DocumentDAO documentDAO) {
1700                 _documentDAO = documentDAO;
1701         }
1702
1703         /**
1704          * Get the descriptionAttributeDAO.
1705          * 
1706          * @return the descriptionAttributeDAO
1707          */
1708         public DescriptionAttributeDAO getDescriptionAttributeDAO() {
1709                 return _descriptionAttributeDAO;
1710         }
1711
1712         /**
1713          * Set the descriptionAttributeDAO.
1714          * 
1715          * @param descriptionAttributeDAO
1716          *            the descriptionAttributeDAO to set
1717          */
1718         public void setDescriptionAttributeDAO(
1719                         final DescriptionAttributeDAO descriptionAttributeDAO) {
1720                 _descriptionAttributeDAO = descriptionAttributeDAO;
1721         }
1722
1723         /**
1724          * Get the usedByRelationDAO.
1725          * 
1726          * @return the usedByRelationDAO
1727          */
1728         public UsedByRelationDAO getUsedByRelationDAO() {
1729                 return _usedByRelationDAO;
1730         }
1731
1732         /**
1733          * Set the usedByRelationDAO.
1734          * 
1735          * @param usedByRelationDAO
1736          *            the usedByRelationDAO to set
1737          */
1738         public void setUsedByRelationDAO(final UsedByRelationDAO usedByRelationDAO) {
1739                 _usedByRelationDAO = usedByRelationDAO;
1740         }
1741
1742 }