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.exception.DocumentIsUsedException;
38 import org.splat.kernel.InvalidPropertyException;
39 import org.splat.kernel.MismatchException;
40 import org.splat.kernel.MissedPropertyException;
41 import org.splat.kernel.MultiplyDefinedException;
42 import org.splat.kernel.NotApplicableException;
43 import org.splat.log.AppLogger;
44 import org.splat.service.technical.IndexService;
45 import org.splat.service.technical.ProjectSettingsService;
46 import org.splat.som.Revision;
47 import org.splat.som.Step;
48 import org.springframework.transaction.annotation.Transactional;
51 * Step service implementation.
53 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
55 public class StepServiceImpl implements StepService {
58 * logger for the service.
60 public final static AppLogger LOG = AppLogger
61 .getLogger(StepServiceImpl.class);
63 * Injected index service.
65 private IndexService _indexService;
67 * Injected document service.
69 private DocumentService _documentService;
71 * Injected document type service.
73 private DocumentTypeService _documentTypeService;
75 * Injected document DAO.
77 private DocumentDAO _documentDAO;
79 * Injected relation DAO.
81 private RelationDAO _relationDAO;
85 private FileDAO _fileDAO;
87 * Injected simulation context service.
89 private SimulationContextService _simulationContextService;
91 * Injected simulation context DAO.
93 private SimulationContextDAO _simulationContextDAO;
95 * Injected project element DAO.
97 private ProjectElementDAO _projectElementDAO;
99 * Injected versions relation DAO.
101 private VersionsRelationDAO _versionsRelationDAO;
103 * Injected project service.
105 private ProjectSettingsService _projectSettings;
107 * Injected publication DAO.
109 private PublicationDAO _publicationDAO;
114 * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext.Properties)
116 public SimulationContext addSimulationContext(final Step aStep,
117 final SimulationContext.Properties dprop)
118 throws MissedPropertyException, InvalidPropertyException,
119 MultiplyDefinedException {
120 SimulationContext context = new SimulationContext(dprop.setStep(aStep
122 return addSimulationContext(aStep, context);
128 * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
131 public SimulationContext addSimulationContext(final Step aStep,
132 final SimulationContext context) {
133 SimulationContext res = null;
134 getSimulationContextService().hold(context); // Increments the reference count of simulation context
135 if (aStep.getOwner().isSaved()) {
137 if (!context.isSaved()) {
138 getSimulationContextDAO().create(context);
140 aStep.getOwner().add(context);
141 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
142 getProjectElementDAO().update(aStep.getOwner());
143 updateKnowledgeElementsIndex(aStep);
145 } catch (Exception error) {
146 LOG.debug(error.getMessage(), error);
148 } else { // Happens when copying a scenario
149 aStep.getOwner().add(context);
150 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
151 // In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
158 * Update lucene index of knowledge elements of a scenario or a study which the given step is related to.
161 * the step (activity)
163 private void updateKnowledgeElementsIndex(final Step aStep) {
165 if (aStep.getOwner() instanceof Scenario) {
166 scenarii = new Scenario[1];
167 scenarii[0] = (Scenario) aStep.getOwner();
169 scenarii = aStep.getOwnerStudy().getScenarii();
172 for (int i = 0; i < scenarii.length; i++) {
173 Scenario scene = scenarii[i];
174 List<KnowledgeElement> knelm = scene.getAllKnowledgeElements();
175 for (Iterator<KnowledgeElement> j = knelm.iterator(); j
177 KnowledgeElement kelm = j.next();
178 getIndexService().update(kelm);
180 updateScenarioIndex(scene);
182 } catch (Exception error) {
183 LOG.error("Unable to re-index Knowledge Elements, reason:", error);
188 * Update lucene index for knowledge elements of the scenario.
192 * @throws IOException
193 * if can't update lucene index
195 private void updateScenarioIndex(final Scenario scene) throws IOException {
196 if (scene.getUcase() == null) {
197 for (Iterator<KnowledgeElement> i = scene.getKnowledgeElements()
198 .iterator(); i.hasNext();) {
199 KnowledgeElement kelm = i.next();
200 if (!kelm.getType().equals("usecase")) {
203 scene.setUcase(kelm);
207 getIndexService().update(scene.getUcase());
213 * @see org.splat.service.StepService#removeSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
216 public boolean removeSimulationContext(final Step aStep,
217 final SimulationContext context) {
218 SimulationContext torem = aStep
219 .getSimulationContext(context.getIndex());
221 boolean isOk = (torem != null) && (aStep.getOwner().remove(torem));
224 aStep.getContex().remove(torem);
225 getProjectElementDAO().update(aStep.getOwner());
226 if (torem.isShared()) {
227 getSimulationContextService().release(torem);
228 getSimulationContextDAO().update(torem);
230 getSimulationContextDAO().delete(torem);
239 * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
242 public Publication createDocument(final Step aStep,
243 final Document.Properties dprop) throws MissedPropertyException,
244 InvalidPropertyException, MultiplyDefinedException, IOException {
245 if (LOG.isDebugEnabled()) {
246 LOG.debug("Local index before: "
247 + aStep.getOwnerStudy().getLastLocalIndex());
249 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
250 .setStep(aStep.getStep()));
251 getDocumentService().generateDocumentId(newdoc, dprop);
253 // Creation of the save directory
254 java.io.File wdir = getDocumentService().getSaveDirectory(newdoc);
255 if ((!wdir.exists()) && (!wdir.mkdirs())) {
256 throw new IOException(
257 "Cannot create the repository vault directory");
260 // Identification and save
261 aStep.getOwnerStudy().setLastLocalIndex(
262 dprop.getOwner().getOwnerStudy().getLastLocalIndex());
263 if (LOG.isDebugEnabled()) {
264 LOG.debug("Local index after: "
265 + dprop.getOwner().getOwnerStudy().getLastLocalIndex());
267 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwnerStudy());
268 getDocumentDAO().create(newdoc);
270 return new Publication(newdoc, aStep.getOwner());
276 * @see org.splat.service.StepService#assignDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
278 public Publication assignDocument(final Step aStep,
279 final Document.Properties dprop) throws MissedPropertyException,
280 InvalidPropertyException, NotApplicableException {
281 String refid = dprop.getReference();
282 Publication res = null;
284 Document slot = getDocumentService().selectDocument(refid,
285 new Revision().toString());
286 if ((slot != null) && (slot.isUndefined())) {
287 getDocumentService().initialize(slot,
288 dprop.setOwner(aStep.getOwnerStudy()));
289 res = new Publication(slot, aStep.getOwner());
296 * Create a new version of a document in the given study step.
301 * the base document published version
302 * @return the new version publication
303 * @throws MissedPropertyException
304 * if a mandatory property is missed
305 * @throws InvalidPropertyException
306 * if some property doesn't exist
307 * @throws MultiplyDefinedException
308 * if some property is defined several times
309 * @throws IOException
310 * if a file system error occurs
311 * @throws MismatchException
312 * if the document is not applicable to the given study step
314 public Publication versionDocument(final Step aStep, final Publication base)
315 throws MissedPropertyException, InvalidPropertyException,
316 MultiplyDefinedException, IOException, MismatchException {
317 return versionDocument(aStep, base, new Document.Properties());
321 * Create a new version of a document in the given study step.
326 * the base document published version
328 * the comment for the new version
329 * @return the new version publication
330 * @throws MissedPropertyException
331 * if a mandatory property is missed
332 * @throws InvalidPropertyException
333 * if some property doesn't exist
334 * @throws MultiplyDefinedException
335 * if some property is defined several times
336 * @throws IOException
337 * if a file system error occurs
338 * @throws MismatchException
339 * if the document is not applicable to the given study step
341 public Publication versionDocument(final Step aStep,
342 final Publication base, final String reason)
343 throws MissedPropertyException, InvalidPropertyException,
344 MultiplyDefinedException, IOException, MismatchException {
345 return versionDocument(aStep, base, new Document.Properties()
346 .setDescription(reason));
350 * Create a new version of a document in the given study step.
355 * the base document published version
357 * properties of the new version
358 * @return the new version publication
359 * @throws MissedPropertyException
360 * if a mandatory property is missed
361 * @throws InvalidPropertyException
362 * if some property doesn't exist
363 * @throws MultiplyDefinedException
364 * if some property is defined several times
365 * @throws IOException
366 * if a file system error occurs
367 * @throws MismatchException
368 * if the document is not applicable to the given study step
371 public Publication versionDocument(final Step aStep,
372 final Publication base, final Document.Properties dprop)
373 throws MissedPropertyException, InvalidPropertyException,
374 MultiplyDefinedException, IOException, MismatchException {
375 Document previous = base.value();
377 // RKV: Keep the new file format if it is related to the same document type on this step.
378 String newFormat = dprop.getFormat();
380 dprop.setDocument(previous, getProjectSettings().getStep(
381 base.getStep().getNumber())); // Initializes the Step property
382 if (dprop.getStep().getNumber() != aStep.getNumber()) {
383 throw new MismatchException();
386 if (newFormat != null
387 && previous.getType().equals(
388 getProjectSettings().getDefaultDocumentType(
389 aStep.getStep(), newFormat))) {
390 dprop.setFormat(newFormat);
393 if (dprop.getAuthor() == null) {
394 dprop.setAuthor(previous.getAuthor());
396 String summary = dprop.getDescription();
398 // Creation of the document
399 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
400 .setStep(aStep.getStep()));
401 getDocumentService().generateDocumentId(newdoc, dprop);
402 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwner(),
404 getDocumentDAO().create(newdoc);
407 VersionsRelation aRel;
408 aRel = new VersionsRelation(newdoc, previous, summary);
409 // getVersionsRelationDAO().create(aRel);
410 newdoc.addRelation(aRel);
412 // Update of usedby relations, if exist
414 * RKV: Consider the new version as not used by old dependent documents. So these documents must be marked as outdated then. List<Relation>
415 * relist = previous.getRelations(UsedByRelation.class); Study scope = aStep.getOwnerStudy(); for (Iterator<Relation> i =
416 * relist.iterator(); i.hasNext();) { UsedByRelation relation = (UsedByRelation) i.next(); Document relatedoc = relation.getTo(); if
417 * (scope.shares(relatedoc)) { relatedoc.addRelation(new UsesRelation(relatedoc, newdoc)); } else { relation.moveTo(newdoc); } }
419 return new Publication(newdoc, aStep.getOwner());
423 * Get document types which are applicable for the given study step (activity).
427 * @return the list of document types
429 public List<DocumentType> getValidDocumentTypes(final Step aStep) {
430 return getDocumentTypeService().selectTypesOf(aStep.getStep());
434 * Add a document publication to the given step.
437 * the target study step
439 * the document publication to add
440 * @return true if publication succeeded
442 public boolean add(final Step aStep, final Publication newdoc) {
443 boolean res = aStep.getOwner().add(newdoc); // Updates the study in memory
445 aStep.getDocuments().add(0, newdoc); // Updates this step
446 getDocumentService().hold(newdoc.value()); // Increments the configuration tag count of document
447 // If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
448 // database (it will be saved later by cascading the update of owner scenario).
454 * Remove a document publication from the given step.
459 * the document publication to remove
460 * @return true if removing of the publication succeeded
462 public boolean remove(final Step aStep, final Publication oldoc) {
463 aStep.getDocuments().remove(oldoc); // Updates this step
464 // Synchronize with database
465 ProjectElement owner = getProjectElementDAO().merge(aStep.getOwner());
467 aStep.getOwner().remove(oldoc); // in transient copy
468 owner.remove(oldoc); // in persistent copy
470 getDocumentService().release(oldoc.value()); // Decrements the configuration tag count of document
471 // The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
476 * Remove a document from the given step and from the database if it is no more used.
482 * @return true if removing of the document succeeded
483 * @throws DocumentIsUsedException
484 * if the document is used by other documents
487 public boolean removeDocument(final Step aStep, final long docId)
488 throws DocumentIsUsedException {
489 Publication torem = aStep.getDocument(docId);
490 boolean res = (torem != null);
492 if (!torem.value().getRelations(UsedByRelation.class).isEmpty()) {
493 throw new DocumentIsUsedException(torem.value().getTitle());
495 remove(aStep, torem);
496 Document value = torem.value();
497 if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
498 List<Document> using = new ArrayList<Document>();
499 List<Relation> converts = new ArrayList<Relation>();
500 for (Relation link : value.getAllRelations()) {
501 if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
503 } else if (link.getClass().equals(UsesRelation.class)) { // Document dependency
504 using.add((Document) link.getTo());
507 // value.getAllRelations().removeAll(converts);
508 // Remove relations from depending documents
509 if (LOG.isDebugEnabled()) {
510 LOG.debug("Remove " + using.size() + " UsedByRelation(s).");
512 for (Document doc : using) {
513 if (LOG.isDebugEnabled()) {
514 LOG.debug("Remove UsedByRelation from "
515 + doc.getTitle() + " to " + value.getTitle());
517 doc.removeRelation(UsedByRelation.class, value);
518 getDocumentDAO().merge(doc);
520 value = getPublicationDAO().merge(torem).value();
521 // Synchronize deleted objects with the database to avoid hibernate exception
522 // org.hibernate.PropertyValueException: not-null property references a null or transient value:
523 // org.splat.dal.bo.som.UsedByRelation.refer
524 getDocumentDAO().flush(); // To show to the database that files from ConvertsRelation(s) are deleted already
525 getDocumentDAO().delete(value); // The corresponding physical file is not removed from the vault
526 // Delete document's files
527 for (Relation link : converts) {
528 File file = (File) link.getTo();
529 getFileDAO().delete(file); // The corresponding physical file is not removed from the vault
537 * Get the documentService.
539 * @return the documentService
541 public DocumentService getDocumentService() {
542 return _documentService;
546 * Set the documentService.
548 * @param documentService
549 * the documentService to set
551 public void setDocumentService(final DocumentService documentService) {
552 _documentService = documentService;
556 * Get the simulationContextService.
558 * @return the simulationContextService
560 public SimulationContextService getSimulationContextService() {
561 return _simulationContextService;
565 * Set the simulationContextService.
567 * @param simulationContextService
568 * the simulationContextService to set
570 public void setSimulationContextService(
571 final SimulationContextService simulationContextService) {
572 _simulationContextService = simulationContextService;
576 * Get the documentDAO.
578 * @return the documentDAO
580 public DocumentDAO getDocumentDAO() {
585 * Set the documentDAO.
588 * the documentDAO to set
590 public void setDocumentDAO(final DocumentDAO documentDAO) {
591 _documentDAO = documentDAO;
595 * Get the simulationContextDAO.
597 * @return the simulationContextDAO
599 public SimulationContextDAO getSimulationContextDAO() {
600 return _simulationContextDAO;
604 * Set the simulationContextDAO.
606 * @param simulationContextDAO
607 * the simulationContextDAO to set
609 public void setSimulationContextDAO(
610 final SimulationContextDAO simulationContextDAO) {
611 _simulationContextDAO = simulationContextDAO;
615 * Get the projectElementDAO.
617 * @return the projectElementDAO
619 public ProjectElementDAO getProjectElementDAO() {
620 return _projectElementDAO;
624 * Set the projectElementDAO.
626 * @param projectElementDAO
627 * the projectElementDAO to set
629 public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
630 _projectElementDAO = projectElementDAO;
634 * Get the indexService.
636 * @return the indexService
638 public IndexService getIndexService() {
639 return _indexService;
643 * Set the indexService.
645 * @param indexService
646 * the indexService to set
648 public void setIndexService(final IndexService indexService) {
649 _indexService = indexService;
655 * @return the fileDAO
657 public FileDAO getFileDAO() {
667 public void setFileDAO(final FileDAO fileDAO) {
672 * Get the documentTypeService.
674 * @return the documentTypeService
676 public DocumentTypeService getDocumentTypeService() {
677 return _documentTypeService;
681 * Set the documentTypeService.
683 * @param documentTypeService
684 * the documentTypeService to set
686 public void setDocumentTypeService(
687 final DocumentTypeService documentTypeService) {
688 _documentTypeService = documentTypeService;
692 * Get the versionsRelationDAO.
694 * @return the versionsRelationDAO
696 public VersionsRelationDAO getVersionsRelationDAO() {
697 return _versionsRelationDAO;
701 * Set the versionsRelationDAO.
703 * @param versionsRelationDAO
704 * the versionsRelationDAO to set
706 public void setVersionsRelationDAO(
707 final VersionsRelationDAO versionsRelationDAO) {
708 _versionsRelationDAO = versionsRelationDAO;
712 * Get project settings.
714 * @return Project settings service
716 private ProjectSettingsService getProjectSettings() {
717 return _projectSettings;
721 * Set project settings service.
723 * @param projectSettingsService
724 * project settings service
726 public void setProjectSettings(
727 final ProjectSettingsService projectSettingsService) {
728 _projectSettings = projectSettingsService;
732 * Get the publicationDAO.
734 * @return the publicationDAO
736 public PublicationDAO getPublicationDAO() {
737 return _publicationDAO;
741 * Set the publicationDAO.
743 * @param publicationDAO
744 * the publicationDAO to set
746 public void setPublicationDAO(final PublicationDAO publicationDAO) {
747 this._publicationDAO = publicationDAO;
751 * Get the relationDAO.
753 * @return the relationDAO
755 public RelationDAO getRelationDAO() {
760 * Set the relationDAO.
763 * the relationDAO to set
765 public void setRelationDAO(final RelationDAO relationDAO) {
766 _relationDAO = relationDAO;