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.List;
16 import org.hibernate.criterion.Restrictions;
17 import org.splat.dal.bo.kernel.Relation;
18 import org.splat.dal.bo.kernel.User;
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.StepCommentAttribute;
29 import org.splat.dal.bo.som.UsedByRelation;
30 import org.splat.dal.bo.som.UsesRelation;
31 import org.splat.dal.bo.som.VersionsRelation;
32 import org.splat.dal.dao.kernel.RelationDAO;
33 import org.splat.dal.dao.kernel.UserDAO;
34 import org.splat.dal.dao.som.DocumentDAO;
35 import org.splat.dal.dao.som.FileDAO;
36 import org.splat.dal.dao.som.ProjectElementDAO;
37 import org.splat.dal.dao.som.PublicationDAO;
38 import org.splat.dal.dao.som.SimulationContextDAO;
39 import org.splat.dal.dao.som.StepCommentAttributeDAO;
40 import org.splat.dal.dao.som.VersionsRelationDAO;
41 import org.splat.exception.DocumentIsUsedException;
42 import org.splat.exception.InvalidParameterException;
43 import org.splat.kernel.InvalidPropertyException;
44 import org.splat.kernel.MismatchException;
45 import org.splat.kernel.MissedPropertyException;
46 import org.splat.kernel.MultiplyDefinedException;
47 import org.splat.kernel.NotApplicableException;
48 import org.splat.log.AppLogger;
49 import org.splat.service.dto.StepCommentDTO;
50 import org.splat.service.technical.IndexService;
51 import org.splat.service.technical.ProjectSettingsService;
52 import org.splat.som.Revision;
53 import org.splat.som.Step;
54 import org.splat.util.BeanHelper;
55 import org.springframework.transaction.annotation.Transactional;
58 * Step service implementation.
60 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
62 public class StepServiceImpl implements StepService {
65 * logger for the service.
67 public final static AppLogger LOG = AppLogger
68 .getLogger(StepServiceImpl.class);
70 * Injected index service.
72 private IndexService _indexService;
74 * Injected document service.
76 private DocumentService _documentService;
78 * Injected document type service.
80 private DocumentTypeService _documentTypeService;
82 * Injected document DAO.
84 private DocumentDAO _documentDAO;
86 * Injected relation DAO.
88 private RelationDAO _relationDAO;
92 private FileDAO _fileDAO;
94 * Injected simulation context service.
96 private SimulationContextService _simulationContextService;
98 * Injected simulation context DAO.
100 private SimulationContextDAO _simulationContextDAO;
102 * Injected project element DAO.
104 private ProjectElementDAO _projectElementDAO;
106 * Injected versions relation DAO.
108 private VersionsRelationDAO _versionsRelationDAO;
110 * Injected project service.
112 private ProjectSettingsService _projectSettings;
114 * Injected publication DAO.
116 private PublicationDAO _publicationDAO;
119 * Injected text attribute DAO.
121 private StepCommentAttributeDAO _stepCommentAttributeDAO;
126 private UserDAO _userDAO;
131 * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext.Properties)
134 public SimulationContext addSimulationContext(final Step aStep,
135 final SimulationContext.Properties dprop)
136 throws MissedPropertyException, InvalidPropertyException,
137 MultiplyDefinedException {
138 SimulationContext context = new SimulationContext(dprop.setStep(aStep
140 return addSimulationContext(aStep, context);
146 * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
150 public SimulationContext addSimulationContext(final Step aStep,
151 final SimulationContext context) {
152 SimulationContext res = null;
153 getSimulationContextService().hold(context); // Increments the reference count of simulation context
154 if (aStep.getOwner().isSaved()) {
156 if (!context.isSaved()) {
157 getSimulationContextDAO().create(context);
159 aStep.getOwner().add(context);
160 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
161 getProjectElementDAO().update(aStep.getOwner());
162 updateKnowledgeElementsIndex(aStep);
164 } catch (Exception error) {
165 LOG.debug(error.getMessage(), error);
167 } else { // Happens when copying a scenario
168 aStep.getOwner().add(context);
169 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
170 // In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
177 * Update lucene index of knowledge elements of a scenario or a study which the given step is related to.
180 * the step (activity)
182 private void updateKnowledgeElementsIndex(final Step aStep) {
184 if (aStep.getOwner() instanceof Scenario) {
185 scenarii = new Scenario[1];
186 scenarii[0] = (Scenario) aStep.getOwner();
188 scenarii = aStep.getOwnerStudy().getScenarii();
190 for (int i = 0; i < scenarii.length; i++) {
191 Scenario scene = scenarii[i];
192 updateScenarioIndex(scene);
197 * Update lucene index for knowledge elements of the scenario.
202 private void updateScenarioIndex(final Scenario scene) {
203 if (scene.getUcase() == null) {
204 for (KnowledgeElement kelm : scene.getKnowledgeElements()) {
205 if (kelm.getType().equals("usecase")) {
206 scene.setUcase(kelm);
216 * @see org.splat.service.StepService#removeSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
220 public boolean removeSimulationContext(final Step aStep,
221 final SimulationContext context) {
222 SimulationContext torem = aStep
223 .getSimulationContext(context.getIndex());
225 boolean isOk = (torem != null) && (aStep.getOwner().remove(torem));
228 aStep.getContex().remove(torem);
229 getProjectElementDAO().update(aStep.getOwner());
230 if (torem.isShared()) {
231 getSimulationContextService().release(torem);
232 getSimulationContextDAO().update(torem);
234 getSimulationContextDAO().delete(torem);
243 * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
247 public Publication createDocument(final Step aStep,
248 final Document.Properties dprop) throws MissedPropertyException,
249 InvalidPropertyException, MultiplyDefinedException, IOException {
250 if (LOG.isDebugEnabled()) {
251 LOG.debug("Local index before: "
252 + aStep.getOwnerStudy().getLastLocalIndex());
254 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
255 .setStep(aStep.getStep()));
256 getDocumentService().generateDocumentId(newdoc, dprop);
258 // Creation of the save directory
259 java.io.File wdir = getDocumentService().getSaveDirectory(newdoc);
260 if ((!wdir.exists()) && (!wdir.mkdirs())) {
261 throw new IOException(
262 "Cannot create the repository vault directory");
265 // Identification and save
266 if (LOG.isDebugEnabled()) {
267 LOG.debug("Local index after: "
268 + aStep.getOwnerStudy().getLastLocalIndex());
270 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwnerStudy());
271 getDocumentDAO().create(newdoc);
273 return new Publication(newdoc, aStep.getOwner());
279 * @see org.splat.service.StepService#assignDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
282 public Publication assignDocument(final Step aStep,
283 final Document.Properties dprop) throws MissedPropertyException,
284 InvalidPropertyException, NotApplicableException {
285 String refid = dprop.getReference();
286 Publication res = null;
288 Document slot = getDocumentService().selectDocument(refid,
289 new Revision().toString());
290 if ((slot != null) && (slot.isUndefined())) {
291 getDocumentService().initialize(slot,
292 dprop.setOwner(aStep.getOwnerStudy()));
293 res = new Publication(slot, aStep.getOwner());
300 * Create a new version of a document in the given study step.
305 * the base document published version
306 * @return the new version publication
307 * @throws MissedPropertyException
308 * if a mandatory property is missed
309 * @throws InvalidPropertyException
310 * if some property doesn't exist
311 * @throws MultiplyDefinedException
312 * if some property is defined several times
313 * @throws IOException
314 * if a file system error occurs
315 * @throws MismatchException
316 * if the document is not applicable to the given study step
318 public Publication versionDocument(final Step aStep, final Publication base)
319 throws MissedPropertyException, InvalidPropertyException,
320 MultiplyDefinedException, IOException, MismatchException {
321 return versionDocument(aStep, base, new Document.Properties());
325 * Create a new version of a document in the given study step.
330 * the base document published version
332 * the comment for the new version
333 * @return the new version publication
334 * @throws MissedPropertyException
335 * if a mandatory property is missed
336 * @throws InvalidPropertyException
337 * if some property doesn't exist
338 * @throws MultiplyDefinedException
339 * if some property is defined several times
340 * @throws IOException
341 * if a file system error occurs
342 * @throws MismatchException
343 * if the document is not applicable to the given study step
345 public Publication versionDocument(final Step aStep,
346 final Publication base, final String reason)
347 throws MissedPropertyException, InvalidPropertyException,
348 MultiplyDefinedException, IOException, MismatchException {
349 return versionDocument(aStep, base, new Document.Properties()
350 .setDescription(reason));
354 * Create a new version of a document in the given study step.
359 * the base document published version
361 * properties of the new version
362 * @return the new version publication
363 * @throws MissedPropertyException
364 * if a mandatory property is missed
365 * @throws InvalidPropertyException
366 * if some property doesn't exist
367 * @throws MultiplyDefinedException
368 * if some property is defined several times
369 * @throws IOException
370 * if a file system error occurs
371 * @throws MismatchException
372 * if the document is not applicable to the given study step
375 public Publication versionDocument(final Step aStep,
376 final Publication base, final Document.Properties dprop)
377 throws MissedPropertyException, InvalidPropertyException,
378 MultiplyDefinedException, IOException, MismatchException {
379 Document previous = base.value();
381 // RKV: Keep the new file format if it is related to the same document type on this step.
382 String newFormat = dprop.getFormat();
384 dprop.setDocument(previous, getProjectSettings().getStep(
385 base.getStep().getNumber())); // Initializes the Step property
386 if (dprop.getStep().getNumber() != aStep.getNumber()) {
387 throw new MismatchException();
390 if (newFormat != null
392 * && previous.getType().equals( getProjectSettings().getDefaultDocumentType( aStep.getStep(), newFormat))
394 dprop.setFormat(newFormat);
397 if (dprop.getAuthor() == null) {
398 dprop.setAuthor(previous.getAuthor());
400 String summary = dprop.getDescription();
402 // Creation of the document
403 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
404 .setStep(aStep.getStep()));
405 getDocumentService().generateDocumentId(newdoc, dprop);
406 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwner(),
408 getDocumentDAO().create(newdoc);
411 VersionsRelation aRel;
412 aRel = new VersionsRelation(newdoc, previous, summary);
413 // getVersionsRelationDAO().create(aRel);
414 newdoc.addRelation(aRel);
416 // Update of usedby relations, if exist
418 * RKV: Consider the new version as not used by old dependent documents. So these documents must be marked as outdated then. List<Relation>
419 * relist = previous.getRelations(UsedByRelation.class); Study scope = aStep.getOwnerStudy(); for (Iterator<Relation> i =
420 * relist.iterator(); i.hasNext();) { UsedByRelation relation = (UsedByRelation) i.next(); Document relatedoc = relation.getTo(); if
421 * (scope.shares(relatedoc)) { relatedoc.addRelation(new UsesRelation(relatedoc, newdoc)); } else { relation.moveTo(newdoc); } }
423 return new Publication(newdoc, aStep.getOwner());
427 * Get document types which are applicable for the given study step (activity).
431 * @return the list of document types
434 public List<DocumentType> getValidDocumentTypes(final Step aStep) {
435 return getDocumentTypeService().selectTypesOf(aStep.getStep());
439 * Add a document publication to the given step.
442 * the target study step
444 * the document publication to add
445 * @return true if publication succeeded
448 public boolean add(final Step aStep, final Publication newdoc) {
449 boolean res = aStep.getOwner().add(newdoc); // Updates the study in memory
451 aStep.getDocuments().add(0, newdoc); // Updates this step
452 getDocumentService().hold(newdoc.value()); // Increments the configuration tag count of document
453 // If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
454 // database (it will be saved later by cascading the update of owner scenario).
460 * Remove a document publication from the given step.
465 * the document publication to remove
466 * @return true if removing of the publication succeeded
469 public boolean remove(final Step aStep, final Publication oldoc) {
470 aStep.getDocuments().remove(oldoc); // Updates this step
471 aStep.getOwner().remove(oldoc); // remove from the parent project element
472 getProjectElementDAO().merge(aStep.getOwner().getOwnerStudy());
473 getDocumentService().release(oldoc.value()); // Decrements the configuration tag count of document
474 // The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
479 * Remove a document from the given step and from the database if it is no more used.
485 * @return true if removing of the document succeeded
486 * @throws DocumentIsUsedException
487 * if the document is used by other documents
491 public boolean removeDocument(final Step aStep, final long docId)
492 throws DocumentIsUsedException {
493 Publication torem = aStep.getDocument(docId);
494 boolean res = (torem != null);
496 if (!torem.value().getRelations(UsedByRelation.class).isEmpty()) {
497 throw new DocumentIsUsedException(torem.value().getTitle());
499 remove(aStep, torem);
500 Document value = torem.value();
501 if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
502 List<Document> using = new ArrayList<Document>();
503 List<File> files = new ArrayList<File>();
504 for (Relation link : value.getAllRelations()) {
505 if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
506 files.add((File) link.getTo());
507 } else if (link.getClass().equals(UsesRelation.class)) { // Document dependency
508 using.add((Document) link.getTo());
511 // Remove relations from depending documents
512 if (LOG.isDebugEnabled()) {
513 LOG.debug("Remove " + using.size() + " UsedByRelation(s).");
515 for (Document doc : using) {
516 if (LOG.isDebugEnabled()) {
517 LOG.debug("Remove UsedByRelation from "
518 + doc.getTitle() + " to " + value.getTitle());
519 LOG.debug("Nb relations of doc " + doc.getTitle()
520 + " before: " + doc.getAllRelations().size());
522 doc.removeRelation(UsedByRelation.class, value);
523 if (LOG.isDebugEnabled()) {
524 LOG.debug("Nb relations of doc " + doc.getTitle()
525 + " after: " + doc.getAllRelations().size());
527 getDocumentDAO().merge(doc);
529 // Synchronize deleted objects with the database to avoid hibernate exception
530 // org.hibernate.PropertyValueException: not-null property references a null or transient value
531 getDocumentDAO().flush();
532 // The corresponding physical file is not removed from the vault
533 getDocumentDAO().delete(getDocumentDAO().merge(torem.value()));
534 // Delete document's files
535 //TODO: delete files from file system
536 // for (File file : files) {
537 // getFileDAO().delete(getFileDAO().merge(file)); // The corresponding physical file is not removed from the vault
547 * @see org.splat.service.StepService#addComment(org.splat.som.Step, org.splat.dal.bo.som.CommentAttribute)
551 public void addStepComment(final StepCommentDTO comment)
552 throws InvalidParameterException {
554 if (comment.getId() != null) {
555 throw new InvalidParameterException("id", String.valueOf(comment
558 User user = getUserDAO().get(comment.getUserId());
560 throw new InvalidParameterException("userId", String
561 .valueOf(comment.getUserId()));
563 ProjectElement projectElement = getProjectElementDAO().get(
564 comment.getProjectElementId());
565 if (projectElement == null) {
566 throw new InvalidParameterException("projectElementId", comment
567 .getProjectElementId().toString());
569 if (comment.getStep() == null || comment.getStep() < 0) {
570 throw new InvalidParameterException("step", String.valueOf(comment
573 if (comment.getDate() == null) {
574 throw new InvalidParameterException("date", String.valueOf(comment
577 if (comment.getTitle() == null) {
578 throw new InvalidParameterException("title", String.valueOf(comment
582 StepCommentAttribute newComment = new StepCommentAttribute(
583 projectElement, comment.getText(), comment.getDate(), comment
584 .getStep(), user, comment.getTitle());
586 Long resultKey = getStepCommentAttributeDAO().create(newComment);
587 comment.setId(resultKey);
593 * @see org.splat.service.StepService#getStepComments(org.splat.som.Step)
596 @Transactional(readOnly = true)
597 public List<StepCommentDTO> getStepComments(final Step step)
598 throws InvalidParameterException {
599 ProjectElement owner = _projectElementDAO.get(step.getOwner().getRid());
601 throw new InvalidParameterException("step owner id", Long.valueOf(
602 step.getOwner().getRid()).toString());
604 List<StepCommentAttribute> comments = _stepCommentAttributeDAO
605 .getFilteredList(Restrictions.and(Restrictions.eq("step",
606 Integer.valueOf(step.getNumber())), Restrictions.eq(
608 List<StepCommentDTO> commentDTOs = new ArrayList<StepCommentDTO>();
609 for (StepCommentAttribute comment : comments) {
610 StepCommentDTO stepCommentDTO = BeanHelper.copyBean(comment,
611 StepCommentDTO.class);
612 stepCommentDTO.setText(comment.getValue());
613 stepCommentDTO.setId(Long.valueOf(comment.getRid()));
614 commentDTOs.add(stepCommentDTO);
622 * @see org.splat.service.StepService#removeStepComment(long)
626 public void removeStepComment(final long commentId)
627 throws InvalidParameterException {
628 StepCommentAttribute stepComment = _stepCommentAttributeDAO.get(Long
629 .valueOf(commentId));
630 if (stepComment == null) {
631 throw new InvalidParameterException("commentId", String
632 .valueOf(commentId));
634 _stepCommentAttributeDAO.delete(stepComment);
640 * @see org.splat.service.StepService#editStepComment(long, java.lang.String, java.lang.String)
644 public void editStepComment(final long commentId, final String newValue,
645 final String newTitle) throws InvalidParameterException {
646 StepCommentAttribute comment = _stepCommentAttributeDAO.get(Long
647 .valueOf(commentId));
648 if (comment == null) {
649 throw new InvalidParameterException("commentId", String
650 .valueOf(commentId));
652 if (newTitle != null) {
653 comment.setTitle(newTitle);
655 if (newValue != null) {
656 comment.setValue(newValue);
658 _stepCommentAttributeDAO.update(comment);
664 * @see org.splat.service.StepService#isCommentMadeByUser(long, long)
667 @Transactional(readOnly = true)
668 public boolean isCommentMadeByUser(final long commentId, final long userId)
669 throws InvalidParameterException {
670 StepCommentAttribute comment = _stepCommentAttributeDAO.get(Long
671 .valueOf(commentId));
672 if (comment == null) {
673 throw new InvalidParameterException("commentId", String
674 .valueOf(commentId));
676 return comment.getUser().getIndex() == userId;
680 * Get the documentService.
682 * @return the documentService
684 public DocumentService getDocumentService() {
685 return _documentService;
689 * Set the documentService.
691 * @param documentService
692 * the documentService to set
694 public void setDocumentService(final DocumentService documentService) {
695 _documentService = documentService;
699 * Get the simulationContextService.
701 * @return the simulationContextService
703 public SimulationContextService getSimulationContextService() {
704 return _simulationContextService;
708 * Set the simulationContextService.
710 * @param simulationContextService
711 * the simulationContextService to set
713 public void setSimulationContextService(
714 final SimulationContextService simulationContextService) {
715 _simulationContextService = simulationContextService;
719 * Get the documentDAO.
721 * @return the documentDAO
723 public DocumentDAO getDocumentDAO() {
728 * Set the documentDAO.
731 * the documentDAO to set
733 public void setDocumentDAO(final DocumentDAO documentDAO) {
734 _documentDAO = documentDAO;
738 * Get the simulationContextDAO.
740 * @return the simulationContextDAO
742 public SimulationContextDAO getSimulationContextDAO() {
743 return _simulationContextDAO;
747 * Set the simulationContextDAO.
749 * @param simulationContextDAO
750 * the simulationContextDAO to set
752 public void setSimulationContextDAO(
753 final SimulationContextDAO simulationContextDAO) {
754 _simulationContextDAO = simulationContextDAO;
758 * Get the projectElementDAO.
760 * @return the projectElementDAO
762 public ProjectElementDAO getProjectElementDAO() {
763 return _projectElementDAO;
767 * Set the projectElementDAO.
769 * @param projectElementDAO
770 * the projectElementDAO to set
772 public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
773 _projectElementDAO = projectElementDAO;
777 * Get the indexService.
779 * @return the indexService
781 public IndexService getIndexService() {
782 return _indexService;
786 * Set the indexService.
788 * @param indexService
789 * the indexService to set
791 public void setIndexService(final IndexService indexService) {
792 _indexService = indexService;
798 * @return the fileDAO
800 public FileDAO getFileDAO() {
810 public void setFileDAO(final FileDAO fileDAO) {
815 * Get the documentTypeService.
817 * @return the documentTypeService
819 public DocumentTypeService getDocumentTypeService() {
820 return _documentTypeService;
824 * Set the documentTypeService.
826 * @param documentTypeService
827 * the documentTypeService to set
829 public void setDocumentTypeService(
830 final DocumentTypeService documentTypeService) {
831 _documentTypeService = documentTypeService;
835 * Get the versionsRelationDAO.
837 * @return the versionsRelationDAO
839 public VersionsRelationDAO getVersionsRelationDAO() {
840 return _versionsRelationDAO;
844 * Set the versionsRelationDAO.
846 * @param versionsRelationDAO
847 * the versionsRelationDAO to set
849 public void setVersionsRelationDAO(
850 final VersionsRelationDAO versionsRelationDAO) {
851 _versionsRelationDAO = versionsRelationDAO;
855 * Get project settings.
857 * @return Project settings service
859 private ProjectSettingsService getProjectSettings() {
860 return _projectSettings;
864 * Set project settings service.
866 * @param projectSettingsService
867 * project settings service
869 public void setProjectSettings(
870 final ProjectSettingsService projectSettingsService) {
871 _projectSettings = projectSettingsService;
875 * Get the stepCommentAttributeDAO.
877 * @return the stepCommentAttributeDAO
879 public StepCommentAttributeDAO getStepCommentAttributeDAO() {
880 return _stepCommentAttributeDAO;
884 * Set the stepCommentAttributeDAO.
886 * @param commentAttributeDAO
887 * the stepCommentAttributeDAO to set
889 public void setStepCommentAttributeDAO(
890 final StepCommentAttributeDAO commentAttributeDAO) {
891 _stepCommentAttributeDAO = commentAttributeDAO;
897 * @return the userDAO
899 public UserDAO getUserDAO() {
909 public void setUserDAO(final UserDAO userDAO) {
914 * Get the publicationDAO.
916 * @return the publicationDAO
918 public PublicationDAO getPublicationDAO() {
919 return _publicationDAO;
923 * Set the publicationDAO.
925 * @param publicationDAO
926 * the publicationDAO to set
928 public void setPublicationDAO(final PublicationDAO publicationDAO) {
929 this._publicationDAO = publicationDAO;
933 * Get the relationDAO.
935 * @return the relationDAO
937 public RelationDAO getRelationDAO() {
942 * Set the relationDAO.
945 * the relationDAO to set
947 public void setRelationDAO(final RelationDAO relationDAO) {
948 _relationDAO = relationDAO;