Salome HOME
Fixes for checkin and user creation.
[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.Iterator;
18 import java.util.List;
19 import java.util.Map;
20
21 import org.splat.common.properties.MessageKeyEnum;
22 import org.splat.dal.bo.kernel.Relation;
23 import org.splat.dal.bo.kernel.User;
24 import org.splat.dal.bo.som.ConvertsRelation;
25 import org.splat.dal.bo.som.Document;
26 import org.splat.dal.bo.som.DocumentType;
27 import org.splat.dal.bo.som.File;
28 import org.splat.dal.bo.som.KnowledgeElement;
29 import org.splat.dal.bo.som.KnowledgeElementType;
30 import org.splat.dal.bo.som.ProgressState;
31 import org.splat.dal.bo.som.Publication;
32 import org.splat.dal.bo.som.Scenario;
33 import org.splat.dal.bo.som.SimulationContext;
34 import org.splat.dal.bo.som.Study;
35 import org.splat.dal.bo.som.UsesRelation;
36 import org.splat.dal.dao.kernel.UserDAO;
37 import org.splat.dal.dao.som.KnowledgeElementDAO;
38 import org.splat.dal.dao.som.KnowledgeElementTypeDAO;
39 import org.splat.dal.dao.som.ScenarioDAO;
40 import org.splat.dal.dao.som.StudyDAO;
41 import org.splat.kernel.InvalidPropertyException;
42 import org.splat.kernel.MismatchException;
43 import org.splat.kernel.MissedPropertyException;
44 import org.splat.kernel.MultiplyDefinedException;
45 import org.splat.kernel.NotApplicableException;
46 import org.splat.log.AppLogger;
47 import org.splat.service.dto.DocumentDTO;
48 import org.splat.service.dto.FileDTO;
49 import org.splat.service.dto.StepDTO;
50 import org.splat.service.technical.IndexService;
51 import org.splat.service.technical.ProjectSettingsService;
52 import org.splat.som.Step;
53 import org.splat.util.BeanHelper;
54 import org.springframework.transaction.annotation.Transactional;
55
56 /**
57  * Scenario service implementation.
58  * 
59  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
60  */
61 public class ScenarioServiceImpl implements ScenarioService {
62
63         /**
64          * The logger for the service.
65          */
66         public final static AppLogger LOG = AppLogger
67                         .getLogger(ScenarioServiceImpl.class);
68
69         /**
70          * Injected index service.
71          */
72         private IndexService _indexService;
73         /**
74          * Injected step service.
75          */
76         private StepService _stepService;
77         /**
78          * Injected study service.
79          */
80         private StudyService _studyService;
81         /**
82          * Injected publication service.
83          */
84         private PublicationService _publicationService;
85         /**
86          * Injected project element service.
87          */
88         private ProjectElementService _projectElementService;
89         /**
90          * Injected knowledge element DAO.
91          */
92         private KnowledgeElementDAO _knowledgeElementDAO;
93         /**
94          * Injected scenario DAO.
95          */
96         private ScenarioDAO _scenarioDAO;
97
98         /**
99          * Injected study DAO.
100          */
101         private StudyDAO _studyDAO;
102
103         /**
104          * Injected knowledge element service.
105          */
106         private KnowledgeElementTypeService _knowledgeElementTypeService;
107
108         /**
109          * Injected user service.
110          */
111         private UserService _userService;
112
113         /**
114          * Injected user DAO.
115          */
116         private UserDAO _userDAO;
117
118         /**
119          * Injected knowledge element type DAO.
120          */
121         private KnowledgeElementTypeDAO _knowledgeElementTypeDAO;
122
123         /**
124          * Injected simulation context service.
125          */
126         private SimulationContextService _simulationContextService;
127
128         /**
129          * Injected project service.
130          */
131         private ProjectSettingsService _projectSettings;
132
133         /**
134          * Injected document type service.
135          */
136         private DocumentTypeService _documentTypeService;
137
138         /**
139          * Get the projectElementService.
140          * 
141          * @return the projectElementService
142          */
143         public ProjectElementService getProjectElementService() {
144                 return _projectElementService;
145         }
146
147         /**
148          * Set the projectElementService.
149          * 
150          * @param projectElementService
151          *            the projectElementService to set
152          */
153         public void setProjectElementService(
154                         final ProjectElementService projectElementService) {
155                 _projectElementService = projectElementService;
156         }
157
158         /**
159          * Get the publicationService.
160          * 
161          * @return the publicationService
162          */
163         public PublicationService getPublicationService() {
164                 return _publicationService;
165         }
166
167         /**
168          * Set the publicationService.
169          * 
170          * @param publicationService
171          *            the publicationService to set
172          */
173         public void setPublicationService(
174                         final PublicationService publicationService) {
175                 _publicationService = publicationService;
176         }
177
178         /**
179          * Get the stepService.
180          * 
181          * @return the stepService
182          */
183         public StepService getStepService() {
184                 return _stepService;
185         }
186
187         /**
188          * Set the stepService.
189          * 
190          * @param stepService
191          *            the stepService to set
192          */
193         public void setStepService(final StepService stepService) {
194                 _stepService = stepService;
195         }
196
197         /**
198          * {@inheritDoc}
199          * 
200          * @see org.splat.service.ScenarioService#getScenarioInfo(long)
201          */
202         @Transactional(readOnly = true)
203         public List<StepDTO> getScenarioInfo(final long scenarioId) {
204                 List<StepDTO> res = new ArrayList<StepDTO>();
205                 // Get the scenario from the database by id
206                 Scenario scen = getScenarioDAO().get(scenarioId);
207                 if (LOG.isDebugEnabled()) {
208                         LOG.debug("Scenario[" + scenarioId + "]: Number of publications: "
209                                         + scen.getDocums().size());
210                 }
211                 // Get activities of the scenario
212                 Step[] steps = getProjectElementService().getSteps(scen);
213                 StepDTO stepDTO;
214                 DocumentDTO docDTO;
215                 String docType, fileFormat;
216                 String processing;
217                 boolean doImport;
218                 // For each activity create a step DTO and add it to the result list
219                 for (Step step : steps) {
220                         stepDTO = BeanHelper.copyBean(step.getStep(), StepDTO.class);
221                         res.add(stepDTO);
222                         if (LOG.isDebugEnabled()) {
223                                 LOG.debug("Step[" + stepDTO.getNumber()
224                                                 + "]: Number of documents: "
225                                                 + step.getDocuments().size());
226                         }
227                         // For each publication of the activity create a document DTO.
228                         // Each file is considered as a source file.
229                         for (Publication tag : step.getDocuments()) {
230                                 docDTO = stepDTO.addDoc(tag.value().getIndex(), tag.value()
231                                                 .getTitle());
232                                 char aState = tag.getIsnew();
233                                 docType = tag.value().getType().getName();
234                                 // For each file of the document create a file DTO
235                                 // Process source file of the document
236                                 fileFormat = tag.value().getFile().getFormat();
237                                 doImport = getProjectSettings().doImport(docType, fileFormat);
238                                 if (doImport && (!tag.isOutdated())) {
239                                         processing = "file-import";
240                                 } else {
241                                         processing = "file-download";
242                                 }
243                                 docDTO.addFile(tag.value().getFile().getRelativePath(), aState,
244                                                 processing, false);
245                                 // Process all exported files
246                                 for (Relation rel : tag.value().getRelations(
247                                                 ConvertsRelation.class)) {
248                                         File aFile = ((ConvertsRelation) rel).getTo();
249                                         fileFormat = aFile.getFormat();
250                                         doImport = getProjectSettings().doImport(docType,
251                                                         fileFormat);
252                                         if (doImport && (!tag.isOutdated())) {
253                                                 processing = "file-import";
254                                         } else {
255                                                 processing = "file-download";
256                                         }
257                                         docDTO.addFile(aFile.getRelativePath(), aState, processing,
258                                                         false);
259                                 }
260                         }
261                 }
262                 return res;
263         }
264
265         /**
266          * Create a new study with one scenario and "product" simulation context.
267          * 
268          * @param sprop
269          *            the study properties
270          * @param oprop
271          *            the scenario properties
272          * @param cprop
273          *            the "product" simulation context properties
274          * @return the created study
275          * @throws MissedPropertyException
276          *             if a mandatory property is missed
277          * @throws InvalidPropertyException
278          *             if a property is invalid
279          * @throws MultiplyDefinedException
280          *             if some property occurs several times
281          */
282         @Transactional
283         public Study createStudy(final Study.Properties sprop,
284                         final Scenario.Properties oprop,
285                         final SimulationContext.Properties cprop)
286                         throws MissedPropertyException, InvalidPropertyException,
287                         MultiplyDefinedException {
288                 Study study = getStudyService().createStudy(sprop);
289                 addScenario(study, oprop);
290                 if (cprop.getIndex() == 0) { // Input of new project context
291                         cprop.setType(getSimulationContextService().selectType("product"))
292                                         .setValue(cprop.getValue());
293                         getStudyService().addProjectContext(study, cprop);
294                 } else { // Selection of existing project context
295                         SimulationContext context = getSimulationContextService()
296                                         .selectSimulationContext(cprop.getIndex());
297                         getStudyService().addProjectContext(study, context);
298                 }
299                 return study;
300         }
301
302         /**
303          * {@inheritDoc}
304          * 
305          * @see org.splat.service.ScenarioService#addKnowledgeElement(org.splat.dal.bo.som.Scenario,
306          *      org.splat.dal.bo.som.KnowledgeElement.Properties)
307          */
308         @Transactional
309         public KnowledgeElement addKnowledgeElement(final Scenario aScenarioDTO,
310                         final KnowledgeElement.Properties kprop)
311                         throws MissedPropertyException, InvalidPropertyException,
312                         MultiplyDefinedException {
313                 KnowledgeElement kelm = null;
314                 try {
315                         long aScenarioId = aScenarioDTO.getIndex();
316                         if (LOG.isDebugEnabled()) {
317                                 LOG.debug("Add a knowledge element to the scenario #"
318                                                 + aScenarioId);
319                         }
320                         // Get the persistent scenario.
321                         Scenario aScenario = getScenarioDAO().get(aScenarioId);
322                         // Get persistent objects for creating a new knowledge.
323                         // TODO: Actions must use DTO instead of persistent objects.
324                         getUserDAO().merge(kprop.getAuthor());
325                         getKnowledgeElementTypeDAO().merge(kprop.getType());
326                         // Create a transient knowledge element related to the given scenario.
327                         kelm = new KnowledgeElement(kprop.setOwnerScenario(aScenario));
328                         // Save the new knowledge in the database.
329                         getKnowledgeElementDAO().create(kelm);
330                         // Update scenario transient data.
331                         if (kelm.getType().equals("usecase")) {
332                                 aScenarioDTO.setUcase(kelm);
333                         } else if (aScenarioDTO.getKnowledgeElementsList() != null) { // If null, knowl will be initialized when needed
334                                 aScenarioDTO.getKnowledgeElementsList().add(kelm);
335                         }
336
337                         // Load the workflow for the parent study to take into account
338                         // all study actors durng reindexing.
339                         getStudyService().loadWorkflow(aScenario.getOwnerStudy());
340
341                         // Update the lucene index of knowledge elements.
342                         getIndexService().add(kelm);
343                         if (LOG.isDebugEnabled()) {
344                                 LOG.debug("A knowledge element #" + kelm.getIndex()
345                                                 + " is added to the scenario #" + aScenario.getIndex());
346                         }
347                 } catch (IOException error) {
348                         LOG.error("Unable to index the knowedge element '"
349                                         + kelm.getIndex() + "', reason:", error);
350                         kelm = null;
351                 }
352
353                 return kelm;
354         }
355
356         /**
357          * Update the scenario in the database.
358          * 
359          * @param aScenario
360          *            the scenario to update
361          * @return true if updating succeeded
362          */
363         @Transactional
364         private boolean update(final Scenario aScenario) {
365                 boolean isOk = false;
366                 try {
367                         getScenarioDAO().update(aScenario); // Update of relational base
368                         isOk = true;
369                 } catch (Exception error) {
370                         LOG.error("Unable to re-index the knowledge element '"
371                                         + aScenario.getIndex() + "', reason:", error);
372                 }
373                 return isOk;
374         }
375
376         /**
377          * {@inheritDoc}
378          * 
379          * @see org.splat.service.ScenarioService#checkin(long, long, java.util.List)
380          */
381         @Transactional
382         public void checkin(final long scenId, final long userId,
383                         final List<StepDTO> scInfo) throws InvalidPropertyException,
384                         MissedPropertyException, MultiplyDefinedException,
385                         MismatchException, IOException, NotApplicableException {
386                 // Get the scenario from the database by id
387                 Scenario aScenario = getScenarioDAO().get(scenId);
388                 // Get the user who perform this check-in operation
389                 User aUser = getUserService().selectUser(userId);
390                 // Get activities of the scenario
391                 Step[] steps = getProjectElementService().getSteps(aScenario);
392                 // Find result document types
393                 List<DocumentType> resTypes = getDocumentTypeService()
394                                 .selectResultTypes();
395
396                 // For each processed existing document keep its new version
397                 Map<Document, Document> newVersion = new HashMap<Document, Document>();
398                 // Keep newly created documents to create uses relations to results of a previous step.
399                 List<Publication> newVers = new ArrayList<Publication>();
400                 List<Publication> newDocs = new ArrayList<Publication>();
401                 // For each step DTO
402                 DocumentType resType;
403                 java.io.File updir;
404                 Document.Properties dprop = new Document.Properties();
405                 Date aDate = new Date();
406                 for (StepDTO stepDTO : scInfo) {
407                         if (LOG.isDebugEnabled()) {
408                                 LOG.debug("Checkin the step:\n" + stepDTO);
409                         }
410                         // Find a result document type of the step
411                         int i = 0;
412                         resType = null;
413                         do {
414                                 if (resTypes.get(i).isResultOf(
415                                                 getProjectSettings().getStep(stepDTO.getNumber()))) {
416                                         resType = resTypes.get(i);
417                                 }
418                                 i++;
419                         } while ((resType == null) && (i < resTypes.size()));
420
421                         // Find the appropriate scenario step
422                         Step step = findStep(stepDTO, steps);
423
424                         // Process documents of the step
425                         for (DocumentDTO doc : stepDTO.getDocs()) {
426                                 if (doc.getFiles().size() > 0) {
427                                         // NOTE: Process only the first attached file for each document
428                                         FileDTO file = doc.getFiles().get(0);
429
430                                         // Get document title as the file name
431                                         java.io.File upfile = new java.io.File(file.getPath());
432                                         String fileFormat = upfile.getName().substring(
433                                                         upfile.getName().lastIndexOf('.') + 1);
434                                         String docname = upfile.getName().substring(0,
435                                                         upfile.getName().lastIndexOf('.'));
436
437                                         // Create a new document or a new version of the document
438                                         dprop.clear();
439                                         dprop.setAuthor(aUser).setDate(aDate);
440                                         Publication pub, newPub;
441
442                                         if (doc.getId() > 0) {
443                                                 // If the document already exists then create a new version of it
444                                                 // Find the document publication
445                                                 pub = step.getDocument(doc.getId());
446                                                 if (pub == null) {
447                                                         throw new InvalidPropertyException(
448                                                                         MessageKeyEnum.SCN_000002.toString(), doc
449                                                                                         .getId());
450                                                 }
451                                                 if (pub.value() == null) {
452                                                         throw new MismatchException(
453                                                                         MessageKeyEnum.SCN_000002.toString(), doc
454                                                                                         .getId());
455                                                 }
456                                                 newPub = getStepService().versionDocument(step, pub,
457                                                                 dprop);
458                                                 // Remeber the link from the old document to the new document version
459                                                 newVersion.put(pub.value(), newPub.value());
460                                                 // Remember the new version publication
461                                                 newVers.add(newPub);
462                                         } else {
463
464                                                 // Otherwise create a new document of the result type
465                                                 // If result type is not found try to get type by file extension
466                                                 if (resType == null) {
467                                                         dprop.setType(getProjectSettings()
468                                                                         .getDefaultDocumentType(step.getStep(),
469                                                                                         fileFormat));
470                                                 } else {
471                                                         dprop.setType(resType);
472                                                 }
473                                                 dprop.setDescription("Checked in").setName(docname)
474                                                                 .setFormat(fileFormat);
475                                                 newPub = getStepService().createDocument(step, dprop);
476
477                                                 // Remeber the new document
478                                                 newDocs.add(newPub);
479                                         }
480
481                                         // Attach the file to the created document
482                                         updir = newPub.getSourceFile().asFile();
483                                         if (LOG.isDebugEnabled()) {
484                                                 LOG.debug("Moving \"" + upfile.getName() + "\" to \""
485                                                                 + updir.getPath() + "\".");
486                                         }
487                                         if (updir.exists()) {
488                                                 if (updir.delete()) {
489                                                         LOG.info(MessageKeyEnum.SCN_000003.toString(),
490                                                                         updir.getAbsoluteFile(), scenId);
491                                                 } else {
492                                                         throw new IOException(
493                                                                         "Can't delete the existing destination file to move file from "
494                                                                                         + file.getPath() + " to "
495                                                                                         + updir.getAbsolutePath());
496                                                 }
497                                         }
498                                         if (upfile.renameTo(updir)) {
499                                                 // Save the new publication in the scenario.
500                                                 // The old publication is removed from the scenario here.
501                                                 getPublicationService().saveAs(newPub,
502                                                                 ProgressState.inWORK); // May throw FileNotFound if rename was not done
503                                         } else {
504                                                 throw new IOException("Can't move file from "
505                                                                 + file.getPath() + " to "
506                                                                 + updir.getAbsolutePath());
507                                         }
508                                 }
509                         }
510                 }
511
512                 // Set uses/used relations
513
514                 // For each new version copy uses relations from the previous version.
515                 for (Publication newVer : newVers) {
516                         // For each Uses relation of the previous version
517                         Document prevDoc = newVer.value().getPreviousVersion();// prevVersion.get(newVer);
518                         if (LOG.isDebugEnabled()) {
519                                 LOG.debug("Previous version for publication #"
520                                                 + newVer.getIndex() + " is found: " + prevDoc);
521                         }
522                         List<Relation> usesRelations = prevDoc
523                                         .getRelations(UsesRelation.class);
524                         for (Relation rel : usesRelations) {
525                                 // If used document has been also versioned then refer to its new version.
526                                 Document usedDoc = ((UsesRelation) rel).getTo();
527                                 if (newVersion.containsKey(usedDoc)) {
528                                         usedDoc = newVersion.get(usedDoc);
529                                 }
530                                 // Build the appropriate relation for the new version.
531                                 newVer.addDependency(usedDoc);
532                         }
533                         // TODO: Outdate documents which depend from the previous version and were not checked in during this operation.
534
535                 }
536
537                 // For each new document create uses relation to the last versions of
538                 // results of the previous step.
539                 for (Publication newDoc : newDocs) {
540                         // Find used document type according to the configuration.
541                         // Find documents of used type in the previous study step.
542
543                         // Create uses relation from the new document
544                         // to the found document in the previous step.
545                         // newDoc.addDependency(to);
546                 }
547
548                 // Mark the scenario as checked in
549                 checkin(aScenario);
550         }
551
552         /**
553          * Find appropriate step in the array of scenario steps according to the given step DTO.
554          * 
555          * @param stepDTO
556          *            the stepDTO
557          * @param steps
558          *            scenario steps
559          * @return appropriate scenario step
560          * @throws InvalidPropertyException
561          *             if appropriate step is not found
562          */
563         private Step findStep(final StepDTO stepDTO, final Step[] steps)
564                         throws InvalidPropertyException {
565                 int i = 0;
566                 Step step = null;
567                 do {
568                         if (steps[i].getNumber() == stepDTO.getNumber()) {
569                                 step = steps[i];
570                         }
571                         i++;
572                 } while ((step == null) && (i < steps.length));
573
574                 if (step == null) {
575                         throw new InvalidPropertyException(MessageKeyEnum.SCN_000001
576                                         .toString(), stepDTO.getNumber());
577                 }
578                 return step;
579         }
580
581         /**
582          * {@inheritDoc}
583          * 
584          * @see org.splat.service.ScenarioService#checkin(org.splat.dal.bo.som.Scenario)
585          */
586         public void checkin(final Scenario aScenario) {
587                 aScenario.setUser(null);
588                 aScenario.setLastModificationDate(Calendar.getInstance().getTime());
589                 getScenarioDAO().update(aScenario);
590         }
591
592         /**
593          * {@inheritDoc}
594          * 
595          * @see org.splat.service.ScenarioService#checkout(org.splat.dal.bo.som.Scenario, org.splat.dal.bo.kernel.User)
596          */
597         public boolean checkout(final Scenario aScenario, final User user) {
598                 boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
599                                 user);
600                 if (res) {
601                         aScenario.setUser(user);
602                         aScenario.setLastModificationDate(Calendar.getInstance().getTime());
603                         getScenarioDAO().update(aScenario);
604                 }
605                 return res;
606         }
607
608         /**
609          * {@inheritDoc}
610          * 
611          * @see org.splat.service.ScenarioService#copyContentsUpTo(org.splat.dal.bo.som.Scenario, org.splat.som.Step)
612          */
613         public void copyContentsUpTo(final Scenario scenario, final Step lastep) {
614                 Scenario base = (Scenario) lastep.getOwner();
615                 Step[] from = getProjectElementService().getSteps(base);
616                 Step[] to = getProjectElementService().getSteps(scenario);
617                 for (int i = 0; i < from.length; i++) {
618                         Step step = from[i];
619                         if (step.getNumber() > lastep.getNumber()) {
620                                 break;
621                         }
622
623                         List<Publication> docs = step.getAllDocuments();
624                         for (Iterator<Publication> j = docs.iterator(); j.hasNext();) {
625                                 Publication doc = getPublicationService().copy(j.next(),
626                                                 scenario); // Creation of a new reference to the document
627                                 // Database.getSession().save(doc); Publications MUST be saved later through cascading when saving the scenario
628                                 getStepService().add(to[i], doc);
629                         }
630                         List<SimulationContext> ctex = step.getAllSimulationContexts();
631                         for (Iterator<SimulationContext> j = ctex.iterator(); j.hasNext();) {
632                                 getStepService().addSimulationContext(to[i], j.next());
633                         }
634                 }
635         }
636
637         /**
638          * {@inheritDoc}
639          * 
640          * @see org.splat.service.ScenarioService#isEmpty(org.splat.dal.bo.som.Scenario)
641          */
642         public boolean isEmpty(final Scenario scenario) {
643                 Step[] mystep = getProjectElementService().getSteps(scenario);
644                 boolean isEmp = true;
645                 for (int i = 0; i < mystep.length; i++) {
646                         if (mystep[i].isStarted()) {
647                                 isEmp = false;
648                                 break;
649                         }
650                 }
651                 return isEmp;
652         }
653
654         /**
655          * @param scenario
656          * @return
657          */
658         public boolean isFinished(final Scenario scenario) {
659                 Step[] mystep = getProjectElementService().getSteps(scenario);
660                 boolean notempty = false; // If this is empty, this is not finished
661                 for (int i = 0; i < mystep.length; i++) {
662                         if (!mystep[i].isStarted()) {
663                                 continue;
664                         }
665                         if (!mystep[i].isFinished()) {
666                                 return false;
667                         }
668                         notempty = true;
669                 }
670                 return notempty;
671         }
672
673         /**
674          * {@inheritDoc}
675          * 
676          * @see org.splat.service.StudyService#addScenario(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Scenario.Properties)
677          */
678         @Transactional
679         public Scenario addScenario(final Study aStudy,
680                         final Scenario.Properties sprop) throws MissedPropertyException,
681                         InvalidPropertyException, MultiplyDefinedException {
682                 if (sprop.getManager() == null) {
683                         sprop.setManager(aStudy.getAuthor());
684                 }
685
686                 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
687                 if (sprop.getBaseStep() != null) {
688                         copyContentsUpTo(scenario, sprop.getBaseStep());
689                 }
690                 Scenario previous = sprop.getInsertAfter();
691
692                 if (previous == null) {
693                         aStudy.getScenariiList().add(scenario);
694                 } else {
695                         aStudy.getScenariiList().add(
696                                         aStudy.getScenariiList().indexOf(previous) + 1, scenario);
697                 }
698                 getStudyDAO().update(aStudy); // No need to update the Lucene index
699                 getScenarioDAO().create(scenario); // Must be done after updating this study because of the back reference to the study
700                 if (sprop.getBaseStep() != null) {
701                         // No need to update the Knowledge Element index as Knowledge Elements are not copied
702                         getProjectElementService().refresh(scenario); // Because saving the scenario changes the hashcode of copied Publications
703                 }
704                 KnowledgeElementType ucase = getKnowledgeElementTypeService()
705                                 .selectType("usecase");
706                 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
707                 User admin = getUserService().selectUser(1); // First user created when creating the database
708                 kprop.setType(ucase).setTitle(aStudy.getTitle()).setValue(
709                                 scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
710                 // knowledges
711                 addKnowledgeElement(scenario, kprop);
712                 return scenario;
713         }
714
715         /**
716          * Remove a knowledge element from a scenario.
717          * 
718          * @param scenario
719          *            the scenario
720          * @param kelm
721          *            the knowledge element to remove
722          * @return true if removal succeeded
723          */
724         public boolean removeKnowledgeElement(final Scenario scenario,
725                         final KnowledgeElement kelm) {
726                 KnowledgeElement torem = scenario.getKnowledgeElement(kelm.getIndex());
727                 if (torem == null) {
728                         return false;
729                 }
730                 boolean done = scenario.getKnowledgeElements().remove(torem);
731                 if (done) {
732                         // Update of my transient data
733                         // RKV: These transient data are not used indeed.
734                         // RKV: List<KnowledgeElement> kelms = scenario.getKnowledgeByType().get(
735                         // RKV: kelm.getType().getIndex());
736                         // RKV: kelms.remove(torem);
737                         if (scenario.getKnowledgeElementsList() != null) {
738                                 scenario.getKnowledgeElementsList().remove(torem);
739                         }
740                         getScenarioDAO().update(scenario);
741                         // TODO: If the owner study is not private, remove the knowledge from the Lucene index
742                         return true;
743                 } else {
744                         return false;
745                 }
746         }
747
748         /**
749          * Get the knowledgeElementDAO.
750          * 
751          * @return the knowledgeElementDAO
752          */
753         public KnowledgeElementDAO getKnowledgeElementDAO() {
754                 return _knowledgeElementDAO;
755         }
756
757         /**
758          * Set the knowledgeElementDAO.
759          * 
760          * @param knowledgeElementDAO
761          *            the knowledgeElementDAO to set
762          */
763         public void setKnowledgeElementDAO(
764                         final KnowledgeElementDAO knowledgeElementDAO) {
765                 _knowledgeElementDAO = knowledgeElementDAO;
766         }
767
768         /**
769          * Get the indexService.
770          * 
771          * @return the indexService
772          */
773         public IndexService getIndexService() {
774                 return _indexService;
775         }
776
777         /**
778          * Set the indexService.
779          * 
780          * @param indexService
781          *            the indexService to set
782          */
783         public void setIndexService(final IndexService indexService) {
784                 _indexService = indexService;
785         }
786
787         /**
788          * Get the scenarioDAO.
789          * 
790          * @return the scenarioDAO
791          */
792         public ScenarioDAO getScenarioDAO() {
793                 return _scenarioDAO;
794         }
795
796         /**
797          * Set the scenarioDAO.
798          * 
799          * @param scenarioDAO
800          *            the scenarioDAO to set
801          */
802         public void setScenarioDAO(final ScenarioDAO scenarioDAO) {
803                 _scenarioDAO = scenarioDAO;
804         }
805
806         /**
807          * Get the studyDAO.
808          * 
809          * @return the studyDAO
810          */
811         public StudyDAO getStudyDAO() {
812                 return _studyDAO;
813         }
814
815         /**
816          * Set the studyDAO.
817          * 
818          * @param studyDAO
819          *            the studyDAO to set
820          */
821         public void setStudyDAO(final StudyDAO studyDAO) {
822                 _studyDAO = studyDAO;
823         }
824
825         /**
826          * Get the knowledgeElementTypeService.
827          * 
828          * @return the knowledgeElementTypeService
829          */
830         public KnowledgeElementTypeService getKnowledgeElementTypeService() {
831                 return _knowledgeElementTypeService;
832         }
833
834         /**
835          * Set the knowledgeElementTypeService.
836          * 
837          * @param knowledgeElementTypeService
838          *            the knowledgeElementTypeService to set
839          */
840         public void setKnowledgeElementTypeService(
841                         final KnowledgeElementTypeService knowledgeElementTypeService) {
842                 _knowledgeElementTypeService = knowledgeElementTypeService;
843         }
844
845         /**
846          * Get the studyService.
847          * 
848          * @return the studyService
849          */
850         public StudyService getStudyService() {
851                 return _studyService;
852         }
853
854         /**
855          * Set the studyService.
856          * 
857          * @param studyService
858          *            the studyService to set
859          */
860         public void setStudyService(final StudyService studyService) {
861                 _studyService = studyService;
862         }
863
864         /**
865          * Get the userService.
866          * 
867          * @return the userService
868          */
869         public UserService getUserService() {
870                 return _userService;
871         }
872
873         /**
874          * Set the userService.
875          * 
876          * @param userService
877          *            the userService to set
878          */
879         public void setUserService(final UserService userService) {
880                 _userService = userService;
881         }
882
883         /**
884          * Get the userDAO.
885          * 
886          * @return the userDAO
887          */
888         public UserDAO getUserDAO() {
889                 return _userDAO;
890         }
891
892         /**
893          * Set the userDAO.
894          * 
895          * @param userDAO
896          *            the userDAO to set
897          */
898         public void setUserDAO(final UserDAO userDAO) {
899                 _userDAO = userDAO;
900         }
901
902         /**
903          * Get the knowledgeElementTypeDAO.
904          * 
905          * @return the knowledgeElementTypeDAO
906          */
907         public KnowledgeElementTypeDAO getKnowledgeElementTypeDAO() {
908                 return _knowledgeElementTypeDAO;
909         }
910
911         /**
912          * Set the knowledgeElementTypeDAO.
913          * 
914          * @param knowledgeElementTypeDAO
915          *            the knowledgeElementTypeDAO to set
916          */
917         public void setKnowledgeElementTypeDAO(
918                         final KnowledgeElementTypeDAO knowledgeElementTypeDAO) {
919                 _knowledgeElementTypeDAO = knowledgeElementTypeDAO;
920         }
921
922         /**
923          * Get the simulationContextService.
924          * 
925          * @return the simulationContextService
926          */
927         public SimulationContextService getSimulationContextService() {
928                 return _simulationContextService;
929         }
930
931         /**
932          * Set the simulationContextService.
933          * 
934          * @param simulationContextService
935          *            the simulationContextService to set
936          */
937         public void setSimulationContextService(
938                         final SimulationContextService simulationContextService) {
939                 _simulationContextService = simulationContextService;
940         }
941
942         /**
943          * Get project settings.
944          * 
945          * @return Project settings service
946          */
947         private ProjectSettingsService getProjectSettings() {
948                 return _projectSettings;
949         }
950
951         /**
952          * Set project settings service.
953          * 
954          * @param projectSettingsService
955          *            project settings service
956          */
957         public void setProjectSettings(
958                         final ProjectSettingsService projectSettingsService) {
959                 _projectSettings = projectSettingsService;
960         }
961
962         /**
963          * Get the documentTypeService.
964          * 
965          * @return the documentTypeService
966          */
967         public DocumentTypeService getDocumentTypeService() {
968                 return _documentTypeService;
969         }
970
971         /**
972          * Set the documentTypeService.
973          * 
974          * @param documentTypeService
975          *            the documentTypeService to set
976          */
977         public void setDocumentTypeService(
978                         final DocumentTypeService documentTypeService) {
979                 _documentTypeService = documentTypeService;
980         }
981
982 }