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