1 /*****************************************************************************
5 * Creation date 06.10.2012
8 *****************************************************************************/
10 package org.splat.service;
12 import java.io.IOException;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
17 import org.splat.dal.bo.kernel.Relation;
18 import org.splat.dal.bo.som.ConvertsRelation;
19 import org.splat.dal.bo.som.Document;
20 import org.splat.dal.bo.som.DocumentType;
21 import org.splat.dal.bo.som.File;
22 import org.splat.dal.bo.som.KnowledgeElement;
23 import org.splat.dal.bo.som.ProjectElement;
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.UsedByRelation;
28 import org.splat.dal.bo.som.UsesRelation;
29 import org.splat.dal.bo.som.VersionsRelation;
30 import org.splat.dal.dao.kernel.RelationDAO;
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.PublicationDAO;
35 import org.splat.dal.dao.som.SimulationContextDAO;
36 import org.splat.dal.dao.som.VersionsRelationDAO;
37 import org.splat.kernel.InvalidPropertyException;
38 import org.splat.kernel.MismatchException;
39 import org.splat.kernel.MissedPropertyException;
40 import org.splat.kernel.MultiplyDefinedException;
41 import org.splat.kernel.NotApplicableException;
42 import org.splat.log.AppLogger;
43 import org.splat.service.technical.IndexService;
44 import org.splat.service.technical.ProjectSettingsService;
45 import org.splat.som.Revision;
46 import org.splat.som.Step;
47 import org.springframework.transaction.annotation.Transactional;
50 * Step service implementation.
52 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
54 public class StepServiceImpl implements StepService {
57 * logger for the service.
59 public final static AppLogger LOG = AppLogger
60 .getLogger(StepServiceImpl.class);
62 * Injected index service.
64 private IndexService _indexService;
66 * Injected document service.
68 private DocumentService _documentService;
70 * Injected document type service.
72 private DocumentTypeService _documentTypeService;
74 * Injected document DAO.
76 private DocumentDAO _documentDAO;
78 * Injected relation DAO.
80 private RelationDAO _relationDAO;
84 private FileDAO _fileDAO;
86 * Injected simulation context service.
88 private SimulationContextService _simulationContextService;
90 * Injected simulation context DAO.
92 private SimulationContextDAO _simulationContextDAO;
94 * Injected project element DAO.
96 private ProjectElementDAO _projectElementDAO;
98 * Injected versions relation DAO.
100 private VersionsRelationDAO _versionsRelationDAO;
102 * Injected project service.
104 private ProjectSettingsService _projectSettings;
106 * Injected publication DAO.
108 private PublicationDAO _publicationDAO;
113 * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext.Properties)
115 public SimulationContext addSimulationContext(final Step aStep,
116 final SimulationContext.Properties dprop)
117 throws MissedPropertyException, InvalidPropertyException,
118 MultiplyDefinedException {
119 SimulationContext context = new SimulationContext(dprop.setStep(aStep
121 return addSimulationContext(aStep, context);
127 * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
130 public SimulationContext addSimulationContext(final Step aStep,
131 final SimulationContext context) {
132 SimulationContext res = null;
133 getSimulationContextService().hold(context); // Increments the reference count of simulation context
134 if (aStep.getOwner().isSaved()) {
136 if (!context.isSaved()) {
137 getSimulationContextDAO().create(context);
139 aStep.getOwner().add(context);
140 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
141 getProjectElementDAO().update(aStep.getOwner());
142 updateKnowledgeElementsIndex(aStep);
144 } catch (Exception error) {
145 LOG.debug(error.getMessage(), error);
147 } else { // Happens when copying a scenario
148 aStep.getOwner().add(context);
149 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
150 // In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
157 * Update lucene index of knowledge elements of a scenario or a study which the given step is related to.
160 * the step (activity)
162 private void updateKnowledgeElementsIndex(final Step aStep) {
164 if (aStep.getOwner() instanceof Scenario) {
165 scenarii = new Scenario[1];
166 scenarii[0] = (Scenario) aStep.getOwner();
168 scenarii = aStep.getOwnerStudy().getScenarii();
171 for (int i = 0; i < scenarii.length; i++) {
172 Scenario scene = scenarii[i];
173 List<KnowledgeElement> knelm = scene.getAllKnowledgeElements();
174 for (Iterator<KnowledgeElement> j = knelm.iterator(); j
176 KnowledgeElement kelm = j.next();
177 getIndexService().update(kelm);
179 updateScenarioIndex(scene);
181 } catch (Exception error) {
182 LOG.error("Unable to re-index Knowledge Elements, reason:", error);
187 * Update lucene index for knowledge elements of the scenario.
191 * @throws IOException
192 * if can't update lucene index
194 private void updateScenarioIndex(final Scenario scene) throws IOException {
195 if (scene.getUcase() == null) {
196 for (Iterator<KnowledgeElement> i = scene.getKnowledgeElements()
197 .iterator(); i.hasNext();) {
198 KnowledgeElement kelm = i.next();
199 if (!kelm.getType().equals("usecase")) {
202 scene.setUcase(kelm);
206 getIndexService().update(scene.getUcase());
212 * @see org.splat.service.StepService#removeSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
215 public boolean removeSimulationContext(final Step aStep,
216 final SimulationContext context) {
217 SimulationContext torem = aStep
218 .getSimulationContext(context.getIndex());
220 boolean isOk = (torem != null) && (aStep.getOwner().remove(torem));
223 aStep.getContex().remove(torem);
224 getProjectElementDAO().update(aStep.getOwner());
225 if (torem.isShared()) {
226 getSimulationContextService().release(torem);
227 getSimulationContextDAO().update(torem);
229 getSimulationContextDAO().delete(torem);
238 * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
241 public Publication createDocument(final Step aStep,
242 final Document.Properties dprop) throws MissedPropertyException,
243 InvalidPropertyException, MultiplyDefinedException, IOException {
244 if (LOG.isDebugEnabled()) {
245 LOG.debug("Local index before: "
246 + aStep.getOwnerStudy().getLastLocalIndex());
248 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
249 .setStep(aStep.getStep()));
250 getDocumentService().generateDocumentId(newdoc, dprop);
252 // Creation of the save directory
253 java.io.File wdir = getDocumentService().getSaveDirectory(newdoc);
254 if ((!wdir.exists()) && (!wdir.mkdirs())) {
255 throw new IOException(
256 "Cannot create the repository vault directory");
259 // Identification and save
260 aStep.getOwnerStudy().setLastLocalIndex(
261 dprop.getOwner().getOwnerStudy().getLastLocalIndex());
262 if (LOG.isDebugEnabled()) {
263 LOG.debug("Local index after: "
264 + dprop.getOwner().getOwnerStudy().getLastLocalIndex());
266 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwnerStudy());
267 getDocumentDAO().create(newdoc);
269 return new Publication(newdoc, aStep.getOwner());
275 * @see org.splat.service.StepService#assignDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
277 public Publication assignDocument(final Step aStep,
278 final Document.Properties dprop) throws MissedPropertyException,
279 InvalidPropertyException, NotApplicableException {
280 String refid = dprop.getReference();
281 Publication res = null;
283 Document slot = getDocumentService().selectDocument(refid,
284 new Revision().toString());
285 if ((slot != null) && (slot.isUndefined())) {
286 getDocumentService().initialize(slot,
287 dprop.setOwner(aStep.getOwnerStudy()));
288 res = new Publication(slot, aStep.getOwner());
295 * Create a new version of a document in the given study step.
300 * the base document published version
301 * @return the new version publication
302 * @throws MissedPropertyException
303 * if a mandatory property is missed
304 * @throws InvalidPropertyException
305 * if some property doesn't exist
306 * @throws MultiplyDefinedException
307 * if some property is defined several times
308 * @throws IOException
309 * if a file system error occurs
310 * @throws MismatchException
311 * if the document is not applicable to the given study step
313 public Publication versionDocument(final Step aStep, final Publication base)
314 throws MissedPropertyException, InvalidPropertyException,
315 MultiplyDefinedException, IOException, MismatchException {
316 return versionDocument(aStep, base, new Document.Properties());
320 * Create a new version of a document in the given study step.
325 * the base document published version
327 * the comment for the new version
328 * @return the new version publication
329 * @throws MissedPropertyException
330 * if a mandatory property is missed
331 * @throws InvalidPropertyException
332 * if some property doesn't exist
333 * @throws MultiplyDefinedException
334 * if some property is defined several times
335 * @throws IOException
336 * if a file system error occurs
337 * @throws MismatchException
338 * if the document is not applicable to the given study step
340 public Publication versionDocument(final Step aStep,
341 final Publication base, final String reason)
342 throws MissedPropertyException, InvalidPropertyException,
343 MultiplyDefinedException, IOException, MismatchException {
344 return versionDocument(aStep, base, new Document.Properties()
345 .setDescription(reason));
349 * Create a new version of a document in the given study step.
354 * the base document published version
356 * properties of the new version
357 * @return the new version publication
358 * @throws MissedPropertyException
359 * if a mandatory property is missed
360 * @throws InvalidPropertyException
361 * if some property doesn't exist
362 * @throws MultiplyDefinedException
363 * if some property is defined several times
364 * @throws IOException
365 * if a file system error occurs
366 * @throws MismatchException
367 * if the document is not applicable to the given study step
370 public Publication versionDocument(final Step aStep,
371 final Publication base, final Document.Properties dprop)
372 throws MissedPropertyException, InvalidPropertyException,
373 MultiplyDefinedException, IOException, MismatchException {
374 Document previous = base.value();
376 // RKV: Keep the new file format if it is related to the same document type on this step.
377 String newFormat = dprop.getFormat();
379 dprop.setDocument(previous, getProjectSettings().getStep(
380 base.getStep().getNumber())); // Initializes the Step property
381 if (dprop.getStep().getNumber() != aStep.getNumber()) {
382 throw new MismatchException();
385 if (newFormat != null
386 && previous.getType().equals(
387 getProjectSettings().getDefaultDocumentType(
388 aStep.getStep(), newFormat))) {
389 dprop.setFormat(newFormat);
392 if (dprop.getAuthor() == null) {
393 dprop.setAuthor(previous.getAuthor());
395 String summary = dprop.getDescription();
397 // Creation of the document
398 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
399 .setStep(aStep.getStep()));
400 getDocumentService().generateDocumentId(newdoc, dprop);
401 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwner(),
403 getDocumentDAO().create(newdoc);
406 VersionsRelation aRel;
407 aRel = new VersionsRelation(newdoc, previous, summary);
408 // getVersionsRelationDAO().create(aRel);
409 newdoc.addRelation(aRel);
411 // Update of usedby relations, if exist
413 * RKV: Consider the new version as not used by old dependent documents. So these documents must be marked as outdated then. List<Relation>
414 * relist = previous.getRelations(UsedByRelation.class); Study scope = aStep.getOwnerStudy(); for (Iterator<Relation> i =
415 * relist.iterator(); i.hasNext();) { UsedByRelation relation = (UsedByRelation) i.next(); Document relatedoc = relation.getTo(); if
416 * (scope.shares(relatedoc)) { relatedoc.addRelation(new UsesRelation(relatedoc, newdoc)); } else { relation.moveTo(newdoc); } }
418 return new Publication(newdoc, aStep.getOwner());
422 * Get document types which are applicable for the given study step (activity).
426 * @return the list of document types
428 public List<DocumentType> getValidDocumentTypes(final Step aStep) {
429 return getDocumentTypeService().selectTypesOf(aStep.getStep());
433 * Add a document publication to the given step.
436 * the target study step
438 * the document publication to add
439 * @return true if publication succeeded
441 public boolean add(final Step aStep, final Publication newdoc) {
442 boolean res = aStep.getOwner().add(newdoc); // Updates the study in memory
444 aStep.getDocuments().add(0, newdoc); // Updates this step
445 getDocumentService().hold(newdoc.value()); // Increments the configuration tag count of document
446 // If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
447 // database (it will be saved later by cascading the update of owner scenario).
453 * Remove a document publication from the given step.
458 * the document publication to remove
459 * @return true if removing of the publication succeeded
461 public boolean remove(final Step aStep, final Publication oldoc) {
462 aStep.getDocuments().remove(oldoc); // Updates this step
463 // Synchronize with database
464 ProjectElement owner = getProjectElementDAO().merge(aStep.getOwner());
466 aStep.getOwner().remove(oldoc); // in transient copy
467 owner.remove(oldoc); // in persistent copy
469 getDocumentService().release(oldoc.value()); // Decrements the configuration tag count of document
470 // The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
475 * Remove a document from the given step and from the database if it is no more used.
481 * @return true if removing of the document succeeded
484 public boolean removeDocument(final Step aStep, final long docId) {
485 Publication torem = aStep.getDocument(docId);
486 boolean res = (torem != null);
488 torem = getPublicationDAO().merge(torem);
489 remove(aStep, torem);
490 Document value = torem.value();
491 if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
492 List<Document> using = new ArrayList<Document>();
493 List<Relation> converts = new ArrayList<Relation>();
494 for (Relation link : value.getAllRelations()) {
495 if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
497 } else if (link.getClass().equals(UsesRelation.class)) { // Document dependency
498 using.add((Document) link.getTo());
501 // value.getAllRelations().removeAll(converts);
502 // Remove relations from depending documents
503 if (LOG.isDebugEnabled()) {
504 LOG.debug("Remove " + using.size() + " UsedByRelation(s).");
506 for (Document doc : using) {
507 if (LOG.isDebugEnabled()) {
508 LOG.debug("Remove UsedByRelation from "
509 + doc.getTitle() + " to " + value.getTitle());
511 doc.removeRelation(UsedByRelation.class, value);
513 // Synchronize deleted objects with the database to avoid hibernate exception
514 // related with null value of not-nullable property because back reference from Document to Publication is not mapped:
515 // org.hibernate.PropertyValueException: not-null property references a null or transient value:
516 // org.splat.dal.bo.som.Publication.mydoc
517 getDocumentDAO().flush(); // To show to the database that files from ConvertsRelation(s) are deleted already
518 getDocumentDAO().delete(value); // The corresponding physical file is not removed from the vault
519 // Delete document's files
520 for (Relation link : converts) {
521 File file = (File) link.getTo();
522 getFileDAO().delete(file); // The corresponding physical file is not removed from the vault
530 * Get the documentService.
532 * @return the documentService
534 public DocumentService getDocumentService() {
535 return _documentService;
539 * Set the documentService.
541 * @param documentService
542 * the documentService to set
544 public void setDocumentService(final DocumentService documentService) {
545 _documentService = documentService;
549 * Get the simulationContextService.
551 * @return the simulationContextService
553 public SimulationContextService getSimulationContextService() {
554 return _simulationContextService;
558 * Set the simulationContextService.
560 * @param simulationContextService
561 * the simulationContextService to set
563 public void setSimulationContextService(
564 final SimulationContextService simulationContextService) {
565 _simulationContextService = simulationContextService;
569 * Get the documentDAO.
571 * @return the documentDAO
573 public DocumentDAO getDocumentDAO() {
578 * Set the documentDAO.
581 * the documentDAO to set
583 public void setDocumentDAO(final DocumentDAO documentDAO) {
584 _documentDAO = documentDAO;
588 * Get the simulationContextDAO.
590 * @return the simulationContextDAO
592 public SimulationContextDAO getSimulationContextDAO() {
593 return _simulationContextDAO;
597 * Set the simulationContextDAO.
599 * @param simulationContextDAO
600 * the simulationContextDAO to set
602 public void setSimulationContextDAO(
603 final SimulationContextDAO simulationContextDAO) {
604 _simulationContextDAO = simulationContextDAO;
608 * Get the projectElementDAO.
610 * @return the projectElementDAO
612 public ProjectElementDAO getProjectElementDAO() {
613 return _projectElementDAO;
617 * Set the projectElementDAO.
619 * @param projectElementDAO
620 * the projectElementDAO to set
622 public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
623 _projectElementDAO = projectElementDAO;
627 * Get the indexService.
629 * @return the indexService
631 public IndexService getIndexService() {
632 return _indexService;
636 * Set the indexService.
638 * @param indexService
639 * the indexService to set
641 public void setIndexService(final IndexService indexService) {
642 _indexService = indexService;
648 * @return the fileDAO
650 public FileDAO getFileDAO() {
660 public void setFileDAO(final FileDAO fileDAO) {
665 * Get the documentTypeService.
667 * @return the documentTypeService
669 public DocumentTypeService getDocumentTypeService() {
670 return _documentTypeService;
674 * Set the documentTypeService.
676 * @param documentTypeService
677 * the documentTypeService to set
679 public void setDocumentTypeService(
680 final DocumentTypeService documentTypeService) {
681 _documentTypeService = documentTypeService;
685 * Get the versionsRelationDAO.
687 * @return the versionsRelationDAO
689 public VersionsRelationDAO getVersionsRelationDAO() {
690 return _versionsRelationDAO;
694 * Set the versionsRelationDAO.
696 * @param versionsRelationDAO
697 * the versionsRelationDAO to set
699 public void setVersionsRelationDAO(
700 final VersionsRelationDAO versionsRelationDAO) {
701 _versionsRelationDAO = versionsRelationDAO;
705 * Get project settings.
707 * @return Project settings service
709 private ProjectSettingsService getProjectSettings() {
710 return _projectSettings;
714 * Set project settings service.
716 * @param projectSettingsService
717 * project settings service
719 public void setProjectSettings(
720 final ProjectSettingsService projectSettingsService) {
721 _projectSettings = projectSettingsService;
725 * Get the publicationDAO.
727 * @return the publicationDAO
729 public PublicationDAO getPublicationDAO() {
730 return _publicationDAO;
734 * Set the publicationDAO.
736 * @param publicationDAO
737 * the publicationDAO to set
739 public void setPublicationDAO(final PublicationDAO publicationDAO) {
740 this._publicationDAO = publicationDAO;
744 * Get the relationDAO.
746 * @return the relationDAO
748 public RelationDAO getRelationDAO() {
753 * Set the relationDAO.
756 * the relationDAO to set
758 public void setRelationDAO(final RelationDAO relationDAO) {
759 _relationDAO = relationDAO;