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