Salome HOME
checkin method is added to ScenarioService.
[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.Iterator;
16 import java.util.List;
17
18 import org.apache.log4j.Logger;
19 import org.splat.dal.bo.kernel.Relation;
20 import org.splat.dal.bo.kernel.User;
21 import org.splat.dal.bo.som.ConvertsRelation;
22 import org.splat.dal.bo.som.File;
23 import org.splat.dal.bo.som.KnowledgeElement;
24 import org.splat.dal.bo.som.KnowledgeElementType;
25 import org.splat.dal.bo.som.Publication;
26 import org.splat.dal.bo.som.Scenario;
27 import org.splat.dal.bo.som.SimulationContext;
28 import org.splat.dal.bo.som.Study;
29 import org.splat.dal.dao.kernel.UserDAO;
30 import org.splat.dal.dao.som.KnowledgeElementDAO;
31 import org.splat.dal.dao.som.KnowledgeElementTypeDAO;
32 import org.splat.dal.dao.som.ScenarioDAO;
33 import org.splat.dal.dao.som.StudyDAO;
34 import org.splat.kernel.InvalidPropertyException;
35 import org.splat.kernel.MissedPropertyException;
36 import org.splat.kernel.MultiplyDefinedException;
37 import org.splat.service.dto.DocumentDTO;
38 import org.splat.service.dto.StepDTO;
39 import org.splat.service.technical.IndexService;
40 import org.splat.service.technical.ProjectSettingsService;
41 import org.splat.som.Step;
42 import org.splat.util.BeanHelper;
43 import org.springframework.transaction.annotation.Transactional;
44
45 /**
46  * Scenario service implementation.
47  * 
48  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
49  */
50 public class ScenarioServiceImpl implements ScenarioService {
51
52         /**
53          * Logger for this class.
54          */
55         protected final static Logger LOG = Logger
56                         .getLogger(ScenarioServiceImpl.class);
57
58         /**
59          * Injected index service.
60          */
61         private IndexService _indexService;
62         /**
63          * Injected step service.
64          */
65         private StepService _stepService;
66         /**
67          * Injected study service.
68          */
69         private StudyService _studyService;
70         /**
71          * Injected publication service.
72          */
73         private PublicationService _publicationService;
74         /**
75          * Injected project element service.
76          */
77         private ProjectElementService _projectElementService;
78         /**
79          * Injected knowledge element DAO.
80          */
81         private KnowledgeElementDAO _knowledgeElementDAO;
82         /**
83          * Injected scenario DAO.
84          */
85         private ScenarioDAO _scenarioDAO;
86
87         /**
88          * Injected study DAO.
89          */
90         private StudyDAO _studyDAO;
91
92         /**
93          * Injected knowledge element service.
94          */
95         private KnowledgeElementTypeService _knowledgeElementTypeService;
96
97         /**
98          * Injected user service.
99          */
100         private UserService _userService;
101
102         /**
103          * Injected user DAO.
104          */
105         private UserDAO _userDAO;
106
107         /**
108          * Injected knowledge element type DAO.
109          */
110         private KnowledgeElementTypeDAO _knowledgeElementTypeDAO;
111
112         /**
113          * Injected simulation context service.
114          */
115         private SimulationContextService _simulationContextService;
116
117         /**
118          * Injected project service.
119          */
120         private ProjectSettingsService _projectSettings;
121
122         /**
123          * Get the projectElementService.
124          * 
125          * @return the projectElementService
126          */
127         public ProjectElementService getProjectElementService() {
128                 return _projectElementService;
129         }
130
131         /**
132          * Set the projectElementService.
133          * 
134          * @param projectElementService
135          *            the projectElementService to set
136          */
137         public void setProjectElementService(
138                         final ProjectElementService projectElementService) {
139                 _projectElementService = projectElementService;
140         }
141
142         /**
143          * Get the publicationService.
144          * 
145          * @return the publicationService
146          */
147         public PublicationService getPublicationService() {
148                 return _publicationService;
149         }
150
151         /**
152          * Set the publicationService.
153          * 
154          * @param publicationService
155          *            the publicationService to set
156          */
157         public void setPublicationService(
158                         final PublicationService publicationService) {
159                 _publicationService = publicationService;
160         }
161
162         /**
163          * Get the stepService.
164          * 
165          * @return the stepService
166          */
167         public StepService getStepService() {
168                 return _stepService;
169         }
170
171         /**
172          * Set the stepService.
173          * 
174          * @param stepService
175          *            the stepService to set
176          */
177         public void setStepService(final StepService stepService) {
178                 _stepService = stepService;
179         }
180
181         /**
182          * {@inheritDoc}
183          * 
184          * @see org.splat.service.ScenarioService#getScenarioInfo(long)
185          */
186         @Transactional
187         public List<StepDTO> getScenarioInfo(final long scenarioId) {
188                 List<StepDTO> res = new ArrayList<StepDTO>();
189                 // Get the scenario from the database by id
190                 Scenario scen = getScenarioDAO().get(scenarioId);
191                 if (LOG.isDebugEnabled()) {
192                         LOG.debug("Scenario[" + scenarioId + "]: Number of publications: "
193                                         + scen.getDocums().size());
194                 }
195                 // Get activities of the scenario
196                 Step[] steps = getProjectElementService().getSteps(scen);
197                 StepDTO stepDTO;
198                 DocumentDTO docDTO;
199                 String docType, fileFormat;
200                 String processing;
201                 boolean doImport;
202                 // For each activity create a step DTO and add it to the result list
203                 for (Step step : steps) {
204                         stepDTO = BeanHelper.copyBean(step.getStep(), StepDTO.class);
205                         res.add(stepDTO);
206                         if (LOG.isDebugEnabled()) {
207                                 LOG.debug("Step[" + stepDTO.getNumber()
208                                                 + "]: Number of documents: "
209                                                 + step.getDocuments().size());
210                         }
211                         // For each publication of the activity create a document DTO.
212                         // Each file is considered as a source file.
213                         for (Publication tag : step.getDocuments()) {
214                                 docDTO = stepDTO.addDoc(tag.value().getIndex(), tag.value()
215                                                 .getTitle());
216                                 char aState = tag.getIsnew();
217                                 docType = tag.value().getType().getName();
218                                 // For each file of the document create a file DTO
219                                 // Process source file of the document
220                                 fileFormat = tag.value().getFile().getFormat();
221                                 doImport = getProjectSettings().doImport(docType, fileFormat);
222                                 if (doImport && (!tag.isOutdated())) {
223                                         processing = "file-import";
224                                 } else {
225                                         processing = "file-download";
226                                 }
227                                 docDTO.addFile(tag.value().getFile().getRelativePath(), aState,
228                                                 processing, false);
229                                 // Process all exported files
230                                 for (Relation rel : tag.value().getRelations(
231                                                 ConvertsRelation.class)) {
232                                         File aFile = ((ConvertsRelation) rel).getTo();
233                                         fileFormat = aFile.getFormat();
234                                         doImport = getProjectSettings().doImport(docType,
235                                                         fileFormat);
236                                         if (doImport && (!tag.isOutdated())) {
237                                                 processing = "file-import";
238                                         } else {
239                                                 processing = "file-download";
240                                         }
241                                         docDTO.addFile(aFile.getRelativePath(), aState, processing,
242                                                         false);
243                                 }
244                         }
245                 }
246                 return res;
247         }
248
249         /**
250          * Create a new study with one scenario and "product" simulation context.
251          * 
252          * @param sprop
253          *            the study properties
254          * @param oprop
255          *            the scenario properties
256          * @param cprop
257          *            the "product" simulation context properties
258          * @return the created study
259          * @throws MissedPropertyException
260          *             if a mandatory property is missed
261          * @throws InvalidPropertyException
262          *             if a property is invalid
263          * @throws MultiplyDefinedException
264          *             if some property occurs several times
265          */
266         @Transactional
267         public Study createStudy(final Study.Properties sprop,
268                         final Scenario.Properties oprop,
269                         final SimulationContext.Properties cprop)
270                         throws MissedPropertyException, InvalidPropertyException,
271                         MultiplyDefinedException {
272                 Study study = getStudyService().createStudy(sprop);
273                 addScenario(study, oprop);
274                 if (cprop.getIndex() == 0) { // Input of new project context
275                         cprop.setType(getSimulationContextService().selectType("product"))
276                                         .setValue(cprop.getValue());
277                         getStudyService().addProjectContext(study, cprop);
278                 } else { // Selection of existing project context
279                         SimulationContext context = getSimulationContextService()
280                                         .selectSimulationContext(cprop.getIndex());
281                         getStudyService().addProjectContext(study, context);
282                 }
283                 return study;
284         }
285
286         /**
287          * {@inheritDoc}
288          * 
289          * @see org.splat.service.ScenarioService#addKnowledgeElement(org.splat.dal.bo.som.Scenario,
290          *      org.splat.dal.bo.som.KnowledgeElement.Properties)
291          */
292         @Transactional
293         public KnowledgeElement addKnowledgeElement(final Scenario aScenarioDTO,
294                         final KnowledgeElement.Properties kprop)
295                         throws MissedPropertyException, InvalidPropertyException,
296                         MultiplyDefinedException {
297                 KnowledgeElement kelm = null;
298                 try {
299                         long aScenarioId = aScenarioDTO.getIndex();
300                         if (LOG.isDebugEnabled()) {
301                                 LOG.debug("Add a knowledge element to the scenario #"
302                                                 + aScenarioId);
303                         }
304                         // Get the persistent scenario.
305                         Scenario aScenario = getScenarioDAO().get(aScenarioId);
306                         // Get persistent objects for creating a new knowledge.
307                         // TODO: Actions must use DTO instead of persistent objects.
308                         getUserDAO().merge(kprop.getAuthor());
309                         getKnowledgeElementTypeDAO().merge(kprop.getType());
310                         // Create a transient knowledge element related to the given scenario.
311                         kelm = new KnowledgeElement(kprop.setOwnerScenario(aScenario));
312                         // Save the new knowledge in the database.
313                         getKnowledgeElementDAO().create(kelm);
314                         // Update scenario transient data.
315                         if (kelm.getType().equals("usecase")) {
316                                 aScenarioDTO.setUcase(kelm);
317                         } else if (aScenarioDTO.getKnowledgeElementsList() != null) { // If null, knowl will be initialized when needed
318                                 aScenarioDTO.getKnowledgeElementsList().add(kelm);
319                         }
320
321                         // Load the workflow for the parent study to take into account
322                         // all study actors durng reindexing.
323                         getStudyService().loadWorkflow(aScenario.getOwnerStudy());
324
325                         // Update the lucene index of knowledge elements.
326                         getIndexService().add(kelm);
327                         if (LOG.isDebugEnabled()) {
328                                 LOG.debug("A knowledge element #" + kelm.getIndex()
329                                                 + " is added to the scenario #" + aScenario.getIndex());
330                         }
331                 } catch (IOException error) {
332                         LOG.error("Unable to index the knowedge element '"
333                                         + kelm.getIndex() + "', reason:", error);
334                         kelm = null;
335                 }
336
337                 return kelm;
338         }
339
340         /**
341          * Update the scenario in the database.
342          * 
343          * @param aScenario
344          *            the scenario to update
345          * @return true if updating succeeded
346          */
347         @Transactional
348         private boolean update(final Scenario aScenario) {
349                 boolean isOk = false;
350                 try {
351                         getScenarioDAO().update(aScenario); // Update of relational base
352                         isOk = true;
353                 } catch (Exception error) {
354                         LOG.error("Unable to re-index the knowledge element '"
355                                         + aScenario.getIndex() + "', reason:", error);
356                 }
357                 return isOk;
358         }
359
360         /**
361          * {@inheritDoc}
362          * 
363          * @see org.splat.service.ScenarioService#checkin(long, long, java.util.List)
364          */
365         public void checkin(final long scenId, final long userId,
366                         final List<StepDTO> scInfo) {
367
368         }
369
370         /**
371          * {@inheritDoc}
372          * 
373          * @see org.splat.service.ScenarioService#checkin(org.splat.dal.bo.som.Scenario)
374          */
375         public void checkin(final Scenario aScenario) {
376                 aScenario.setUser(null);
377                 aScenario.setLastModificationDate(Calendar.getInstance().getTime());
378                 getScenarioDAO().update(aScenario);
379         }
380
381         /**
382          * {@inheritDoc}
383          * 
384          * @see org.splat.service.ScenarioService#checkout(org.splat.dal.bo.som.Scenario, org.splat.dal.bo.kernel.User)
385          */
386         public boolean checkout(final Scenario aScenario, final User user) {
387                 boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
388                                 user);
389                 if (res) {
390                         aScenario.setUser(user);
391                         aScenario.setLastModificationDate(Calendar.getInstance().getTime());
392                         getScenarioDAO().update(aScenario);
393                 }
394                 return res;
395         }
396
397         /**
398          * {@inheritDoc}
399          * 
400          * @see org.splat.service.ScenarioService#copyContentsUpTo(org.splat.dal.bo.som.Scenario, org.splat.som.Step)
401          */
402         public void copyContentsUpTo(final Scenario scenario, final Step lastep) {
403                 Scenario base = (Scenario) lastep.getOwner();
404                 Step[] from = getProjectElementService().getSteps(base);
405                 Step[] to = getProjectElementService().getSteps(scenario);
406                 for (int i = 0; i < from.length; i++) {
407                         Step step = from[i];
408                         if (step.getNumber() > lastep.getNumber()) {
409                                 break;
410                         }
411
412                         List<Publication> docs = step.getAllDocuments();
413                         for (Iterator<Publication> j = docs.iterator(); j.hasNext();) {
414                                 Publication doc = getPublicationService().copy(j.next(),
415                                                 scenario); // Creation of a new reference to the document
416                                 // Database.getSession().save(doc); Publications MUST be saved later through cascading when saving the scenario
417                                 getStepService().add(to[i], doc);
418                         }
419                         List<SimulationContext> ctex = step.getAllSimulationContexts();
420                         for (Iterator<SimulationContext> j = ctex.iterator(); j.hasNext();) {
421                                 getStepService().addSimulationContext(to[i], j.next());
422                         }
423                 }
424         }
425
426         /**
427          * {@inheritDoc}
428          * 
429          * @see org.splat.service.ScenarioService#isEmpty(org.splat.dal.bo.som.Scenario)
430          */
431         public boolean isEmpty(final Scenario scenario) {
432                 Step[] mystep = getProjectElementService().getSteps(scenario);
433                 boolean isEmp = true;
434                 for (int i = 0; i < mystep.length; i++) {
435                         if (mystep[i].isStarted()) {
436                                 isEmp = false;
437                                 break;
438                         }
439                 }
440                 return isEmp;
441         }
442
443         /**
444          * @param scenario
445          * @return
446          */
447         public boolean isFinished(final Scenario scenario) {
448                 Step[] mystep = getProjectElementService().getSteps(scenario);
449                 boolean notempty = false; // If this is empty, this is not finished
450                 for (int i = 0; i < mystep.length; i++) {
451                         if (!mystep[i].isStarted()) {
452                                 continue;
453                         }
454                         if (!mystep[i].isFinished()) {
455                                 return false;
456                         }
457                         notempty = true;
458                 }
459                 return notempty;
460         }
461
462         /**
463          * {@inheritDoc}
464          * 
465          * @see org.splat.service.StudyService#addScenario(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Scenario.Properties)
466          */
467         @Transactional
468         public Scenario addScenario(final Study aStudy,
469                         final Scenario.Properties sprop) throws MissedPropertyException,
470                         InvalidPropertyException, MultiplyDefinedException {
471                 if (sprop.getManager() == null) {
472                         sprop.setManager(aStudy.getAuthor());
473                 }
474
475                 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
476                 if (sprop.getBaseStep() != null) {
477                         copyContentsUpTo(scenario, sprop.getBaseStep());
478                 }
479                 Scenario previous = sprop.getInsertAfter();
480
481                 if (previous == null) {
482                         aStudy.getScenariiList().add(scenario);
483                 } else {
484                         aStudy.getScenariiList().add(
485                                         aStudy.getScenariiList().indexOf(previous) + 1, scenario);
486                 }
487                 getStudyDAO().update(aStudy); // No need to update the Lucene index
488                 getScenarioDAO().create(scenario); // Must be done after updating this study because of the back reference to the study
489                 if (sprop.getBaseStep() != null) {
490                         // No need to update the Knowledge Element index as Knowledge Elements are not copied
491                         getProjectElementService().refresh(scenario); // Because saving the scenario changes the hashcode of copied Publications
492                 }
493                 KnowledgeElementType ucase = getKnowledgeElementTypeService()
494                                 .selectType("usecase");
495                 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
496                 User admin = getUserService().selectUser(1); // First user created when creating the database
497                 kprop.setType(ucase).setTitle(aStudy.getTitle()).setValue(
498                                 scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
499                 // knowledges
500                 addKnowledgeElement(scenario, kprop);
501                 return scenario;
502         }
503
504         /**
505          * Remove a knowledge element from a scenario.
506          * 
507          * @param scenario
508          *            the scenario
509          * @param kelm
510          *            the knowledge element to remove
511          * @return true if removal succeeded
512          */
513         public boolean removeKnowledgeElement(final Scenario scenario,
514                         final KnowledgeElement kelm) {
515                 KnowledgeElement torem = scenario.getKnowledgeElement(kelm.getIndex());
516                 if (torem == null) {
517                         return false;
518                 }
519                 boolean done = scenario.getKnowledgeElements().remove(torem);
520                 if (done) {
521                         // Update of my transient data
522                         // RKV: These transient data are not used indeed.
523                         // RKV: List<KnowledgeElement> kelms = scenario.getKnowledgeByType().get(
524                         // RKV: kelm.getType().getIndex());
525                         // RKV: kelms.remove(torem);
526                         if (scenario.getKnowledgeElementsList() != null) {
527                                 scenario.getKnowledgeElementsList().remove(torem);
528                         }
529                         getScenarioDAO().update(scenario);
530                         // TODO: If the owner study is not private, remove the knowledge from the Lucene index
531                         return true;
532                 } else {
533                         return false;
534                 }
535         }
536
537         /**
538          * Get the knowledgeElementDAO.
539          * 
540          * @return the knowledgeElementDAO
541          */
542         public KnowledgeElementDAO getKnowledgeElementDAO() {
543                 return _knowledgeElementDAO;
544         }
545
546         /**
547          * Set the knowledgeElementDAO.
548          * 
549          * @param knowledgeElementDAO
550          *            the knowledgeElementDAO to set
551          */
552         public void setKnowledgeElementDAO(
553                         final KnowledgeElementDAO knowledgeElementDAO) {
554                 _knowledgeElementDAO = knowledgeElementDAO;
555         }
556
557         /**
558          * Get the indexService.
559          * 
560          * @return the indexService
561          */
562         public IndexService getIndexService() {
563                 return _indexService;
564         }
565
566         /**
567          * Set the indexService.
568          * 
569          * @param indexService
570          *            the indexService to set
571          */
572         public void setIndexService(final IndexService indexService) {
573                 _indexService = indexService;
574         }
575
576         /**
577          * Get the scenarioDAO.
578          * 
579          * @return the scenarioDAO
580          */
581         public ScenarioDAO getScenarioDAO() {
582                 return _scenarioDAO;
583         }
584
585         /**
586          * Set the scenarioDAO.
587          * 
588          * @param scenarioDAO
589          *            the scenarioDAO to set
590          */
591         public void setScenarioDAO(final ScenarioDAO scenarioDAO) {
592                 _scenarioDAO = scenarioDAO;
593         }
594
595         /**
596          * Get the studyDAO.
597          * 
598          * @return the studyDAO
599          */
600         public StudyDAO getStudyDAO() {
601                 return _studyDAO;
602         }
603
604         /**
605          * Set the studyDAO.
606          * 
607          * @param studyDAO
608          *            the studyDAO to set
609          */
610         public void setStudyDAO(final StudyDAO studyDAO) {
611                 _studyDAO = studyDAO;
612         }
613
614         /**
615          * Get the knowledgeElementTypeService.
616          * 
617          * @return the knowledgeElementTypeService
618          */
619         public KnowledgeElementTypeService getKnowledgeElementTypeService() {
620                 return _knowledgeElementTypeService;
621         }
622
623         /**
624          * Set the knowledgeElementTypeService.
625          * 
626          * @param knowledgeElementTypeService
627          *            the knowledgeElementTypeService to set
628          */
629         public void setKnowledgeElementTypeService(
630                         final KnowledgeElementTypeService knowledgeElementTypeService) {
631                 _knowledgeElementTypeService = knowledgeElementTypeService;
632         }
633
634         /**
635          * Get the studyService.
636          * 
637          * @return the studyService
638          */
639         public StudyService getStudyService() {
640                 return _studyService;
641         }
642
643         /**
644          * Set the studyService.
645          * 
646          * @param studyService
647          *            the studyService to set
648          */
649         public void setStudyService(final StudyService studyService) {
650                 _studyService = studyService;
651         }
652
653         /**
654          * Get the userService.
655          * 
656          * @return the userService
657          */
658         public UserService getUserService() {
659                 return _userService;
660         }
661
662         /**
663          * Set the userService.
664          * 
665          * @param userService
666          *            the userService to set
667          */
668         public void setUserService(final UserService userService) {
669                 _userService = userService;
670         }
671
672         /**
673          * Get the userDAO.
674          * 
675          * @return the userDAO
676          */
677         public UserDAO getUserDAO() {
678                 return _userDAO;
679         }
680
681         /**
682          * Set the userDAO.
683          * 
684          * @param userDAO
685          *            the userDAO to set
686          */
687         public void setUserDAO(final UserDAO userDAO) {
688                 _userDAO = userDAO;
689         }
690
691         /**
692          * Get the knowledgeElementTypeDAO.
693          * 
694          * @return the knowledgeElementTypeDAO
695          */
696         public KnowledgeElementTypeDAO getKnowledgeElementTypeDAO() {
697                 return _knowledgeElementTypeDAO;
698         }
699
700         /**
701          * Set the knowledgeElementTypeDAO.
702          * 
703          * @param knowledgeElementTypeDAO
704          *            the knowledgeElementTypeDAO to set
705          */
706         public void setKnowledgeElementTypeDAO(
707                         final KnowledgeElementTypeDAO knowledgeElementTypeDAO) {
708                 _knowledgeElementTypeDAO = knowledgeElementTypeDAO;
709         }
710
711         /**
712          * Get the simulationContextService.
713          * 
714          * @return the simulationContextService
715          */
716         public SimulationContextService getSimulationContextService() {
717                 return _simulationContextService;
718         }
719
720         /**
721          * Set the simulationContextService.
722          * 
723          * @param simulationContextService
724          *            the simulationContextService to set
725          */
726         public void setSimulationContextService(
727                         final SimulationContextService simulationContextService) {
728                 _simulationContextService = simulationContextService;
729         }
730
731         /**
732          * Get project settings.
733          * 
734          * @return Project settings service
735          */
736         private ProjectSettingsService getProjectSettings() {
737                 return _projectSettings;
738         }
739
740         /**
741          * Set project settings service.
742          * 
743          * @param projectSettingsService
744          *            project settings service
745          */
746         public void setProjectSettings(
747                         final ProjectSettingsService projectSettingsService) {
748                 _projectSettings = projectSettingsService;
749         }
750
751 }