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