1 /*****************************************************************************
5 * Creation date 06.10.2012
8 *****************************************************************************/
10 package org.splat.service;
12 import java.io.IOException;
13 import java.util.Iterator;
14 import java.util.List;
16 import java.util.Vector;
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;
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 logger = 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 _projectSettingsService;
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) throws MissedPropertyException,
108 InvalidPropertyException, MultiplyDefinedException {
109 SimulationContext context = new SimulationContext(dprop.setStep(aStep
111 return addSimulationContext(aStep, context);
117 * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
120 public SimulationContext addSimulationContext(final Step aStep,
121 final SimulationContext context) {
122 getSimulationContextService().hold(context); // Increments the reference count of simulation context
123 if (aStep.getOwner().isSaved()) {
125 if (!context.isSaved()) {
126 getSimulationContextDAO().create(context);
128 aStep.getOwner().add(context);
129 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
130 getProjectElementDAO().update(aStep.getOwner());
131 updateKnowledgeElementsIndex(aStep);
132 } catch (Exception error) {
135 } else { // Happens when copying a scenario
136 aStep.getOwner().add(context);
137 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
138 // In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
144 * Update lucene index of knowledge elements of a scenario or a study which the given step is related to.
147 * the step (activity)
149 private void updateKnowledgeElementsIndex(final Step aStep) {
151 if (aStep.getOwner() instanceof Scenario) {
152 scenarii = new Scenario[1];
153 scenarii[0] = (Scenario) aStep.getOwner();
155 scenarii = aStep.getOwnerStudy().getScenarii();
158 for (int i = 0; i < scenarii.length; i++) {
159 Scenario scene = scenarii[i];
160 List<KnowledgeElement> knelm = scene.getAllKnowledgeElements();
161 for (Iterator<KnowledgeElement> j = knelm.iterator(); j
163 KnowledgeElement kelm = j.next();
164 getIndexService().update(kelm);
166 updateScenarioIndex(scene);
168 } catch (Exception error) {
169 logger.error("Unable to re-index Knowledge Elements, reason:",
175 * Update lucene index for knowledge elements of the scenario.
179 * @throws IOException
180 * if can't update lucene index
182 private void updateScenarioIndex(final Scenario scene) throws IOException {
183 if (scene.getUcase() == null) {
184 for (Iterator<KnowledgeElement> i = scene.getKnowledgeElements()
185 .iterator(); i.hasNext();) {
186 KnowledgeElement kelm = i.next();
187 if (!kelm.getType().equals("usecase")) {
190 scene.setUcase(kelm);
194 getIndexService().update(scene.getUcase());
200 * @see org.splat.service.StepService#removeSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
203 public boolean removeSimulationContext(final Step aStep, final SimulationContext context) {
204 boolean isOk = false;
205 SimulationContext torem = aStep
206 .getSimulationContext(context.getIndex());
208 if ((torem != null) && (aStep.getOwner().remove(torem))) {
210 aStep.getContex().remove(torem);
211 getProjectElementDAO().update(aStep.getOwner());
212 if (torem.isShared()) {
213 getSimulationContextService().release(torem);
214 getSimulationContextDAO().update(torem);
216 getSimulationContextDAO().delete(torem);
226 * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
229 public Publication createDocument(final Step aStep, final Document.Properties dprop)
230 throws MissedPropertyException, InvalidPropertyException,
231 MultiplyDefinedException, IOException {
232 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
233 .setStep(aStep.getStep()));
234 getDocumentService().generateDocumentId(newdoc, dprop);
236 // Creation of the save directory
237 java.io.File wdir = getDocumentService().getSaveDirectory(newdoc);
238 if (!wdir.exists()) {
239 if (!wdir.mkdirs()) {
240 throw new IOException(
241 "Cannot create the repository vault directory");
245 // Identification and save
246 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwnerStudy());
247 getDocumentDAO().create(newdoc);
249 return new Publication(newdoc, aStep.getOwner());
255 * @see org.splat.service.StepService#assignDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
257 public Publication assignDocument(final Step aStep, final Document.Properties dprop)
258 throws MissedPropertyException, InvalidPropertyException,
259 NotApplicableException {
260 String refid = dprop.getReference();
265 Document slot = getDocumentService().selectDocument(refid,
266 new Revision().toString());
270 if (!slot.isUndefined()) {
271 return null; // Should not happen
274 getDocumentService().initialize(slot,
275 dprop.setOwner(aStep.getOwnerStudy()));
276 return new Publication(slot, aStep.getOwner());
280 * Create a new version of a document in the given study step.
285 * the base document published version
286 * @return the new version publication
287 * @throws MissedPropertyException
288 * if a mandatory property is missed
289 * @throws InvalidPropertyException
290 * if some property doesn't exist
291 * @throws MultiplyDefinedException
292 * if some property is defined several times
293 * @throws IOException
294 * if a file system error occurs
295 * @throws MismatchException
296 * if the document is not applicable to the given study step
298 public Publication versionDocument(final Step aStep, final Publication base)
299 throws MissedPropertyException, InvalidPropertyException,
300 MultiplyDefinedException, IOException, MismatchException {
301 return versionDocument(aStep, base, new Document.Properties());
305 * Create a new version of a document in the given study step.
310 * the base document published version
312 * the comment for the new version
313 * @return the new version publication
314 * @throws MissedPropertyException
315 * if a mandatory property is missed
316 * @throws InvalidPropertyException
317 * if some property doesn't exist
318 * @throws MultiplyDefinedException
319 * if some property is defined several times
320 * @throws IOException
321 * if a file system error occurs
322 * @throws MismatchException
323 * if the document is not applicable to the given study step
325 public Publication versionDocument(final Step aStep, final Publication base,
326 final String reason) throws MissedPropertyException,
327 InvalidPropertyException, MultiplyDefinedException, IOException,
329 return versionDocument(aStep, base, new Document.Properties()
330 .setDescription(reason));
334 * Create a new version of a document in the given study step.
339 * the base document published version
341 * properties of the new version
342 * @return the new version publication
343 * @throws MissedPropertyException
344 * if a mandatory property is missed
345 * @throws InvalidPropertyException
346 * if some property doesn't exist
347 * @throws MultiplyDefinedException
348 * if some property is defined several times
349 * @throws IOException
350 * if a file system error occurs
351 * @throws MismatchException
352 * if the document is not applicable to the given study step
355 public Publication versionDocument(final Step aStep, final Publication base,
356 final Document.Properties dprop) throws MissedPropertyException,
357 InvalidPropertyException, MultiplyDefinedException, IOException,
359 Document previous = base.value();
361 dprop.setDocument(previous, getProjectSettings().getStep(base.getStep().getNumber())); // Initializes the Step property
362 if (dprop.getStep().getNumber() != aStep.getNumber()) {
363 throw new MismatchException();
366 if (dprop.getAuthor() == null) {
367 dprop.setAuthor(previous.getAuthor());
369 String summary = dprop.getDescription();
371 // Creation of the document
372 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
373 .setStep(aStep.getStep()));
374 getDocumentService().generateDocumentId(newdoc, dprop);
375 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwner(),
377 getDocumentDAO().create(newdoc);
380 VersionsRelation aRel;
381 aRel = new VersionsRelation(newdoc, previous, summary);
382 // getVersionsRelationDAO().create(aRel);
383 newdoc.addRelation(aRel);
385 // Update of usedby relations, if exist
386 List<Relation> relist = previous.getRelations(UsedByRelation.class);
387 Study scope = aStep.getOwnerStudy();
388 for (Iterator<Relation> i = relist.iterator(); i.hasNext();) {
389 UsedByRelation relation = (UsedByRelation) i.next();
390 Document relatedoc = relation.getTo();
391 if (scope.shares(relatedoc)) {
392 relatedoc.addRelation(new UsesRelation(relatedoc, newdoc));
394 relation.moveTo(newdoc);
397 return new Publication(newdoc, aStep.getOwner());
401 * Get document types which are applicable for the given study step (activity).
405 * @return the list of document types
407 public List<DocumentType> getValidDocumentTypes(final Step aStep) {
408 return getDocumentTypeService().selectTypesOf(aStep.getStep());
412 * Add a document publication to the given step.
415 * the target study step
417 * the document publication to add
418 * @return true if publication succeeded
420 public boolean add(final Step aStep, final Publication newdoc) {
421 if (!aStep.getOwner().add(newdoc)) {
422 return false; // Updates the study in memory
424 aStep.getDocuments().add(0, newdoc); // Updates this step
425 getDocumentService().hold(newdoc.value()); // Increments the configuration tag count of document
426 // If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
427 // database (it will be saved later by cascading the update of owner scenario).
432 * Remove a document publication from the given step.
437 * the document publication to remove
438 * @return true if removing of the publication succeeded
440 public boolean remove(final Step aStep, final Publication oldoc) {
441 if (!aStep.getOwner().remove(oldoc)) {
442 return false; // Updates the study in memory
444 aStep.getDocuments().remove(oldoc); // Updates this step
445 getDocumentService().release(oldoc.value()); // Decrements the configuration tag count of document
446 // The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
451 * Remove a document from the given step.
456 * the document publication
457 * @return true if removing of the document succeeded
460 public boolean removeDocument(final Step aStep, final Publication doctag) {
461 Document value = doctag.value();
462 getDocumentDAO().update(value);
463 Publication torem = aStep.getDocument(value.getIndex());
469 remove(aStep, torem);
470 getProjectElementDAO().update(aStep.getOwner());
471 if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
472 Set<Relation> links = value.getAllRelations(); // Get all relation of the document to remove them
473 List<Document> using = new Vector<Document>();
474 for (Iterator<Relation> i = links.iterator(); i.hasNext();) {
475 Relation link = i.next();
476 if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
477 getFileDAO().delete((File) link.getTo()); // The corresponding physical file is not removed from the vault
478 } else if (link.getClass().equals(UsesRelation.class)) { // Document dependency
479 using.add((Document) link.getTo());
482 for (Iterator<Document> i = using.iterator(); i.hasNext();) {
483 i.next().removeRelation(UsedByRelation.class, value); // TODO: RKV: don't use Database.getSession in removeRelation
485 getDocumentDAO().delete(value); // The corresponding physical file is not removed from the vault
491 * Get the documentService.
493 * @return the documentService
495 public DocumentService getDocumentService() {
496 return _documentService;
500 * Set the documentService.
502 * @param documentService
503 * the documentService to set
505 public void setDocumentService(final DocumentService documentService) {
506 _documentService = documentService;
510 * Get the simulationContextService.
512 * @return the simulationContextService
514 public SimulationContextService getSimulationContextService() {
515 return _simulationContextService;
519 * Set the simulationContextService.
521 * @param simulationContextService
522 * the simulationContextService to set
524 public void setSimulationContextService(
525 final SimulationContextService simulationContextService) {
526 _simulationContextService = simulationContextService;
530 * Get the documentDAO.
532 * @return the documentDAO
534 public DocumentDAO getDocumentDAO() {
539 * Set the documentDAO.
542 * the documentDAO to set
544 public void setDocumentDAO(final DocumentDAO documentDAO) {
545 _documentDAO = documentDAO;
549 * Get the simulationContextDAO.
551 * @return the simulationContextDAO
553 public SimulationContextDAO getSimulationContextDAO() {
554 return _simulationContextDAO;
558 * Set the simulationContextDAO.
560 * @param simulationContextDAO
561 * the simulationContextDAO to set
563 public void setSimulationContextDAO(
564 final SimulationContextDAO simulationContextDAO) {
565 _simulationContextDAO = simulationContextDAO;
569 * Get the projectElementDAO.
571 * @return the projectElementDAO
573 public ProjectElementDAO getProjectElementDAO() {
574 return _projectElementDAO;
578 * Set the projectElementDAO.
580 * @param projectElementDAO
581 * the projectElementDAO to set
583 public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
584 _projectElementDAO = projectElementDAO;
588 * Get the indexService.
590 * @return the indexService
592 public IndexService getIndexService() {
593 return _indexService;
597 * Set the indexService.
599 * @param indexService
600 * the indexService to set
602 public void setIndexService(final IndexService indexService) {
603 _indexService = indexService;
609 * @return the fileDAO
611 public FileDAO getFileDAO() {
621 public void setFileDAO(final FileDAO fileDAO) {
626 * Get the documentTypeService.
628 * @return the documentTypeService
630 public DocumentTypeService getDocumentTypeService() {
631 return _documentTypeService;
635 * Set the documentTypeService.
637 * @param documentTypeService
638 * the documentTypeService to set
640 public void setDocumentTypeService(final DocumentTypeService documentTypeService) {
641 _documentTypeService = documentTypeService;
645 * Get the versionsRelationDAO.
646 * @return the versionsRelationDAO
648 public VersionsRelationDAO getVersionsRelationDAO() {
649 return _versionsRelationDAO;
653 * Set the versionsRelationDAO.
654 * @param versionsRelationDAO the versionsRelationDAO to set
656 public void setVersionsRelationDAO(final VersionsRelationDAO versionsRelationDAO) {
657 _versionsRelationDAO = versionsRelationDAO;
661 * Get project settings.
663 * @return Project settings service
665 private ProjectSettingsService getProjectSettings() {
666 return _projectSettingsService;
670 * Set project settings service.
672 * @param projectSettingsService
673 * project settings service
675 public void setProjectSettings(
676 final ProjectSettingsService projectSettingsService) {
677 _projectSettingsService = projectSettingsService;