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.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 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) 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 SimulationContext res = null;
123 getSimulationContextService().hold(context); // Increments the reference count of simulation context
124 if (aStep.getOwner().isSaved()) {
126 if (!context.isSaved()) {
127 getSimulationContextDAO().create(context);
129 aStep.getOwner().add(context);
130 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
131 getProjectElementDAO().update(aStep.getOwner());
132 updateKnowledgeElementsIndex(aStep);
134 } catch (Exception error) {
135 LOG.debug(error.getMessage(), error);
137 } else { // Happens when copying a scenario
138 aStep.getOwner().add(context);
139 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
140 // In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
147 * Update lucene index of knowledge elements of a scenario or a study which the given step is related to.
150 * the step (activity)
152 private void updateKnowledgeElementsIndex(final Step aStep) {
154 if (aStep.getOwner() instanceof Scenario) {
155 scenarii = new Scenario[1];
156 scenarii[0] = (Scenario) aStep.getOwner();
158 scenarii = aStep.getOwnerStudy().getScenarii();
161 for (int i = 0; i < scenarii.length; i++) {
162 Scenario scene = scenarii[i];
163 List<KnowledgeElement> knelm = scene.getAllKnowledgeElements();
164 for (Iterator<KnowledgeElement> j = knelm.iterator(); j
166 KnowledgeElement kelm = j.next();
167 getIndexService().update(kelm);
169 updateScenarioIndex(scene);
171 } catch (Exception error) {
172 LOG.error("Unable to re-index Knowledge Elements, reason:",
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, final SimulationContext context) {
207 SimulationContext torem = aStep
208 .getSimulationContext(context.getIndex());
210 boolean isOk = (torem != null) && (aStep.getOwner().remove(torem));
213 aStep.getContex().remove(torem);
214 getProjectElementDAO().update(aStep.getOwner());
215 if (torem.isShared()) {
216 getSimulationContextService().release(torem);
217 getSimulationContextDAO().update(torem);
219 getSimulationContextDAO().delete(torem);
228 * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
231 public Publication createDocument(final Step aStep, final Document.Properties dprop)
232 throws MissedPropertyException, InvalidPropertyException,
233 MultiplyDefinedException, IOException {
234 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
235 .setStep(aStep.getStep()));
236 getDocumentService().generateDocumentId(newdoc, dprop);
238 // Creation of the save directory
239 java.io.File wdir = getDocumentService().getSaveDirectory(newdoc);
240 if ((!wdir.exists()) && (!wdir.mkdirs())) {
241 throw new IOException(
242 "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,
258 final Document.Properties dprop) throws MissedPropertyException,
259 InvalidPropertyException, NotApplicableException {
260 String refid = dprop.getReference();
261 Publication res = null;
263 Document slot = getDocumentService().selectDocument(refid,
264 new Revision().toString());
265 if ((slot != null) && (slot.isUndefined())) {
266 getDocumentService().initialize(slot,
267 dprop.setOwner(aStep.getOwnerStudy()));
268 res = new Publication(slot, aStep.getOwner());
275 * Create a new version of a document in the given study step.
280 * the base document published version
281 * @return the new version publication
282 * @throws MissedPropertyException
283 * if a mandatory property is missed
284 * @throws InvalidPropertyException
285 * if some property doesn't exist
286 * @throws MultiplyDefinedException
287 * if some property is defined several times
288 * @throws IOException
289 * if a file system error occurs
290 * @throws MismatchException
291 * if the document is not applicable to the given study step
293 public Publication versionDocument(final Step aStep, final Publication base)
294 throws MissedPropertyException, InvalidPropertyException,
295 MultiplyDefinedException, IOException, MismatchException {
296 return versionDocument(aStep, base, new Document.Properties());
300 * Create a new version of a document in the given study step.
305 * the base document published version
307 * the comment for the new version
308 * @return the new version publication
309 * @throws MissedPropertyException
310 * if a mandatory property is missed
311 * @throws InvalidPropertyException
312 * if some property doesn't exist
313 * @throws MultiplyDefinedException
314 * if some property is defined several times
315 * @throws IOException
316 * if a file system error occurs
317 * @throws MismatchException
318 * if the document is not applicable to the given study step
320 public Publication versionDocument(final Step aStep, final Publication base,
321 final String reason) throws MissedPropertyException,
322 InvalidPropertyException, MultiplyDefinedException, IOException,
324 return versionDocument(aStep, base, new Document.Properties()
325 .setDescription(reason));
329 * Create a new version of a document in the given study step.
334 * the base document published version
336 * properties of the new version
337 * @return the new version publication
338 * @throws MissedPropertyException
339 * if a mandatory property is missed
340 * @throws InvalidPropertyException
341 * if some property doesn't exist
342 * @throws MultiplyDefinedException
343 * if some property is defined several times
344 * @throws IOException
345 * if a file system error occurs
346 * @throws MismatchException
347 * if the document is not applicable to the given study step
350 public Publication versionDocument(final Step aStep, final Publication base,
351 final Document.Properties dprop) throws MissedPropertyException,
352 InvalidPropertyException, MultiplyDefinedException, IOException,
354 Document previous = base.value();
356 dprop.setDocument(previous, getProjectSettings().getStep(base.getStep().getNumber())); // Initializes the Step property
357 if (dprop.getStep().getNumber() != aStep.getNumber()) {
358 throw new MismatchException();
361 if (dprop.getAuthor() == null) {
362 dprop.setAuthor(previous.getAuthor());
364 String summary = dprop.getDescription();
366 // Creation of the document
367 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
368 .setStep(aStep.getStep()));
369 getDocumentService().generateDocumentId(newdoc, dprop);
370 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwner(),
372 getDocumentDAO().create(newdoc);
375 VersionsRelation aRel;
376 aRel = new VersionsRelation(newdoc, previous, summary);
377 // getVersionsRelationDAO().create(aRel);
378 newdoc.addRelation(aRel);
380 // Update of usedby relations, if exist
381 List<Relation> relist = previous.getRelations(UsedByRelation.class);
382 Study scope = aStep.getOwnerStudy();
383 for (Iterator<Relation> i = relist.iterator(); i.hasNext();) {
384 UsedByRelation relation = (UsedByRelation) i.next();
385 Document relatedoc = relation.getTo();
386 if (scope.shares(relatedoc)) {
387 relatedoc.addRelation(new UsesRelation(relatedoc, newdoc));
389 relation.moveTo(newdoc);
392 return new Publication(newdoc, aStep.getOwner());
396 * Get document types which are applicable for the given study step (activity).
400 * @return the list of document types
402 public List<DocumentType> getValidDocumentTypes(final Step aStep) {
403 return getDocumentTypeService().selectTypesOf(aStep.getStep());
407 * Add a document publication to the given step.
410 * the target study step
412 * the document publication to add
413 * @return true if publication succeeded
415 public boolean add(final Step aStep, final Publication newdoc) {
416 boolean res = aStep.getOwner().add(newdoc); // Updates the study in memory
418 aStep.getDocuments().add(0, newdoc); // Updates this step
419 getDocumentService().hold(newdoc.value()); // Increments the configuration tag count of document
420 // If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
421 // database (it will be saved later by cascading the update of owner scenario).
427 * Remove a document publication from the given step.
432 * the document publication to remove
433 * @return true if removing of the publication succeeded
435 public boolean remove(final Step aStep, final Publication oldoc) {
436 boolean res = aStep.getOwner().remove(oldoc); // Updates the study in memory
438 aStep.getDocuments().remove(oldoc); // Updates this step
439 getDocumentService().release(oldoc.value()); // Decrements the configuration tag count of document
440 // The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
446 * Remove a document from the given step.
451 * the document publication
452 * @return true if removing of the document succeeded
455 public boolean removeDocument(final Step aStep, final Publication doctag) {
456 Document value = doctag.value();
457 getDocumentDAO().update(value);
458 Publication torem = aStep.getDocument(value.getIndex());
460 boolean res = (torem != null);
462 remove(aStep, torem);
463 getProjectElementDAO().update(aStep.getOwner());
464 if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
465 Set<Relation> links = value.getAllRelations(); // Get all relation of the document to remove them
466 List<Document> using = new ArrayList<Document>();
467 for (Iterator<Relation> i = links.iterator(); i.hasNext();) {
468 Relation link = i.next();
469 if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
470 getFileDAO().delete((File) link.getTo()); // The corresponding physical file is not removed from the vault
471 } else if (link.getClass().equals(UsesRelation.class)) { // Document dependency
472 using.add((Document) link.getTo());
475 for (Iterator<Document> i = using.iterator(); i.hasNext();) {
476 i.next().removeRelation(UsedByRelation.class, value); // TODO: RKV: don't use Database.getSession in removeRelation
478 getDocumentDAO().delete(value); // The corresponding physical file is not removed from the vault
485 * Get the documentService.
487 * @return the documentService
489 public DocumentService getDocumentService() {
490 return _documentService;
494 * Set the documentService.
496 * @param documentService
497 * the documentService to set
499 public void setDocumentService(final DocumentService documentService) {
500 _documentService = documentService;
504 * Get the simulationContextService.
506 * @return the simulationContextService
508 public SimulationContextService getSimulationContextService() {
509 return _simulationContextService;
513 * Set the simulationContextService.
515 * @param simulationContextService
516 * the simulationContextService to set
518 public void setSimulationContextService(
519 final SimulationContextService simulationContextService) {
520 _simulationContextService = simulationContextService;
524 * Get the documentDAO.
526 * @return the documentDAO
528 public DocumentDAO getDocumentDAO() {
533 * Set the documentDAO.
536 * the documentDAO to set
538 public void setDocumentDAO(final DocumentDAO documentDAO) {
539 _documentDAO = documentDAO;
543 * Get the simulationContextDAO.
545 * @return the simulationContextDAO
547 public SimulationContextDAO getSimulationContextDAO() {
548 return _simulationContextDAO;
552 * Set the simulationContextDAO.
554 * @param simulationContextDAO
555 * the simulationContextDAO to set
557 public void setSimulationContextDAO(
558 final SimulationContextDAO simulationContextDAO) {
559 _simulationContextDAO = simulationContextDAO;
563 * Get the projectElementDAO.
565 * @return the projectElementDAO
567 public ProjectElementDAO getProjectElementDAO() {
568 return _projectElementDAO;
572 * Set the projectElementDAO.
574 * @param projectElementDAO
575 * the projectElementDAO to set
577 public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
578 _projectElementDAO = projectElementDAO;
582 * Get the indexService.
584 * @return the indexService
586 public IndexService getIndexService() {
587 return _indexService;
591 * Set the indexService.
593 * @param indexService
594 * the indexService to set
596 public void setIndexService(final IndexService indexService) {
597 _indexService = indexService;
603 * @return the fileDAO
605 public FileDAO getFileDAO() {
615 public void setFileDAO(final FileDAO fileDAO) {
620 * Get the documentTypeService.
622 * @return the documentTypeService
624 public DocumentTypeService getDocumentTypeService() {
625 return _documentTypeService;
629 * Set the documentTypeService.
631 * @param documentTypeService
632 * the documentTypeService to set
634 public void setDocumentTypeService(final DocumentTypeService documentTypeService) {
635 _documentTypeService = documentTypeService;
639 * Get the versionsRelationDAO.
640 * @return the versionsRelationDAO
642 public VersionsRelationDAO getVersionsRelationDAO() {
643 return _versionsRelationDAO;
647 * Set the versionsRelationDAO.
648 * @param versionsRelationDAO the versionsRelationDAO to set
650 public void setVersionsRelationDAO(final VersionsRelationDAO versionsRelationDAO) {
651 _versionsRelationDAO = versionsRelationDAO;
655 * Get project settings.
657 * @return Project settings service
659 private ProjectSettingsService getProjectSettings() {
660 return _projectSettings;
664 * Set project settings service.
666 * @param projectSettingsService
667 * project settings service
669 public void setProjectSettings(
670 final ProjectSettingsService projectSettingsService) {
671 _projectSettings = projectSettingsService;