Salome HOME
Fix for updating the left activities list state
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / ScenarioServiceImpl.java
1 /*****************************************************************************
2  * Company         OPEN CASCADE
3  * Application     SIMAN
4  * File            $Id$ 
5  * Creation date   06.10.2012
6  * @author         $Author$
7  * @version        $Revision$
8  *****************************************************************************/
9
10 package org.splat.service;
11
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.Calendar;
15 import java.util.Date;
16 import java.util.HashMap;
17 import java.util.HashSet;
18 import java.util.Iterator;
19 import java.util.List;
20 import java.util.Map;
21 import java.util.Set;
22
23 import org.hibernate.criterion.DetachedCriteria;
24 import org.hibernate.criterion.Order;
25 import org.hibernate.criterion.Projections;
26 import org.hibernate.criterion.Restrictions;
27 import org.hibernate.transform.Transformers;
28 import org.splat.common.properties.MessageKeyEnum;
29 import org.splat.dal.bo.kernel.Relation;
30 import org.splat.dal.bo.kernel.Role;
31 import org.splat.dal.bo.kernel.User;
32 import org.splat.dal.bo.som.ConvertsRelation;
33 import org.splat.dal.bo.som.Document;
34 import org.splat.dal.bo.som.DocumentType;
35 import org.splat.dal.bo.som.File;
36 import org.splat.dal.bo.som.KnowledgeElement;
37 import org.splat.dal.bo.som.KnowledgeElementType;
38 import org.splat.dal.bo.som.ProgressState;
39 import org.splat.dal.bo.som.ProjectElement;
40 import org.splat.dal.bo.som.Publication;
41 import org.splat.dal.bo.som.Scenario;
42 import org.splat.dal.bo.som.SimulationContext;
43 import org.splat.dal.bo.som.SimulationContextType;
44 import org.splat.dal.bo.som.Study;
45 import org.splat.dal.bo.som.UsedByRelation;
46 import org.splat.dal.bo.som.UsesRelation;
47 import org.splat.dal.bo.som.ValidationCycle;
48 import org.splat.dal.bo.som.Document.Properties;
49 import org.splat.dal.dao.kernel.RoleDAO;
50 import org.splat.dal.dao.kernel.UserDAO;
51 import org.splat.dal.dao.som.DocumentDAO;
52 import org.splat.dal.dao.som.KnowledgeElementDAO;
53 import org.splat.dal.dao.som.KnowledgeElementTypeDAO;
54 import org.splat.dal.dao.som.ScenarioDAO;
55 import org.splat.dal.dao.som.StudyDAO;
56 import org.splat.dal.dao.som.ValidationCycleDAO;
57 import org.splat.exception.InvalidParameterException;
58 import org.splat.i18n.I18nUtils;
59 import org.splat.kernel.InvalidPropertyException;
60 import org.splat.kernel.MismatchException;
61 import org.splat.kernel.MissedPropertyException;
62 import org.splat.kernel.MultiplyDefinedException;
63 import org.splat.kernel.NotApplicableException;
64 import org.splat.log.AppLogger;
65 import org.splat.service.dto.DocumentDTO;
66 import org.splat.service.dto.FileDTO;
67 import org.splat.service.dto.ScenarioDTO;
68 import org.splat.service.dto.StepDTO;
69 import org.splat.service.technical.IndexService;
70 import org.splat.service.technical.ProjectSettingsService;
71 import org.splat.service.technical.RepositoryService;
72 import org.splat.service.technical.StepsConfigService;
73 import org.splat.som.Step;
74 import org.splat.util.BeanHelper;
75 import org.splat.util.IOUtils;
76 import org.springframework.transaction.annotation.Transactional;
77
78 /**
79  * Scenario service implementation.
80  * 
81  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
82  */
83 public class ScenarioServiceImpl implements ScenarioService {
84
85         /**
86          * The logger for the service.
87          */
88         public final static AppLogger LOG = AppLogger
89                         .getLogger(ScenarioServiceImpl.class);
90
91         /**
92          * " to " literal.
93          */
94         private static final String TO = " to ";
95         /**
96          * Injected index service.
97          */
98         private IndexService _indexService;
99         /**
100          * Injected step service.
101          */
102         private StepService _stepService;
103         /**
104          * Injected study service.
105          */
106         private StudyService _studyService;
107         /**
108          * Injected publication service.
109          */
110         private PublicationService _publicationService;
111         /**
112          * Injected project element service.
113          */
114         private ProjectElementService _projectElementService;
115         /**
116          * Injected knowledge element DAO.
117          */
118         private KnowledgeElementDAO _knowledgeElementDAO;
119         /**
120          * Injected scenario DAO.
121          */
122         private ScenarioDAO _scenarioDAO;
123
124         /**
125          * Injected study DAO.
126          */
127         private StudyDAO _studyDAO;
128
129         /**
130          * Injected knowledge element service.
131          */
132         private KnowledgeElementTypeService _knowledgeElementTypeService;
133
134         /**
135          * Injected user service.
136          */
137         private UserService _userService;
138
139         /**
140          * Injected user DAO.
141          */
142         private UserDAO _userDAO;
143
144         /**
145          * Injected role DAO.
146          */
147         private RoleDAO _roleDAO;
148
149         /**
150          * Injected knowledge element type DAO.
151          */
152         private KnowledgeElementTypeDAO _knowledgeElementTypeDAO;
153         
154         /**
155          * Injected document DAO.
156          */
157         private DocumentDAO _documentDAO;
158
159         /**
160          * Injected simulation context service.
161          */
162         private SimulationContextService _simulationContextService;
163
164         /**
165          * Injected simulation context type service.
166          */
167         private SimulationContextTypeService _simulationContextTypeService;
168
169         /**
170          * Injected project service.
171          */
172         private ProjectSettingsService _projectSettings;
173
174         /**
175          * Injected document type service.
176          */
177         private DocumentTypeService _documentTypeService;
178
179         /**
180          * Injected validation cycle DAO.
181          */
182         private ValidationCycleDAO _validationCycleDAO;
183
184         /**
185          * Injected project settings service.
186          */
187         private StepsConfigService _stepsConfigService;
188
189         /**
190          * Injected repository service.
191          */
192         private RepositoryService _repositoryService;
193
194         /**
195          * Get the projectElementService.
196          * 
197          * @return the projectElementService
198          */
199         public ProjectElementService getProjectElementService() {
200                 return _projectElementService;
201         }
202
203         /**
204          * Set the projectElementService.
205          * 
206          * @param projectElementService
207          *            the projectElementService to set
208          */
209         public void setProjectElementService(
210                         final ProjectElementService projectElementService) {
211                 _projectElementService = projectElementService;
212         }
213
214         /**
215          * Get the publicationService.
216          * 
217          * @return the publicationService
218          */
219         public PublicationService getPublicationService() {
220                 return _publicationService;
221         }
222
223         /**
224          * Set the publicationService.
225          * 
226          * @param publicationService
227          *            the publicationService to set
228          */
229         public void setPublicationService(
230                         final PublicationService publicationService) {
231                 _publicationService = publicationService;
232         }
233
234         /**
235          * Get the stepService.
236          * 
237          * @return the stepService
238          */
239         public StepService getStepService() {
240                 return _stepService;
241         }
242
243         /**
244          * Set the stepService.
245          * 
246          * @param stepService
247          *            the stepService to set
248          */
249         public void setStepService(final StepService stepService) {
250                 _stepService = stepService;
251         }
252
253         /**
254          * {@inheritDoc}
255          * 
256          * @see org.splat.service.ScenarioService#getStudyScenarios(java.lang.Long)
257          */
258         @Override
259         @Transactional(readOnly = true)
260         public List<ScenarioDTO> getStudyScenarios(final Long studyId) {
261                 DetachedCriteria query = DetachedCriteria
262                                 .forClass(Scenario.class, "scen")
263                                 .add(Restrictions.eq("owner.rid", studyId))
264                                 .setProjection(
265                                                 Projections.projectionList().add(
266                                                                 Projections.property("scen.title"), "title")
267                                                                 .add(Projections.property("scen.rid"), "index"))
268                                 .setResultTransformer(
269                                                 Transformers.aliasToBean(ScenarioDTO.class));
270                 return getScenarioDAO().getFilteredDTOList(query);
271         }
272
273         /**
274          * {@inheritDoc}
275          * 
276          * @see org.splat.service.ScenarioService#copyStudyContent(long, long, int, long)
277          */
278         @Override
279         @Transactional
280         public void copyStudyContent(final long fromStudyId, final long fromScenId,
281                         final int finalStepNum, final long toStudyId)
282                         throws InvalidParameterException, MissedPropertyException,
283                         InvalidPropertyException, MultiplyDefinedException,
284                         NotApplicableException, IOException {
285                 Study fromStudy = getStudyService().selectStudy(fromStudyId);
286                 if (fromStudy == null) {
287                         throw new InvalidParameterException(MessageKeyEnum.STD_000002
288                                         .toString(), String.valueOf(fromStudyId));
289                 }
290                 Scenario fromScen = null;
291                 for (Scenario scen : fromStudy.getScenariiList()) {
292                         if (scen.getIndex() == fromScenId) {
293                                 fromScen = scen;
294                                 break;
295                         }
296                 }
297
298                 Study toStudy = getStudyService().selectStudy(toStudyId);
299                 if (toStudy == null) {
300                         throw new InvalidParameterException(MessageKeyEnum.STD_000002
301                                         .toString(), String.valueOf(toStudy));
302                 }
303
304                 // Check if the step is applied to a scenario and scenario is defined
305                 if (fromScen == null
306                                 && getStepsConfigService().stepInvolves(finalStepNum,
307                                                 Scenario.class)) {
308                         throw new InvalidParameterException(MessageKeyEnum.SCN_000006
309                                         .toString(), String.valueOf(fromScenId));
310                 }
311
312                 // Copy validation cycles
313                 copyValidationCycles(fromStudy, toStudy);
314
315                 // Copy content of the study up to the given step
316                 Map<Publication, Publication> oldToNewPub = new HashMap<Publication, Publication>();
317                 copyDocs(fromStudy, toStudy, finalStepNum, oldToNewPub);
318                 if (fromScen != null) {
319                         copyDocs(fromScen, toStudy.getScenariiList().get(0), finalStepNum,
320                                         oldToNewPub);
321                 }
322                 copyDependencies(fromStudy, finalStepNum, oldToNewPub);
323                 if (fromScen != null) {
324                         copyDependencies(fromScen, finalStepNum, oldToNewPub);
325                 }
326         }
327
328         /**
329          * Copy validation cycles from study to study.
330          * 
331          * @param fromStudy
332          *            the source study
333          * @param toStudy
334          *            the destination study
335          */
336         private void copyValidationCycles(final Study fromStudy, final Study toStudy) {
337                 for (ValidationCycle fromCycle : fromStudy.getValidationCycles()
338                                 .values()) {
339                         if (fromCycle.isAssigned()) {
340                                 ValidationCycle cycle = fromCycle.clone(toStudy);
341                                 getValidationCycleDAO().create(cycle);
342                                 toStudy.addRelation(cycle.getContext());
343                                 toStudy.getValidationCycles().put(
344                                                 cycle.getDocumentType().getName(), cycle); // Replaces the cycle if exists as default,
345                         }
346                 }
347         }
348
349         /**
350          * Copy dependencies between documents from the given project element up to <BR>
351          * the given step according to the given map of old publications to new publications.
352          * 
353          * @param from
354          *            the source project element
355          * @param finalStepNum
356          *            the final step for copy processing
357          * @param oldToNewPub
358          *            the old to new publications map
359          */
360         private void copyDependencies(final ProjectElement from,
361                         final int finalStepNum,
362                         final Map<Publication, Publication> oldToNewPub) {
363                 // Copy dependencies between copied documents
364                 for (Publication pub : from.getDocums()) {
365                         // If the document in the step before the final one
366                         if (pub.value().getStep() <= finalStepNum) {
367                                 Publication newPub = oldToNewPub.get(pub);
368                                 for (Publication used : pub.getRelations(UsesRelation.class)) {
369                                         newPub.addDependency(oldToNewPub.get(used));
370                                 }
371                         }
372                 }
373         }
374
375         /**
376          * Copy documents with dependencies up to the given step.
377          * 
378          * @param from
379          *            the source project element
380          * @param to
381          *            the destination project element
382          * @param finalStepNum
383          *            the final step for copy process
384          * @param oldToNewPub2
385          * @throws MissedPropertyException
386          *             if document creation is failed
387          * @throws InvalidPropertyException
388          *             if document creation is failed
389          * @throws MultiplyDefinedException
390          *             if document creation is failed
391          * @throws IOException
392          *             if document file creation is failed
393          * @throws NotApplicableException
394          *             if document state is not applicable
395          * @param oldToNewPub
396          *            the old to new publications map
397          * 
398          */
399         private void copyDocs(final ProjectElement from, final ProjectElement to,
400                         final int finalStepNum,
401                         final Map<Publication, Publication> oldToNewPub)
402                         throws MissedPropertyException, InvalidPropertyException,
403                         MultiplyDefinedException, NotApplicableException, IOException {
404                 Map<Integer, Step> steps = getProjectElementService().getStepsMap(to);
405                 // Copy publications without old versions and relations to not copied steps documents
406                 for (Publication pub : from.getDocums()) {
407                         // If the document in the step before the final one
408                         if (pub.value().getStep() <= finalStepNum) {
409                                 // Copy the document
410                                 oldToNewPub.put(pub, createDoc(pub.value(), steps.get(pub
411                                                 .value().getStep())));
412                         }
413                 }
414         }
415
416         /**
417          * Create a copy of the given document and publish it in the given step.
418          * 
419          * @param fromDoc
420          *            the source document
421          * @param step
422          *            the destination step
423          * @return the created publication
424          * @throws MissedPropertyException
425          *             if document creation is failed
426          * @throws InvalidPropertyException
427          *             if document creation is failed
428          * @throws MultiplyDefinedException
429          *             if document creation is failed
430          * @throws IOException
431          *             if document file creation is failed
432          * @throws NotApplicableException
433          *             if document state is not applicable
434          */
435         private Publication createDoc(final Document fromDoc, final Step step)
436                         throws MissedPropertyException, InvalidPropertyException,
437                         MultiplyDefinedException, IOException, NotApplicableException {
438
439                 java.io.File srcFile = fromDoc.getSourceFile().asFile();
440                 // Creation of the document
441                 Document.Properties dprop = new Document.Properties().setName(
442                                 fromDoc.getTitle()).setType(fromDoc.getType()).setFormat(
443                                 fromDoc.getFormat()).setAuthor(fromDoc.getAuthor());
444
445                 java.io.File tmpDir = getRepositoryService().getDownloadDirectory(
446                                 step.getOwnerStudy().getAuthor());
447
448                 // Remove local file index prefix to get original filename.
449                 java.io.File upfile = new java.io.File(tmpDir.getPath()
450                                 + "/"
451                                 + srcFile.getName().substring(
452                                                 srcFile.getName().indexOf('_') + 1));
453                 // Copy the source file into the temporary folder with original filename.
454                 copyFile(srcFile, upfile);
455
456                 dprop.setLocalPath(upfile.getPath());
457                 Publication addoc = getStepService().createDocument(step, dprop);
458
459                 // Move the temporary file into the repository
460                 moveFile(upfile, addoc.getSourceFile().asFile());
461
462                 getPublicationService().saveAs(addoc, fromDoc.getProgressState());
463
464                 // Copy attached files
465                 for (Relation rel : fromDoc.getRelations(ConvertsRelation.class)) {
466                         File attach = ((ConvertsRelation) rel).getTo();
467                         ConvertsRelation export = getPublicationService().attach(addoc,
468                                         attach.getFormat());
469                         // Copy the source document attachment file to the new study vault
470                         copyFile(attach.asFile(), export.getTo().asFile());
471                 }
472                 return addoc;
473         }
474
475         /**
476          * Copy a file. Print info message.
477          * 
478          * @param upfile
479          *            the source file.
480          * @param file
481          *            the target file
482          * @throws IOException
483          *             if failed
484          */
485         private void copyFile(final java.io.File upfile, final java.io.File file)
486                         throws IOException {
487                 if (LOG.isInfoEnabled()) {
488                         LOG.info("Copy " + upfile.getAbsolutePath() + TO + file.getPath());
489                 }
490                 IOUtils.copy(upfile, file);
491         }
492
493         /**
494          * Copy a file. Print info message.
495          * 
496          * @param upfile
497          *            the source file.
498          * @param file
499          *            the target file
500          * @return true if renamed otherwise return false
501          */
502         private boolean moveFile(final java.io.File upfile, final java.io.File file) {
503                 if (LOG.isInfoEnabled()) {
504                         LOG.info("Move " + upfile.getAbsolutePath() + TO + file.getPath());
505                 }
506                 return upfile.renameTo(file);
507         }
508
509         /**
510          * {@inheritDoc}
511          * 
512          * @see org.splat.service.ScenarioService#getScenarioInfo(long)
513          */
514         @Transactional(readOnly = true)
515         public List<StepDTO> getScenarioInfo(final long scenarioId) {
516                 List<StepDTO> res = new ArrayList<StepDTO>();
517                 // Get the scenario from the database by id
518                 Scenario scen = getScenarioDAO().get(scenarioId);
519                 if (LOG.isDebugEnabled()) {
520                         LOG.debug("Scenario[" + scenarioId + "]: Number of publications: "
521                                         + scen.getDocums().size());
522                 }
523                 // Get activities of the scenario
524                 Step[] steps = getProjectElementService().getSteps(scen);
525                 StepDTO stepDTO;
526                 DocumentDTO docDTO;
527                 String docType, fileFormat;
528                 String processing;
529                 boolean doImport;
530                 // For each activity create a step DTO and add it to the result list
531                 for (Step step : steps) {
532                         stepDTO = BeanHelper.copyBean(step.getStep(), StepDTO.class);
533                         res.add(stepDTO);
534                         if (LOG.isDebugEnabled()) {
535                                 LOG.debug("Step[" + stepDTO.getNumber()
536                                                 + "]: Number of documents: "
537                                                 + step.getDocuments().size());
538                         }
539                         // For each publication of the activity create a document DTO.
540                         // Each file is considered as a source file.
541                         for (Publication tag : step.getDocuments()) {
542                                 docDTO = stepDTO.addDoc(tag.value().getIndex(), tag.value()
543                                                 .getTitle());
544                                 char aState = tag.getIsnew();
545                                 docType = tag.value().getType().getName();
546                                 // For each file of the document create a file DTO
547                                 // Process source file of the document
548                                 fileFormat = tag.value().getFile().getFormat();
549                                 doImport = getProjectSettings().doImport(docType, fileFormat);
550                                 if (doImport && (!tag.isOutdated())) {
551                                         processing = "file-import";
552                                 } else {
553                                         processing = "file-download";
554                                 }
555                                 File aFile = tag.value().getFile();
556                                 docDTO.addFile(aFile.getIndex(), aFile.getRelativePath(),
557                                                 aState, processing, false);
558                                 // Process all exported files
559                                 for (Relation rel : tag.value().getRelations(
560                                                 ConvertsRelation.class)) {
561                                         aFile = ((ConvertsRelation) rel).getTo();
562                                         fileFormat = aFile.getFormat();
563                                         doImport = getProjectSettings().doImport(docType,
564                                                         fileFormat);
565                                         if (doImport && (!tag.isOutdated())) {
566                                                 processing = "file-import";
567                                         } else {
568                                                 processing = "file-download";
569                                         }
570                                         docDTO.addFile(aFile.getIndex(), aFile.getRelativePath(),
571                                                         aState, processing, false);
572                                 }
573                         }
574                 }
575                 return res;
576         }
577
578         /**
579          * {@inheritDoc}
580          * 
581          * @see org.splat.service.ScenarioService#createStudy(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
582          */
583         @Transactional
584         public long createStudy(final String username, final String title,
585                         final String productName, final String description)
586                         throws InvalidPropertyException, MissedPropertyException,
587                         MultiplyDefinedException {
588                 long id = 0;
589
590                 // Find the author
591                 User author = getUserService().selectUser(username);
592                 if (author == null) {
593                         // User is not found
594                         throw new InvalidPropertyException(MessageKeyEnum.USR_000001
595                                         .toString(), username);
596                 }
597
598                 // Set the study properties
599                 Study.Properties sprop = new Study.Properties();
600                 sprop.setTitle(title).setManager(author);
601                 sprop.setDescription(description);
602
603                 // Find the product simulation context
604                 SimulationContextType productContextType = getSimulationContextService()
605                                 .selectType("product");
606                 SimulationContext.Properties cprop = new SimulationContext.Properties();
607                 cprop.setType(productContextType).setValue(productName);
608                 SimulationContext productCtx = getSimulationContextService()
609                                 .selectSimulationContext(productContextType, productName);
610                 if (productCtx != null) {
611                         cprop.setIndex(productCtx.getIndex());
612                 }
613
614                 // Set a first scenario properties
615                 Scenario.Properties oprop = new Scenario.Properties();
616                 oprop.setTitle(I18nUtils.getMessageLocaleDefault("label.scenario")
617                                 + " 1");
618
619                 Study study = createStudy(sprop, oprop, cprop);
620                 id = study.getIndex();
621
622                 return id;
623         }
624
625         /**
626          * Create a new study with one scenario and "product" simulation context.
627          * 
628          * @param sprop
629          *            the study properties
630          * @param oprop
631          *            the scenario properties
632          * @param cprop
633          *            the "product" simulation context properties
634          * @return the created study
635          * @throws MissedPropertyException
636          *             if a mandatory property is missed
637          * @throws InvalidPropertyException
638          *             if a property is invalid
639          * @throws MultiplyDefinedException
640          *             if some property occurs several times
641          */
642         @Transactional
643         public Study createStudy(final Study.Properties sprop,
644                         final Scenario.Properties oprop,
645                         final SimulationContext.Properties cprop)
646                         throws MissedPropertyException, InvalidPropertyException,
647                         MultiplyDefinedException {
648                 Study study = getStudyService().createStudy(sprop);
649                 addScenario(study, oprop);
650                 if (cprop.getIndex() == 0) { // Input of new project context
651                         cprop.setType(getSimulationContextService().selectType("product"))
652                                         .setValue(cprop.getValue());
653                         getStudyService().addProjectContext(study, cprop);
654                 } else { // Selection of existing project context
655                         SimulationContext context = getSimulationContextService()
656                                         .selectSimulationContext(cprop.getIndex());
657                         getStudyService().addProjectContext(study, context);
658                 }
659                 return study;
660         }
661
662         /**
663          * {@inheritDoc}
664          * 
665          * @see org.splat.service.ScenarioService#assignStudyContext(java.lang.Long, java.lang.String, java.lang.String)
666          */
667         @Transactional
668         public void assignStudyContext(final Long studyId, final String ctxType,
669                         final String ctxValue) throws MissedPropertyException,
670                         InvalidPropertyException, MultiplyDefinedException {
671                 // Find the study by the given id
672                 Study study = getStudyDAO().get(studyId);
673                 if (study == null) {
674                         throw new InvalidPropertyException(MessageKeyEnum.STD_000002
675                                         .toString(), studyId);
676                 }
677                 // Find the context type by its name
678                 SimulationContextType celt = getSimulationContextService().selectType(
679                                 ctxType);
680                 if (celt == null) {
681                         // Creation of a new context type
682                         celt = getSimulationContextTypeService().createType(ctxType,
683                                         getProjectElementService().getFirstStep(study).getStep());
684                 }
685                 // Find the given context value of the given type
686                 SimulationContext context = getSimulationContextService()
687                                 .selectSimulationContext(celt, ctxValue);
688                 if (context == null) { // Input of a new project context
689                         SimulationContext.Properties cprop = new SimulationContext.Properties();
690                         cprop.setType(celt).setValue(ctxValue);
691                         getStudyService().addProjectContext(study, cprop);
692                 } else { // Selection of existing project context
693                         getStudyService().addProjectContext(study, context);
694                 }
695         }
696
697         /**
698          * {@inheritDoc}
699          * 
700          * @see org.splat.service.ScenarioService#addKnowledgeElement(org.splat.dal.bo.som.Scenario,
701          *      org.splat.dal.bo.som.KnowledgeElement.Properties)
702          */
703         @Transactional
704         public KnowledgeElement addKnowledgeElement(final Scenario aScenarioDTO,
705                         final KnowledgeElement.Properties kprop)
706                         throws MissedPropertyException, InvalidPropertyException,
707                         MultiplyDefinedException {
708                 KnowledgeElement kelm = null;
709                 // try {
710                 long aScenarioId = aScenarioDTO.getIndex();
711                 if (LOG.isDebugEnabled()) {
712                         LOG
713                                         .debug("Add a knowledge element to the scenario #"
714                                                         + aScenarioId);
715                 }
716                 // Get the persistent scenario.
717                 Scenario aScenario = getScenarioDAO().get(aScenarioId);
718                 // Get persistent objects for creating a new knowledge.
719                 // TODO: Actions must use DTO instead of persistent objects.
720                 getUserDAO().merge(kprop.getAuthor());
721                 getKnowledgeElementTypeDAO().merge(kprop.getType());
722                 // Create a transient knowledge element related to the given scenario.
723                 kelm = new KnowledgeElement(kprop.setOwnerScenario(aScenario));
724                 // Save the new knowledge in the database.
725                 getKnowledgeElementDAO().create(kelm);
726                 // Update scenario transient data.
727                 if (kelm.getType().equals("usecase")) {
728                         aScenarioDTO.setUcase(kelm);
729                 } else if (aScenarioDTO.getKnowledgeElementsList() != null) { // If null, knowl will be initialized when needed
730                         aScenarioDTO.getKnowledgeElementsList().add(kelm);
731                 }
732
733                 // Load the workflow for the parent study to take into account
734                 // all study actors durng reindexing.
735                 getStudyService().loadWorkflow(aScenario.getOwnerStudy());
736
737                 // // Update the lucene index of knowledge elements.
738                 // getIndexService().add(kelm);
739                 if (LOG.isDebugEnabled()) {
740                         LOG.debug("A knowledge element #" + kelm.getIndex()
741                                         + " is added to the scenario #" + aScenario.getIndex());
742                 }
743                 // } catch (IOException error) {
744                 // LOG.error("Unable to index the knowedge element '"
745                 // + kelm.getIndex() + "', reason:", error);
746                 // kelm = null;
747                 // }
748
749                 return kelm;
750         }
751
752         /**
753          * {@inheritDoc}
754          * 
755          * @see org.splat.service.ScenarioService#checkin(long, long, java.util.List)
756          */
757         @Transactional
758         public void checkin(final long scenId, final long userId,
759                         final List<StepDTO> scInfo) throws InvalidPropertyException,
760                         MissedPropertyException, MultiplyDefinedException,
761                         MismatchException, IOException, NotApplicableException {
762                 // Get the scenario from the database by id
763                 Scenario aScenario = getScenarioDAO().get(scenId);
764                 // Get the user who perform this check-in operation
765                 User aUser = getUserService().selectUser(userId);
766                 // Get activities of the scenario
767                 Step[] steps = getProjectElementService().getSteps(aScenario);
768                 // Find result document types
769                 List<DocumentType> resTypes = getDocumentTypeService()
770                                 .selectResultTypes();
771
772                 // Keep newly created documents to create uses relations to results of a previous step.
773                 // For each processed existing document keep its new version
774                 Map<Document, Document> newVersion = new HashMap<Document, Document>();
775                 // Created publications of new created versions of existing documents
776                 List<Publication> newVers = new ArrayList<Publication>();
777                 // The list of publications of new created documents not existing before the checkin
778                 List<Publication> newDocs = new ArrayList<Publication>();
779                 // For each step DTO
780                 DocumentType resType;
781                 Date aDate = new Date(); // The timestamp of the checkin operation
782                 for (StepDTO stepDTO : scInfo) {
783                         if (LOG.isDebugEnabled()) {
784                                 LOG.debug("Checkin the step:\n" + stepDTO);
785                         }
786                         // Find a result document type of the step
787                         int i = 0;
788                         resType = null;
789                         do {
790                                 if (resTypes.get(i).isResultOf(
791                                                 getProjectSettings().getStep(stepDTO.getNumber()))) {
792                                         resType = resTypes.get(i);
793                                 }
794                                 i++;
795                         } while ((resType == null) && (i < resTypes.size()));
796
797                         // Find the appropriate scenario step
798                         Step step = findStep(stepDTO, steps);
799
800                         // Process each document of the step
801                         for (DocumentDTO doc : stepDTO.getDocs()) {
802                                 checkinDoc(step, doc, aUser, resType, aDate, newVersion,
803                                                 newVers, newDocs);
804                         }
805                 }
806
807                 // Set uses/used relations
808                 updateRelationsAfterCheckin(aScenario, newVersion, newVers, newDocs);
809
810                 // Mark the scenario as checked in
811                 checkin(aScenario);
812         }
813
814         /**
815          * Updated uses/used relations after checkin operation:<BR>
816          * <ul>
817          * <li>For each new version copy uses relations from the previous version.</li>
818          * <li>Outdate documents which depend from the previous version and were not checked in during this operation.</li>
819          * <li>For each new document create uses relation to the last versions of results of the previous step.</li>
820          * </ul>
821          * 
822          * @param aScenario
823          *            the checked in scenario
824          * @param newVersion
825          *            the mapping of documents existed before the checkin to their new created versions
826          * @param newVers
827          *            the list of publications of new created versions of documents existed before the checkin
828          * @param newDocs
829          *            the list of publications of new created documents not existed before the checkin
830          */
831         private void updateRelationsAfterCheckin(final Scenario aScenario,
832                         final Map<Document, Document> newVersion,
833                         final List<Publication> newVers, final List<Publication> newDocs) {
834                 // For each new version copy uses relations from the previous version.
835                 for (Publication newVer : newVers) {
836                         // For each Uses relation of the previous version
837                         Document prevDoc = newVer.value().getPreviousVersion();// prevVersion.get(newVer);
838                         if (LOG.isDebugEnabled()) {
839                                 LOG.debug("Previous version for publication #"
840                                                 + newVer.getIndex() + " is found: " + prevDoc);
841                         }
842                         List<Relation> usesRelations = prevDoc
843                                         .getRelations(UsesRelation.class);
844                         for (Relation rel : usesRelations) {
845                                 // If used document has been also versioned then refer to its new version.
846                                 Document usedDoc = ((UsesRelation) rel).getTo();
847                                 if (newVersion.containsKey(usedDoc)) {
848                                         usedDoc = newVersion.get(usedDoc);
849                                 }
850                                 // Build the appropriate relation for the new version.
851                                 newVer.addDependency(usedDoc);
852                         }
853                         // Outdate documents which depend from the previous version and
854                         // were not checked in during this operation.
855                         // 1. Get all usedBy relations of the previous document version
856                         for (Relation rel : prevDoc.getRelations(UsedByRelation.class)) {
857                                 Document using = ((UsedByRelation) rel).getTo();
858                                 // Check that not checked in dependent documents became outdated
859                                 Publication usingPub = aScenario.getPublication(using);
860                                 if (usingPub != null) { // if the document using the old version is still published
861                                         usingPub.setIsnew('O');
862                                 }
863                         }
864                 }
865
866                 // For each new document create uses relation to the last versions of
867                 // results of the previous step.
868                 for (Publication newPub : newDocs) {
869                         // Find used document type according to the configuration.
870                         Set<DocumentType> usedTypes = newPub.value().getType()
871                                         .getDefaultUses();
872                         // Find documents of used type in the previous study step.
873                         for (Publication pub : aScenario.getDocums()) {
874                                 if ((pub.getStep().getNumber() <= newPub.getStep().getNumber())
875                                                 && (!pub.isOutdated())
876                                                 && usedTypes.contains(pub.value().getType())) {
877                                         // Create uses relation from the new document
878                                         // to the found document in the previous step.
879                                         newPub.addDependency(pub);
880                                 }
881                         }
882                 }
883         }
884
885         /**
886          * Pure checkin of the document without creation of uses/usedBy relations. For an existing document a new version is created. New
887          * documents become published in the given step of the appropriate scenario. The appropriate uploaded file is attached to the created
888          * document and the document is published in the scenario. The publication of the old version is removed from the scenario.
889          * 
890          * @param step
891          *            the destination scenario step
892          * @param doc
893          *            the DTO of the document to checkin
894          * @param aUser
895          *            the user who performs checkin
896          * @param resType
897          *            the result document type of the given step
898          * @param aDate
899          *            timestamp of the checkin operation
900          * @param newVersion
901          *            the mapping of existing documents to their new created versions
902          * @param newVers
903          *            the list of publications of new created versions of existing documents
904          * @param newDocs
905          *            the list of publications of new created documents not existing before the checkin
906          * @throws InvalidPropertyException
907          *             if the scenario hasn't some of given steps or documents
908          * @throws IOException
909          *             if a file can't be moved into the vault
910          * @throws MismatchException
911          *             if version creation in some of steps is failed
912          * @throws MissedPropertyException
913          *             if some mandatory property is missed when new document or new document version is created
914          * @throws MultiplyDefinedException
915          *             if some property is defined several times when new document or new document version is created
916          * @throws NotApplicableException
917          *             if failed saving of a new publication with a given state
918          */
919         private void checkinDoc(final Step step, final DocumentDTO doc,
920                         final User aUser, final DocumentType resType, final Date aDate,
921                         final Map<Document, Document> newVersion,
922                         final List<Publication> newVers, final List<Publication> newDocs)
923                         throws InvalidPropertyException, MismatchException,
924                         MissedPropertyException, MultiplyDefinedException, IOException,
925                         NotApplicableException {
926                 if (doc.getFiles().size() > 0) {
927                         Document.Properties dprop = new Document.Properties();
928                         // NOTE: Process only the first attached file for each document
929                         FileDTO file = doc.getFiles().get(0);
930                         dprop.setLocalPath(file.getPath());
931
932                         // Get document title as the file name
933                         java.io.File upfile = new java.io.File(file.getPath());
934                         String fileFormat = upfile.getName().substring(
935                                         upfile.getName().lastIndexOf('.') + 1);
936
937                         // Attach the file via ConvertsRelation, create a new document or
938                         // create a new version of the document
939                         dprop.setAuthor(aUser).setDate(aDate).setFormat(fileFormat);
940                         String authorName = I18nUtils.getMessageLocaleDefault(aUser
941                                         .getDisplayName());
942                         String summary = I18nUtils.getMessageLocaleDefault(
943                                         MessageKeyEnum.DCT_000005.toString(), authorName);
944                         dprop.setDescription(summary);
945
946                         if (doc.getId() > 0) {
947                                 checkinExistingDoc(step, doc, dprop, fileFormat, upfile,
948                                                 newVersion, newVers);
949                         } else {
950
951                                 // Otherwise create a new document of the result type
952                                 // If result type is not found try to get type by file extension
953                                 if (resType == null) {
954                                         dprop.setType(getProjectSettings().getDefaultDocumentType(
955                                                         step.getStep(), fileFormat));
956                                 } else {
957                                         dprop.setType(resType);
958                                 }
959                                 // New document title generation as <document type name>_N
960                                 String docname = dprop.getType().getName();
961                                 int i = 1;
962                                 for (Publication scenPub : step.getOwner().getDocums()) {
963                                         if (scenPub.value().getTitle().startsWith(docname)) {
964                                                 i++;
965                                         }
966                                 }
967                                 docname += "_" + i; // The generated new document title
968
969                                 dprop.setName(docname);
970                                 Publication newPub = getStepService().createDocument(step,
971                                                 dprop);
972
973                                 // Remember the new document
974                                 newDocs.add(newPub);
975
976                                 saveFile(newPub, step, upfile);
977                         }
978                 }
979         }
980
981         /**
982          * Check in existing document.
983          * 
984          * @param step
985          *            study step to check in
986          * @param doc
987          *            document DTO to check in
988          * @param dprop
989          *            document properties
990          * @param fileFormat
991          *            checked in file format
992          * @param upfile
993          *            the file to check in
994          * @param newVersion
995          *            the map of created versions during this check in
996          * @param newVers
997          *            the list of new versions created during this check in
998          * @throws InvalidPropertyException
999          *             if publication of the document is not found in the step
1000          * @throws MismatchException
1001          *             if the found publication does not point to a document
1002          * @throws IOException
1003          *             if can not move the file into the vault
1004          * @throws MultiplyDefinedException
1005          *             thrown by versionDocument
1006          * @throws MissedPropertyException
1007          *             thrown by versionDocument
1008          * @throws NotApplicableException
1009          *             if failed saving of a new publication with a given state
1010          */
1011         private void checkinExistingDoc(final Step step, final DocumentDTO doc,
1012                         final Properties dprop, final String fileFormat,
1013                         final java.io.File upfile,
1014                         final Map<Document, Document> newVersion,
1015                         final List<Publication> newVers) throws InvalidPropertyException,
1016                         MismatchException, MissedPropertyException,
1017                         MultiplyDefinedException, IOException, NotApplicableException {
1018                 // If the document already exists then
1019                 // Attach the file via ConvertsRelation if the extension of the
1020                 // new file differs from the old one.
1021                 // If file format (i.e. extension) is the same then create a new
1022                 // version of the document.
1023                 // Find the document publication
1024                 Publication pub = step.getDocument(doc.getId());
1025                 if (pub == null) {
1026                         throw new InvalidPropertyException(MessageKeyEnum.SCN_000002
1027                                         .toString(), doc.getId());
1028                 }
1029                 if (pub.value() == null) {
1030                         throw new MismatchException(MessageKeyEnum.SCN_000002.toString(),
1031                                         doc.getId());
1032                 }
1033                 if (LOG.isDebugEnabled()) {
1034                         LOG.debug("Old format: " + pub.value().getFormat()
1035                                         + " => New format: " + fileFormat);
1036                 }
1037                 // If formats are same then create a new document version
1038                 if (pub.value().getFormat() != null
1039                                 && pub.value().getFormat().equals(fileFormat)) {
1040                         Publication newPub = getStepService().versionDocument(step, pub,
1041                                         dprop);
1042                         if (LOG.isDebugEnabled()) {
1043                                 LOG.debug("Created document type: "
1044                                                 + newPub.value().getType().getName() + ", format: "
1045                                                 + newPub.value().getFormat());
1046                         }
1047                         // Remeber the link from the old document to the new document version
1048                         newVersion.put(pub.value(), newPub.value());
1049                         // Remember the new version publication
1050                         newVers.add(newPub);
1051
1052                         saveFile(newPub, step, upfile);
1053
1054                 } else { // If formats are different then attach the new file via ConvertsRelation
1055                         File attach = pub.value().getAttachedFile(fileFormat);
1056                         if (attach == null) {
1057                                 // If there is no attachment with this extension then attach the new one
1058                                 ConvertsRelation export = getPublicationService().attach(pub,
1059                                                 fileFormat);
1060                                 moveFile(upfile, export.getTo().asFile());
1061                         } else {
1062                                 // If an attachment with this extension already exists then
1063                                 // replace it by the new one
1064                                 moveFile(upfile, attach.asFile());
1065                                 // Update attached file modification date
1066                                 attach.setDate(new Date());
1067                         }
1068                 }
1069         }
1070
1071         /**
1072          * Save the file in the vault and create its publication in the step.
1073          * 
1074          * @param newPub
1075          *            the new publication to save
1076          * @param step
1077          *            the study step to publish the document
1078          * @param upfile
1079          *            the downloaded file
1080          * @throws IOException
1081          *             if a file can't be moved into the vault
1082          * @throws NotApplicableException
1083          *             if failed saving of a new publication with a given state
1084          */
1085         private void saveFile(final Publication newPub, final Step step,
1086                         final java.io.File upfile) throws IOException,
1087                         NotApplicableException {
1088                 // Attach the file to the created document
1089                 java.io.File updir = newPub.getSourceFile().asFile();
1090                 if (updir.exists()) {
1091                         if (updir.delete()) {
1092                                 LOG.info(MessageKeyEnum.SCN_000003.toString(), updir
1093                                                 .getAbsoluteFile(), step.getOwner().getIndex());
1094                         } else {
1095                                 throw new IOException(
1096                                                 "Can't delete the existing destination file to move file from "
1097                                                                 + upfile.getAbsolutePath() + TO
1098                                                                 + updir.getAbsolutePath());
1099                         }
1100                 }
1101                 if (moveFile(upfile, updir)) {
1102                         // Save the new publication in the scenario.
1103                         // The old publication is removed from the scenario here.
1104                         getPublicationService().saveAs(newPub, ProgressState.inWORK); // May throw FileNotFound if rename was not done
1105                 } else {
1106                         throw new IOException("Can't move file from "
1107                                         + upfile.getAbsolutePath() + TO + updir.getAbsolutePath());
1108                 }
1109         }
1110
1111         /**
1112          * Find appropriate step in the array of scenario steps according to the given step DTO.
1113          * 
1114          * @param stepDTO
1115          *            the stepDTO
1116          * @param steps
1117          *            scenario steps
1118          * @return appropriate scenario step
1119          * @throws InvalidPropertyException
1120          *             if appropriate step is not found
1121          */
1122         private Step findStep(final StepDTO stepDTO, final Step[] steps)
1123                         throws InvalidPropertyException {
1124                 int i = 0;
1125                 Step step = null;
1126                 do {
1127                         if (steps[i].getNumber() == stepDTO.getNumber()) {
1128                                 step = steps[i];
1129                         }
1130                         i++;
1131                 } while ((step == null) && (i < steps.length));
1132
1133                 if (step == null) {
1134                         throw new InvalidPropertyException(MessageKeyEnum.SCN_000001
1135                                         .toString(), stepDTO.getNumber());
1136                 }
1137                 return step;
1138         }
1139
1140         /**
1141          * {@inheritDoc}
1142          * 
1143          * @see org.splat.service.ScenarioService#checkin(long)
1144          */
1145         @Transactional
1146         public void checkin(final long scenarioId) throws InvalidPropertyException {
1147                 Scenario aScenario = getScenarioDAO().get(scenarioId);
1148                 if (aScenario == null) {
1149                         // Scenario not found
1150                         throw new InvalidPropertyException(MessageKeyEnum.SCN_000006
1151                                         .toString(), scenarioId);
1152                 }
1153                 checkin(aScenario);
1154         }
1155
1156         /**
1157          * Mark the scenario as checked in.
1158          * 
1159          * @param aScenario
1160          *            the scenario to check in.
1161          */
1162         private void checkin(final Scenario aScenario) {
1163                 aScenario.setUser(null);
1164                 aScenario.setLastModificationDate(Calendar.getInstance().getTime());
1165                 // getScenarioDAO().update(aScenario);
1166         }
1167
1168         /**
1169          * {@inheritDoc}
1170          * 
1171          * @see org.splat.service.ScenarioService#checkout(org.splat.dal.bo.som.Scenario, org.splat.dal.bo.kernel.User)
1172          */
1173         public boolean checkout(final Scenario aScenario, final User user) {
1174                 boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
1175                                 user);
1176                 if (res) {
1177                         aScenario.setUser(user);
1178                         aScenario.setLastModificationDate(Calendar.getInstance().getTime());
1179                         // RKV: getScenarioDAO().update(aScenario);
1180                 }
1181                 return res;
1182         }
1183
1184         /**
1185          * Mark the given scenario as checked out by the given user.
1186          * 
1187          * @param scenarioId
1188          *            the scenario id
1189          * @param userId
1190          *            the id of the user performing the check out
1191          * @throws InvalidPropertyException
1192          *             if the user or the scenario is not found in the database
1193          * @throws NotApplicableException
1194          *             if the given user can not check out the scenario
1195          */
1196         @Transactional
1197         public void checkout(final long scenarioId, final long userId)
1198                         throws InvalidPropertyException, NotApplicableException {
1199                 User aUser = getUserService().selectUser(userId);
1200                 if (aUser == null) {
1201                         // User not found
1202                         throw new InvalidPropertyException(MessageKeyEnum.USR_000001
1203                                         .toString(), userId);
1204                 }
1205                 Scenario aScenario = getScenarioDAO().get(scenarioId);
1206                 if (aScenario == null) {
1207                         // Scenario not found
1208                         throw new InvalidPropertyException(MessageKeyEnum.SCN_000006
1209                                         .toString(), scenarioId);
1210                 }
1211                 boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
1212                                 aUser);
1213                 if (res) {
1214                         if (aScenario.isCheckedout()
1215                                         && (!aScenario.getUser().getUsername().equals(
1216                                                         aUser.getUsername()))) {
1217                                 throw new NotApplicableException(MessageKeyEnum.SCN_000008
1218                                                 .toString(), scenarioId, aScenario.getUser()
1219                                                 .getUsername());
1220                         }
1221                         aScenario.setUser(aUser);
1222                         aScenario.setLastModificationDate(Calendar.getInstance().getTime());
1223                 } else {
1224                         // User doesn't participate in the scenario
1225                         throw new NotApplicableException(MessageKeyEnum.SCN_000007
1226                                         .toString(), aUser.getUsername(), scenarioId);
1227                 }
1228         }
1229
1230         /**
1231          * {@inheritDoc}
1232          * 
1233          * @see org.splat.service.ScenarioService#copyContentsUpTo(org.splat.dal.bo.som.Scenario, org.splat.som.Step)
1234          */
1235         public void copyContentsUpTo(final Scenario scenario, final Step lastep) {
1236                 Scenario base = (Scenario) lastep.getOwner();
1237                 Step[] from = getProjectElementService().getSteps(base);
1238                 Step[] to = getProjectElementService().getSteps(scenario);
1239                 for (int i = 0; i < from.length; i++) {
1240                         Step step = from[i];
1241                         if (step.getNumber() > lastep.getNumber()) {
1242                                 break;
1243                         }
1244
1245                         List<Publication> docs = step.getAllDocuments();
1246                         for (Iterator<Publication> j = docs.iterator(); j.hasNext();) {
1247                                 Publication doc = getPublicationService().copy(j.next(),
1248                                                 scenario); // Creation of a new reference to the document
1249                                 // Database.getSession().save(doc); Publications MUST be saved later through cascading when saving the scenario
1250                                 getStepService().add(to[i], doc);
1251                         }
1252                         List<SimulationContext> ctex = step.getAllSimulationContexts();
1253                         for (Iterator<SimulationContext> j = ctex.iterator(); j.hasNext();) {
1254                                 getStepService().addSimulationContext(to[i], j.next());
1255                         }
1256                 }
1257         }
1258
1259         /**
1260          * {@inheritDoc}
1261          * 
1262          * @see org.splat.service.ScenarioService#isEmpty(org.splat.dal.bo.som.Scenario)
1263          */
1264         public boolean isEmpty(final Scenario scenario) {
1265                 Step[] mystep = getProjectElementService().getSteps(scenario);
1266                 boolean isEmp = true;
1267                 for (int i = 0; i < mystep.length; i++) {
1268                         if (mystep[i].isStarted()) {
1269                                 isEmp = false;
1270                                 break;
1271                         }
1272                 }
1273                 return isEmp;
1274         }
1275
1276         /**
1277          * @param scenario
1278          * @return
1279          */
1280         public boolean isFinished(final Scenario scenario) {
1281                 Step[] mystep = getProjectElementService().getSteps(scenario);
1282                 boolean notempty = false; // If this is empty, this is not finished
1283                 for (int i = 0; i < mystep.length; i++) {
1284                         if (!mystep[i].isStarted()) {
1285                                 continue;
1286                         }
1287                         if (!mystep[i].isFinished()) {
1288                                 return false;
1289                         }
1290                         notempty = true;
1291                 }
1292                 return notempty;
1293         }
1294
1295         /**
1296          * {@inheritDoc}
1297          * 
1298          * @see org.splat.service.StudyService#addScenario(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Scenario.Properties)
1299          */
1300         @Transactional
1301         public Scenario addScenario(final Study aStudy,
1302                         final Scenario.Properties sprop) throws MissedPropertyException,
1303                         InvalidPropertyException, MultiplyDefinedException {
1304                 if (sprop.getManager() == null) {
1305                         sprop.setManager(aStudy.getAuthor());
1306                 }
1307
1308                 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
1309                 if (sprop.getBaseStep() != null) {
1310                         copyContentsUpTo(scenario, sprop.getBaseStep());
1311                 }
1312                 Scenario previous = sprop.getInsertAfter();
1313
1314                 if (previous == null) {
1315                         aStudy.getScenariiList().add(scenario);
1316                 } else {
1317                         aStudy.getScenariiList().add(
1318                                         aStudy.getScenariiList().indexOf(previous) + 1, scenario);
1319                 }
1320                 getStudyDAO().update(aStudy); // No need to update the Lucene index
1321                 getScenarioDAO().create(scenario); // Must be done after updating this study because of the back reference to the study
1322                 if (sprop.getBaseStep() != null) {
1323                         // No need to update the Knowledge Element index as Knowledge Elements are not copied
1324                         getProjectElementService().refresh(scenario); // Because saving the scenario changes the hashcode of copied Publications
1325                 }
1326                 KnowledgeElementType ucase = getKnowledgeElementTypeService()
1327                                 .selectType("usecase");
1328                 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
1329                 // TODO: Get appropriate user by its role: UserService.getAdmin();
1330                 // User admin = getUserService().selectUser(1); // First user created when creating the database
1331                 Role adminRole = getRoleDAO().getFilteredList(
1332                                 Restrictions.like("role", "%sysadmin%")).get(0);
1333                 User admin = getUserDAO().getFilteredList(
1334                                 Restrictions.eq("role", adminRole), Order.asc("rid")).get(0); // First sysadmin in the database
1335
1336                 kprop.setType(ucase).setTitle(aStudy.getTitle()).setValue(
1337                                 scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
1338                 // knowledges
1339                 addKnowledgeElement(scenario, kprop);
1340                 return scenario;
1341         }
1342
1343         /**
1344          * Remove a knowledge element from a scenario.
1345          * 
1346          * @param scenario
1347          *            the scenario
1348          * @param kelm
1349          *            the knowledge element to remove
1350          * @return true if removal succeeded
1351          */
1352         @Transactional
1353         public boolean removeKnowledgeElement(final Scenario scenario,
1354                         final KnowledgeElement kelm) {
1355                 KnowledgeElement torem = scenario.getKnowledgeElement(kelm.getIndex());
1356                 boolean isOk = (torem != null);
1357                 if (isOk) {
1358                         isOk = scenario.getKnowledgeElements().remove(torem);
1359                         if (isOk) {
1360                                 getScenarioDAO().merge(scenario);
1361                                 // Update of my transient data
1362                                 // RKV: These transient data are not used indeed.
1363                                 // RKV: List<KnowledgeElement> kelms = scenario.getKnowledgeByType().get(
1364                                 // RKV: kelm.getType().getIndex());
1365                                 // RKV: kelms.remove(torem);
1366                                 if (scenario.getKnowledgeElementsList() != null) {
1367                                         scenario.getKnowledgeElementsList().remove(torem);
1368                                 }
1369                                 // TODO: If the owner study is not private, remove the knowledge from the Lucene index
1370                         }
1371                 }
1372                 return isOk;
1373         }
1374
1375         /**
1376          * 
1377          * {@inheritDoc}
1378          * 
1379          * @see org.splat.service.ScenarioService#renameScenario(java.lang.String)
1380          */
1381         @Transactional
1382         public void renameScenario(final Scenario scenario) {
1383                 getScenarioDAO().merge(scenario);
1384         }
1385         
1386         /** 
1387          * {@inheritDoc}
1388          * @see org.splat.service.ScenarioService#removeScenario(long)
1389          */
1390         @Transactional
1391         public void removeScenario(final long scenarioId) {
1392                 Scenario scenario = getScenarioDAO().get(scenarioId);
1393                 Study study = scenario.getOwnerStudy();
1394                 
1395                 if (scenario != null && study != null) {
1396                         getScenarioDAO().delete(scenario);
1397                         
1398                         // Collect all documents which are published in another scenario
1399                         // or are previous versions of documents published in another scenario
1400                         Set<Document> untouched = new HashSet<Document>();
1401                 
1402                         List<Scenario> otherScenarios = study.getScenariiList();
1403                         otherScenarios.remove(scenario);
1404                         
1405                         for (Scenario otherScenario : otherScenarios) {
1406                                 for (Publication publication : otherScenario.getDocums()) {
1407                                         for (Document document = publication.value(); document != null;
1408                                                         document = document.getPreviousVersion()) {
1409                                                 untouched.add(document);
1410                                         }
1411                                 }
1412                         }
1413         
1414                         // Collect all documents which are published in this scenario
1415                         // or are previous versions of documents published in this scenario
1416                         Set<Document> toRemove = new HashSet<Document>();
1417                         for (Publication publication : scenario.getDocums()) {
1418                                 for (Document document = publication.value(); document != null; 
1419                                                 document = document.getPreviousVersion()) {
1420                                         toRemove.add(document);
1421                                 }
1422                         }
1423                         
1424                         toRemove.removeAll(untouched);
1425                         
1426                         // Delete all necessary documents
1427                         for (Document document : toRemove) {
1428                                 _documentDAO.delete(document);
1429                         }
1430                 }
1431         }
1432
1433         /**
1434          * Get the knowledgeElementDAO.
1435          * 
1436          * @return the knowledgeElementDAO
1437          */
1438         public KnowledgeElementDAO getKnowledgeElementDAO() {
1439                 return _knowledgeElementDAO;
1440         }
1441
1442         /**
1443          * Set the knowledgeElementDAO.
1444          * 
1445          * @param knowledgeElementDAO
1446          *            the knowledgeElementDAO to set
1447          */
1448         public void setKnowledgeElementDAO(
1449                         final KnowledgeElementDAO knowledgeElementDAO) {
1450                 _knowledgeElementDAO = knowledgeElementDAO;
1451         }
1452
1453         /**
1454          * Get the indexService.
1455          * 
1456          * @return the indexService
1457          */
1458         public IndexService getIndexService() {
1459                 return _indexService;
1460         }
1461
1462         /**
1463          * Set the indexService.
1464          * 
1465          * @param indexService
1466          *            the indexService to set
1467          */
1468         public void setIndexService(final IndexService indexService) {
1469                 _indexService = indexService;
1470         }
1471
1472         /**
1473          * Get the scenarioDAO.
1474          * 
1475          * @return the scenarioDAO
1476          */
1477         public ScenarioDAO getScenarioDAO() {
1478                 return _scenarioDAO;
1479         }
1480
1481         /**
1482          * Set the scenarioDAO.
1483          * 
1484          * @param scenarioDAO
1485          *            the scenarioDAO to set
1486          */
1487         public void setScenarioDAO(final ScenarioDAO scenarioDAO) {
1488                 _scenarioDAO = scenarioDAO;
1489         }
1490
1491         /**
1492          * Get the studyDAO.
1493          * 
1494          * @return the studyDAO
1495          */
1496         public StudyDAO getStudyDAO() {
1497                 return _studyDAO;
1498         }
1499
1500         /**
1501          * Set the studyDAO.
1502          * 
1503          * @param studyDAO
1504          *            the studyDAO to set
1505          */
1506         public void setStudyDAO(final StudyDAO studyDAO) {
1507                 _studyDAO = studyDAO;
1508         }
1509
1510         /**
1511          * Get the knowledgeElementTypeService.
1512          * 
1513          * @return the knowledgeElementTypeService
1514          */
1515         public KnowledgeElementTypeService getKnowledgeElementTypeService() {
1516                 return _knowledgeElementTypeService;
1517         }
1518
1519         /**
1520          * Set the knowledgeElementTypeService.
1521          * 
1522          * @param knowledgeElementTypeService
1523          *            the knowledgeElementTypeService to set
1524          */
1525         public void setKnowledgeElementTypeService(
1526                         final KnowledgeElementTypeService knowledgeElementTypeService) {
1527                 _knowledgeElementTypeService = knowledgeElementTypeService;
1528         }
1529
1530         /**
1531          * Get the studyService.
1532          * 
1533          * @return the studyService
1534          */
1535         public StudyService getStudyService() {
1536                 return _studyService;
1537         }
1538
1539         /**
1540          * Set the studyService.
1541          * 
1542          * @param studyService
1543          *            the studyService to set
1544          */
1545         public void setStudyService(final StudyService studyService) {
1546                 _studyService = studyService;
1547         }
1548
1549         /**
1550          * Get the userService.
1551          * 
1552          * @return the userService
1553          */
1554         public UserService getUserService() {
1555                 return _userService;
1556         }
1557
1558         /**
1559          * Set the userService.
1560          * 
1561          * @param userService
1562          *            the userService to set
1563          */
1564         public void setUserService(final UserService userService) {
1565                 _userService = userService;
1566         }
1567
1568         /**
1569          * Get the userDAO.
1570          * 
1571          * @return the userDAO
1572          */
1573         public UserDAO getUserDAO() {
1574                 return _userDAO;
1575         }
1576
1577         /**
1578          * Set the userDAO.
1579          * 
1580          * @param userDAO
1581          *            the userDAO to set
1582          */
1583         public void setUserDAO(final UserDAO userDAO) {
1584                 _userDAO = userDAO;
1585         }
1586
1587         /**
1588          * Get the knowledgeElementTypeDAO.
1589          * 
1590          * @return the knowledgeElementTypeDAO
1591          */
1592         public KnowledgeElementTypeDAO getKnowledgeElementTypeDAO() {
1593                 return _knowledgeElementTypeDAO;
1594         }
1595
1596         /**
1597          * Set the knowledgeElementTypeDAO.
1598          * 
1599          * @param knowledgeElementTypeDAO
1600          *            the knowledgeElementTypeDAO to set
1601          */
1602         public void setKnowledgeElementTypeDAO(
1603                         final KnowledgeElementTypeDAO knowledgeElementTypeDAO) {
1604                 _knowledgeElementTypeDAO = knowledgeElementTypeDAO;
1605         }
1606         
1607         /**
1608          * Get the documentDAO.
1609          * @return the documentDAO
1610          */
1611         public DocumentDAO getDocumentDAO() {
1612                 return _documentDAO;
1613         }
1614
1615         /**
1616          * Set the documentDAO.
1617          * @param documentDAO the documentDAO to set
1618          */
1619         public void setDocumentDAO(final DocumentDAO documentDAO) {
1620                 _documentDAO = documentDAO;
1621         }
1622
1623         /**
1624          * Get the simulationContextService.
1625          * 
1626          * @return the simulationContextService
1627          */
1628         public SimulationContextService getSimulationContextService() {
1629                 return _simulationContextService;
1630         }
1631
1632         /**
1633          * Set the simulationContextService.
1634          * 
1635          * @param simulationContextService
1636          *            the simulationContextService to set
1637          */
1638         public void setSimulationContextService(
1639                         final SimulationContextService simulationContextService) {
1640                 _simulationContextService = simulationContextService;
1641         }
1642
1643         /**
1644          * Get project settings.
1645          * 
1646          * @return Project settings service
1647          */
1648         private ProjectSettingsService getProjectSettings() {
1649                 return _projectSettings;
1650         }
1651
1652         /**
1653          * Set project settings service.
1654          * 
1655          * @param projectSettingsService
1656          *            project settings service
1657          */
1658         public void setProjectSettings(
1659                         final ProjectSettingsService projectSettingsService) {
1660                 _projectSettings = projectSettingsService;
1661         }
1662
1663         /**
1664          * Get the documentTypeService.
1665          * 
1666          * @return the documentTypeService
1667          */
1668         public DocumentTypeService getDocumentTypeService() {
1669                 return _documentTypeService;
1670         }
1671
1672         /**
1673          * Set the documentTypeService.
1674          * 
1675          * @param documentTypeService
1676          *            the documentTypeService to set
1677          */
1678         public void setDocumentTypeService(
1679                         final DocumentTypeService documentTypeService) {
1680                 _documentTypeService = documentTypeService;
1681         }
1682
1683         /**
1684          * Get the roleDAO.
1685          * 
1686          * @return the roleDAO
1687          */
1688         public RoleDAO getRoleDAO() {
1689                 return _roleDAO;
1690         }
1691
1692         /**
1693          * Set the roleDAO.
1694          * 
1695          * @param roleDAO
1696          *            the roleDAO to set
1697          */
1698         public void setRoleDAO(final RoleDAO roleDAO) {
1699                 _roleDAO = roleDAO;
1700         }
1701
1702         /**
1703          * Get the simulationContextTypeService.
1704          * 
1705          * @return the simulationContextTypeService
1706          */
1707         public SimulationContextTypeService getSimulationContextTypeService() {
1708                 return _simulationContextTypeService;
1709         }
1710
1711         /**
1712          * Set the simulationContextTypeService.
1713          * 
1714          * @param simulationContextTypeService
1715          *            the simulationContextTypeService to set
1716          */
1717         public void setSimulationContextTypeService(
1718                         final SimulationContextTypeService simulationContextTypeService) {
1719                 _simulationContextTypeService = simulationContextTypeService;
1720         }
1721
1722         /**
1723          * Get the validationCycleDAO.
1724          * 
1725          * @return the validationCycleDAO
1726          */
1727         public ValidationCycleDAO getValidationCycleDAO() {
1728                 return _validationCycleDAO;
1729         }
1730
1731         /**
1732          * Set the validationCycleDAO.
1733          * 
1734          * @param validationCycleDAO
1735          *            the validationCycleDAO to set
1736          */
1737         public void setValidationCycleDAO(
1738                         final ValidationCycleDAO validationCycleDAO) {
1739                 _validationCycleDAO = validationCycleDAO;
1740         }
1741
1742         /**
1743          * Get steps config.
1744          * 
1745          * @return steps config service
1746          */
1747         private StepsConfigService getStepsConfigService() {
1748                 return _stepsConfigService;
1749         }
1750
1751         /**
1752          * Set steps config service.
1753          * 
1754          * @param stepsConfigService
1755          *            steps config service
1756          */
1757         public void setStepsConfigService(
1758                         final StepsConfigService stepsConfigService) {
1759                 _stepsConfigService = stepsConfigService;
1760         }
1761
1762         /**
1763          * Get the repositoryService.
1764          * 
1765          * @return the repositoryService
1766          */
1767         public RepositoryService getRepositoryService() {
1768                 return _repositoryService;
1769         }
1770
1771         /**
1772          * Set the repositoryService.
1773          * 
1774          * @param repositoryService
1775          *            the repositoryService to set
1776          */
1777         public void setRepositoryService(final RepositoryService repositoryService) {
1778                 _repositoryService = repositoryService;
1779         }
1780
1781 }