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;
18 import org.splat.dal.bo.kernel.Relation;
19 import org.splat.dal.bo.som.ConvertsRelation;
20 import org.splat.dal.bo.som.Document;
21 import org.splat.dal.bo.som.DocumentType;
22 import org.splat.dal.bo.som.File;
23 import org.splat.dal.bo.som.KnowledgeElement;
24 import org.splat.dal.bo.som.ProjectElement;
25 import org.splat.dal.bo.som.Publication;
26 import org.splat.dal.bo.som.Scenario;
27 import org.splat.dal.bo.som.SimulationContext;
28 import org.splat.dal.bo.som.UsedByRelation;
29 import org.splat.dal.bo.som.UsesRelation;
30 import org.splat.dal.bo.som.VersionsRelation;
31 import org.splat.dal.dao.som.DocumentDAO;
32 import org.splat.dal.dao.som.FileDAO;
33 import org.splat.dal.dao.som.ProjectElementDAO;
34 import org.splat.dal.dao.som.SimulationContextDAO;
35 import org.splat.dal.dao.som.VersionsRelationDAO;
36 import org.splat.kernel.InvalidPropertyException;
37 import org.splat.kernel.MismatchException;
38 import org.splat.kernel.MissedPropertyException;
39 import org.splat.kernel.MultiplyDefinedException;
40 import org.splat.kernel.NotApplicableException;
41 import org.splat.log.AppLogger;
42 import org.splat.service.technical.IndexService;
43 import org.splat.service.technical.ProjectSettingsService;
44 import org.splat.som.Revision;
45 import org.splat.som.Step;
46 import org.springframework.transaction.annotation.Transactional;
49 * Step service implementation.
51 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
53 public class StepServiceImpl implements StepService {
56 * logger for the service.
58 public final static AppLogger LOG = AppLogger
59 .getLogger(StepServiceImpl.class);
61 * Injected index service.
63 private IndexService _indexService;
65 * Injected document service.
67 private DocumentService _documentService;
69 * Injected document type service.
71 private DocumentTypeService _documentTypeService;
73 * Injected document DAO.
75 private DocumentDAO _documentDAO;
79 private FileDAO _fileDAO;
81 * Injected simulation context service.
83 private SimulationContextService _simulationContextService;
85 * Injected simulation context DAO.
87 private SimulationContextDAO _simulationContextDAO;
89 * Injected project element DAO.
91 private ProjectElementDAO _projectElementDAO;
93 * Injected versions relation DAO.
95 private VersionsRelationDAO _versionsRelationDAO;
97 * Injected project service.
99 private ProjectSettingsService _projectSettings;
104 * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext.Properties)
106 public SimulationContext addSimulationContext(final Step aStep,
107 final SimulationContext.Properties dprop)
108 throws MissedPropertyException, InvalidPropertyException,
109 MultiplyDefinedException {
110 SimulationContext context = new SimulationContext(dprop.setStep(aStep
112 return addSimulationContext(aStep, context);
118 * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
121 public SimulationContext addSimulationContext(final Step aStep,
122 final SimulationContext context) {
123 SimulationContext res = null;
124 getSimulationContextService().hold(context); // Increments the reference count of simulation context
125 if (aStep.getOwner().isSaved()) {
127 if (!context.isSaved()) {
128 getSimulationContextDAO().create(context);
130 aStep.getOwner().add(context);
131 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
132 getProjectElementDAO().update(aStep.getOwner());
133 updateKnowledgeElementsIndex(aStep);
135 } catch (Exception error) {
136 LOG.debug(error.getMessage(), error);
138 } else { // Happens when copying a scenario
139 aStep.getOwner().add(context);
140 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
141 // In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
148 * Update lucene index of knowledge elements of a scenario or a study which the given step is related to.
151 * the step (activity)
153 private void updateKnowledgeElementsIndex(final Step aStep) {
155 if (aStep.getOwner() instanceof Scenario) {
156 scenarii = new Scenario[1];
157 scenarii[0] = (Scenario) aStep.getOwner();
159 scenarii = aStep.getOwnerStudy().getScenarii();
162 for (int i = 0; i < scenarii.length; i++) {
163 Scenario scene = scenarii[i];
164 List<KnowledgeElement> knelm = scene.getAllKnowledgeElements();
165 for (Iterator<KnowledgeElement> j = knelm.iterator(); j
167 KnowledgeElement kelm = j.next();
168 getIndexService().update(kelm);
170 updateScenarioIndex(scene);
172 } catch (Exception error) {
173 LOG.error("Unable to re-index Knowledge Elements, reason:", error);
178 * Update lucene index for knowledge elements of the scenario.
182 * @throws IOException
183 * if can't update lucene index
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")) {
193 scene.setUcase(kelm);
197 getIndexService().update(scene.getUcase());
203 * @see org.splat.service.StepService#removeSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
206 public boolean removeSimulationContext(final Step aStep,
207 final SimulationContext context) {
208 SimulationContext torem = aStep
209 .getSimulationContext(context.getIndex());
211 boolean isOk = (torem != null) && (aStep.getOwner().remove(torem));
214 aStep.getContex().remove(torem);
215 getProjectElementDAO().update(aStep.getOwner());
216 if (torem.isShared()) {
217 getSimulationContextService().release(torem);
218 getSimulationContextDAO().update(torem);
220 getSimulationContextDAO().delete(torem);
229 * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
232 public Publication createDocument(final Step aStep,
233 final Document.Properties dprop) throws MissedPropertyException,
234 InvalidPropertyException, MultiplyDefinedException, IOException {
235 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
236 .setStep(aStep.getStep()));
237 getDocumentService().generateDocumentId(newdoc, dprop);
239 // Creation of the save directory
240 java.io.File wdir = getDocumentService().getSaveDirectory(newdoc);
241 if ((!wdir.exists()) && (!wdir.mkdirs())) {
242 throw new IOException(
243 "Cannot create the repository vault directory");
246 // Identification and save
247 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwnerStudy());
248 getDocumentDAO().create(newdoc);
250 return new Publication(newdoc, aStep.getOwner());
256 * @see org.splat.service.StepService#assignDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
258 public Publication assignDocument(final Step aStep,
259 final Document.Properties dprop) throws MissedPropertyException,
260 InvalidPropertyException, NotApplicableException {
261 String refid = dprop.getReference();
262 Publication res = null;
264 Document slot = getDocumentService().selectDocument(refid,
265 new Revision().toString());
266 if ((slot != null) && (slot.isUndefined())) {
267 getDocumentService().initialize(slot,
268 dprop.setOwner(aStep.getOwnerStudy()));
269 res = new Publication(slot, aStep.getOwner());
276 * Create a new version of a document in the given study step.
281 * the base document published version
282 * @return the new version publication
283 * @throws MissedPropertyException
284 * if a mandatory property is missed
285 * @throws InvalidPropertyException
286 * if some property doesn't exist
287 * @throws MultiplyDefinedException
288 * if some property is defined several times
289 * @throws IOException
290 * if a file system error occurs
291 * @throws MismatchException
292 * if the document is not applicable to the given study step
294 public Publication versionDocument(final Step aStep, final Publication base)
295 throws MissedPropertyException, InvalidPropertyException,
296 MultiplyDefinedException, IOException, MismatchException {
297 return versionDocument(aStep, base, new Document.Properties());
301 * Create a new version of a document in the given study step.
306 * the base document published version
308 * the comment for the new version
309 * @return the new version publication
310 * @throws MissedPropertyException
311 * if a mandatory property is missed
312 * @throws InvalidPropertyException
313 * if some property doesn't exist
314 * @throws MultiplyDefinedException
315 * if some property is defined several times
316 * @throws IOException
317 * if a file system error occurs
318 * @throws MismatchException
319 * if the document is not applicable to the given study step
321 public Publication versionDocument(final Step aStep,
322 final Publication base, final String reason)
323 throws MissedPropertyException, InvalidPropertyException,
324 MultiplyDefinedException, IOException, MismatchException {
325 return versionDocument(aStep, base, new Document.Properties()
326 .setDescription(reason));
330 * Create a new version of a document in the given study step.
335 * the base document published version
337 * properties of the new version
338 * @return the new version publication
339 * @throws MissedPropertyException
340 * if a mandatory property is missed
341 * @throws InvalidPropertyException
342 * if some property doesn't exist
343 * @throws MultiplyDefinedException
344 * if some property is defined several times
345 * @throws IOException
346 * if a file system error occurs
347 * @throws MismatchException
348 * if the document is not applicable to the given study step
351 public Publication versionDocument(final Step aStep,
352 final Publication base, final Document.Properties dprop)
353 throws MissedPropertyException, InvalidPropertyException,
354 MultiplyDefinedException, IOException, MismatchException {
355 Document previous = base.value();
357 // RKV: Keep the new file format if it is related to the same document type on this step.
358 String newFormat = dprop.getFormat();
360 dprop.setDocument(previous, getProjectSettings().getStep(
361 base.getStep().getNumber())); // Initializes the Step property
362 if (dprop.getStep().getNumber() != aStep.getNumber()) {
363 throw new MismatchException();
366 if (newFormat != null
367 && previous.getType().equals(
368 getProjectSettings().getDefaultDocumentType(
369 aStep.getStep(), newFormat))) {
370 dprop.setFormat(newFormat);
373 if (dprop.getAuthor() == null) {
374 dprop.setAuthor(previous.getAuthor());
376 String summary = dprop.getDescription();
378 // Creation of the document
379 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
380 .setStep(aStep.getStep()));
381 getDocumentService().generateDocumentId(newdoc, dprop);
382 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwner(),
384 getDocumentDAO().create(newdoc);
387 VersionsRelation aRel;
388 aRel = new VersionsRelation(newdoc, previous, summary);
389 // getVersionsRelationDAO().create(aRel);
390 newdoc.addRelation(aRel);
392 // Update of usedby relations, if exist
394 * RKV: Consider the new version as not used by old dependent documents. So these documents must be marked as outdated then. List<Relation>
395 * relist = previous.getRelations(UsedByRelation.class); Study scope = aStep.getOwnerStudy(); for (Iterator<Relation> i =
396 * relist.iterator(); i.hasNext();) { UsedByRelation relation = (UsedByRelation) i.next(); Document relatedoc = relation.getTo(); if
397 * (scope.shares(relatedoc)) { relatedoc.addRelation(new UsesRelation(relatedoc, newdoc)); } else { relation.moveTo(newdoc); } }
399 return new Publication(newdoc, aStep.getOwner());
403 * Get document types which are applicable for the given study step (activity).
407 * @return the list of document types
409 public List<DocumentType> getValidDocumentTypes(final Step aStep) {
410 return getDocumentTypeService().selectTypesOf(aStep.getStep());
414 * Add a document publication to the given step.
417 * the target study step
419 * the document publication to add
420 * @return true if publication succeeded
422 public boolean add(final Step aStep, final Publication newdoc) {
423 boolean res = aStep.getOwner().add(newdoc); // Updates the study in memory
425 aStep.getDocuments().add(0, newdoc); // Updates this step
426 getDocumentService().hold(newdoc.value()); // Increments the configuration tag count of document
427 // If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
428 // database (it will be saved later by cascading the update of owner scenario).
434 * Remove a document publication from the given step.
439 * the document publication to remove
440 * @return true if removing of the publication succeeded
442 public boolean remove(final Step aStep, final Publication oldoc) {
443 boolean res = aStep.getOwner().remove(oldoc); // Updates the study in memory
445 aStep.getDocuments().remove(oldoc); // Updates this step
446 ProjectElement owner = aStep.getOwner();
450 getDocumentService().release(oldoc.value()); // Decrements the configuration tag count of document
451 // The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
457 * Remove a document from the given step.
462 * the document publication
463 * @return true if removing of the document succeeded
466 public boolean removeDocument(final Step aStep, final Publication doctag) {
467 Document value = doctag.value();
468 getDocumentDAO().update(value);
469 Publication torem = aStep.getDocument(value.getIndex());
471 boolean res = (torem != null);
473 remove(aStep, torem);
474 getProjectElementDAO().update(aStep.getOwner());
475 if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
476 Set<Relation> links = value.getAllRelations(); // Get all relation of the document to remove them
477 List<Document> using = new ArrayList<Document>();
478 for (Iterator<Relation> i = links.iterator(); i.hasNext();) {
479 Relation link = i.next();
480 if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
481 getFileDAO().delete((File) link.getTo()); // The corresponding physical file is not removed from the vault
482 } else if (link.getClass().equals(UsesRelation.class)) { // Document dependency
483 using.add((Document) link.getTo());
486 for (Iterator<Document> i = using.iterator(); i.hasNext();) {
487 i.next().removeRelation(UsedByRelation.class, value); // TODO: RKV: don't use Database.getSession in removeRelation
489 getDocumentDAO().delete(value); // The corresponding physical file is not removed from the vault
496 * Get the documentService.
498 * @return the documentService
500 public DocumentService getDocumentService() {
501 return _documentService;
505 * Set the documentService.
507 * @param documentService
508 * the documentService to set
510 public void setDocumentService(final DocumentService documentService) {
511 _documentService = documentService;
515 * Get the simulationContextService.
517 * @return the simulationContextService
519 public SimulationContextService getSimulationContextService() {
520 return _simulationContextService;
524 * Set the simulationContextService.
526 * @param simulationContextService
527 * the simulationContextService to set
529 public void setSimulationContextService(
530 final SimulationContextService simulationContextService) {
531 _simulationContextService = simulationContextService;
535 * Get the documentDAO.
537 * @return the documentDAO
539 public DocumentDAO getDocumentDAO() {
544 * Set the documentDAO.
547 * the documentDAO to set
549 public void setDocumentDAO(final DocumentDAO documentDAO) {
550 _documentDAO = documentDAO;
554 * Get the simulationContextDAO.
556 * @return the simulationContextDAO
558 public SimulationContextDAO getSimulationContextDAO() {
559 return _simulationContextDAO;
563 * Set the simulationContextDAO.
565 * @param simulationContextDAO
566 * the simulationContextDAO to set
568 public void setSimulationContextDAO(
569 final SimulationContextDAO simulationContextDAO) {
570 _simulationContextDAO = simulationContextDAO;
574 * Get the projectElementDAO.
576 * @return the projectElementDAO
578 public ProjectElementDAO getProjectElementDAO() {
579 return _projectElementDAO;
583 * Set the projectElementDAO.
585 * @param projectElementDAO
586 * the projectElementDAO to set
588 public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
589 _projectElementDAO = projectElementDAO;
593 * Get the indexService.
595 * @return the indexService
597 public IndexService getIndexService() {
598 return _indexService;
602 * Set the indexService.
604 * @param indexService
605 * the indexService to set
607 public void setIndexService(final IndexService indexService) {
608 _indexService = indexService;
614 * @return the fileDAO
616 public FileDAO getFileDAO() {
626 public void setFileDAO(final FileDAO fileDAO) {
631 * Get the documentTypeService.
633 * @return the documentTypeService
635 public DocumentTypeService getDocumentTypeService() {
636 return _documentTypeService;
640 * Set the documentTypeService.
642 * @param documentTypeService
643 * the documentTypeService to set
645 public void setDocumentTypeService(
646 final DocumentTypeService documentTypeService) {
647 _documentTypeService = documentTypeService;
651 * Get the versionsRelationDAO.
653 * @return the versionsRelationDAO
655 public VersionsRelationDAO getVersionsRelationDAO() {
656 return _versionsRelationDAO;
660 * Set the versionsRelationDAO.
662 * @param versionsRelationDAO
663 * the versionsRelationDAO to set
665 public void setVersionsRelationDAO(
666 final VersionsRelationDAO versionsRelationDAO) {
667 _versionsRelationDAO = versionsRelationDAO;
671 * Get project settings.
673 * @return Project settings service
675 private ProjectSettingsService getProjectSettings() {
676 return _projectSettings;
680 * Set project settings service.
682 * @param projectSettingsService
683 * project settings service
685 public void setProjectSettings(
686 final ProjectSettingsService projectSettingsService) {
687 _projectSettings = projectSettingsService;