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