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());
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 for (File file : files) {
536 getFileDAO().delete(getFileDAO().merge(file)); // The corresponding physical file is not removed from the vault
546 * @see org.splat.service.StepService#addComment(org.splat.som.Step, org.splat.dal.bo.som.CommentAttribute)
550 public void addStepComment(final StepCommentDTO comment)
551 throws InvalidParameterException {
553 if (comment.getId() != null) {
554 throw new InvalidParameterException("id", String.valueOf(comment
557 User user = getUserDAO().get(comment.getUserId());
559 throw new InvalidParameterException("userId", String
560 .valueOf(comment.getUserId()));
562 ProjectElement projectElement = getProjectElementDAO().get(
563 comment.getProjectElementId());
564 if (projectElement == null) {
565 throw new InvalidParameterException("projectElementId", comment
566 .getProjectElementId().toString());
568 if (comment.getStep() == null || comment.getStep() < 0) {
569 throw new InvalidParameterException("step", String.valueOf(comment
572 if (comment.getDate() == null) {
573 throw new InvalidParameterException("date", String.valueOf(comment
576 if (comment.getTitle() == null) {
577 throw new InvalidParameterException("title", String.valueOf(comment
581 StepCommentAttribute newComment = new StepCommentAttribute(
582 projectElement, comment.getText(), comment.getDate(), comment
583 .getStep(), user, comment.getTitle());
585 Long resultKey = getStepCommentAttributeDAO().create(newComment);
586 comment.setId(resultKey);
592 * @see org.splat.service.StepService#getStepComments(org.splat.som.Step)
595 @Transactional(readOnly = true)
596 public List<StepCommentDTO> getStepComments(final Step step)
597 throws InvalidParameterException {
598 ProjectElement owner = _projectElementDAO.get(step.getOwner().getRid());
600 throw new InvalidParameterException("step owner id", Long.valueOf(
601 step.getOwner().getRid()).toString());
603 List<StepCommentAttribute> comments = _stepCommentAttributeDAO
604 .getFilteredList(Restrictions.and(Restrictions.eq("step",
605 Integer.valueOf(step.getNumber())), Restrictions.eq(
607 List<StepCommentDTO> commentDTOs = new ArrayList<StepCommentDTO>();
608 for (StepCommentAttribute comment : comments) {
609 StepCommentDTO stepCommentDTO = BeanHelper.copyBean(comment,
610 StepCommentDTO.class);
611 stepCommentDTO.setText(comment.getValue());
612 stepCommentDTO.setId(Long.valueOf(comment.getRid()));
613 commentDTOs.add(stepCommentDTO);
621 * @see org.splat.service.StepService#removeStepComment(long)
625 public void removeStepComment(final long commentId)
626 throws InvalidParameterException {
627 StepCommentAttribute stepComment = _stepCommentAttributeDAO.get(Long
628 .valueOf(commentId));
629 if (stepComment == null) {
630 throw new InvalidParameterException("commentId", String
631 .valueOf(commentId));
633 _stepCommentAttributeDAO.delete(stepComment);
639 * @see org.splat.service.StepService#editStepComment(long, java.lang.String, java.lang.String)
643 public void editStepComment(final long commentId, final String newValue,
644 final String newTitle) throws InvalidParameterException {
645 StepCommentAttribute comment = _stepCommentAttributeDAO.get(Long
646 .valueOf(commentId));
647 if (comment == null) {
648 throw new InvalidParameterException("commentId", String
649 .valueOf(commentId));
651 if (newTitle != null) {
652 comment.setTitle(newTitle);
654 if (newValue != null) {
655 comment.setValue(newValue);
657 _stepCommentAttributeDAO.update(comment);
663 * @see org.splat.service.StepService#isCommentMadeByUser(long, long)
666 @Transactional(readOnly = true)
667 public boolean isCommentMadeByUser(final long commentId, final long userId)
668 throws InvalidParameterException {
669 StepCommentAttribute comment = _stepCommentAttributeDAO.get(Long
670 .valueOf(commentId));
671 if (comment == null) {
672 throw new InvalidParameterException("commentId", String
673 .valueOf(commentId));
675 return comment.getUser().getIndex() == userId;
679 * Get the documentService.
681 * @return the documentService
683 public DocumentService getDocumentService() {
684 return _documentService;
688 * Set the documentService.
690 * @param documentService
691 * the documentService to set
693 public void setDocumentService(final DocumentService documentService) {
694 _documentService = documentService;
698 * Get the simulationContextService.
700 * @return the simulationContextService
702 public SimulationContextService getSimulationContextService() {
703 return _simulationContextService;
707 * Set the simulationContextService.
709 * @param simulationContextService
710 * the simulationContextService to set
712 public void setSimulationContextService(
713 final SimulationContextService simulationContextService) {
714 _simulationContextService = simulationContextService;
718 * Get the documentDAO.
720 * @return the documentDAO
722 public DocumentDAO getDocumentDAO() {
727 * Set the documentDAO.
730 * the documentDAO to set
732 public void setDocumentDAO(final DocumentDAO documentDAO) {
733 _documentDAO = documentDAO;
737 * Get the simulationContextDAO.
739 * @return the simulationContextDAO
741 public SimulationContextDAO getSimulationContextDAO() {
742 return _simulationContextDAO;
746 * Set the simulationContextDAO.
748 * @param simulationContextDAO
749 * the simulationContextDAO to set
751 public void setSimulationContextDAO(
752 final SimulationContextDAO simulationContextDAO) {
753 _simulationContextDAO = simulationContextDAO;
757 * Get the projectElementDAO.
759 * @return the projectElementDAO
761 public ProjectElementDAO getProjectElementDAO() {
762 return _projectElementDAO;
766 * Set the projectElementDAO.
768 * @param projectElementDAO
769 * the projectElementDAO to set
771 public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
772 _projectElementDAO = projectElementDAO;
776 * Get the indexService.
778 * @return the indexService
780 public IndexService getIndexService() {
781 return _indexService;
785 * Set the indexService.
787 * @param indexService
788 * the indexService to set
790 public void setIndexService(final IndexService indexService) {
791 _indexService = indexService;
797 * @return the fileDAO
799 public FileDAO getFileDAO() {
809 public void setFileDAO(final FileDAO fileDAO) {
814 * Get the documentTypeService.
816 * @return the documentTypeService
818 public DocumentTypeService getDocumentTypeService() {
819 return _documentTypeService;
823 * Set the documentTypeService.
825 * @param documentTypeService
826 * the documentTypeService to set
828 public void setDocumentTypeService(
829 final DocumentTypeService documentTypeService) {
830 _documentTypeService = documentTypeService;
834 * Get the versionsRelationDAO.
836 * @return the versionsRelationDAO
838 public VersionsRelationDAO getVersionsRelationDAO() {
839 return _versionsRelationDAO;
843 * Set the versionsRelationDAO.
845 * @param versionsRelationDAO
846 * the versionsRelationDAO to set
848 public void setVersionsRelationDAO(
849 final VersionsRelationDAO versionsRelationDAO) {
850 _versionsRelationDAO = versionsRelationDAO;
854 * Get project settings.
856 * @return Project settings service
858 private ProjectSettingsService getProjectSettings() {
859 return _projectSettings;
863 * Set project settings service.
865 * @param projectSettingsService
866 * project settings service
868 public void setProjectSettings(
869 final ProjectSettingsService projectSettingsService) {
870 _projectSettings = projectSettingsService;
874 * Get the stepCommentAttributeDAO.
876 * @return the stepCommentAttributeDAO
878 public StepCommentAttributeDAO getStepCommentAttributeDAO() {
879 return _stepCommentAttributeDAO;
883 * Set the stepCommentAttributeDAO.
885 * @param commentAttributeDAO
886 * the stepCommentAttributeDAO to set
888 public void setStepCommentAttributeDAO(
889 final StepCommentAttributeDAO commentAttributeDAO) {
890 _stepCommentAttributeDAO = commentAttributeDAO;
896 * @return the userDAO
898 public UserDAO getUserDAO() {
908 public void setUserDAO(final UserDAO userDAO) {
913 * Get the publicationDAO.
915 * @return the publicationDAO
917 public PublicationDAO getPublicationDAO() {
918 return _publicationDAO;
922 * Set the publicationDAO.
924 * @param publicationDAO
925 * the publicationDAO to set
927 public void setPublicationDAO(final PublicationDAO publicationDAO) {
928 this._publicationDAO = publicationDAO;
932 * Get the relationDAO.
934 * @return the relationDAO
936 public RelationDAO getRelationDAO() {
941 * Set the relationDAO.
944 * the relationDAO to set
946 public void setRelationDAO(final RelationDAO relationDAO) {
947 _relationDAO = relationDAO;