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