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.StepsConfigService;
70 import org.splat.som.Step;
71 import org.splat.util.BeanHelper;
72 import org.splat.util.IOUtils;
73 import org.springframework.transaction.annotation.Transactional;
76 * Scenario service implementation.
78 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
80 public class ScenarioServiceImpl implements ScenarioService {
83 * The logger for the service.
85 public final static AppLogger LOG = AppLogger
86 .getLogger(ScenarioServiceImpl.class);
91 private static final String TO = " to ";
93 * Injected index service.
95 private IndexService _indexService;
97 * Injected step service.
99 private StepService _stepService;
101 * Injected study service.
103 private StudyService _studyService;
105 * Injected publication service.
107 private PublicationService _publicationService;
109 * Injected project element service.
111 private ProjectElementService _projectElementService;
113 * Injected knowledge element DAO.
115 private KnowledgeElementDAO _knowledgeElementDAO;
117 * Injected scenario DAO.
119 private ScenarioDAO _scenarioDAO;
122 * Injected study DAO.
124 private StudyDAO _studyDAO;
127 * Injected knowledge element service.
129 private KnowledgeElementTypeService _knowledgeElementTypeService;
132 * Injected user service.
134 private UserService _userService;
139 private UserDAO _userDAO;
144 private RoleDAO _roleDAO;
147 * Injected knowledge element type DAO.
149 private KnowledgeElementTypeDAO _knowledgeElementTypeDAO;
152 * Injected simulation context service.
154 private SimulationContextService _simulationContextService;
157 * Injected simulation context type service.
159 private SimulationContextTypeService _simulationContextTypeService;
162 * Injected project service.
164 private ProjectSettingsService _projectSettings;
167 * Injected document type service.
169 private DocumentTypeService _documentTypeService;
172 * Injected validation cycle DAO.
174 private ValidationCycleDAO _validationCycleDAO;
177 * Injected project settings service.
179 private StepsConfigService _stepsConfigService;
182 * Get the projectElementService.
184 * @return the projectElementService
186 public ProjectElementService getProjectElementService() {
187 return _projectElementService;
191 * Set the projectElementService.
193 * @param projectElementService
194 * the projectElementService to set
196 public void setProjectElementService(
197 final ProjectElementService projectElementService) {
198 _projectElementService = projectElementService;
202 * Get the publicationService.
204 * @return the publicationService
206 public PublicationService getPublicationService() {
207 return _publicationService;
211 * Set the publicationService.
213 * @param publicationService
214 * the publicationService to set
216 public void setPublicationService(
217 final PublicationService publicationService) {
218 _publicationService = publicationService;
222 * Get the stepService.
224 * @return the stepService
226 public StepService getStepService() {
231 * Set the stepService.
234 * the stepService to set
236 public void setStepService(final StepService stepService) {
237 _stepService = stepService;
243 * @see org.splat.service.ScenarioService#getStudyScenarios(java.lang.Long)
246 @Transactional(readOnly = true)
247 public List<ScenarioDTO> getStudyScenarios(final Long studyId) {
248 DetachedCriteria query = DetachedCriteria
249 .forClass(Scenario.class, "scen")
250 .add(Restrictions.eq("owner.rid", studyId))
252 Projections.projectionList().add(
253 Projections.property("scen.title"), "title")
254 .add(Projections.property("scen.rid"), "index"))
255 .setResultTransformer(
256 Transformers.aliasToBean(ScenarioDTO.class));
257 return getScenarioDAO().getFilteredDTOList(query);
263 * @see org.splat.service.ScenarioService#copyStudyContent(long, long, int, long)
267 public void copyStudyContent(final long fromStudyId, final long fromScenId,
268 final int finalStepNum, final long toStudyId)
269 throws InvalidParameterException, MissedPropertyException,
270 InvalidPropertyException, MultiplyDefinedException,
271 NotApplicableException, IOException {
272 Study fromStudy = getStudyService().selectStudy(fromStudyId);
273 if (fromStudy == null) {
274 throw new InvalidParameterException(MessageKeyEnum.STD_000002
275 .toString(), String.valueOf(fromStudyId));
277 Scenario fromScen = null;
278 for (Scenario scen : fromStudy.getScenariiList()) {
279 if (scen.getIndex() == fromScenId) {
284 Study toStudy = getStudyService().selectStudy(toStudyId);
285 if (toStudy == null) {
286 throw new InvalidParameterException(MessageKeyEnum.STD_000002
287 .toString(), String.valueOf(toStudy));
290 // Check if the step is applied to a scenario and scenario is defined
292 && getStepsConfigService().stepInvolves(finalStepNum,
294 throw new InvalidParameterException(MessageKeyEnum.SCN_000006
295 .toString(), String.valueOf(fromScenId));
298 // Copy validation cycles
299 for (ValidationCycle fromCycle : fromStudy.getValidationCycles()
301 ValidationCycle cycle = new ValidationCycle(toStudy, fromCycle);
302 getValidationCycleDAO().create(cycle);
303 toStudy.addRelation(cycle.getContext());
304 toStudy.getValidationCycles().put(
305 cycle.getDocumentType().getName(), cycle); // Replaces the cycle if exists as default,
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 dependencies between documents from the given project element up to <BR>
323 * the given step according to the given map of old publications to new publications.
326 * the source project element
327 * @param finalStepNum
328 * the final step for copy processing
330 * the old to new publications map
332 private void copyDependencies(final ProjectElement from,
333 final int finalStepNum,
334 final Map<Publication, Publication> oldToNewPub) {
335 // Copy dependencies between copied documents
336 for (Publication pub : from.getDocums()) {
337 // If the document in the step before the final one
338 if (pub.value().getStep() <= finalStepNum) {
339 Publication newPub = oldToNewPub.get(pub);
340 for (Publication used : pub.getRelations(UsesRelation.class)) {
341 newPub.addDependency(oldToNewPub.get(used));
348 * Copy documents with dependencies up to the given step.
351 * the source project element
353 * the destination project element
354 * @param finalStepNum
355 * the final step for copy process
356 * @param oldToNewPub2
357 * @throws MissedPropertyException
358 * if document creation is failed
359 * @throws InvalidPropertyException
360 * if document creation is failed
361 * @throws MultiplyDefinedException
362 * if document creation is failed
363 * @throws IOException
364 * if document file creation is failed
365 * @throws NotApplicableException
366 * if document state is not applicable
368 * the old to new publications map
371 private void copyDocs(final ProjectElement from, final ProjectElement to,
372 final int finalStepNum,
373 final Map<Publication, Publication> oldToNewPub)
374 throws MissedPropertyException, InvalidPropertyException,
375 MultiplyDefinedException, NotApplicableException, IOException {
376 Map<Integer, Step> steps = getProjectElementService().getStepsMap(to);
377 // Copy publications without old versions and relations to not copied steps documents
378 for (Publication pub : from.getDocums()) {
379 // If the document in the step before the final one
380 if (pub.value().getStep() <= finalStepNum) {
382 oldToNewPub.put(pub, createDoc(pub.value(), steps.get(pub
383 .value().getStep())));
389 * Create a copy of the given document and publish it in the given step.
392 * the source document
394 * the destination step
395 * @return the created publication
396 * @throws MissedPropertyException
397 * if document creation is failed
398 * @throws InvalidPropertyException
399 * if document creation is failed
400 * @throws MultiplyDefinedException
401 * if document creation is failed
402 * @throws IOException
403 * if document file creation is failed
404 * @throws NotApplicableException
405 * if document state is not applicable
407 private Publication createDoc(final Document fromDoc, final Step step)
408 throws MissedPropertyException, InvalidPropertyException,
409 MultiplyDefinedException, IOException, NotApplicableException {
411 java.io.File upfile = fromDoc.getSourceFile().asFile();
412 // Creation of the document
413 Document.Properties dprop = new Document.Properties().setName(
414 fromDoc.getTitle()).setType(fromDoc.getType()).setFormat(
415 fromDoc.getFormat()).setAuthor(fromDoc.getAuthor());
416 dprop.setLocalPath(upfile.getPath());
417 Publication addoc = getStepService().createDocument(step, dprop);
418 copyFile(upfile, addoc.getSourceFile());
419 getPublicationService().saveAs(addoc, fromDoc.getProgressState());
421 // Copy attached files
422 for (Relation rel : addoc.value().getRelations(ConvertsRelation.class)) {
423 File attach = ((ConvertsRelation) rel).getTo();
424 ConvertsRelation export = getPublicationService().attach(addoc,
426 copyFile(attach.asFile(), export.getTo());
432 * Copy a file. Print info message.
438 * @throws IOException
441 private void copyFile(final java.io.File upfile, final File targetFile)
443 if (LOG.isInfoEnabled()) {
444 LOG.info("Copy " + upfile.getAbsolutePath() + TO
445 + targetFile.asFile().getPath());
447 IOUtils.copy(upfile, targetFile.asFile());
453 * @see org.splat.service.ScenarioService#getScenarioInfo(long)
455 @Transactional(readOnly = true)
456 public List<StepDTO> getScenarioInfo(final long scenarioId) {
457 List<StepDTO> res = new ArrayList<StepDTO>();
458 // Get the scenario from the database by id
459 Scenario scen = getScenarioDAO().get(scenarioId);
460 if (LOG.isDebugEnabled()) {
461 LOG.debug("Scenario[" + scenarioId + "]: Number of publications: "
462 + scen.getDocums().size());
464 // Get activities of the scenario
465 Step[] steps = getProjectElementService().getSteps(scen);
468 String docType, fileFormat;
471 // For each activity create a step DTO and add it to the result list
472 for (Step step : steps) {
473 stepDTO = BeanHelper.copyBean(step.getStep(), StepDTO.class);
475 if (LOG.isDebugEnabled()) {
476 LOG.debug("Step[" + stepDTO.getNumber()
477 + "]: Number of documents: "
478 + step.getDocuments().size());
480 // For each publication of the activity create a document DTO.
481 // Each file is considered as a source file.
482 for (Publication tag : step.getDocuments()) {
483 docDTO = stepDTO.addDoc(tag.value().getIndex(), tag.value()
485 char aState = tag.getIsnew();
486 docType = tag.value().getType().getName();
487 // For each file of the document create a file DTO
488 // Process source file of the document
489 fileFormat = tag.value().getFile().getFormat();
490 doImport = getProjectSettings().doImport(docType, fileFormat);
491 if (doImport && (!tag.isOutdated())) {
492 processing = "file-import";
494 processing = "file-download";
496 File aFile = tag.value().getFile();
497 docDTO.addFile(aFile.getIndex(), aFile.getRelativePath(),
498 aState, processing, false);
499 // Process all exported files
500 for (Relation rel : tag.value().getRelations(
501 ConvertsRelation.class)) {
502 aFile = ((ConvertsRelation) rel).getTo();
503 fileFormat = aFile.getFormat();
504 doImport = getProjectSettings().doImport(docType,
506 if (doImport && (!tag.isOutdated())) {
507 processing = "file-import";
509 processing = "file-download";
511 docDTO.addFile(aFile.getIndex(), aFile.getRelativePath(),
512 aState, processing, false);
522 * @see org.splat.service.ScenarioService#createStudy(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
525 public long createStudy(final String username, final String title,
526 final String productName, final String description)
527 throws InvalidPropertyException, MissedPropertyException,
528 MultiplyDefinedException {
532 User author = getUserService().selectUser(username);
533 if (author == null) {
535 throw new InvalidPropertyException(MessageKeyEnum.USR_000001
536 .toString(), username);
539 // Set the study properties
540 Study.Properties sprop = new Study.Properties();
541 sprop.setTitle(title).setManager(author);
542 sprop.setDescription(description);
544 // Find the product simulation context
545 SimulationContextType productContextType = getSimulationContextService()
546 .selectType("product");
547 SimulationContext.Properties cprop = new SimulationContext.Properties();
548 cprop.setType(productContextType).setValue(productName);
549 SimulationContext productCtx = getSimulationContextService()
550 .selectSimulationContext(productContextType, productName);
551 if (productCtx != null) {
552 cprop.setIndex(productCtx.getIndex());
555 // Set a first scenario properties
556 Scenario.Properties oprop = new Scenario.Properties();
557 oprop.setTitle(I18nUtils.getMessageLocaleDefault("label.scenario")
560 Study study = createStudy(sprop, oprop, cprop);
561 id = study.getIndex();
567 * Create a new study with one scenario and "product" simulation context.
570 * the study properties
572 * the scenario properties
574 * the "product" simulation context properties
575 * @return the created study
576 * @throws MissedPropertyException
577 * if a mandatory property is missed
578 * @throws InvalidPropertyException
579 * if a property is invalid
580 * @throws MultiplyDefinedException
581 * if some property occurs several times
584 public Study createStudy(final Study.Properties sprop,
585 final Scenario.Properties oprop,
586 final SimulationContext.Properties cprop)
587 throws MissedPropertyException, InvalidPropertyException,
588 MultiplyDefinedException {
589 Study study = getStudyService().createStudy(sprop);
590 addScenario(study, oprop);
591 if (cprop.getIndex() == 0) { // Input of new project context
592 cprop.setType(getSimulationContextService().selectType("product"))
593 .setValue(cprop.getValue());
594 getStudyService().addProjectContext(study, cprop);
595 } else { // Selection of existing project context
596 SimulationContext context = getSimulationContextService()
597 .selectSimulationContext(cprop.getIndex());
598 getStudyService().addProjectContext(study, context);
606 * @see org.splat.service.ScenarioService#assignStudyContext(java.lang.Long, java.lang.String, java.lang.String)
609 public void assignStudyContext(final Long studyId, final String ctxType,
610 final String ctxValue) throws MissedPropertyException,
611 InvalidPropertyException, MultiplyDefinedException {
612 // Find the study by the given id
613 Study study = getStudyDAO().get(studyId);
615 throw new InvalidPropertyException(MessageKeyEnum.STD_000002
616 .toString(), studyId);
618 // Find the context type by its name
619 SimulationContextType celt = getSimulationContextService().selectType(
622 // Creation of a new context type
623 celt = getSimulationContextTypeService().createType(ctxType,
624 getProjectElementService().getFirstStep(study).getStep());
626 // Find the given context value of the given type
627 SimulationContext context = getSimulationContextService()
628 .selectSimulationContext(celt, ctxValue);
629 if (context == null) { // Input of a new project context
630 SimulationContext.Properties cprop = new SimulationContext.Properties();
631 cprop.setType(celt).setValue(ctxValue);
632 getStudyService().addProjectContext(study, cprop);
633 } else { // Selection of existing project context
634 getStudyService().addProjectContext(study, context);
641 * @see org.splat.service.ScenarioService#addKnowledgeElement(org.splat.dal.bo.som.Scenario,
642 * org.splat.dal.bo.som.KnowledgeElement.Properties)
645 public KnowledgeElement addKnowledgeElement(final Scenario aScenarioDTO,
646 final KnowledgeElement.Properties kprop)
647 throws MissedPropertyException, InvalidPropertyException,
648 MultiplyDefinedException {
649 KnowledgeElement kelm = null;
651 long aScenarioId = aScenarioDTO.getIndex();
652 if (LOG.isDebugEnabled()) {
654 .debug("Add a knowledge element to the scenario #"
657 // Get the persistent scenario.
658 Scenario aScenario = getScenarioDAO().get(aScenarioId);
659 // Get persistent objects for creating a new knowledge.
660 // TODO: Actions must use DTO instead of persistent objects.
661 getUserDAO().merge(kprop.getAuthor());
662 getKnowledgeElementTypeDAO().merge(kprop.getType());
663 // Create a transient knowledge element related to the given scenario.
664 kelm = new KnowledgeElement(kprop.setOwnerScenario(aScenario));
665 // Save the new knowledge in the database.
666 getKnowledgeElementDAO().create(kelm);
667 // Update scenario transient data.
668 if (kelm.getType().equals("usecase")) {
669 aScenarioDTO.setUcase(kelm);
670 } else if (aScenarioDTO.getKnowledgeElementsList() != null) { // If null, knowl will be initialized when needed
671 aScenarioDTO.getKnowledgeElementsList().add(kelm);
674 // Load the workflow for the parent study to take into account
675 // all study actors durng reindexing.
676 getStudyService().loadWorkflow(aScenario.getOwnerStudy());
678 // // Update the lucene index of knowledge elements.
679 // getIndexService().add(kelm);
680 if (LOG.isDebugEnabled()) {
681 LOG.debug("A knowledge element #" + kelm.getIndex()
682 + " is added to the scenario #" + aScenario.getIndex());
684 // } catch (IOException error) {
685 // LOG.error("Unable to index the knowedge element '"
686 // + kelm.getIndex() + "', reason:", error);
696 * @see org.splat.service.ScenarioService#checkin(long, long, java.util.List)
699 public void checkin(final long scenId, final long userId,
700 final List<StepDTO> scInfo) throws InvalidPropertyException,
701 MissedPropertyException, MultiplyDefinedException,
702 MismatchException, IOException, NotApplicableException {
703 // Get the scenario from the database by id
704 Scenario aScenario = getScenarioDAO().get(scenId);
705 // Get the user who perform this check-in operation
706 User aUser = getUserService().selectUser(userId);
707 // Get activities of the scenario
708 Step[] steps = getProjectElementService().getSteps(aScenario);
709 // Find result document types
710 List<DocumentType> resTypes = getDocumentTypeService()
711 .selectResultTypes();
713 // Keep newly created documents to create uses relations to results of a previous step.
714 // For each processed existing document keep its new version
715 Map<Document, Document> newVersion = new HashMap<Document, Document>();
716 // Created publications of new created versions of existing documents
717 List<Publication> newVers = new ArrayList<Publication>();
718 // The list of publications of new created documents not existing before the checkin
719 List<Publication> newDocs = new ArrayList<Publication>();
721 DocumentType resType;
722 Date aDate = new Date(); // The timestamp of the checkin operation
723 for (StepDTO stepDTO : scInfo) {
724 if (LOG.isDebugEnabled()) {
725 LOG.debug("Checkin the step:\n" + stepDTO);
727 // Find a result document type of the step
731 if (resTypes.get(i).isResultOf(
732 getProjectSettings().getStep(stepDTO.getNumber()))) {
733 resType = resTypes.get(i);
736 } while ((resType == null) && (i < resTypes.size()));
738 // Find the appropriate scenario step
739 Step step = findStep(stepDTO, steps);
741 // Process each document of the step
742 for (DocumentDTO doc : stepDTO.getDocs()) {
743 checkinDoc(step, doc, aUser, resType, aDate, newVersion,
748 // Set uses/used relations
749 updateRelationsAfterCheckin(aScenario, newVersion, newVers, newDocs);
751 // Mark the scenario as checked in
756 * Updated uses/used relations after checkin operation:<BR>
758 * <li>For each new version copy uses relations from the previous version.</li>
759 * <li>Outdate documents which depend from the previous version and were not checked in during this operation.</li>
760 * <li>For each new document create uses relation to the last versions of results of the previous step.</li>
764 * the checked in scenario
766 * the mapping of documents existed before the checkin to their new created versions
768 * the list of publications of new created versions of documents existed before the checkin
770 * the list of publications of new created documents not existed before the checkin
772 private void updateRelationsAfterCheckin(final Scenario aScenario,
773 final Map<Document, Document> newVersion,
774 final List<Publication> newVers, final List<Publication> newDocs) {
775 // For each new version copy uses relations from the previous version.
776 for (Publication newVer : newVers) {
777 // For each Uses relation of the previous version
778 Document prevDoc = newVer.value().getPreviousVersion();// prevVersion.get(newVer);
779 if (LOG.isDebugEnabled()) {
780 LOG.debug("Previous version for publication #"
781 + newVer.getIndex() + " is found: " + prevDoc);
783 List<Relation> usesRelations = prevDoc
784 .getRelations(UsesRelation.class);
785 for (Relation rel : usesRelations) {
786 // If used document has been also versioned then refer to its new version.
787 Document usedDoc = ((UsesRelation) rel).getTo();
788 if (newVersion.containsKey(usedDoc)) {
789 usedDoc = newVersion.get(usedDoc);
791 // Build the appropriate relation for the new version.
792 newVer.addDependency(usedDoc);
794 // Outdate documents which depend from the previous version and
795 // were not checked in during this operation.
796 // 1. Get all usedBy relations of the previous document version
797 for (Relation rel : prevDoc.getRelations(UsedByRelation.class)) {
798 Document using = ((UsedByRelation) rel).getTo();
799 // Check that not checked in dependent documents became outdated
800 Publication usingPub = aScenario.getPublication(using);
801 if (usingPub != null) { // if the document using the old version is still published
802 usingPub.setIsnew('O');
807 // For each new document create uses relation to the last versions of
808 // results of the previous step.
809 for (Publication newPub : newDocs) {
810 // Find used document type according to the configuration.
811 Set<DocumentType> usedTypes = newPub.value().getType()
813 // Find documents of used type in the previous study step.
814 for (Publication pub : aScenario.getDocums()) {
815 if ((pub.getStep().getNumber() <= newPub.getStep().getNumber())
816 && (!pub.isOutdated())
817 && usedTypes.contains(pub.value().getType())) {
818 // Create uses relation from the new document
819 // to the found document in the previous step.
820 newPub.addDependency(pub);
827 * Pure checkin of the document without creation of uses/usedBy relations. For an existing document a new version is created. New
828 * documents become published in the given step of the appropriate scenario. The appropriate uploaded file is attached to the created
829 * document and the document is published in the scenario. The publication of the old version is removed from the scenario.
832 * the destination scenario step
834 * the DTO of the document to checkin
836 * the user who performs checkin
838 * the result document type of the given step
840 * timestamp of the checkin operation
842 * the mapping of existing documents to their new created versions
844 * the list of publications of new created versions of existing documents
846 * the list of publications of new created documents not existing before the checkin
847 * @throws InvalidPropertyException
848 * if the scenario hasn't some of given steps or documents
849 * @throws IOException
850 * if a file can't be moved into the vault
851 * @throws MismatchException
852 * if version creation in some of steps is failed
853 * @throws MissedPropertyException
854 * if some mandatory property is missed when new document or new document version is created
855 * @throws MultiplyDefinedException
856 * if some property is defined several times when new document or new document version is created
857 * @throws NotApplicableException
858 * if failed saving of a new publication with a given state
860 private void checkinDoc(final Step step, final DocumentDTO doc,
861 final User aUser, final DocumentType resType, final Date aDate,
862 final Map<Document, Document> newVersion,
863 final List<Publication> newVers, final List<Publication> newDocs)
864 throws InvalidPropertyException, MismatchException,
865 MissedPropertyException, MultiplyDefinedException, IOException,
866 NotApplicableException {
867 if (doc.getFiles().size() > 0) {
868 Document.Properties dprop = new Document.Properties();
869 // NOTE: Process only the first attached file for each document
870 FileDTO file = doc.getFiles().get(0);
871 dprop.setLocalPath(file.getPath());
873 // Get document title as the file name
874 java.io.File upfile = new java.io.File(file.getPath());
875 String fileFormat = upfile.getName().substring(
876 upfile.getName().lastIndexOf('.') + 1);
878 // Attach the file via ConvertsRelation, create a new document or
879 // create a new version of the document
880 dprop.setAuthor(aUser).setDate(aDate).setFormat(fileFormat);
882 if (doc.getId() > 0) {
883 checkinExistingDoc(step, doc, dprop, fileFormat, upfile,
884 newVersion, newVers);
887 // Otherwise create a new document of the result type
888 // If result type is not found try to get type by file extension
889 if (resType == null) {
890 dprop.setType(getProjectSettings().getDefaultDocumentType(
891 step.getStep(), fileFormat));
893 dprop.setType(resType);
895 // New document title generation as <document type name>_N
896 String docname = dprop.getType().getName();
898 for (Publication scenPub : step.getOwner().getDocums()) {
899 if (scenPub.value().getTitle().startsWith(docname)) {
903 docname += "_" + i; // The generated new document title
905 dprop.setDescription("Checked in").setName(docname);
906 Publication newPub = getStepService().createDocument(step,
909 // Remember the new document
912 saveFile(newPub, step, upfile);
918 * Check in existing document.
921 * study step to check in
923 * document DTO to check in
925 * document properties
927 * checked in file format
929 * the file to check in
931 * the map of created versions during this check in
933 * the list of new versions created during this check in
934 * @throws InvalidPropertyException
935 * if publication of the document is not found in the step
936 * @throws MismatchException
937 * if the found publication does not point to a document
938 * @throws IOException
939 * if can not move the file into the vault
940 * @throws MultiplyDefinedException
941 * thrown by versionDocument
942 * @throws MissedPropertyException
943 * thrown by versionDocument
944 * @throws NotApplicableException
945 * if failed saving of a new publication with a given state
947 private void checkinExistingDoc(final Step step, final DocumentDTO doc,
948 final Properties dprop, final String fileFormat,
949 final java.io.File upfile,
950 final Map<Document, Document> newVersion,
951 final List<Publication> newVers) throws InvalidPropertyException,
952 MismatchException, MissedPropertyException,
953 MultiplyDefinedException, IOException, NotApplicableException {
954 // If the document already exists then
955 // Attach the file via ConvertsRelation if the extension of the
956 // new file differs from the old one.
957 // If file format (i.e. extension) is the same then create a new
958 // version of the document.
959 // Find the document publication
960 Publication pub = step.getDocument(doc.getId());
962 throw new InvalidPropertyException(MessageKeyEnum.SCN_000002
963 .toString(), doc.getId());
965 if (pub.value() == null) {
966 throw new MismatchException(MessageKeyEnum.SCN_000002.toString(),
969 if (LOG.isDebugEnabled()) {
970 LOG.debug("Old format: " + pub.value().getFormat()
971 + " => New format: " + fileFormat);
973 // If formats are same then create a new document version
974 if (pub.value().getFormat() != null
975 && pub.value().getFormat().equals(fileFormat)) {
976 Publication newPub = getStepService().versionDocument(step, pub,
978 if (LOG.isDebugEnabled()) {
979 LOG.debug("Created document type: "
980 + newPub.value().getType().getName() + ", format: "
981 + newPub.value().getFormat());
983 // Remeber the link from the old document to the new document version
984 newVersion.put(pub.value(), newPub.value());
985 // Remember the new version publication
988 saveFile(newPub, step, upfile);
990 } else { // If formats are different then attach the new file via ConvertsRelation
991 File attach = pub.value().getAttachedFile(fileFormat);
992 if (attach == null) {
993 // If there is no attachment with this extension then attach the new one
994 ConvertsRelation export = getPublicationService().attach(pub,
996 if (LOG.isDebugEnabled()) {
997 LOG.debug("Moving " + upfile.getName() + TO
998 + export.getTo().asFile().getPath());
1000 upfile.renameTo(export.getTo().asFile());
1002 // If an attachment with this extension already exists then
1003 // replace it by the new one
1004 upfile.renameTo(attach.asFile());
1005 // Update attached file modification date
1006 attach.setDate(new Date());
1012 * Save the file in the vault and create its publication in the step.
1015 * the new publication to save
1017 * the study step to publish the document
1019 * the downloaded file
1020 * @throws IOException
1021 * if a file can't be moved into the vault
1022 * @throws NotApplicableException
1023 * if failed saving of a new publication with a given state
1025 private void saveFile(final Publication newPub, final Step step,
1026 final java.io.File upfile) throws IOException,
1027 NotApplicableException {
1028 // Attach the file to the created document
1029 java.io.File updir = newPub.getSourceFile().asFile();
1030 if (LOG.isDebugEnabled()) {
1031 LOG.debug("Moving \"" + upfile.getName() + "\" to \""
1032 + updir.getPath() + "\".");
1034 if (updir.exists()) {
1035 if (updir.delete()) {
1036 LOG.info(MessageKeyEnum.SCN_000003.toString(), updir
1037 .getAbsoluteFile(), step.getOwner().getIndex());
1039 throw new IOException(
1040 "Can't delete the existing destination file to move file from "
1041 + upfile.getAbsolutePath() + TO
1042 + updir.getAbsolutePath());
1045 if (upfile.renameTo(updir)) {
1046 // Save the new publication in the scenario.
1047 // The old publication is removed from the scenario here.
1048 getPublicationService().saveAs(newPub, ProgressState.inWORK); // May throw FileNotFound if rename was not done
1050 throw new IOException("Can't move file from "
1051 + upfile.getAbsolutePath() + TO + updir.getAbsolutePath());
1056 * Find appropriate step in the array of scenario steps according to the given step DTO.
1062 * @return appropriate scenario step
1063 * @throws InvalidPropertyException
1064 * if appropriate step is not found
1066 private Step findStep(final StepDTO stepDTO, final Step[] steps)
1067 throws InvalidPropertyException {
1071 if (steps[i].getNumber() == stepDTO.getNumber()) {
1075 } while ((step == null) && (i < steps.length));
1078 throw new InvalidPropertyException(MessageKeyEnum.SCN_000001
1079 .toString(), stepDTO.getNumber());
1087 * @see org.splat.service.ScenarioService#checkin(long)
1090 public void checkin(final long scenarioId) throws InvalidPropertyException {
1091 Scenario aScenario = getScenarioDAO().get(scenarioId);
1092 if (aScenario == null) {
1093 // Scenario not found
1094 throw new InvalidPropertyException(MessageKeyEnum.SCN_000006
1095 .toString(), scenarioId);
1101 * Mark the scenario as checked in.
1104 * the scenario to check in.
1106 private void checkin(final Scenario aScenario) {
1107 aScenario.setUser(null);
1108 aScenario.setLastModificationDate(Calendar.getInstance().getTime());
1109 // getScenarioDAO().update(aScenario);
1115 * @see org.splat.service.ScenarioService#checkout(org.splat.dal.bo.som.Scenario, org.splat.dal.bo.kernel.User)
1117 public boolean checkout(final Scenario aScenario, final User user) {
1118 boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
1121 aScenario.setUser(user);
1122 aScenario.setLastModificationDate(Calendar.getInstance().getTime());
1123 // RKV: getScenarioDAO().update(aScenario);
1129 * Mark the given scenario as checked out by the given user.
1134 * the id of the user performing the check out
1135 * @throws InvalidPropertyException
1136 * if the user or the scenario is not found in the database
1137 * @throws NotApplicableException
1138 * if the given user can not check out the scenario
1141 public void checkout(final long scenarioId, final long userId)
1142 throws InvalidPropertyException, NotApplicableException {
1143 User aUser = getUserService().selectUser(userId);
1144 if (aUser == null) {
1146 throw new InvalidPropertyException(MessageKeyEnum.USR_000001
1147 .toString(), userId);
1149 Scenario aScenario = getScenarioDAO().get(scenarioId);
1150 if (aScenario == null) {
1151 // Scenario not found
1152 throw new InvalidPropertyException(MessageKeyEnum.SCN_000006
1153 .toString(), scenarioId);
1155 boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
1158 if (aScenario.isCheckedout()
1159 && (!aScenario.getUser().getUsername().equals(
1160 aUser.getUsername()))) {
1161 throw new NotApplicableException(MessageKeyEnum.SCN_000008
1162 .toString(), scenarioId, aScenario.getUser()
1165 aScenario.setUser(aUser);
1166 aScenario.setLastModificationDate(Calendar.getInstance().getTime());
1168 // User doesn't participate in the scenario
1169 throw new NotApplicableException(MessageKeyEnum.SCN_000007
1170 .toString(), aUser.getUsername(), scenarioId);
1177 * @see org.splat.service.ScenarioService#copyContentsUpTo(org.splat.dal.bo.som.Scenario, org.splat.som.Step)
1179 public void copyContentsUpTo(final Scenario scenario, final Step lastep) {
1180 Scenario base = (Scenario) lastep.getOwner();
1181 Step[] from = getProjectElementService().getSteps(base);
1182 Step[] to = getProjectElementService().getSteps(scenario);
1183 for (int i = 0; i < from.length; i++) {
1184 Step step = from[i];
1185 if (step.getNumber() > lastep.getNumber()) {
1189 List<Publication> docs = step.getAllDocuments();
1190 for (Iterator<Publication> j = docs.iterator(); j.hasNext();) {
1191 Publication doc = getPublicationService().copy(j.next(),
1192 scenario); // Creation of a new reference to the document
1193 // Database.getSession().save(doc); Publications MUST be saved later through cascading when saving the scenario
1194 getStepService().add(to[i], doc);
1196 List<SimulationContext> ctex = step.getAllSimulationContexts();
1197 for (Iterator<SimulationContext> j = ctex.iterator(); j.hasNext();) {
1198 getStepService().addSimulationContext(to[i], j.next());
1206 * @see org.splat.service.ScenarioService#isEmpty(org.splat.dal.bo.som.Scenario)
1208 public boolean isEmpty(final Scenario scenario) {
1209 Step[] mystep = getProjectElementService().getSteps(scenario);
1210 boolean isEmp = true;
1211 for (int i = 0; i < mystep.length; i++) {
1212 if (mystep[i].isStarted()) {
1224 public boolean isFinished(final Scenario scenario) {
1225 Step[] mystep = getProjectElementService().getSteps(scenario);
1226 boolean notempty = false; // If this is empty, this is not finished
1227 for (int i = 0; i < mystep.length; i++) {
1228 if (!mystep[i].isStarted()) {
1231 if (!mystep[i].isFinished()) {
1242 * @see org.splat.service.StudyService#addScenario(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Scenario.Properties)
1245 public Scenario addScenario(final Study aStudy,
1246 final Scenario.Properties sprop) throws MissedPropertyException,
1247 InvalidPropertyException, MultiplyDefinedException {
1248 if (sprop.getManager() == null) {
1249 sprop.setManager(aStudy.getAuthor());
1252 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
1253 if (sprop.getBaseStep() != null) {
1254 copyContentsUpTo(scenario, sprop.getBaseStep());
1256 Scenario previous = sprop.getInsertAfter();
1258 if (previous == null) {
1259 aStudy.getScenariiList().add(scenario);
1261 aStudy.getScenariiList().add(
1262 aStudy.getScenariiList().indexOf(previous) + 1, scenario);
1264 getStudyDAO().update(aStudy); // No need to update the Lucene index
1265 getScenarioDAO().create(scenario); // Must be done after updating this study because of the back reference to the study
1266 if (sprop.getBaseStep() != null) {
1267 // No need to update the Knowledge Element index as Knowledge Elements are not copied
1268 getProjectElementService().refresh(scenario); // Because saving the scenario changes the hashcode of copied Publications
1270 KnowledgeElementType ucase = getKnowledgeElementTypeService()
1271 .selectType("usecase");
1272 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
1273 // TODO: Get appropriate user by its role: UserService.getAdmin();
1274 // User admin = getUserService().selectUser(1); // First user created when creating the database
1275 Role adminRole = getRoleDAO().getFilteredList(
1276 Restrictions.like("role", "%sysadmin%")).get(0);
1277 User admin = getUserDAO().getFilteredList(
1278 Restrictions.eq("role", adminRole), Order.asc("rid")).get(0); // First sysadmin in the database
1280 kprop.setType(ucase).setTitle(aStudy.getTitle()).setValue(
1281 scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
1283 addKnowledgeElement(scenario, kprop);
1288 * Remove a knowledge element from a scenario.
1293 * the knowledge element to remove
1294 * @return true if removal succeeded
1297 public boolean removeKnowledgeElement(final Scenario scenario,
1298 final KnowledgeElement kelm) {
1299 KnowledgeElement torem = scenario.getKnowledgeElement(kelm.getIndex());
1300 boolean isOk = (torem != null);
1302 isOk = scenario.getKnowledgeElements().remove(torem);
1304 getScenarioDAO().merge(scenario);
1305 // Update of my transient data
1306 // RKV: These transient data are not used indeed.
1307 // RKV: List<KnowledgeElement> kelms = scenario.getKnowledgeByType().get(
1308 // RKV: kelm.getType().getIndex());
1309 // RKV: kelms.remove(torem);
1310 if (scenario.getKnowledgeElementsList() != null) {
1311 scenario.getKnowledgeElementsList().remove(torem);
1313 // TODO: If the owner study is not private, remove the knowledge from the Lucene index
1323 * @see org.splat.service.ScenarioService#renameScenario(java.lang.String)
1326 public void renameScenario(final Scenario scenario) {
1327 getScenarioDAO().merge(scenario);
1331 * Get the knowledgeElementDAO.
1333 * @return the knowledgeElementDAO
1335 public KnowledgeElementDAO getKnowledgeElementDAO() {
1336 return _knowledgeElementDAO;
1340 * Set the knowledgeElementDAO.
1342 * @param knowledgeElementDAO
1343 * the knowledgeElementDAO to set
1345 public void setKnowledgeElementDAO(
1346 final KnowledgeElementDAO knowledgeElementDAO) {
1347 _knowledgeElementDAO = knowledgeElementDAO;
1351 * Get the indexService.
1353 * @return the indexService
1355 public IndexService getIndexService() {
1356 return _indexService;
1360 * Set the indexService.
1362 * @param indexService
1363 * the indexService to set
1365 public void setIndexService(final IndexService indexService) {
1366 _indexService = indexService;
1370 * Get the scenarioDAO.
1372 * @return the scenarioDAO
1374 public ScenarioDAO getScenarioDAO() {
1375 return _scenarioDAO;
1379 * Set the scenarioDAO.
1381 * @param scenarioDAO
1382 * the scenarioDAO to set
1384 public void setScenarioDAO(final ScenarioDAO scenarioDAO) {
1385 _scenarioDAO = scenarioDAO;
1391 * @return the studyDAO
1393 public StudyDAO getStudyDAO() {
1401 * the studyDAO to set
1403 public void setStudyDAO(final StudyDAO studyDAO) {
1404 _studyDAO = studyDAO;
1408 * Get the knowledgeElementTypeService.
1410 * @return the knowledgeElementTypeService
1412 public KnowledgeElementTypeService getKnowledgeElementTypeService() {
1413 return _knowledgeElementTypeService;
1417 * Set the knowledgeElementTypeService.
1419 * @param knowledgeElementTypeService
1420 * the knowledgeElementTypeService to set
1422 public void setKnowledgeElementTypeService(
1423 final KnowledgeElementTypeService knowledgeElementTypeService) {
1424 _knowledgeElementTypeService = knowledgeElementTypeService;
1428 * Get the studyService.
1430 * @return the studyService
1432 public StudyService getStudyService() {
1433 return _studyService;
1437 * Set the studyService.
1439 * @param studyService
1440 * the studyService to set
1442 public void setStudyService(final StudyService studyService) {
1443 _studyService = studyService;
1447 * Get the userService.
1449 * @return the userService
1451 public UserService getUserService() {
1452 return _userService;
1456 * Set the userService.
1458 * @param userService
1459 * the userService to set
1461 public void setUserService(final UserService userService) {
1462 _userService = userService;
1468 * @return the userDAO
1470 public UserDAO getUserDAO() {
1478 * the userDAO to set
1480 public void setUserDAO(final UserDAO userDAO) {
1485 * Get the knowledgeElementTypeDAO.
1487 * @return the knowledgeElementTypeDAO
1489 public KnowledgeElementTypeDAO getKnowledgeElementTypeDAO() {
1490 return _knowledgeElementTypeDAO;
1494 * Set the knowledgeElementTypeDAO.
1496 * @param knowledgeElementTypeDAO
1497 * the knowledgeElementTypeDAO to set
1499 public void setKnowledgeElementTypeDAO(
1500 final KnowledgeElementTypeDAO knowledgeElementTypeDAO) {
1501 _knowledgeElementTypeDAO = knowledgeElementTypeDAO;
1505 * Get the simulationContextService.
1507 * @return the simulationContextService
1509 public SimulationContextService getSimulationContextService() {
1510 return _simulationContextService;
1514 * Set the simulationContextService.
1516 * @param simulationContextService
1517 * the simulationContextService to set
1519 public void setSimulationContextService(
1520 final SimulationContextService simulationContextService) {
1521 _simulationContextService = simulationContextService;
1525 * Get project settings.
1527 * @return Project settings service
1529 private ProjectSettingsService getProjectSettings() {
1530 return _projectSettings;
1534 * Set project settings service.
1536 * @param projectSettingsService
1537 * project settings service
1539 public void setProjectSettings(
1540 final ProjectSettingsService projectSettingsService) {
1541 _projectSettings = projectSettingsService;
1545 * Get the documentTypeService.
1547 * @return the documentTypeService
1549 public DocumentTypeService getDocumentTypeService() {
1550 return _documentTypeService;
1554 * Set the documentTypeService.
1556 * @param documentTypeService
1557 * the documentTypeService to set
1559 public void setDocumentTypeService(
1560 final DocumentTypeService documentTypeService) {
1561 _documentTypeService = documentTypeService;
1567 * @return the roleDAO
1569 public RoleDAO getRoleDAO() {
1577 * the roleDAO to set
1579 public void setRoleDAO(final RoleDAO roleDAO) {
1584 * Get the simulationContextTypeService.
1586 * @return the simulationContextTypeService
1588 public SimulationContextTypeService getSimulationContextTypeService() {
1589 return _simulationContextTypeService;
1593 * Set the simulationContextTypeService.
1595 * @param simulationContextTypeService
1596 * the simulationContextTypeService to set
1598 public void setSimulationContextTypeService(
1599 final SimulationContextTypeService simulationContextTypeService) {
1600 _simulationContextTypeService = simulationContextTypeService;
1604 * Get the validationCycleDAO.
1606 * @return the validationCycleDAO
1608 public ValidationCycleDAO getValidationCycleDAO() {
1609 return _validationCycleDAO;
1613 * Set the validationCycleDAO.
1615 * @param validationCycleDAO
1616 * the validationCycleDAO to set
1618 public void setValidationCycleDAO(
1619 final ValidationCycleDAO validationCycleDAO) {
1620 _validationCycleDAO = validationCycleDAO;
1626 * @return steps config service
1628 private StepsConfigService getStepsConfigService() {
1629 return _stepsConfigService;
1633 * Set steps config service.
1635 * @param stepsConfigService
1636 * steps config service
1638 public void setStepsConfigService(
1639 final StepsConfigService stepsConfigService) {
1640 _stepsConfigService = stepsConfigService;