Salome HOME
4aae91f4cee24acfae520f79c0d1e411820784c6
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / StepServiceImpl.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.Iterator;
15 import java.util.List;
16 import java.util.Set;
17
18 import org.splat.dal.bo.kernel.Relation;
19 import org.splat.dal.bo.som.ConvertsRelation;
20 import org.splat.dal.bo.som.Document;
21 import org.splat.dal.bo.som.DocumentType;
22 import org.splat.dal.bo.som.File;
23 import org.splat.dal.bo.som.KnowledgeElement;
24 import org.splat.dal.bo.som.ProjectElement;
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.UsedByRelation;
29 import org.splat.dal.bo.som.UsesRelation;
30 import org.splat.dal.bo.som.VersionsRelation;
31 import org.splat.dal.dao.som.DocumentDAO;
32 import org.splat.dal.dao.som.FileDAO;
33 import org.splat.dal.dao.som.ProjectElementDAO;
34 import org.splat.dal.dao.som.SimulationContextDAO;
35 import org.splat.dal.dao.som.VersionsRelationDAO;
36 import org.splat.kernel.InvalidPropertyException;
37 import org.splat.kernel.MismatchException;
38 import org.splat.kernel.MissedPropertyException;
39 import org.splat.kernel.MultiplyDefinedException;
40 import org.splat.kernel.NotApplicableException;
41 import org.splat.log.AppLogger;
42 import org.splat.service.technical.IndexService;
43 import org.splat.service.technical.ProjectSettingsService;
44 import org.splat.som.Revision;
45 import org.splat.som.Step;
46 import org.springframework.transaction.annotation.Transactional;
47
48 /**
49  * Step service implementation.
50  * 
51  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
52  */
53 public class StepServiceImpl implements StepService {
54
55         /**
56          * logger for the service.
57          */
58         public final static AppLogger LOG = AppLogger
59                         .getLogger(StepServiceImpl.class);
60         /**
61          * Injected index service.
62          */
63         private IndexService _indexService;
64         /**
65          * Injected document service.
66          */
67         private DocumentService _documentService;
68         /**
69          * Injected document type service.
70          */
71         private DocumentTypeService _documentTypeService;
72         /**
73          * Injected document DAO.
74          */
75         private DocumentDAO _documentDAO;
76         /**
77          * Injected file DAO.
78          */
79         private FileDAO _fileDAO;
80         /**
81          * Injected simulation context service.
82          */
83         private SimulationContextService _simulationContextService;
84         /**
85          * Injected simulation context DAO.
86          */
87         private SimulationContextDAO _simulationContextDAO;
88         /**
89          * Injected project element DAO.
90          */
91         private ProjectElementDAO _projectElementDAO;
92         /**
93          * Injected versions relation DAO.
94          */
95         private VersionsRelationDAO _versionsRelationDAO;
96         /**
97          * Injected project service.
98          */
99         private ProjectSettingsService _projectSettings;
100
101         /**
102          * {@inheritDoc}
103          * 
104          * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext.Properties)
105          */
106         public SimulationContext addSimulationContext(final Step aStep,
107                         final SimulationContext.Properties dprop)
108                         throws MissedPropertyException, InvalidPropertyException,
109                         MultiplyDefinedException {
110                 SimulationContext context = new SimulationContext(dprop.setStep(aStep
111                                 .getStep()));
112                 return addSimulationContext(aStep, context);
113         }
114
115         /**
116          * {@inheritDoc}
117          * 
118          * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
119          */
120         @Transactional
121         public SimulationContext addSimulationContext(final Step aStep,
122                         final SimulationContext context) {
123                 SimulationContext res = null;
124                 getSimulationContextService().hold(context); // Increments the reference count of simulation context
125                 if (aStep.getOwner().isSaved()) {
126                         try {
127                                 if (!context.isSaved()) {
128                                         getSimulationContextDAO().create(context);
129                                 }
130                                 aStep.getOwner().add(context);
131                                 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
132                                 getProjectElementDAO().update(aStep.getOwner());
133                                 updateKnowledgeElementsIndex(aStep);
134                                 res = context;
135                         } catch (Exception error) {
136                                 LOG.debug(error.getMessage(), error);
137                         }
138                 } else { // Happens when copying a scenario
139                         aStep.getOwner().add(context);
140                         aStep.getContex().add(context); // The context is also referenced from this (transient) Step
141                         // In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
142                         res = context;
143                 }
144                 return res;
145         }
146
147         /**
148          * Update lucene index of knowledge elements of a scenario or a study which the given step is related to.
149          * 
150          * @param aStep
151          *            the step (activity)
152          */
153         private void updateKnowledgeElementsIndex(final Step aStep) {
154                 Scenario[] scenarii;
155                 if (aStep.getOwner() instanceof Scenario) {
156                         scenarii = new Scenario[1];
157                         scenarii[0] = (Scenario) aStep.getOwner();
158                 } else {
159                         scenarii = aStep.getOwnerStudy().getScenarii();
160                 }
161                 try {
162                         for (int i = 0; i < scenarii.length; i++) {
163                                 Scenario scene = scenarii[i];
164                                 List<KnowledgeElement> knelm = scene.getAllKnowledgeElements();
165                                 for (Iterator<KnowledgeElement> j = knelm.iterator(); j
166                                                 .hasNext();) {
167                                         KnowledgeElement kelm = j.next();
168                                         getIndexService().update(kelm);
169                                 }
170                                 updateScenarioIndex(scene);
171                         }
172                 } catch (Exception error) {
173                         LOG.error("Unable to re-index Knowledge Elements, reason:", error);
174                 }
175         }
176
177         /**
178          * Update lucene index for knowledge elements of the scenario.
179          * 
180          * @param scene
181          *            the scenario
182          * @throws IOException
183          *             if can't update lucene index
184          */
185         private void updateScenarioIndex(final Scenario scene) throws IOException {
186                 if (scene.getUcase() == null) {
187                         for (Iterator<KnowledgeElement> i = scene.getKnowledgeElements()
188                                         .iterator(); i.hasNext();) {
189                                 KnowledgeElement kelm = i.next();
190                                 if (!kelm.getType().equals("usecase")) {
191                                         continue;
192                                 }
193                                 scene.setUcase(kelm);
194                                 break;
195                         }
196                 }
197                 getIndexService().update(scene.getUcase());
198         }
199
200         /**
201          * {@inheritDoc}
202          * 
203          * @see org.splat.service.StepService#removeSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
204          */
205         @Transactional
206         public boolean removeSimulationContext(final Step aStep,
207                         final SimulationContext context) {
208                 SimulationContext torem = aStep
209                                 .getSimulationContext(context.getIndex());
210
211                 boolean isOk = (torem != null) && (aStep.getOwner().remove(torem));
212                 if (isOk) {
213
214                         aStep.getContex().remove(torem);
215                         getProjectElementDAO().update(aStep.getOwner());
216                         if (torem.isShared()) {
217                                 getSimulationContextService().release(torem);
218                                 getSimulationContextDAO().update(torem);
219                         } else {
220                                 getSimulationContextDAO().delete(torem);
221                         }
222                 }
223                 return isOk;
224         }
225
226         /**
227          * {@inheritDoc}
228          * 
229          * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
230          */
231         @Transactional
232         public Publication createDocument(final Step aStep,
233                         final Document.Properties dprop) throws MissedPropertyException,
234                         InvalidPropertyException, MultiplyDefinedException, IOException {
235                 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
236                                 .setStep(aStep.getStep()));
237                 getDocumentService().generateDocumentId(newdoc, dprop);
238
239                 // Creation of the save directory
240                 java.io.File wdir = getDocumentService().getSaveDirectory(newdoc);
241                 if ((!wdir.exists()) && (!wdir.mkdirs())) {
242                         throw new IOException(
243                                         "Cannot create the repository vault directory");
244                 }
245
246                 // Identification and save
247                 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwnerStudy());
248                 getDocumentDAO().create(newdoc);
249
250                 return new Publication(newdoc, aStep.getOwner());
251         }
252
253         /**
254          * {@inheritDoc}
255          * 
256          * @see org.splat.service.StepService#assignDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
257          */
258         public Publication assignDocument(final Step aStep,
259                         final Document.Properties dprop) throws MissedPropertyException,
260                         InvalidPropertyException, NotApplicableException {
261                 String refid = dprop.getReference();
262                 Publication res = null;
263                 if (refid != null) {
264                         Document slot = getDocumentService().selectDocument(refid,
265                                         new Revision().toString());
266                         if ((slot != null) && (slot.isUndefined())) {
267                                 getDocumentService().initialize(slot,
268                                                 dprop.setOwner(aStep.getOwnerStudy()));
269                                 res = new Publication(slot, aStep.getOwner());
270                         }
271                 }
272                 return res;
273         }
274
275         /**
276          * Create a new version of a document in the given study step.
277          * 
278          * @param aStep
279          *            the study step
280          * @param base
281          *            the base document published version
282          * @return the new version publication
283          * @throws MissedPropertyException
284          *             if a mandatory property is missed
285          * @throws InvalidPropertyException
286          *             if some property doesn't exist
287          * @throws MultiplyDefinedException
288          *             if some property is defined several times
289          * @throws IOException
290          *             if a file system error occurs
291          * @throws MismatchException
292          *             if the document is not applicable to the given study step
293          */
294         public Publication versionDocument(final Step aStep, final Publication base)
295                         throws MissedPropertyException, InvalidPropertyException,
296                         MultiplyDefinedException, IOException, MismatchException {
297                 return versionDocument(aStep, base, new Document.Properties());
298         }
299
300         /**
301          * Create a new version of a document in the given study step.
302          * 
303          * @param aStep
304          *            the study step
305          * @param base
306          *            the base document published version
307          * @param reason
308          *            the comment for the new version
309          * @return the new version publication
310          * @throws MissedPropertyException
311          *             if a mandatory property is missed
312          * @throws InvalidPropertyException
313          *             if some property doesn't exist
314          * @throws MultiplyDefinedException
315          *             if some property is defined several times
316          * @throws IOException
317          *             if a file system error occurs
318          * @throws MismatchException
319          *             if the document is not applicable to the given study step
320          */
321         public Publication versionDocument(final Step aStep,
322                         final Publication base, final String reason)
323                         throws MissedPropertyException, InvalidPropertyException,
324                         MultiplyDefinedException, IOException, MismatchException {
325                 return versionDocument(aStep, base, new Document.Properties()
326                                 .setDescription(reason));
327         }
328
329         /**
330          * Create a new version of a document in the given study step.
331          * 
332          * @param aStep
333          *            the study step
334          * @param base
335          *            the base document published version
336          * @param dprop
337          *            properties of the new version
338          * @return the new version publication
339          * @throws MissedPropertyException
340          *             if a mandatory property is missed
341          * @throws InvalidPropertyException
342          *             if some property doesn't exist
343          * @throws MultiplyDefinedException
344          *             if some property is defined several times
345          * @throws IOException
346          *             if a file system error occurs
347          * @throws MismatchException
348          *             if the document is not applicable to the given study step
349          */
350         @Transactional
351         public Publication versionDocument(final Step aStep,
352                         final Publication base, final Document.Properties dprop)
353                         throws MissedPropertyException, InvalidPropertyException,
354                         MultiplyDefinedException, IOException, MismatchException {
355                 Document previous = base.value();
356
357                 // RKV: Keep the new file format if it is related to the same document type on this step.
358                 String newFormat = dprop.getFormat();
359
360                 dprop.setDocument(previous, getProjectSettings().getStep(
361                                 base.getStep().getNumber())); // Initializes the Step property
362                 if (dprop.getStep().getNumber() != aStep.getNumber()) {
363                         throw new MismatchException();
364                 }
365
366                 if (newFormat != null
367                                 && previous.getType().equals(
368                                                 getProjectSettings().getDefaultDocumentType(
369                                                                 aStep.getStep(), newFormat))) {
370                         dprop.setFormat(newFormat);
371                 }
372                 
373                 if (dprop.getAuthor() == null) {
374                         dprop.setAuthor(previous.getAuthor());
375                 }
376                 String summary = dprop.getDescription();
377
378                 // Creation of the document
379                 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
380                                 .setStep(aStep.getStep()));
381                 getDocumentService().generateDocumentId(newdoc, dprop);
382                 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwner(),
383                                 previous);
384                 getDocumentDAO().create(newdoc);
385
386                 // Versioning
387                 VersionsRelation aRel;
388                 aRel = new VersionsRelation(newdoc, previous, summary);
389                 // getVersionsRelationDAO().create(aRel);
390                 newdoc.addRelation(aRel);
391
392                 // Update of usedby relations, if exist
393                 /*
394                  * RKV: Consider the new version as not used by old dependent documents. So these documents must be marked as outdated then. List<Relation>
395                  * relist = previous.getRelations(UsedByRelation.class); Study scope = aStep.getOwnerStudy(); for (Iterator<Relation> i =
396                  * relist.iterator(); i.hasNext();) { UsedByRelation relation = (UsedByRelation) i.next(); Document relatedoc = relation.getTo(); if
397                  * (scope.shares(relatedoc)) { relatedoc.addRelation(new UsesRelation(relatedoc, newdoc)); } else { relation.moveTo(newdoc); } }
398                  */
399                 return new Publication(newdoc, aStep.getOwner());
400         }
401
402         /**
403          * Get document types which are applicable for the given study step (activity).
404          * 
405          * @param aStep
406          *            the study step
407          * @return the list of document types
408          */
409         public List<DocumentType> getValidDocumentTypes(final Step aStep) {
410                 return getDocumentTypeService().selectTypesOf(aStep.getStep());
411         }
412
413         /**
414          * Add a document publication to the given step.
415          * 
416          * @param aStep
417          *            the target study step
418          * @param newdoc
419          *            the document publication to add
420          * @return true if publication succeeded
421          */
422         public boolean add(final Step aStep, final Publication newdoc) {
423                 boolean res = aStep.getOwner().add(newdoc); // Updates the study in memory
424                 if (res) {
425                         aStep.getDocuments().add(0, newdoc); // Updates this step
426                         getDocumentService().hold(newdoc.value()); // Increments the configuration tag count of document
427                         // If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
428                         // database (it will be saved later by cascading the update of owner scenario).
429                 }
430                 return res;
431         }
432
433         /**
434          * Remove a document publication from the given step.
435          * 
436          * @param aStep
437          *            the study step
438          * @param oldoc
439          *            the document publication to remove
440          * @return true if removing of the publication succeeded
441          */
442         public boolean remove(final Step aStep, final Publication oldoc) {
443                 boolean res = aStep.getOwner().remove(oldoc); // Updates the study in memory
444                 if (res) {
445                         aStep.getDocuments().remove(oldoc); // Updates this step
446                         ProjectElement owner = aStep.getOwner();
447                         if (owner != null) {
448                                 owner.remove(oldoc);
449                         }
450                         getDocumentService().release(oldoc.value()); // Decrements the configuration tag count of document
451                         // The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
452                 }
453                 return res;
454         }
455
456         /**
457          * Remove a document from the given step.
458          * 
459          * @param aStep
460          *            the study step
461          * @param doctag
462          *            the document publication
463          * @return true if removing of the document succeeded
464          */
465         @Transactional
466         public boolean removeDocument(final Step aStep, final Publication doctag) {
467                 Document value = doctag.value();
468                 getDocumentDAO().update(value);
469                 Publication torem = aStep.getDocument(value.getIndex());
470
471                 boolean res = (torem != null);
472                 if (res) {
473                         remove(aStep, torem);
474                         getProjectElementDAO().update(aStep.getOwner());
475                         if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
476                                 Set<Relation> links = value.getAllRelations(); // Get all relation of the document to remove them
477                                 List<Document> using = new ArrayList<Document>();
478                                 for (Iterator<Relation> i = links.iterator(); i.hasNext();) {
479                                         Relation link = i.next();
480                                         if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
481                                                 getFileDAO().delete((File) link.getTo()); // The corresponding physical file is not removed from the vault
482                                         } else if (link.getClass().equals(UsesRelation.class)) { // Document dependency
483                                                 using.add((Document) link.getTo());
484                                         }
485                                 }
486                                 for (Iterator<Document> i = using.iterator(); i.hasNext();) {
487                                         i.next().removeRelation(UsedByRelation.class, value); // TODO: RKV: don't use Database.getSession in removeRelation
488                                 }
489                                 getDocumentDAO().delete(value); // The corresponding physical file is not removed from the vault
490                         }
491                 }
492                 return res;
493         }
494
495         /**
496          * Get the documentService.
497          * 
498          * @return the documentService
499          */
500         public DocumentService getDocumentService() {
501                 return _documentService;
502         }
503
504         /**
505          * Set the documentService.
506          * 
507          * @param documentService
508          *            the documentService to set
509          */
510         public void setDocumentService(final DocumentService documentService) {
511                 _documentService = documentService;
512         }
513
514         /**
515          * Get the simulationContextService.
516          * 
517          * @return the simulationContextService
518          */
519         public SimulationContextService getSimulationContextService() {
520                 return _simulationContextService;
521         }
522
523         /**
524          * Set the simulationContextService.
525          * 
526          * @param simulationContextService
527          *            the simulationContextService to set
528          */
529         public void setSimulationContextService(
530                         final SimulationContextService simulationContextService) {
531                 _simulationContextService = simulationContextService;
532         }
533
534         /**
535          * Get the documentDAO.
536          * 
537          * @return the documentDAO
538          */
539         public DocumentDAO getDocumentDAO() {
540                 return _documentDAO;
541         }
542
543         /**
544          * Set the documentDAO.
545          * 
546          * @param documentDAO
547          *            the documentDAO to set
548          */
549         public void setDocumentDAO(final DocumentDAO documentDAO) {
550                 _documentDAO = documentDAO;
551         }
552
553         /**
554          * Get the simulationContextDAO.
555          * 
556          * @return the simulationContextDAO
557          */
558         public SimulationContextDAO getSimulationContextDAO() {
559                 return _simulationContextDAO;
560         }
561
562         /**
563          * Set the simulationContextDAO.
564          * 
565          * @param simulationContextDAO
566          *            the simulationContextDAO to set
567          */
568         public void setSimulationContextDAO(
569                         final SimulationContextDAO simulationContextDAO) {
570                 _simulationContextDAO = simulationContextDAO;
571         }
572
573         /**
574          * Get the projectElementDAO.
575          * 
576          * @return the projectElementDAO
577          */
578         public ProjectElementDAO getProjectElementDAO() {
579                 return _projectElementDAO;
580         }
581
582         /**
583          * Set the projectElementDAO.
584          * 
585          * @param projectElementDAO
586          *            the projectElementDAO to set
587          */
588         public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
589                 _projectElementDAO = projectElementDAO;
590         }
591
592         /**
593          * Get the indexService.
594          * 
595          * @return the indexService
596          */
597         public IndexService getIndexService() {
598                 return _indexService;
599         }
600
601         /**
602          * Set the indexService.
603          * 
604          * @param indexService
605          *            the indexService to set
606          */
607         public void setIndexService(final IndexService indexService) {
608                 _indexService = indexService;
609         }
610
611         /**
612          * Get the fileDAO.
613          * 
614          * @return the fileDAO
615          */
616         public FileDAO getFileDAO() {
617                 return _fileDAO;
618         }
619
620         /**
621          * Set the fileDAO.
622          * 
623          * @param fileDAO
624          *            the fileDAO to set
625          */
626         public void setFileDAO(final FileDAO fileDAO) {
627                 _fileDAO = fileDAO;
628         }
629
630         /**
631          * Get the documentTypeService.
632          * 
633          * @return the documentTypeService
634          */
635         public DocumentTypeService getDocumentTypeService() {
636                 return _documentTypeService;
637         }
638
639         /**
640          * Set the documentTypeService.
641          * 
642          * @param documentTypeService
643          *            the documentTypeService to set
644          */
645         public void setDocumentTypeService(
646                         final DocumentTypeService documentTypeService) {
647                 _documentTypeService = documentTypeService;
648         }
649
650         /**
651          * Get the versionsRelationDAO.
652          * 
653          * @return the versionsRelationDAO
654          */
655         public VersionsRelationDAO getVersionsRelationDAO() {
656                 return _versionsRelationDAO;
657         }
658
659         /**
660          * Set the versionsRelationDAO.
661          * 
662          * @param versionsRelationDAO
663          *            the versionsRelationDAO to set
664          */
665         public void setVersionsRelationDAO(
666                         final VersionsRelationDAO versionsRelationDAO) {
667                 _versionsRelationDAO = versionsRelationDAO;
668         }
669
670         /**
671          * Get project settings.
672          * 
673          * @return Project settings service
674          */
675         private ProjectSettingsService getProjectSettings() {
676                 return _projectSettings;
677         }
678
679         /**
680          * Set project settings service.
681          * 
682          * @param projectSettingsService
683          *            project settings service
684          */
685         public void setProjectSettings(
686                         final ProjectSettingsService projectSettingsService) {
687                 _projectSettings = projectSettingsService;
688         }
689 }