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.Calendar;
15 import java.util.Date;
16 import java.util.HashMap;
17 import java.util.Iterator;
18 import java.util.List;
22 import org.hibernate.criterion.DetachedCriteria;
23 import org.hibernate.criterion.Order;
24 import org.hibernate.criterion.Projections;
25 import org.hibernate.criterion.Restrictions;
26 import org.hibernate.transform.Transformers;
27 import org.splat.common.properties.MessageKeyEnum;
28 import org.splat.dal.bo.kernel.Relation;
29 import org.splat.dal.bo.kernel.Role;
30 import org.splat.dal.bo.kernel.User;
31 import org.splat.dal.bo.som.ConvertsRelation;
32 import org.splat.dal.bo.som.Document;
33 import org.splat.dal.bo.som.DocumentType;
34 import org.splat.dal.bo.som.File;
35 import org.splat.dal.bo.som.KnowledgeElement;
36 import org.splat.dal.bo.som.KnowledgeElementType;
37 import org.splat.dal.bo.som.ProgressState;
38 import org.splat.dal.bo.som.ProjectElement;
39 import org.splat.dal.bo.som.Publication;
40 import org.splat.dal.bo.som.Scenario;
41 import org.splat.dal.bo.som.SimulationContext;
42 import org.splat.dal.bo.som.SimulationContextType;
43 import org.splat.dal.bo.som.Study;
44 import org.splat.dal.bo.som.UsedByRelation;
45 import org.splat.dal.bo.som.UsesRelation;
46 import org.splat.dal.bo.som.ValidationCycle;
47 import org.splat.dal.bo.som.Document.Properties;
48 import org.splat.dal.dao.kernel.RoleDAO;
49 import org.splat.dal.dao.kernel.UserDAO;
50 import org.splat.dal.dao.som.KnowledgeElementDAO;
51 import org.splat.dal.dao.som.KnowledgeElementTypeDAO;
52 import org.splat.dal.dao.som.ScenarioDAO;
53 import org.splat.dal.dao.som.StudyDAO;
54 import org.splat.dal.dao.som.ValidationCycleDAO;
55 import org.splat.exception.InvalidParameterException;
56 import org.splat.i18n.I18nUtils;
57 import org.splat.kernel.InvalidPropertyException;
58 import org.splat.kernel.MismatchException;
59 import org.splat.kernel.MissedPropertyException;
60 import org.splat.kernel.MultiplyDefinedException;
61 import org.splat.kernel.NotApplicableException;
62 import org.splat.log.AppLogger;
63 import org.splat.service.dto.DocumentDTO;
64 import org.splat.service.dto.FileDTO;
65 import org.splat.service.dto.ScenarioDTO;
66 import org.splat.service.dto.StepDTO;
67 import org.splat.service.technical.IndexService;
68 import org.splat.service.technical.ProjectSettingsService;
69 import org.splat.service.technical.RepositoryService;
70 import org.splat.service.technical.StepsConfigService;
71 import org.splat.som.Step;
72 import org.splat.util.BeanHelper;
73 import org.splat.util.IOUtils;
74 import org.springframework.transaction.annotation.Transactional;
77 * Scenario service implementation.
79 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
81 public class ScenarioServiceImpl implements ScenarioService {
84 * The logger for the service.
86 public final static AppLogger LOG = AppLogger
87 .getLogger(ScenarioServiceImpl.class);
92 private static final String TO = " to ";
94 * Injected index service.
96 private IndexService _indexService;
98 * Injected step service.
100 private StepService _stepService;
102 * Injected study service.
104 private StudyService _studyService;
106 * Injected publication service.
108 private PublicationService _publicationService;
110 * Injected project element service.
112 private ProjectElementService _projectElementService;
114 * Injected knowledge element DAO.
116 private KnowledgeElementDAO _knowledgeElementDAO;
118 * Injected scenario DAO.
120 private ScenarioDAO _scenarioDAO;
123 * Injected study DAO.
125 private StudyDAO _studyDAO;
128 * Injected knowledge element service.
130 private KnowledgeElementTypeService _knowledgeElementTypeService;
133 * Injected user service.
135 private UserService _userService;
140 private UserDAO _userDAO;
145 private RoleDAO _roleDAO;
148 * Injected knowledge element type DAO.
150 private KnowledgeElementTypeDAO _knowledgeElementTypeDAO;
153 * Injected simulation context service.
155 private SimulationContextService _simulationContextService;
158 * Injected simulation context type service.
160 private SimulationContextTypeService _simulationContextTypeService;
163 * Injected project service.
165 private ProjectSettingsService _projectSettings;
168 * Injected document type service.
170 private DocumentTypeService _documentTypeService;
173 * Injected validation cycle DAO.
175 private ValidationCycleDAO _validationCycleDAO;
178 * Injected project settings service.
180 private StepsConfigService _stepsConfigService;
183 * Injected repository service.
185 private RepositoryService _repositoryService;
188 * Get the projectElementService.
190 * @return the projectElementService
192 public ProjectElementService getProjectElementService() {
193 return _projectElementService;
197 * Set the projectElementService.
199 * @param projectElementService
200 * the projectElementService to set
202 public void setProjectElementService(
203 final ProjectElementService projectElementService) {
204 _projectElementService = projectElementService;
208 * Get the publicationService.
210 * @return the publicationService
212 public PublicationService getPublicationService() {
213 return _publicationService;
217 * Set the publicationService.
219 * @param publicationService
220 * the publicationService to set
222 public void setPublicationService(
223 final PublicationService publicationService) {
224 _publicationService = publicationService;
228 * Get the stepService.
230 * @return the stepService
232 public StepService getStepService() {
237 * Set the stepService.
240 * the stepService to set
242 public void setStepService(final StepService stepService) {
243 _stepService = stepService;
249 * @see org.splat.service.ScenarioService#getStudyScenarios(java.lang.Long)
252 @Transactional(readOnly = true)
253 public List<ScenarioDTO> getStudyScenarios(final Long studyId) {
254 DetachedCriteria query = DetachedCriteria
255 .forClass(Scenario.class, "scen")
256 .add(Restrictions.eq("owner.rid", studyId))
258 Projections.projectionList().add(
259 Projections.property("scen.title"), "title")
260 .add(Projections.property("scen.rid"), "index"))
261 .setResultTransformer(
262 Transformers.aliasToBean(ScenarioDTO.class));
263 return getScenarioDAO().getFilteredDTOList(query);
269 * @see org.splat.service.ScenarioService#copyStudyContent(long, long, int, long)
273 public void copyStudyContent(final long fromStudyId, final long fromScenId,
274 final int finalStepNum, final long toStudyId)
275 throws InvalidParameterException, MissedPropertyException,
276 InvalidPropertyException, MultiplyDefinedException,
277 NotApplicableException, IOException {
278 Study fromStudy = getStudyService().selectStudy(fromStudyId);
279 if (fromStudy == null) {
280 throw new InvalidParameterException(MessageKeyEnum.STD_000002
281 .toString(), String.valueOf(fromStudyId));
283 Scenario fromScen = null;
284 for (Scenario scen : fromStudy.getScenariiList()) {
285 if (scen.getIndex() == fromScenId) {
291 Study toStudy = getStudyService().selectStudy(toStudyId);
292 if (toStudy == null) {
293 throw new InvalidParameterException(MessageKeyEnum.STD_000002
294 .toString(), String.valueOf(toStudy));
297 // Check if the step is applied to a scenario and scenario is defined
299 && getStepsConfigService().stepInvolves(finalStepNum,
301 throw new InvalidParameterException(MessageKeyEnum.SCN_000006
302 .toString(), String.valueOf(fromScenId));
305 // Copy validation cycles
306 copyValidationCycles(fromStudy, toStudy);
308 // Copy content of the study up to the given step
309 Map<Publication, Publication> oldToNewPub = new HashMap<Publication, Publication>();
310 copyDocs(fromStudy, toStudy, finalStepNum, oldToNewPub);
311 if (fromScen != null) {
312 copyDocs(fromScen, toStudy.getScenariiList().get(0), finalStepNum,
315 copyDependencies(fromStudy, finalStepNum, oldToNewPub);
316 if (fromScen != null) {
317 copyDependencies(fromScen, finalStepNum, oldToNewPub);
322 * Copy validation cycles from study to study.
327 * the destination study
329 private void copyValidationCycles(final Study fromStudy, final Study toStudy) {
330 for (ValidationCycle fromCycle : fromStudy.getValidationCycles()
332 if (fromCycle.isAssigned()) {
333 ValidationCycle cycle = fromCycle.clone(toStudy);
334 getValidationCycleDAO().create(cycle);
335 toStudy.addRelation(cycle.getContext());
336 toStudy.getValidationCycles().put(
337 cycle.getDocumentType().getName(), cycle); // Replaces the cycle if exists as default,
343 * Copy dependencies between documents from the given project element up to <BR>
344 * the given step according to the given map of old publications to new publications.
347 * the source project element
348 * @param finalStepNum
349 * the final step for copy processing
351 * the old to new publications map
353 private void copyDependencies(final ProjectElement from,
354 final int finalStepNum,
355 final Map<Publication, Publication> oldToNewPub) {
356 // Copy dependencies between copied documents
357 for (Publication pub : from.getDocums()) {
358 // If the document in the step before the final one
359 if (pub.value().getStep() <= finalStepNum) {
360 Publication newPub = oldToNewPub.get(pub);
361 for (Publication used : pub.getRelations(UsesRelation.class)) {
362 newPub.addDependency(oldToNewPub.get(used));
369 * Copy documents with dependencies up to the given step.
372 * the source project element
374 * the destination project element
375 * @param finalStepNum
376 * the final step for copy process
377 * @param oldToNewPub2
378 * @throws MissedPropertyException
379 * if document creation is failed
380 * @throws InvalidPropertyException
381 * if document creation is failed
382 * @throws MultiplyDefinedException
383 * if document creation is failed
384 * @throws IOException
385 * if document file creation is failed
386 * @throws NotApplicableException
387 * if document state is not applicable
389 * the old to new publications map
392 private void copyDocs(final ProjectElement from, final ProjectElement to,
393 final int finalStepNum,
394 final Map<Publication, Publication> oldToNewPub)
395 throws MissedPropertyException, InvalidPropertyException,
396 MultiplyDefinedException, NotApplicableException, IOException {
397 Map<Integer, Step> steps = getProjectElementService().getStepsMap(to);
398 // Copy publications without old versions and relations to not copied steps documents
399 for (Publication pub : from.getDocums()) {
400 // If the document in the step before the final one
401 if (pub.value().getStep() <= finalStepNum) {
403 oldToNewPub.put(pub, createDoc(pub.value(), steps.get(pub
404 .value().getStep())));
410 * Create a copy of the given document and publish it in the given step.
413 * the source document
415 * the destination step
416 * @return the created publication
417 * @throws MissedPropertyException
418 * if document creation is failed
419 * @throws InvalidPropertyException
420 * if document creation is failed
421 * @throws MultiplyDefinedException
422 * if document creation is failed
423 * @throws IOException
424 * if document file creation is failed
425 * @throws NotApplicableException
426 * if document state is not applicable
428 private Publication createDoc(final Document fromDoc, final Step step)
429 throws MissedPropertyException, InvalidPropertyException,
430 MultiplyDefinedException, IOException, NotApplicableException {
432 java.io.File srcFile = fromDoc.getSourceFile().asFile();
433 // Creation of the document
434 Document.Properties dprop = new Document.Properties().setName(
435 fromDoc.getTitle()).setType(fromDoc.getType()).setFormat(
436 fromDoc.getFormat()).setAuthor(fromDoc.getAuthor());
438 java.io.File tmpDir = getRepositoryService().getDownloadDirectory(
439 step.getOwnerStudy().getAuthor());
441 // Remove local file index prefix to get original filename.
442 java.io.File upfile = new java.io.File(tmpDir.getPath()
444 + srcFile.getName().substring(
445 srcFile.getName().indexOf('_') + 1));
446 // Copy the source file into the temporary folder with original filename.
447 copyFile(srcFile, upfile);
449 dprop.setLocalPath(upfile.getPath());
450 Publication addoc = getStepService().createDocument(step, dprop);
452 // Move the temporary file into the repository
453 moveFile(upfile, addoc.getSourceFile().asFile());
455 getPublicationService().saveAs(addoc, fromDoc.getProgressState());
457 // Copy attached files
458 for (Relation rel : fromDoc.getRelations(ConvertsRelation.class)) {
459 File attach = ((ConvertsRelation) rel).getTo();
460 ConvertsRelation export = getPublicationService().attach(addoc,
462 // Copy the source document attachment file to the new study vault
463 copyFile(attach.asFile(), export.getTo().asFile());
469 * Copy a file. Print info message.
475 * @throws IOException
478 private void copyFile(final java.io.File upfile, final java.io.File file)
480 if (LOG.isInfoEnabled()) {
481 LOG.info("Copy " + upfile.getAbsolutePath() + TO + file.getPath());
483 IOUtils.copy(upfile, file);
487 * Copy a file. Print info message.
493 * @return true if renamed otherwise return false
495 private boolean moveFile(final java.io.File upfile, final java.io.File file) {
496 if (LOG.isInfoEnabled()) {
497 LOG.info("Move " + upfile.getAbsolutePath() + TO + file.getPath());
499 return upfile.renameTo(file);
505 * @see org.splat.service.ScenarioService#getScenarioInfo(long)
507 @Transactional(readOnly = true)
508 public List<StepDTO> getScenarioInfo(final long scenarioId) {
509 List<StepDTO> res = new ArrayList<StepDTO>();
510 // Get the scenario from the database by id
511 Scenario scen = getScenarioDAO().get(scenarioId);
512 if (LOG.isDebugEnabled()) {
513 LOG.debug("Scenario[" + scenarioId + "]: Number of publications: "
514 + scen.getDocums().size());
516 // Get activities of the scenario
517 Step[] steps = getProjectElementService().getSteps(scen);
520 String docType, fileFormat;
523 // For each activity create a step DTO and add it to the result list
524 for (Step step : steps) {
525 stepDTO = BeanHelper.copyBean(step.getStep(), StepDTO.class);
527 if (LOG.isDebugEnabled()) {
528 LOG.debug("Step[" + stepDTO.getNumber()
529 + "]: Number of documents: "
530 + step.getDocuments().size());
532 // For each publication of the activity create a document DTO.
533 // Each file is considered as a source file.
534 for (Publication tag : step.getDocuments()) {
535 docDTO = stepDTO.addDoc(tag.value().getIndex(), tag.value()
537 char aState = tag.getIsnew();
538 docType = tag.value().getType().getName();
539 // For each file of the document create a file DTO
540 // Process source file of the document
541 fileFormat = tag.value().getFile().getFormat();
542 doImport = getProjectSettings().doImport(docType, fileFormat);
543 if (doImport && (!tag.isOutdated())) {
544 processing = "file-import";
546 processing = "file-download";
548 File aFile = tag.value().getFile();
549 docDTO.addFile(aFile.getIndex(), aFile.getRelativePath(),
550 aState, processing, false);
551 // Process all exported files
552 for (Relation rel : tag.value().getRelations(
553 ConvertsRelation.class)) {
554 aFile = ((ConvertsRelation) rel).getTo();
555 fileFormat = aFile.getFormat();
556 doImport = getProjectSettings().doImport(docType,
558 if (doImport && (!tag.isOutdated())) {
559 processing = "file-import";
561 processing = "file-download";
563 docDTO.addFile(aFile.getIndex(), aFile.getRelativePath(),
564 aState, processing, false);
574 * @see org.splat.service.ScenarioService#createStudy(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
577 public long createStudy(final String username, final String title,
578 final String productName, final String description)
579 throws InvalidPropertyException, MissedPropertyException,
580 MultiplyDefinedException {
584 User author = getUserService().selectUser(username);
585 if (author == null) {
587 throw new InvalidPropertyException(MessageKeyEnum.USR_000001
588 .toString(), username);
591 // Set the study properties
592 Study.Properties sprop = new Study.Properties();
593 sprop.setTitle(title).setManager(author);
594 sprop.setDescription(description);
596 // Find the product simulation context
597 SimulationContextType productContextType = getSimulationContextService()
598 .selectType("product");
599 SimulationContext.Properties cprop = new SimulationContext.Properties();
600 cprop.setType(productContextType).setValue(productName);
601 SimulationContext productCtx = getSimulationContextService()
602 .selectSimulationContext(productContextType, productName);
603 if (productCtx != null) {
604 cprop.setIndex(productCtx.getIndex());
607 // Set a first scenario properties
608 Scenario.Properties oprop = new Scenario.Properties();
609 oprop.setTitle(I18nUtils.getMessageLocaleDefault("label.scenario")
612 Study study = createStudy(sprop, oprop, cprop);
613 id = study.getIndex();
619 * Create a new study with one scenario and "product" simulation context.
622 * the study properties
624 * the scenario properties
626 * the "product" simulation context properties
627 * @return the created study
628 * @throws MissedPropertyException
629 * if a mandatory property is missed
630 * @throws InvalidPropertyException
631 * if a property is invalid
632 * @throws MultiplyDefinedException
633 * if some property occurs several times
636 public Study createStudy(final Study.Properties sprop,
637 final Scenario.Properties oprop,
638 final SimulationContext.Properties cprop)
639 throws MissedPropertyException, InvalidPropertyException,
640 MultiplyDefinedException {
641 Study study = getStudyService().createStudy(sprop);
642 addScenario(study, oprop);
643 if (cprop.getIndex() == 0) { // Input of new project context
644 cprop.setType(getSimulationContextService().selectType("product"))
645 .setValue(cprop.getValue());
646 getStudyService().addProjectContext(study, cprop);
647 } else { // Selection of existing project context
648 SimulationContext context = getSimulationContextService()
649 .selectSimulationContext(cprop.getIndex());
650 getStudyService().addProjectContext(study, context);
658 * @see org.splat.service.ScenarioService#assignStudyContext(java.lang.Long, java.lang.String, java.lang.String)
661 public void assignStudyContext(final Long studyId, final String ctxType,
662 final String ctxValue) throws MissedPropertyException,
663 InvalidPropertyException, MultiplyDefinedException {
664 // Find the study by the given id
665 Study study = getStudyDAO().get(studyId);
667 throw new InvalidPropertyException(MessageKeyEnum.STD_000002
668 .toString(), studyId);
670 // Find the context type by its name
671 SimulationContextType celt = getSimulationContextService().selectType(
674 // Creation of a new context type
675 celt = getSimulationContextTypeService().createType(ctxType,
676 getProjectElementService().getFirstStep(study).getStep());
678 // Find the given context value of the given type
679 SimulationContext context = getSimulationContextService()
680 .selectSimulationContext(celt, ctxValue);
681 if (context == null) { // Input of a new project context
682 SimulationContext.Properties cprop = new SimulationContext.Properties();
683 cprop.setType(celt).setValue(ctxValue);
684 getStudyService().addProjectContext(study, cprop);
685 } else { // Selection of existing project context
686 getStudyService().addProjectContext(study, context);
693 * @see org.splat.service.ScenarioService#addKnowledgeElement(org.splat.dal.bo.som.Scenario,
694 * org.splat.dal.bo.som.KnowledgeElement.Properties)
697 public KnowledgeElement addKnowledgeElement(final Scenario aScenarioDTO,
698 final KnowledgeElement.Properties kprop)
699 throws MissedPropertyException, InvalidPropertyException,
700 MultiplyDefinedException {
701 KnowledgeElement kelm = null;
703 long aScenarioId = aScenarioDTO.getIndex();
704 if (LOG.isDebugEnabled()) {
706 .debug("Add a knowledge element to the scenario #"
709 // Get the persistent scenario.
710 Scenario aScenario = getScenarioDAO().get(aScenarioId);
711 // Get persistent objects for creating a new knowledge.
712 // TODO: Actions must use DTO instead of persistent objects.
713 getUserDAO().merge(kprop.getAuthor());
714 getKnowledgeElementTypeDAO().merge(kprop.getType());
715 // Create a transient knowledge element related to the given scenario.
716 kelm = new KnowledgeElement(kprop.setOwnerScenario(aScenario));
717 // Save the new knowledge in the database.
718 getKnowledgeElementDAO().create(kelm);
719 // Update scenario transient data.
720 if (kelm.getType().equals("usecase")) {
721 aScenarioDTO.setUcase(kelm);
722 } else if (aScenarioDTO.getKnowledgeElementsList() != null) { // If null, knowl will be initialized when needed
723 aScenarioDTO.getKnowledgeElementsList().add(kelm);
726 // Load the workflow for the parent study to take into account
727 // all study actors durng reindexing.
728 getStudyService().loadWorkflow(aScenario.getOwnerStudy());
730 // // Update the lucene index of knowledge elements.
731 // getIndexService().add(kelm);
732 if (LOG.isDebugEnabled()) {
733 LOG.debug("A knowledge element #" + kelm.getIndex()
734 + " is added to the scenario #" + aScenario.getIndex());
736 // } catch (IOException error) {
737 // LOG.error("Unable to index the knowedge element '"
738 // + kelm.getIndex() + "', reason:", error);
748 * @see org.splat.service.ScenarioService#checkin(long, long, java.util.List)
751 public void checkin(final long scenId, final long userId,
752 final List<StepDTO> scInfo) throws InvalidPropertyException,
753 MissedPropertyException, MultiplyDefinedException,
754 MismatchException, IOException, NotApplicableException {
755 // Get the scenario from the database by id
756 Scenario aScenario = getScenarioDAO().get(scenId);
757 // Get the user who perform this check-in operation
758 User aUser = getUserService().selectUser(userId);
759 // Get activities of the scenario
760 Step[] steps = getProjectElementService().getSteps(aScenario);
761 // Find result document types
762 List<DocumentType> resTypes = getDocumentTypeService()
763 .selectResultTypes();
765 // Keep newly created documents to create uses relations to results of a previous step.
766 // For each processed existing document keep its new version
767 Map<Document, Document> newVersion = new HashMap<Document, Document>();
768 // Created publications of new created versions of existing documents
769 List<Publication> newVers = new ArrayList<Publication>();
770 // The list of publications of new created documents not existing before the checkin
771 List<Publication> newDocs = new ArrayList<Publication>();
773 DocumentType resType;
774 Date aDate = new Date(); // The timestamp of the checkin operation
775 for (StepDTO stepDTO : scInfo) {
776 if (LOG.isDebugEnabled()) {
777 LOG.debug("Checkin the step:\n" + stepDTO);
779 // Find a result document type of the step
783 if (resTypes.get(i).isResultOf(
784 getProjectSettings().getStep(stepDTO.getNumber()))) {
785 resType = resTypes.get(i);
788 } while ((resType == null) && (i < resTypes.size()));
790 // Find the appropriate scenario step
791 Step step = findStep(stepDTO, steps);
793 // Process each document of the step
794 for (DocumentDTO doc : stepDTO.getDocs()) {
795 checkinDoc(step, doc, aUser, resType, aDate, newVersion,
800 // Set uses/used relations
801 updateRelationsAfterCheckin(aScenario, newVersion, newVers, newDocs);
803 // Mark the scenario as checked in
808 * Updated uses/used relations after checkin operation:<BR>
810 * <li>For each new version copy uses relations from the previous version.</li>
811 * <li>Outdate documents which depend from the previous version and were not checked in during this operation.</li>
812 * <li>For each new document create uses relation to the last versions of results of the previous step.</li>
816 * the checked in scenario
818 * the mapping of documents existed before the checkin to their new created versions
820 * the list of publications of new created versions of documents existed before the checkin
822 * the list of publications of new created documents not existed before the checkin
824 private void updateRelationsAfterCheckin(final Scenario aScenario,
825 final Map<Document, Document> newVersion,
826 final List<Publication> newVers, final List<Publication> newDocs) {
827 // For each new version copy uses relations from the previous version.
828 for (Publication newVer : newVers) {
829 // For each Uses relation of the previous version
830 Document prevDoc = newVer.value().getPreviousVersion();// prevVersion.get(newVer);
831 if (LOG.isDebugEnabled()) {
832 LOG.debug("Previous version for publication #"
833 + newVer.getIndex() + " is found: " + prevDoc);
835 List<Relation> usesRelations = prevDoc
836 .getRelations(UsesRelation.class);
837 for (Relation rel : usesRelations) {
838 // If used document has been also versioned then refer to its new version.
839 Document usedDoc = ((UsesRelation) rel).getTo();
840 if (newVersion.containsKey(usedDoc)) {
841 usedDoc = newVersion.get(usedDoc);
843 // Build the appropriate relation for the new version.
844 newVer.addDependency(usedDoc);
846 // Outdate documents which depend from the previous version and
847 // were not checked in during this operation.
848 // 1. Get all usedBy relations of the previous document version
849 for (Relation rel : prevDoc.getRelations(UsedByRelation.class)) {
850 Document using = ((UsedByRelation) rel).getTo();
851 // Check that not checked in dependent documents became outdated
852 Publication usingPub = aScenario.getPublication(using);
853 if (usingPub != null) { // if the document using the old version is still published
854 usingPub.setIsnew('O');
859 // For each new document create uses relation to the last versions of
860 // results of the previous step.
861 for (Publication newPub : newDocs) {
862 // Find used document type according to the configuration.
863 Set<DocumentType> usedTypes = newPub.value().getType()
865 // Find documents of used type in the previous study step.
866 for (Publication pub : aScenario.getDocums()) {
867 if ((pub.getStep().getNumber() <= newPub.getStep().getNumber())
868 && (!pub.isOutdated())
869 && usedTypes.contains(pub.value().getType())) {
870 // Create uses relation from the new document
871 // to the found document in the previous step.
872 newPub.addDependency(pub);
879 * Pure checkin of the document without creation of uses/usedBy relations. For an existing document a new version is created. New
880 * documents become published in the given step of the appropriate scenario. The appropriate uploaded file is attached to the created
881 * document and the document is published in the scenario. The publication of the old version is removed from the scenario.
884 * the destination scenario step
886 * the DTO of the document to checkin
888 * the user who performs checkin
890 * the result document type of the given step
892 * timestamp of the checkin operation
894 * the mapping of existing documents to their new created versions
896 * the list of publications of new created versions of existing documents
898 * the list of publications of new created documents not existing before the checkin
899 * @throws InvalidPropertyException
900 * if the scenario hasn't some of given steps or documents
901 * @throws IOException
902 * if a file can't be moved into the vault
903 * @throws MismatchException
904 * if version creation in some of steps is failed
905 * @throws MissedPropertyException
906 * if some mandatory property is missed when new document or new document version is created
907 * @throws MultiplyDefinedException
908 * if some property is defined several times when new document or new document version is created
909 * @throws NotApplicableException
910 * if failed saving of a new publication with a given state
912 private void checkinDoc(final Step step, final DocumentDTO doc,
913 final User aUser, final DocumentType resType, final Date aDate,
914 final Map<Document, Document> newVersion,
915 final List<Publication> newVers, final List<Publication> newDocs)
916 throws InvalidPropertyException, MismatchException,
917 MissedPropertyException, MultiplyDefinedException, IOException,
918 NotApplicableException {
919 if (doc.getFiles().size() > 0) {
920 Document.Properties dprop = new Document.Properties();
921 // NOTE: Process only the first attached file for each document
922 FileDTO file = doc.getFiles().get(0);
923 dprop.setLocalPath(file.getPath());
925 // Get document title as the file name
926 java.io.File upfile = new java.io.File(file.getPath());
927 String fileFormat = upfile.getName().substring(
928 upfile.getName().lastIndexOf('.') + 1);
930 // Attach the file via ConvertsRelation, create a new document or
931 // create a new version of the document
932 dprop.setAuthor(aUser).setDate(aDate).setFormat(fileFormat);
934 if (doc.getId() > 0) {
935 checkinExistingDoc(step, doc, dprop, fileFormat, upfile,
936 newVersion, newVers);
939 // Otherwise create a new document of the result type
940 // If result type is not found try to get type by file extension
941 if (resType == null) {
942 dprop.setType(getProjectSettings().getDefaultDocumentType(
943 step.getStep(), fileFormat));
945 dprop.setType(resType);
947 // New document title generation as <document type name>_N
948 String docname = dprop.getType().getName();
950 for (Publication scenPub : step.getOwner().getDocums()) {
951 if (scenPub.value().getTitle().startsWith(docname)) {
955 docname += "_" + i; // The generated new document title
957 dprop.setDescription("Checked in").setName(docname);
958 Publication newPub = getStepService().createDocument(step,
961 // Remember the new document
964 saveFile(newPub, step, upfile);
970 * Check in existing document.
973 * study step to check in
975 * document DTO to check in
977 * document properties
979 * checked in file format
981 * the file to check in
983 * the map of created versions during this check in
985 * the list of new versions created during this check in
986 * @throws InvalidPropertyException
987 * if publication of the document is not found in the step
988 * @throws MismatchException
989 * if the found publication does not point to a document
990 * @throws IOException
991 * if can not move the file into the vault
992 * @throws MultiplyDefinedException
993 * thrown by versionDocument
994 * @throws MissedPropertyException
995 * thrown by versionDocument
996 * @throws NotApplicableException
997 * if failed saving of a new publication with a given state
999 private void checkinExistingDoc(final Step step, final DocumentDTO doc,
1000 final Properties dprop, final String fileFormat,
1001 final java.io.File upfile,
1002 final Map<Document, Document> newVersion,
1003 final List<Publication> newVers) throws InvalidPropertyException,
1004 MismatchException, MissedPropertyException,
1005 MultiplyDefinedException, IOException, NotApplicableException {
1006 // If the document already exists then
1007 // Attach the file via ConvertsRelation if the extension of the
1008 // new file differs from the old one.
1009 // If file format (i.e. extension) is the same then create a new
1010 // version of the document.
1011 // Find the document publication
1012 Publication pub = step.getDocument(doc.getId());
1014 throw new InvalidPropertyException(MessageKeyEnum.SCN_000002
1015 .toString(), doc.getId());
1017 if (pub.value() == null) {
1018 throw new MismatchException(MessageKeyEnum.SCN_000002.toString(),
1021 if (LOG.isDebugEnabled()) {
1022 LOG.debug("Old format: " + pub.value().getFormat()
1023 + " => New format: " + fileFormat);
1025 // If formats are same then create a new document version
1026 if (pub.value().getFormat() != null
1027 && pub.value().getFormat().equals(fileFormat)) {
1028 Publication newPub = getStepService().versionDocument(step, pub,
1030 if (LOG.isDebugEnabled()) {
1031 LOG.debug("Created document type: "
1032 + newPub.value().getType().getName() + ", format: "
1033 + newPub.value().getFormat());
1035 // Remeber the link from the old document to the new document version
1036 newVersion.put(pub.value(), newPub.value());
1037 // Remember the new version publication
1038 newVers.add(newPub);
1040 saveFile(newPub, step, upfile);
1042 } else { // If formats are different then attach the new file via ConvertsRelation
1043 File attach = pub.value().getAttachedFile(fileFormat);
1044 if (attach == null) {
1045 // If there is no attachment with this extension then attach the new one
1046 ConvertsRelation export = getPublicationService().attach(pub,
1048 moveFile(upfile, export.getTo().asFile());
1050 // If an attachment with this extension already exists then
1051 // replace it by the new one
1052 moveFile(upfile,attach.asFile());
1053 // Update attached file modification date
1054 attach.setDate(new Date());
1060 * Save the file in the vault and create its publication in the step.
1063 * the new publication to save
1065 * the study step to publish the document
1067 * the downloaded file
1068 * @throws IOException
1069 * if a file can't be moved into the vault
1070 * @throws NotApplicableException
1071 * if failed saving of a new publication with a given state
1073 private void saveFile(final Publication newPub, final Step step,
1074 final java.io.File upfile) throws IOException,
1075 NotApplicableException {
1076 // Attach the file to the created document
1077 java.io.File updir = newPub.getSourceFile().asFile();
1078 if (updir.exists()) {
1079 if (updir.delete()) {
1080 LOG.info(MessageKeyEnum.SCN_000003.toString(), updir
1081 .getAbsoluteFile(), step.getOwner().getIndex());
1083 throw new IOException(
1084 "Can't delete the existing destination file to move file from "
1085 + upfile.getAbsolutePath() + TO
1086 + updir.getAbsolutePath());
1089 if (moveFile(upfile, updir)) {
1090 // Save the new publication in the scenario.
1091 // The old publication is removed from the scenario here.
1092 getPublicationService().saveAs(newPub, ProgressState.inWORK); // May throw FileNotFound if rename was not done
1094 throw new IOException("Can't move file from "
1095 + upfile.getAbsolutePath() + TO + updir.getAbsolutePath());
1100 * Find appropriate step in the array of scenario steps according to the given step DTO.
1106 * @return appropriate scenario step
1107 * @throws InvalidPropertyException
1108 * if appropriate step is not found
1110 private Step findStep(final StepDTO stepDTO, final Step[] steps)
1111 throws InvalidPropertyException {
1115 if (steps[i].getNumber() == stepDTO.getNumber()) {
1119 } while ((step == null) && (i < steps.length));
1122 throw new InvalidPropertyException(MessageKeyEnum.SCN_000001
1123 .toString(), stepDTO.getNumber());
1131 * @see org.splat.service.ScenarioService#checkin(long)
1134 public void checkin(final long scenarioId) throws InvalidPropertyException {
1135 Scenario aScenario = getScenarioDAO().get(scenarioId);
1136 if (aScenario == null) {
1137 // Scenario not found
1138 throw new InvalidPropertyException(MessageKeyEnum.SCN_000006
1139 .toString(), scenarioId);
1145 * Mark the scenario as checked in.
1148 * the scenario to check in.
1150 private void checkin(final Scenario aScenario) {
1151 aScenario.setUser(null);
1152 aScenario.setLastModificationDate(Calendar.getInstance().getTime());
1153 // getScenarioDAO().update(aScenario);
1159 * @see org.splat.service.ScenarioService#checkout(org.splat.dal.bo.som.Scenario, org.splat.dal.bo.kernel.User)
1161 public boolean checkout(final Scenario aScenario, final User user) {
1162 boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
1165 aScenario.setUser(user);
1166 aScenario.setLastModificationDate(Calendar.getInstance().getTime());
1167 // RKV: getScenarioDAO().update(aScenario);
1173 * Mark the given scenario as checked out by the given user.
1178 * the id of the user performing the check out
1179 * @throws InvalidPropertyException
1180 * if the user or the scenario is not found in the database
1181 * @throws NotApplicableException
1182 * if the given user can not check out the scenario
1185 public void checkout(final long scenarioId, final long userId)
1186 throws InvalidPropertyException, NotApplicableException {
1187 User aUser = getUserService().selectUser(userId);
1188 if (aUser == null) {
1190 throw new InvalidPropertyException(MessageKeyEnum.USR_000001
1191 .toString(), userId);
1193 Scenario aScenario = getScenarioDAO().get(scenarioId);
1194 if (aScenario == null) {
1195 // Scenario not found
1196 throw new InvalidPropertyException(MessageKeyEnum.SCN_000006
1197 .toString(), scenarioId);
1199 boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
1202 if (aScenario.isCheckedout()
1203 && (!aScenario.getUser().getUsername().equals(
1204 aUser.getUsername()))) {
1205 throw new NotApplicableException(MessageKeyEnum.SCN_000008
1206 .toString(), scenarioId, aScenario.getUser()
1209 aScenario.setUser(aUser);
1210 aScenario.setLastModificationDate(Calendar.getInstance().getTime());
1212 // User doesn't participate in the scenario
1213 throw new NotApplicableException(MessageKeyEnum.SCN_000007
1214 .toString(), aUser.getUsername(), scenarioId);
1221 * @see org.splat.service.ScenarioService#copyContentsUpTo(org.splat.dal.bo.som.Scenario, org.splat.som.Step)
1223 public void copyContentsUpTo(final Scenario scenario, final Step lastep) {
1224 Scenario base = (Scenario) lastep.getOwner();
1225 Step[] from = getProjectElementService().getSteps(base);
1226 Step[] to = getProjectElementService().getSteps(scenario);
1227 for (int i = 0; i < from.length; i++) {
1228 Step step = from[i];
1229 if (step.getNumber() > lastep.getNumber()) {
1233 List<Publication> docs = step.getAllDocuments();
1234 for (Iterator<Publication> j = docs.iterator(); j.hasNext();) {
1235 Publication doc = getPublicationService().copy(j.next(),
1236 scenario); // Creation of a new reference to the document
1237 // Database.getSession().save(doc); Publications MUST be saved later through cascading when saving the scenario
1238 getStepService().add(to[i], doc);
1240 List<SimulationContext> ctex = step.getAllSimulationContexts();
1241 for (Iterator<SimulationContext> j = ctex.iterator(); j.hasNext();) {
1242 getStepService().addSimulationContext(to[i], j.next());
1250 * @see org.splat.service.ScenarioService#isEmpty(org.splat.dal.bo.som.Scenario)
1252 public boolean isEmpty(final Scenario scenario) {
1253 Step[] mystep = getProjectElementService().getSteps(scenario);
1254 boolean isEmp = true;
1255 for (int i = 0; i < mystep.length; i++) {
1256 if (mystep[i].isStarted()) {
1268 public boolean isFinished(final Scenario scenario) {
1269 Step[] mystep = getProjectElementService().getSteps(scenario);
1270 boolean notempty = false; // If this is empty, this is not finished
1271 for (int i = 0; i < mystep.length; i++) {
1272 if (!mystep[i].isStarted()) {
1275 if (!mystep[i].isFinished()) {
1286 * @see org.splat.service.StudyService#addScenario(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Scenario.Properties)
1289 public Scenario addScenario(final Study aStudy,
1290 final Scenario.Properties sprop) throws MissedPropertyException,
1291 InvalidPropertyException, MultiplyDefinedException {
1292 if (sprop.getManager() == null) {
1293 sprop.setManager(aStudy.getAuthor());
1296 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
1297 if (sprop.getBaseStep() != null) {
1298 copyContentsUpTo(scenario, sprop.getBaseStep());
1300 Scenario previous = sprop.getInsertAfter();
1302 if (previous == null) {
1303 aStudy.getScenariiList().add(scenario);
1305 aStudy.getScenariiList().add(
1306 aStudy.getScenariiList().indexOf(previous) + 1, scenario);
1308 getStudyDAO().update(aStudy); // No need to update the Lucene index
1309 getScenarioDAO().create(scenario); // Must be done after updating this study because of the back reference to the study
1310 if (sprop.getBaseStep() != null) {
1311 // No need to update the Knowledge Element index as Knowledge Elements are not copied
1312 getProjectElementService().refresh(scenario); // Because saving the scenario changes the hashcode of copied Publications
1314 KnowledgeElementType ucase = getKnowledgeElementTypeService()
1315 .selectType("usecase");
1316 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
1317 // TODO: Get appropriate user by its role: UserService.getAdmin();
1318 // User admin = getUserService().selectUser(1); // First user created when creating the database
1319 Role adminRole = getRoleDAO().getFilteredList(
1320 Restrictions.like("role", "%sysadmin%")).get(0);
1321 User admin = getUserDAO().getFilteredList(
1322 Restrictions.eq("role", adminRole), Order.asc("rid")).get(0); // First sysadmin in the database
1324 kprop.setType(ucase).setTitle(aStudy.getTitle()).setValue(
1325 scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
1327 addKnowledgeElement(scenario, kprop);
1332 * Remove a knowledge element from a scenario.
1337 * the knowledge element to remove
1338 * @return true if removal succeeded
1341 public boolean removeKnowledgeElement(final Scenario scenario,
1342 final KnowledgeElement kelm) {
1343 KnowledgeElement torem = scenario.getKnowledgeElement(kelm.getIndex());
1344 boolean isOk = (torem != null);
1346 isOk = scenario.getKnowledgeElements().remove(torem);
1348 getScenarioDAO().merge(scenario);
1349 // Update of my transient data
1350 // RKV: These transient data are not used indeed.
1351 // RKV: List<KnowledgeElement> kelms = scenario.getKnowledgeByType().get(
1352 // RKV: kelm.getType().getIndex());
1353 // RKV: kelms.remove(torem);
1354 if (scenario.getKnowledgeElementsList() != null) {
1355 scenario.getKnowledgeElementsList().remove(torem);
1357 // TODO: If the owner study is not private, remove the knowledge from the Lucene index
1367 * @see org.splat.service.ScenarioService#renameScenario(java.lang.String)
1370 public void renameScenario(final Scenario scenario) {
1371 getScenarioDAO().merge(scenario);
1375 * Get the knowledgeElementDAO.
1377 * @return the knowledgeElementDAO
1379 public KnowledgeElementDAO getKnowledgeElementDAO() {
1380 return _knowledgeElementDAO;
1384 * Set the knowledgeElementDAO.
1386 * @param knowledgeElementDAO
1387 * the knowledgeElementDAO to set
1389 public void setKnowledgeElementDAO(
1390 final KnowledgeElementDAO knowledgeElementDAO) {
1391 _knowledgeElementDAO = knowledgeElementDAO;
1395 * Get the indexService.
1397 * @return the indexService
1399 public IndexService getIndexService() {
1400 return _indexService;
1404 * Set the indexService.
1406 * @param indexService
1407 * the indexService to set
1409 public void setIndexService(final IndexService indexService) {
1410 _indexService = indexService;
1414 * Get the scenarioDAO.
1416 * @return the scenarioDAO
1418 public ScenarioDAO getScenarioDAO() {
1419 return _scenarioDAO;
1423 * Set the scenarioDAO.
1425 * @param scenarioDAO
1426 * the scenarioDAO to set
1428 public void setScenarioDAO(final ScenarioDAO scenarioDAO) {
1429 _scenarioDAO = scenarioDAO;
1435 * @return the studyDAO
1437 public StudyDAO getStudyDAO() {
1445 * the studyDAO to set
1447 public void setStudyDAO(final StudyDAO studyDAO) {
1448 _studyDAO = studyDAO;
1452 * Get the knowledgeElementTypeService.
1454 * @return the knowledgeElementTypeService
1456 public KnowledgeElementTypeService getKnowledgeElementTypeService() {
1457 return _knowledgeElementTypeService;
1461 * Set the knowledgeElementTypeService.
1463 * @param knowledgeElementTypeService
1464 * the knowledgeElementTypeService to set
1466 public void setKnowledgeElementTypeService(
1467 final KnowledgeElementTypeService knowledgeElementTypeService) {
1468 _knowledgeElementTypeService = knowledgeElementTypeService;
1472 * Get the studyService.
1474 * @return the studyService
1476 public StudyService getStudyService() {
1477 return _studyService;
1481 * Set the studyService.
1483 * @param studyService
1484 * the studyService to set
1486 public void setStudyService(final StudyService studyService) {
1487 _studyService = studyService;
1491 * Get the userService.
1493 * @return the userService
1495 public UserService getUserService() {
1496 return _userService;
1500 * Set the userService.
1502 * @param userService
1503 * the userService to set
1505 public void setUserService(final UserService userService) {
1506 _userService = userService;
1512 * @return the userDAO
1514 public UserDAO getUserDAO() {
1522 * the userDAO to set
1524 public void setUserDAO(final UserDAO userDAO) {
1529 * Get the knowledgeElementTypeDAO.
1531 * @return the knowledgeElementTypeDAO
1533 public KnowledgeElementTypeDAO getKnowledgeElementTypeDAO() {
1534 return _knowledgeElementTypeDAO;
1538 * Set the knowledgeElementTypeDAO.
1540 * @param knowledgeElementTypeDAO
1541 * the knowledgeElementTypeDAO to set
1543 public void setKnowledgeElementTypeDAO(
1544 final KnowledgeElementTypeDAO knowledgeElementTypeDAO) {
1545 _knowledgeElementTypeDAO = knowledgeElementTypeDAO;
1549 * Get the simulationContextService.
1551 * @return the simulationContextService
1553 public SimulationContextService getSimulationContextService() {
1554 return _simulationContextService;
1558 * Set the simulationContextService.
1560 * @param simulationContextService
1561 * the simulationContextService to set
1563 public void setSimulationContextService(
1564 final SimulationContextService simulationContextService) {
1565 _simulationContextService = simulationContextService;
1569 * Get project settings.
1571 * @return Project settings service
1573 private ProjectSettingsService getProjectSettings() {
1574 return _projectSettings;
1578 * Set project settings service.
1580 * @param projectSettingsService
1581 * project settings service
1583 public void setProjectSettings(
1584 final ProjectSettingsService projectSettingsService) {
1585 _projectSettings = projectSettingsService;
1589 * Get the documentTypeService.
1591 * @return the documentTypeService
1593 public DocumentTypeService getDocumentTypeService() {
1594 return _documentTypeService;
1598 * Set the documentTypeService.
1600 * @param documentTypeService
1601 * the documentTypeService to set
1603 public void setDocumentTypeService(
1604 final DocumentTypeService documentTypeService) {
1605 _documentTypeService = documentTypeService;
1611 * @return the roleDAO
1613 public RoleDAO getRoleDAO() {
1621 * the roleDAO to set
1623 public void setRoleDAO(final RoleDAO roleDAO) {
1628 * Get the simulationContextTypeService.
1630 * @return the simulationContextTypeService
1632 public SimulationContextTypeService getSimulationContextTypeService() {
1633 return _simulationContextTypeService;
1637 * Set the simulationContextTypeService.
1639 * @param simulationContextTypeService
1640 * the simulationContextTypeService to set
1642 public void setSimulationContextTypeService(
1643 final SimulationContextTypeService simulationContextTypeService) {
1644 _simulationContextTypeService = simulationContextTypeService;
1648 * Get the validationCycleDAO.
1650 * @return the validationCycleDAO
1652 public ValidationCycleDAO getValidationCycleDAO() {
1653 return _validationCycleDAO;
1657 * Set the validationCycleDAO.
1659 * @param validationCycleDAO
1660 * the validationCycleDAO to set
1662 public void setValidationCycleDAO(
1663 final ValidationCycleDAO validationCycleDAO) {
1664 _validationCycleDAO = validationCycleDAO;
1670 * @return steps config service
1672 private StepsConfigService getStepsConfigService() {
1673 return _stepsConfigService;
1677 * Set steps config service.
1679 * @param stepsConfigService
1680 * steps config service
1682 public void setStepsConfigService(
1683 final StepsConfigService stepsConfigService) {
1684 _stepsConfigService = stepsConfigService;
1688 * Get the repositoryService.
1690 * @return the repositoryService
1692 public RepositoryService getRepositoryService() {
1693 return _repositoryService;
1697 * Set the repositoryService.
1699 * @param repositoryService
1700 * the repositoryService to set
1702 public void setRepositoryService(final RepositoryService repositoryService) {
1703 _repositoryService = repositoryService;