Salome HOME
Creation of a new study from an existing one is implemented.
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / ScenarioServiceImpl.java
index 10b5ba93b72c8982120a6cb7570b46b7990e1840..794dd9029d8a799238c577c7524ad9a97a886a60 100644 (file)
 package org.splat.service;
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
 
-import org.apache.log4j.Logger;
+import org.hibernate.criterion.DetachedCriteria;
+import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Projections;
+import org.hibernate.criterion.Restrictions;
+import org.hibernate.transform.Transformers;
+import org.splat.common.properties.MessageKeyEnum;
+import org.splat.dal.bo.kernel.Relation;
+import org.splat.dal.bo.kernel.Role;
 import org.splat.dal.bo.kernel.User;
+import org.splat.dal.bo.som.ConvertsRelation;
+import org.splat.dal.bo.som.Document;
+import org.splat.dal.bo.som.DocumentType;
+import org.splat.dal.bo.som.File;
 import org.splat.dal.bo.som.KnowledgeElement;
 import org.splat.dal.bo.som.KnowledgeElementType;
+import org.splat.dal.bo.som.ProgressState;
+import org.splat.dal.bo.som.ProjectElement;
 import org.splat.dal.bo.som.Publication;
 import org.splat.dal.bo.som.Scenario;
 import org.splat.dal.bo.som.SimulationContext;
+import org.splat.dal.bo.som.SimulationContextType;
 import org.splat.dal.bo.som.Study;
+import org.splat.dal.bo.som.UsedByRelation;
+import org.splat.dal.bo.som.UsesRelation;
+import org.splat.dal.bo.som.ValidationCycle;
+import org.splat.dal.bo.som.Document.Properties;
+import org.splat.dal.dao.kernel.RoleDAO;
+import org.splat.dal.dao.kernel.UserDAO;
 import org.splat.dal.dao.som.KnowledgeElementDAO;
+import org.splat.dal.dao.som.KnowledgeElementTypeDAO;
 import org.splat.dal.dao.som.ScenarioDAO;
 import org.splat.dal.dao.som.StudyDAO;
+import org.splat.dal.dao.som.ValidationCycleDAO;
+import org.splat.exception.InvalidParameterException;
+import org.splat.i18n.I18nUtils;
 import org.splat.kernel.InvalidPropertyException;
+import org.splat.kernel.MismatchException;
 import org.splat.kernel.MissedPropertyException;
 import org.splat.kernel.MultiplyDefinedException;
-import org.splat.kernel.UserDirectory;
+import org.splat.kernel.NotApplicableException;
+import org.splat.log.AppLogger;
+import org.splat.service.dto.DocumentDTO;
+import org.splat.service.dto.FileDTO;
+import org.splat.service.dto.ScenarioDTO;
+import org.splat.service.dto.StepDTO;
 import org.splat.service.technical.IndexService;
+import org.splat.service.technical.ProjectSettingsService;
+import org.splat.service.technical.RepositoryService;
+import org.splat.service.technical.StepsConfigService;
 import org.splat.som.Step;
+import org.splat.util.BeanHelper;
+import org.splat.util.IOUtils;
 import org.springframework.transaction.annotation.Transactional;
 
 /**
@@ -41,11 +81,15 @@ import org.springframework.transaction.annotation.Transactional;
 public class ScenarioServiceImpl implements ScenarioService {
 
        /**
-        * Logger for this class.
+        * The logger for the service.
         */
-       protected final static Logger logger = Logger
+       public final static AppLogger LOG = AppLogger
                        .getLogger(ScenarioServiceImpl.class);
 
+       /**
+        * " to " literal.
+        */
+       private static final String TO = " to ";
        /**
         * Injected index service.
         */
@@ -85,6 +129,61 @@ public class ScenarioServiceImpl implements ScenarioService {
         */
        private KnowledgeElementTypeService _knowledgeElementTypeService;
 
+       /**
+        * Injected user service.
+        */
+       private UserService _userService;
+
+       /**
+        * Injected user DAO.
+        */
+       private UserDAO _userDAO;
+
+       /**
+        * Injected role DAO.
+        */
+       private RoleDAO _roleDAO;
+
+       /**
+        * Injected knowledge element type DAO.
+        */
+       private KnowledgeElementTypeDAO _knowledgeElementTypeDAO;
+
+       /**
+        * Injected simulation context service.
+        */
+       private SimulationContextService _simulationContextService;
+
+       /**
+        * Injected simulation context type service.
+        */
+       private SimulationContextTypeService _simulationContextTypeService;
+
+       /**
+        * Injected project service.
+        */
+       private ProjectSettingsService _projectSettings;
+
+       /**
+        * Injected document type service.
+        */
+       private DocumentTypeService _documentTypeService;
+
+       /**
+        * Injected validation cycle DAO.
+        */
+       private ValidationCycleDAO _validationCycleDAO;
+
+       /**
+        * Injected project settings service.
+        */
+       private StepsConfigService _stepsConfigService;
+
+       /**
+        * Injected repository service.
+        */
+       private RepositoryService _repositoryService;
+
        /**
         * Get the projectElementService.
         * 
@@ -101,7 +200,7 @@ public class ScenarioServiceImpl implements ScenarioService {
         *            the projectElementService to set
         */
        public void setProjectElementService(
-                       ProjectElementService projectElementService) {
+                       final ProjectElementService projectElementService) {
                _projectElementService = projectElementService;
        }
 
@@ -120,7 +219,8 @@ public class ScenarioServiceImpl implements ScenarioService {
         * @param publicationService
         *            the publicationService to set
         */
-       public void setPublicationService(PublicationService publicationService) {
+       public void setPublicationService(
+                       final PublicationService publicationService) {
                _publicationService = publicationService;
        }
 
@@ -139,10 +239,454 @@ public class ScenarioServiceImpl implements ScenarioService {
         * @param stepService
         *            the stepService to set
         */
-       public void setStepService(StepService stepService) {
+       public void setStepService(final StepService stepService) {
                _stepService = stepService;
        }
 
+       /**
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.ScenarioService#getStudyScenarios(java.lang.Long)
+        */
+       @Override
+       @Transactional(readOnly = true)
+       public List<ScenarioDTO> getStudyScenarios(final Long studyId) {
+               DetachedCriteria query = DetachedCriteria
+                               .forClass(Scenario.class, "scen")
+                               .add(Restrictions.eq("owner.rid", studyId))
+                               .setProjection(
+                                               Projections.projectionList().add(
+                                                               Projections.property("scen.title"), "title")
+                                                               .add(Projections.property("scen.rid"), "index"))
+                               .setResultTransformer(
+                                               Transformers.aliasToBean(ScenarioDTO.class));
+               return getScenarioDAO().getFilteredDTOList(query);
+       }
+
+       /**
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.ScenarioService#copyStudyContent(long, long, int, long)
+        */
+       @Override
+       @Transactional
+       public void copyStudyContent(final long fromStudyId, final long fromScenId,
+                       final int finalStepNum, final long toStudyId)
+                       throws InvalidParameterException, MissedPropertyException,
+                       InvalidPropertyException, MultiplyDefinedException,
+                       NotApplicableException, IOException {
+               Study fromStudy = getStudyService().selectStudy(fromStudyId);
+               if (fromStudy == null) {
+                       throw new InvalidParameterException(MessageKeyEnum.STD_000002
+                                       .toString(), String.valueOf(fromStudyId));
+               }
+               Scenario fromScen = null;
+               for (Scenario scen : fromStudy.getScenariiList()) {
+                       if (scen.getIndex() == fromScenId) {
+                               fromScen = scen;
+                               break;
+                       }
+               }
+
+               Study toStudy = getStudyService().selectStudy(toStudyId);
+               if (toStudy == null) {
+                       throw new InvalidParameterException(MessageKeyEnum.STD_000002
+                                       .toString(), String.valueOf(toStudy));
+               }
+
+               // Check if the step is applied to a scenario and scenario is defined
+               if (fromScen == null
+                               && getStepsConfigService().stepInvolves(finalStepNum,
+                                               Scenario.class)) {
+                       throw new InvalidParameterException(MessageKeyEnum.SCN_000006
+                                       .toString(), String.valueOf(fromScenId));
+               }
+
+               // Copy validation cycles
+               copyValidationCycles(fromStudy, toStudy);
+
+               // Copy content of the study up to the given step
+               Map<Publication, Publication> oldToNewPub = new HashMap<Publication, Publication>();
+               copyDocs(fromStudy, toStudy, finalStepNum, oldToNewPub);
+               if (fromScen != null) {
+                       copyDocs(fromScen, toStudy.getScenariiList().get(0), finalStepNum,
+                                       oldToNewPub);
+               }
+               copyDependencies(fromStudy, finalStepNum, oldToNewPub);
+               if (fromScen != null) {
+                       copyDependencies(fromScen, finalStepNum, oldToNewPub);
+               }
+       }
+
+       /**
+        * Copy validation cycles from study to study.
+        * 
+        * @param fromStudy
+        *            the source study
+        * @param toStudy
+        *            the destination study
+        */
+       private void copyValidationCycles(final Study fromStudy, final Study toStudy) {
+               for (ValidationCycle fromCycle : fromStudy.getValidationCycles()
+                               .values()) {
+                       if (fromCycle.isAssigned()) {
+                               ValidationCycle cycle = fromCycle.clone(toStudy);
+                               getValidationCycleDAO().create(cycle);
+                               toStudy.addRelation(cycle.getContext());
+                               toStudy.getValidationCycles().put(
+                                               cycle.getDocumentType().getName(), cycle); // Replaces the cycle if exists as default,
+                       }
+               }
+       }
+
+       /**
+        * Copy dependencies between documents from the given project element up to <BR>
+        * the given step according to the given map of old publications to new publications.
+        * 
+        * @param from
+        *            the source project element
+        * @param finalStepNum
+        *            the final step for copy processing
+        * @param oldToNewPub
+        *            the old to new publications map
+        */
+       private void copyDependencies(final ProjectElement from,
+                       final int finalStepNum,
+                       final Map<Publication, Publication> oldToNewPub) {
+               // Copy dependencies between copied documents
+               for (Publication pub : from.getDocums()) {
+                       // If the document in the step before the final one
+                       if (pub.value().getStep() <= finalStepNum) {
+                               Publication newPub = oldToNewPub.get(pub);
+                               for (Publication used : pub.getRelations(UsesRelation.class)) {
+                                       newPub.addDependency(oldToNewPub.get(used));
+                               }
+                       }
+               }
+       }
+
+       /**
+        * Copy documents with dependencies up to the given step.
+        * 
+        * @param from
+        *            the source project element
+        * @param to
+        *            the destination project element
+        * @param finalStepNum
+        *            the final step for copy process
+        * @param oldToNewPub2
+        * @throws MissedPropertyException
+        *             if document creation is failed
+        * @throws InvalidPropertyException
+        *             if document creation is failed
+        * @throws MultiplyDefinedException
+        *             if document creation is failed
+        * @throws IOException
+        *             if document file creation is failed
+        * @throws NotApplicableException
+        *             if document state is not applicable
+        * @param oldToNewPub
+        *            the old to new publications map
+        * 
+        */
+       private void copyDocs(final ProjectElement from, final ProjectElement to,
+                       final int finalStepNum,
+                       final Map<Publication, Publication> oldToNewPub)
+                       throws MissedPropertyException, InvalidPropertyException,
+                       MultiplyDefinedException, NotApplicableException, IOException {
+               Map<Integer, Step> steps = getProjectElementService().getStepsMap(to);
+               // Copy publications without old versions and relations to not copied steps documents
+               for (Publication pub : from.getDocums()) {
+                       // If the document in the step before the final one
+                       if (pub.value().getStep() <= finalStepNum) {
+                               // Copy the document
+                               oldToNewPub.put(pub, createDoc(pub.value(), steps.get(pub
+                                               .value().getStep())));
+                       }
+               }
+       }
+
+       /**
+        * Create a copy of the given document and publish it in the given step.
+        * 
+        * @param fromDoc
+        *            the source document
+        * @param step
+        *            the destination step
+        * @return the created publication
+        * @throws MissedPropertyException
+        *             if document creation is failed
+        * @throws InvalidPropertyException
+        *             if document creation is failed
+        * @throws MultiplyDefinedException
+        *             if document creation is failed
+        * @throws IOException
+        *             if document file creation is failed
+        * @throws NotApplicableException
+        *             if document state is not applicable
+        */
+       private Publication createDoc(final Document fromDoc, final Step step)
+                       throws MissedPropertyException, InvalidPropertyException,
+                       MultiplyDefinedException, IOException, NotApplicableException {
+
+               java.io.File srcFile = fromDoc.getSourceFile().asFile();
+               // Creation of the document
+               Document.Properties dprop = new Document.Properties().setName(
+                               fromDoc.getTitle()).setType(fromDoc.getType()).setFormat(
+                               fromDoc.getFormat()).setAuthor(fromDoc.getAuthor());
+
+               java.io.File tmpDir = getRepositoryService().getDownloadDirectory(
+                               step.getOwnerStudy().getAuthor());
+
+               // Remove local file index prefix to get original filename.
+               java.io.File upfile = new java.io.File(tmpDir.getPath()
+                               + "/"
+                               + srcFile.getName().substring(
+                                               srcFile.getName().indexOf('_') + 1));
+               // Copy the source file into the temporary folder with original filename.
+               copyFile(srcFile, upfile);
+
+               dprop.setLocalPath(upfile.getPath());
+               Publication addoc = getStepService().createDocument(step, dprop);
+
+               // Move the temporary file into the repository
+               moveFile(upfile, addoc.getSourceFile().asFile());
+
+               getPublicationService().saveAs(addoc, fromDoc.getProgressState());
+
+               // Copy attached files
+               for (Relation rel : fromDoc.getRelations(ConvertsRelation.class)) {
+                       File attach = ((ConvertsRelation) rel).getTo();
+                       ConvertsRelation export = getPublicationService().attach(addoc,
+                                       attach.getFormat());
+                       // Copy the source document attachment file to the new study vault
+                       copyFile(attach.asFile(), export.getTo().asFile());
+               }
+               return addoc;
+       }
+
+       /**
+        * Copy a file. Print info message.
+        * 
+        * @param upfile
+        *            the source file.
+        * @param file
+        *            the target file
+        * @throws IOException
+        *             if failed
+        */
+       private void copyFile(final java.io.File upfile, final java.io.File file)
+                       throws IOException {
+               if (LOG.isInfoEnabled()) {
+                       LOG.info("Copy " + upfile.getAbsolutePath() + TO + file.getPath());
+               }
+               IOUtils.copy(upfile, file);
+       }
+
+       /**
+        * Copy a file. Print info message.
+        * 
+        * @param upfile
+        *            the source file.
+        * @param file
+        *            the target file
+        * @return true if renamed otherwise return false
+        */
+       private boolean moveFile(final java.io.File upfile, final java.io.File file) {
+               if (LOG.isInfoEnabled()) {
+                       LOG.info("Move " + upfile.getAbsolutePath() + TO + file.getPath());
+               }
+               return upfile.renameTo(file);
+       }
+
+       /**
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.ScenarioService#getScenarioInfo(long)
+        */
+       @Transactional(readOnly = true)
+       public List<StepDTO> getScenarioInfo(final long scenarioId) {
+               List<StepDTO> res = new ArrayList<StepDTO>();
+               // Get the scenario from the database by id
+               Scenario scen = getScenarioDAO().get(scenarioId);
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("Scenario[" + scenarioId + "]: Number of publications: "
+                                       + scen.getDocums().size());
+               }
+               // Get activities of the scenario
+               Step[] steps = getProjectElementService().getSteps(scen);
+               StepDTO stepDTO;
+               DocumentDTO docDTO;
+               String docType, fileFormat;
+               String processing;
+               boolean doImport;
+               // For each activity create a step DTO and add it to the result list
+               for (Step step : steps) {
+                       stepDTO = BeanHelper.copyBean(step.getStep(), StepDTO.class);
+                       res.add(stepDTO);
+                       if (LOG.isDebugEnabled()) {
+                               LOG.debug("Step[" + stepDTO.getNumber()
+                                               + "]: Number of documents: "
+                                               + step.getDocuments().size());
+                       }
+                       // For each publication of the activity create a document DTO.
+                       // Each file is considered as a source file.
+                       for (Publication tag : step.getDocuments()) {
+                               docDTO = stepDTO.addDoc(tag.value().getIndex(), tag.value()
+                                               .getTitle());
+                               char aState = tag.getIsnew();
+                               docType = tag.value().getType().getName();
+                               // For each file of the document create a file DTO
+                               // Process source file of the document
+                               fileFormat = tag.value().getFile().getFormat();
+                               doImport = getProjectSettings().doImport(docType, fileFormat);
+                               if (doImport && (!tag.isOutdated())) {
+                                       processing = "file-import";
+                               } else {
+                                       processing = "file-download";
+                               }
+                               File aFile = tag.value().getFile();
+                               docDTO.addFile(aFile.getIndex(), aFile.getRelativePath(),
+                                               aState, processing, false);
+                               // Process all exported files
+                               for (Relation rel : tag.value().getRelations(
+                                               ConvertsRelation.class)) {
+                                       aFile = ((ConvertsRelation) rel).getTo();
+                                       fileFormat = aFile.getFormat();
+                                       doImport = getProjectSettings().doImport(docType,
+                                                       fileFormat);
+                                       if (doImport && (!tag.isOutdated())) {
+                                               processing = "file-import";
+                                       } else {
+                                               processing = "file-download";
+                                       }
+                                       docDTO.addFile(aFile.getIndex(), aFile.getRelativePath(),
+                                                       aState, processing, false);
+                               }
+                       }
+               }
+               return res;
+       }
+
+       /**
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.ScenarioService#createStudy(java.lang.String, java.lang.String, java.lang.String, java.lang.String)
+        */
+       @Transactional
+       public long createStudy(final String username, final String title,
+                       final String productName, final String description)
+                       throws InvalidPropertyException, MissedPropertyException,
+                       MultiplyDefinedException {
+               long id = 0;
+
+               // Find the author
+               User author = getUserService().selectUser(username);
+               if (author == null) {
+                       // User is not found
+                       throw new InvalidPropertyException(MessageKeyEnum.USR_000001
+                                       .toString(), username);
+               }
+
+               // Set the study properties
+               Study.Properties sprop = new Study.Properties();
+               sprop.setTitle(title).setManager(author);
+               sprop.setDescription(description);
+
+               // Find the product simulation context
+               SimulationContextType productContextType = getSimulationContextService()
+                               .selectType("product");
+               SimulationContext.Properties cprop = new SimulationContext.Properties();
+               cprop.setType(productContextType).setValue(productName);
+               SimulationContext productCtx = getSimulationContextService()
+                               .selectSimulationContext(productContextType, productName);
+               if (productCtx != null) {
+                       cprop.setIndex(productCtx.getIndex());
+               }
+
+               // Set a first scenario properties
+               Scenario.Properties oprop = new Scenario.Properties();
+               oprop.setTitle(I18nUtils.getMessageLocaleDefault("label.scenario")
+                               + " 1");
+
+               Study study = createStudy(sprop, oprop, cprop);
+               id = study.getIndex();
+
+               return id;
+       }
+
+       /**
+        * Create a new study with one scenario and "product" simulation context.
+        * 
+        * @param sprop
+        *            the study properties
+        * @param oprop
+        *            the scenario properties
+        * @param cprop
+        *            the "product" simulation context properties
+        * @return the created study
+        * @throws MissedPropertyException
+        *             if a mandatory property is missed
+        * @throws InvalidPropertyException
+        *             if a property is invalid
+        * @throws MultiplyDefinedException
+        *             if some property occurs several times
+        */
+       @Transactional
+       public Study createStudy(final Study.Properties sprop,
+                       final Scenario.Properties oprop,
+                       final SimulationContext.Properties cprop)
+                       throws MissedPropertyException, InvalidPropertyException,
+                       MultiplyDefinedException {
+               Study study = getStudyService().createStudy(sprop);
+               addScenario(study, oprop);
+               if (cprop.getIndex() == 0) { // Input of new project context
+                       cprop.setType(getSimulationContextService().selectType("product"))
+                                       .setValue(cprop.getValue());
+                       getStudyService().addProjectContext(study, cprop);
+               } else { // Selection of existing project context
+                       SimulationContext context = getSimulationContextService()
+                                       .selectSimulationContext(cprop.getIndex());
+                       getStudyService().addProjectContext(study, context);
+               }
+               return study;
+       }
+
+       /**
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.ScenarioService#assignStudyContext(java.lang.Long, java.lang.String, java.lang.String)
+        */
+       @Transactional
+       public void assignStudyContext(final Long studyId, final String ctxType,
+                       final String ctxValue) throws MissedPropertyException,
+                       InvalidPropertyException, MultiplyDefinedException {
+               // Find the study by the given id
+               Study study = getStudyDAO().get(studyId);
+               if (study == null) {
+                       throw new InvalidPropertyException(MessageKeyEnum.STD_000002
+                                       .toString(), studyId);
+               }
+               // Find the context type by its name
+               SimulationContextType celt = getSimulationContextService().selectType(
+                               ctxType);
+               if (celt == null) {
+                       // Creation of a new context type
+                       celt = getSimulationContextTypeService().createType(ctxType,
+                                       getProjectElementService().getFirstStep(study).getStep());
+               }
+               // Find the given context value of the given type
+               SimulationContext context = getSimulationContextService()
+                               .selectSimulationContext(celt, ctxValue);
+               if (context == null) { // Input of a new project context
+                       SimulationContext.Properties cprop = new SimulationContext.Properties();
+                       cprop.setType(celt).setValue(ctxValue);
+                       getStudyService().addProjectContext(study, cprop);
+               } else { // Selection of existing project context
+                       getStudyService().addProjectContext(study, context);
+               }
+       }
+
        /**
         * {@inheritDoc}
         * 
@@ -150,71 +694,463 @@ public class ScenarioServiceImpl implements ScenarioService {
         *      org.splat.dal.bo.som.KnowledgeElement.Properties)
         */
        @Transactional
-       public KnowledgeElement addKnowledgeElement(Scenario aScenario,
-                       KnowledgeElement.Properties kprop) throws MissedPropertyException,
-                       InvalidPropertyException, MultiplyDefinedException {
+       public KnowledgeElement addKnowledgeElement(final Scenario aScenarioDTO,
+                       final KnowledgeElement.Properties kprop)
+                       throws MissedPropertyException, InvalidPropertyException,
+                       MultiplyDefinedException {
                KnowledgeElement kelm = null;
-               try {
-                       // Attach the detached scenario to the new hibernate session.
-                       aScenario = getScenarioDAO().merge(aScenario); // RKV
-                       kelm = new KnowledgeElement(kprop.setOwnerScenario(aScenario));
-                       getKnowledgeElementDAO().create(kelm);
-                       // RKV: commented because of BatchUpdateException during creation of a new study: session.flush(); //RKV
-                       // Update of my persistent data
-                       // RKV aScenario.getKnowledgeElements().add(kelm);
-                       // RKV getKnowledgeElementDAO().flush();
-                       // RKV: commented because of NullPointerException during creation of a new study: session.merge(aScenario); //RKV
-                       // Update of my transient data
-                       List<KnowledgeElement> known = aScenario
-                                       .getKnowledgeElementsOf(kelm.getType()); // Initializes this.known, if not yet done
-                       // RKV: knowledge is already added into persistent set and "known" is constructed from it in the above call: known.add(kelm);
-                       if (kelm.getType().equals("usecase")) {
-                               aScenario.setUcase(kelm);
-                       } else if (aScenario.getKnowledgeElementsList() != null) { // If null, knowl will be initialized when needed
-                               aScenario.getKnowledgeElementsList().add(kelm);
-                       }
-                       // Update of the index of Knowledge Elements
-                       getIndexService().add(kelm);
-                       update(aScenario);
+               // try {
+               long aScenarioId = aScenarioDTO.getIndex();
+               if (LOG.isDebugEnabled()) {
+                       LOG
+                                       .debug("Add a knowledge element to the scenario #"
+                                                       + aScenarioId);
+               }
+               // Get the persistent scenario.
+               Scenario aScenario = getScenarioDAO().get(aScenarioId);
+               // Get persistent objects for creating a new knowledge.
+               // TODO: Actions must use DTO instead of persistent objects.
+               getUserDAO().merge(kprop.getAuthor());
+               getKnowledgeElementTypeDAO().merge(kprop.getType());
+               // Create a transient knowledge element related to the given scenario.
+               kelm = new KnowledgeElement(kprop.setOwnerScenario(aScenario));
+               // Save the new knowledge in the database.
+               getKnowledgeElementDAO().create(kelm);
+               // Update scenario transient data.
+               if (kelm.getType().equals("usecase")) {
+                       aScenarioDTO.setUcase(kelm);
+               } else if (aScenarioDTO.getKnowledgeElementsList() != null) { // If null, knowl will be initialized when needed
+                       aScenarioDTO.getKnowledgeElementsList().add(kelm);
+               }
+
+               // Load the workflow for the parent study to take into account
+               // all study actors durng reindexing.
+               getStudyService().loadWorkflow(aScenario.getOwnerStudy());
 
-               } catch (IOException error) {
-                       logger.error("Unable to index the knowedge element '"
-                                       + kelm.getIndex() + "', reason:", error);
-                       kelm = null;
+               // // Update the lucene index of knowledge elements.
+               // getIndexService().add(kelm);
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("A knowledge element #" + kelm.getIndex()
+                                       + " is added to the scenario #" + aScenario.getIndex());
                }
+               // } catch (IOException error) {
+               // LOG.error("Unable to index the knowedge element '"
+               // + kelm.getIndex() + "', reason:", error);
+               // kelm = null;
+               // }
 
                return kelm;
        }
 
        /**
-        * Update the scenario in the database.
+        * {@inheritDoc}
         * 
-        * @param aScenario
-        *            the scenario to update
-        * @return true if updating succeeded
+        * @see org.splat.service.ScenarioService#checkin(long, long, java.util.List)
         */
        @Transactional
-       private boolean update(Scenario aScenario) {
-               boolean isOk = false;
-               try {
-                       getScenarioDAO().update(aScenario); // Update of relational base
-                       isOk = true;
-               } catch (Exception error) {
-                       logger.error("Unable to re-index the knowledge element '"
-                                       + aScenario.getIndex() + "', reason:", error);
+       public void checkin(final long scenId, final long userId,
+                       final List<StepDTO> scInfo) throws InvalidPropertyException,
+                       MissedPropertyException, MultiplyDefinedException,
+                       MismatchException, IOException, NotApplicableException {
+               // Get the scenario from the database by id
+               Scenario aScenario = getScenarioDAO().get(scenId);
+               // Get the user who perform this check-in operation
+               User aUser = getUserService().selectUser(userId);
+               // Get activities of the scenario
+               Step[] steps = getProjectElementService().getSteps(aScenario);
+               // Find result document types
+               List<DocumentType> resTypes = getDocumentTypeService()
+                               .selectResultTypes();
+
+               // Keep newly created documents to create uses relations to results of a previous step.
+               // For each processed existing document keep its new version
+               Map<Document, Document> newVersion = new HashMap<Document, Document>();
+               // Created publications of new created versions of existing documents
+               List<Publication> newVers = new ArrayList<Publication>();
+               // The list of publications of new created documents not existing before the checkin
+               List<Publication> newDocs = new ArrayList<Publication>();
+               // For each step DTO
+               DocumentType resType;
+               Date aDate = new Date(); // The timestamp of the checkin operation
+               for (StepDTO stepDTO : scInfo) {
+                       if (LOG.isDebugEnabled()) {
+                               LOG.debug("Checkin the step:\n" + stepDTO);
+                       }
+                       // Find a result document type of the step
+                       int i = 0;
+                       resType = null;
+                       do {
+                               if (resTypes.get(i).isResultOf(
+                                               getProjectSettings().getStep(stepDTO.getNumber()))) {
+                                       resType = resTypes.get(i);
+                               }
+                               i++;
+                       } while ((resType == null) && (i < resTypes.size()));
+
+                       // Find the appropriate scenario step
+                       Step step = findStep(stepDTO, steps);
+
+                       // Process each document of the step
+                       for (DocumentDTO doc : stepDTO.getDocs()) {
+                               checkinDoc(step, doc, aUser, resType, aDate, newVersion,
+                                               newVers, newDocs);
+                       }
+               }
+
+               // Set uses/used relations
+               updateRelationsAfterCheckin(aScenario, newVersion, newVers, newDocs);
+
+               // Mark the scenario as checked in
+               checkin(aScenario);
+       }
+
+       /**
+        * Updated uses/used relations after checkin operation:<BR>
+        * <ul>
+        * <li>For each new version copy uses relations from the previous version.</li>
+        * <li>Outdate documents which depend from the previous version and were not checked in during this operation.</li>
+        * <li>For each new document create uses relation to the last versions of results of the previous step.</li>
+        * </ul>
+        * 
+        * @param aScenario
+        *            the checked in scenario
+        * @param newVersion
+        *            the mapping of documents existed before the checkin to their new created versions
+        * @param newVers
+        *            the list of publications of new created versions of documents existed before the checkin
+        * @param newDocs
+        *            the list of publications of new created documents not existed before the checkin
+        */
+       private void updateRelationsAfterCheckin(final Scenario aScenario,
+                       final Map<Document, Document> newVersion,
+                       final List<Publication> newVers, final List<Publication> newDocs) {
+               // For each new version copy uses relations from the previous version.
+               for (Publication newVer : newVers) {
+                       // For each Uses relation of the previous version
+                       Document prevDoc = newVer.value().getPreviousVersion();// prevVersion.get(newVer);
+                       if (LOG.isDebugEnabled()) {
+                               LOG.debug("Previous version for publication #"
+                                               + newVer.getIndex() + " is found: " + prevDoc);
+                       }
+                       List<Relation> usesRelations = prevDoc
+                                       .getRelations(UsesRelation.class);
+                       for (Relation rel : usesRelations) {
+                               // If used document has been also versioned then refer to its new version.
+                               Document usedDoc = ((UsesRelation) rel).getTo();
+                               if (newVersion.containsKey(usedDoc)) {
+                                       usedDoc = newVersion.get(usedDoc);
+                               }
+                               // Build the appropriate relation for the new version.
+                               newVer.addDependency(usedDoc);
+                       }
+                       // Outdate documents which depend from the previous version and
+                       // were not checked in during this operation.
+                       // 1. Get all usedBy relations of the previous document version
+                       for (Relation rel : prevDoc.getRelations(UsedByRelation.class)) {
+                               Document using = ((UsedByRelation) rel).getTo();
+                               // Check that not checked in dependent documents became outdated
+                               Publication usingPub = aScenario.getPublication(using);
+                               if (usingPub != null) { // if the document using the old version is still published
+                                       usingPub.setIsnew('O');
+                               }
+                       }
+               }
+
+               // For each new document create uses relation to the last versions of
+               // results of the previous step.
+               for (Publication newPub : newDocs) {
+                       // Find used document type according to the configuration.
+                       Set<DocumentType> usedTypes = newPub.value().getType()
+                                       .getDefaultUses();
+                       // Find documents of used type in the previous study step.
+                       for (Publication pub : aScenario.getDocums()) {
+                               if ((pub.getStep().getNumber() <= newPub.getStep().getNumber())
+                                               && (!pub.isOutdated())
+                                               && usedTypes.contains(pub.value().getType())) {
+                                       // Create uses relation from the new document
+                                       // to the found document in the previous step.
+                                       newPub.addDependency(pub);
+                               }
+                       }
                }
-               return isOk;
+       }
+
+       /**
+        * Pure checkin of the document without creation of uses/usedBy relations. For an existing document a new version is created. New
+        * documents become published in the given step of the appropriate scenario. The appropriate uploaded file is attached to the created
+        * document and the document is published in the scenario. The publication of the old version is removed from the scenario.
+        * 
+        * @param step
+        *            the destination scenario step
+        * @param doc
+        *            the DTO of the document to checkin
+        * @param aUser
+        *            the user who performs checkin
+        * @param resType
+        *            the result document type of the given step
+        * @param aDate
+        *            timestamp of the checkin operation
+        * @param newVersion
+        *            the mapping of existing documents to their new created versions
+        * @param newVers
+        *            the list of publications of new created versions of existing documents
+        * @param newDocs
+        *            the list of publications of new created documents not existing before the checkin
+        * @throws InvalidPropertyException
+        *             if the scenario hasn't some of given steps or documents
+        * @throws IOException
+        *             if a file can't be moved into the vault
+        * @throws MismatchException
+        *             if version creation in some of steps is failed
+        * @throws MissedPropertyException
+        *             if some mandatory property is missed when new document or new document version is created
+        * @throws MultiplyDefinedException
+        *             if some property is defined several times when new document or new document version is created
+        * @throws NotApplicableException
+        *             if failed saving of a new publication with a given state
+        */
+       private void checkinDoc(final Step step, final DocumentDTO doc,
+                       final User aUser, final DocumentType resType, final Date aDate,
+                       final Map<Document, Document> newVersion,
+                       final List<Publication> newVers, final List<Publication> newDocs)
+                       throws InvalidPropertyException, MismatchException,
+                       MissedPropertyException, MultiplyDefinedException, IOException,
+                       NotApplicableException {
+               if (doc.getFiles().size() > 0) {
+                       Document.Properties dprop = new Document.Properties();
+                       // NOTE: Process only the first attached file for each document
+                       FileDTO file = doc.getFiles().get(0);
+                       dprop.setLocalPath(file.getPath());
+
+                       // Get document title as the file name
+                       java.io.File upfile = new java.io.File(file.getPath());
+                       String fileFormat = upfile.getName().substring(
+                                       upfile.getName().lastIndexOf('.') + 1);
+
+                       // Attach the file via ConvertsRelation, create a new document or
+                       // create a new version of the document
+                       dprop.setAuthor(aUser).setDate(aDate).setFormat(fileFormat);
+
+                       if (doc.getId() > 0) {
+                               checkinExistingDoc(step, doc, dprop, fileFormat, upfile,
+                                               newVersion, newVers);
+                       } else {
+
+                               // Otherwise create a new document of the result type
+                               // If result type is not found try to get type by file extension
+                               if (resType == null) {
+                                       dprop.setType(getProjectSettings().getDefaultDocumentType(
+                                                       step.getStep(), fileFormat));
+                               } else {
+                                       dprop.setType(resType);
+                               }
+                               // New document title generation as <document type name>_N
+                               String docname = dprop.getType().getName();
+                               int i = 1;
+                               for (Publication scenPub : step.getOwner().getDocums()) {
+                                       if (scenPub.value().getTitle().startsWith(docname)) {
+                                               i++;
+                                       }
+                               }
+                               docname += "_" + i; // The generated new document title
+
+                               dprop.setDescription("Checked in").setName(docname);
+                               Publication newPub = getStepService().createDocument(step,
+                                               dprop);
+
+                               // Remember the new document
+                               newDocs.add(newPub);
+
+                               saveFile(newPub, step, upfile);
+                       }
+               }
+       }
+
+       /**
+        * Check in existing document.
+        * 
+        * @param step
+        *            study step to check in
+        * @param doc
+        *            document DTO to check in
+        * @param dprop
+        *            document properties
+        * @param fileFormat
+        *            checked in file format
+        * @param upfile
+        *            the file to check in
+        * @param newVersion
+        *            the map of created versions during this check in
+        * @param newVers
+        *            the list of new versions created during this check in
+        * @throws InvalidPropertyException
+        *             if publication of the document is not found in the step
+        * @throws MismatchException
+        *             if the found publication does not point to a document
+        * @throws IOException
+        *             if can not move the file into the vault
+        * @throws MultiplyDefinedException
+        *             thrown by versionDocument
+        * @throws MissedPropertyException
+        *             thrown by versionDocument
+        * @throws NotApplicableException
+        *             if failed saving of a new publication with a given state
+        */
+       private void checkinExistingDoc(final Step step, final DocumentDTO doc,
+                       final Properties dprop, final String fileFormat,
+                       final java.io.File upfile,
+                       final Map<Document, Document> newVersion,
+                       final List<Publication> newVers) throws InvalidPropertyException,
+                       MismatchException, MissedPropertyException,
+                       MultiplyDefinedException, IOException, NotApplicableException {
+               // If the document already exists then
+               // Attach the file via ConvertsRelation if the extension of the
+               // new file differs from the old one.
+               // If file format (i.e. extension) is the same then create a new
+               // version of the document.
+               // Find the document publication
+               Publication pub = step.getDocument(doc.getId());
+               if (pub == null) {
+                       throw new InvalidPropertyException(MessageKeyEnum.SCN_000002
+                                       .toString(), doc.getId());
+               }
+               if (pub.value() == null) {
+                       throw new MismatchException(MessageKeyEnum.SCN_000002.toString(),
+                                       doc.getId());
+               }
+               if (LOG.isDebugEnabled()) {
+                       LOG.debug("Old format: " + pub.value().getFormat()
+                                       + " => New format: " + fileFormat);
+               }
+               // If formats are same then create a new document version
+               if (pub.value().getFormat() != null
+                               && pub.value().getFormat().equals(fileFormat)) {
+                       Publication newPub = getStepService().versionDocument(step, pub,
+                                       dprop);
+                       if (LOG.isDebugEnabled()) {
+                               LOG.debug("Created document type: "
+                                               + newPub.value().getType().getName() + ", format: "
+                                               + newPub.value().getFormat());
+                       }
+                       // Remeber the link from the old document to the new document version
+                       newVersion.put(pub.value(), newPub.value());
+                       // Remember the new version publication
+                       newVers.add(newPub);
+
+                       saveFile(newPub, step, upfile);
+
+               } else { // If formats are different then attach the new file via ConvertsRelation
+                       File attach = pub.value().getAttachedFile(fileFormat);
+                       if (attach == null) {
+                               // If there is no attachment with this extension then attach the new one
+                               ConvertsRelation export = getPublicationService().attach(pub,
+                                               fileFormat);
+                               moveFile(upfile, export.getTo().asFile());
+                       } else {
+                               // If an attachment with this extension already exists then
+                               // replace it by the new one
+                               moveFile(upfile,attach.asFile());
+                               // Update attached file modification date
+                               attach.setDate(new Date());
+                       }
+               }
+       }
+
+       /**
+        * Save the file in the vault and create its publication in the step.
+        * 
+        * @param newPub
+        *            the new publication to save
+        * @param step
+        *            the study step to publish the document
+        * @param upfile
+        *            the downloaded file
+        * @throws IOException
+        *             if a file can't be moved into the vault
+        * @throws NotApplicableException
+        *             if failed saving of a new publication with a given state
+        */
+       private void saveFile(final Publication newPub, final Step step,
+                       final java.io.File upfile) throws IOException,
+                       NotApplicableException {
+               // Attach the file to the created document
+               java.io.File updir = newPub.getSourceFile().asFile();
+               if (updir.exists()) {
+                       if (updir.delete()) {
+                               LOG.info(MessageKeyEnum.SCN_000003.toString(), updir
+                                               .getAbsoluteFile(), step.getOwner().getIndex());
+                       } else {
+                               throw new IOException(
+                                               "Can't delete the existing destination file to move file from "
+                                                               + upfile.getAbsolutePath() + TO
+                                                               + updir.getAbsolutePath());
+                       }
+               }
+               if (moveFile(upfile, updir)) {
+                       // Save the new publication in the scenario.
+                       // The old publication is removed from the scenario here.
+                       getPublicationService().saveAs(newPub, ProgressState.inWORK); // May throw FileNotFound if rename was not done
+               } else {
+                       throw new IOException("Can't move file from "
+                                       + upfile.getAbsolutePath() + TO + updir.getAbsolutePath());
+               }
+       }
+
+       /**
+        * Find appropriate step in the array of scenario steps according to the given step DTO.
+        * 
+        * @param stepDTO
+        *            the stepDTO
+        * @param steps
+        *            scenario steps
+        * @return appropriate scenario step
+        * @throws InvalidPropertyException
+        *             if appropriate step is not found
+        */
+       private Step findStep(final StepDTO stepDTO, final Step[] steps)
+                       throws InvalidPropertyException {
+               int i = 0;
+               Step step = null;
+               do {
+                       if (steps[i].getNumber() == stepDTO.getNumber()) {
+                               step = steps[i];
+                       }
+                       i++;
+               } while ((step == null) && (i < steps.length));
+
+               if (step == null) {
+                       throw new InvalidPropertyException(MessageKeyEnum.SCN_000001
+                                       .toString(), stepDTO.getNumber());
+               }
+               return step;
        }
 
        /**
         * {@inheritDoc}
         * 
-        * @see org.splat.service.ScenarioService#checkin(org.splat.dal.bo.som.Scenario)
+        * @see org.splat.service.ScenarioService#checkin(long)
+        */
+       @Transactional
+       public void checkin(final long scenarioId) throws InvalidPropertyException {
+               Scenario aScenario = getScenarioDAO().get(scenarioId);
+               if (aScenario == null) {
+                       // Scenario not found
+                       throw new InvalidPropertyException(MessageKeyEnum.SCN_000006
+                                       .toString(), scenarioId);
+               }
+               checkin(aScenario);
+       }
+
+       /**
+        * Mark the scenario as checked in.
+        * 
+        * @param aScenario
+        *            the scenario to check in.
         */
-       public void checkin(Scenario aScenario) {
+       private void checkin(final Scenario aScenario) {
                aScenario.setUser(null);
                aScenario.setLastModificationDate(Calendar.getInstance().getTime());
-               getScenarioDAO().update(aScenario);
+               // getScenarioDAO().update(aScenario);
        }
 
        /**
@@ -222,14 +1158,61 @@ public class ScenarioServiceImpl implements ScenarioService {
         * 
         * @see org.splat.service.ScenarioService#checkout(org.splat.dal.bo.som.Scenario, org.splat.dal.bo.kernel.User)
         */
-       public boolean checkout(Scenario aScenario, User user) {
-               if (!getStudyService().isStaffedBy(aScenario.getOwnerStudy(), user))
-                       return false;
+       public boolean checkout(final Scenario aScenario, final User user) {
+               boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
+                               user);
+               if (res) {
+                       aScenario.setUser(user);
+                       aScenario.setLastModificationDate(Calendar.getInstance().getTime());
+                       // RKV: getScenarioDAO().update(aScenario);
+               }
+               return res;
+       }
 
-               aScenario.setUser(user);
-               aScenario.setLastModificationDate(Calendar.getInstance().getTime());
-               getScenarioDAO().update(aScenario);
-               return true;
+       /**
+        * Mark the given scenario as checked out by the given user.
+        * 
+        * @param scenarioId
+        *            the scenario id
+        * @param userId
+        *            the id of the user performing the check out
+        * @throws InvalidPropertyException
+        *             if the user or the scenario is not found in the database
+        * @throws NotApplicableException
+        *             if the given user can not check out the scenario
+        */
+       @Transactional
+       public void checkout(final long scenarioId, final long userId)
+                       throws InvalidPropertyException, NotApplicableException {
+               User aUser = getUserService().selectUser(userId);
+               if (aUser == null) {
+                       // User not found
+                       throw new InvalidPropertyException(MessageKeyEnum.USR_000001
+                                       .toString(), userId);
+               }
+               Scenario aScenario = getScenarioDAO().get(scenarioId);
+               if (aScenario == null) {
+                       // Scenario not found
+                       throw new InvalidPropertyException(MessageKeyEnum.SCN_000006
+                                       .toString(), scenarioId);
+               }
+               boolean res = getStudyService().isStaffedBy(aScenario.getOwnerStudy(),
+                               aUser);
+               if (res) {
+                       if (aScenario.isCheckedout()
+                                       && (!aScenario.getUser().getUsername().equals(
+                                                       aUser.getUsername()))) {
+                               throw new NotApplicableException(MessageKeyEnum.SCN_000008
+                                               .toString(), scenarioId, aScenario.getUser()
+                                               .getUsername());
+                       }
+                       aScenario.setUser(aUser);
+                       aScenario.setLastModificationDate(Calendar.getInstance().getTime());
+               } else {
+                       // User doesn't participate in the scenario
+                       throw new NotApplicableException(MessageKeyEnum.SCN_000007
+                                       .toString(), aUser.getUsername(), scenarioId);
+               }
        }
 
        /**
@@ -237,14 +1220,15 @@ public class ScenarioServiceImpl implements ScenarioService {
         * 
         * @see org.splat.service.ScenarioService#copyContentsUpTo(org.splat.dal.bo.som.Scenario, org.splat.som.Step)
         */
-       public void copyContentsUpTo(Scenario scenario, Step lastep) {
+       public void copyContentsUpTo(final Scenario scenario, final Step lastep) {
                Scenario base = (Scenario) lastep.getOwner();
                Step[] from = getProjectElementService().getSteps(base);
                Step[] to = getProjectElementService().getSteps(scenario);
                for (int i = 0; i < from.length; i++) {
                        Step step = from[i];
-                       if (step.getNumber() > lastep.getNumber())
+                       if (step.getNumber() > lastep.getNumber()) {
                                break;
+                       }
 
                        List<Publication> docs = step.getAllDocuments();
                        for (Iterator<Publication> j = docs.iterator(); j.hasNext();) {
@@ -265,7 +1249,7 @@ public class ScenarioServiceImpl implements ScenarioService {
         * 
         * @see org.splat.service.ScenarioService#isEmpty(org.splat.dal.bo.som.Scenario)
         */
-       public boolean isEmpty(Scenario scenario) {
+       public boolean isEmpty(final Scenario scenario) {
                Step[] mystep = getProjectElementService().getSteps(scenario);
                boolean isEmp = true;
                for (int i = 0; i < mystep.length; i++) {
@@ -281,14 +1265,16 @@ public class ScenarioServiceImpl implements ScenarioService {
         * @param scenario
         * @return
         */
-       public boolean isFinished(Scenario scenario) {
+       public boolean isFinished(final Scenario scenario) {
                Step[] mystep = getProjectElementService().getSteps(scenario);
                boolean notempty = false; // If this is empty, this is not finished
                for (int i = 0; i < mystep.length; i++) {
-                       if (!mystep[i].isStarted())
+                       if (!mystep[i].isStarted()) {
                                continue;
-                       if (!mystep[i].isFinished())
+                       }
+                       if (!mystep[i].isFinished()) {
                                return false;
+                       }
                        notempty = true;
                }
                return notempty;
@@ -300,15 +1286,17 @@ public class ScenarioServiceImpl implements ScenarioService {
         * @see org.splat.service.StudyService#addScenario(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Scenario.Properties)
         */
        @Transactional
-       public Scenario addScenario(Study aStudy, Scenario.Properties sprop)
-                       throws MissedPropertyException, InvalidPropertyException,
-                       MultiplyDefinedException {
-               if (sprop.getManager() == null)
+       public Scenario addScenario(final Study aStudy,
+                       final Scenario.Properties sprop) throws MissedPropertyException,
+                       InvalidPropertyException, MultiplyDefinedException {
+               if (sprop.getManager() == null) {
                        sprop.setManager(aStudy.getAuthor());
+               }
 
                Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
-               if (sprop.getBaseStep() != null)
+               if (sprop.getBaseStep() != null) {
                        copyContentsUpTo(scenario, sprop.getBaseStep());
+               }
                Scenario previous = sprop.getInsertAfter();
 
                if (previous == null) {
@@ -321,12 +1309,18 @@ public class ScenarioServiceImpl implements ScenarioService {
                getScenarioDAO().create(scenario); // Must be done after updating this study because of the back reference to the study
                if (sprop.getBaseStep() != null) {
                        // No need to update the Knowledge Element index as Knowledge Elements are not copied
-                       scenario.refresh(); // Because saving the scenario changes the hashcode of copied Publications
+                       getProjectElementService().refresh(scenario); // Because saving the scenario changes the hashcode of copied Publications
                }
-               KnowledgeElementType ucase = getKnowledgeElementTypeService().selectType(
-                               "usecase");
+               KnowledgeElementType ucase = getKnowledgeElementTypeService()
+                               .selectType("usecase");
                KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
-               User admin = UserDirectory.selectUser(1); // First user created when creating the database
+               // TODO: Get appropriate user by its role: UserService.getAdmin();
+               // User admin = getUserService().selectUser(1); // First user created when creating the database
+               Role adminRole = getRoleDAO().getFilteredList(
+                               Restrictions.like("role", "%sysadmin%")).get(0);
+               User admin = getUserDAO().getFilteredList(
+                               Restrictions.eq("role", adminRole), Order.asc("rid")).get(0); // First sysadmin in the database
+
                kprop.setType(ucase).setTitle(aStudy.getTitle()).setValue(
                                scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
                // knowledges
@@ -334,6 +1328,49 @@ public class ScenarioServiceImpl implements ScenarioService {
                return scenario;
        }
 
+       /**
+        * Remove a knowledge element from a scenario.
+        * 
+        * @param scenario
+        *            the scenario
+        * @param kelm
+        *            the knowledge element to remove
+        * @return true if removal succeeded
+        */
+       @Transactional
+       public boolean removeKnowledgeElement(final Scenario scenario,
+                       final KnowledgeElement kelm) {
+               KnowledgeElement torem = scenario.getKnowledgeElement(kelm.getIndex());
+               boolean isOk = (torem != null);
+               if (isOk) {
+                       isOk = scenario.getKnowledgeElements().remove(torem);
+                       if (isOk) {
+                               getScenarioDAO().merge(scenario);
+                               // Update of my transient data
+                               // RKV: These transient data are not used indeed.
+                               // RKV: List<KnowledgeElement> kelms = scenario.getKnowledgeByType().get(
+                               // RKV: kelm.getType().getIndex());
+                               // RKV: kelms.remove(torem);
+                               if (scenario.getKnowledgeElementsList() != null) {
+                                       scenario.getKnowledgeElementsList().remove(torem);
+                               }
+                               // TODO: If the owner study is not private, remove the knowledge from the Lucene index
+                       }
+               }
+               return isOk;
+       }
+
+       /**
+        * 
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.ScenarioService#renameScenario(java.lang.String)
+        */
+       @Transactional
+       public void renameScenario(final Scenario scenario) {
+               getScenarioDAO().merge(scenario);
+       }
+
        /**
         * Get the knowledgeElementDAO.
         * 
@@ -349,7 +1386,8 @@ public class ScenarioServiceImpl implements ScenarioService {
         * @param knowledgeElementDAO
         *            the knowledgeElementDAO to set
         */
-       public void setKnowledgeElementDAO(KnowledgeElementDAO knowledgeElementDAO) {
+       public void setKnowledgeElementDAO(
+                       final KnowledgeElementDAO knowledgeElementDAO) {
                _knowledgeElementDAO = knowledgeElementDAO;
        }
 
@@ -368,7 +1406,7 @@ public class ScenarioServiceImpl implements ScenarioService {
         * @param indexService
         *            the indexService to set
         */
-       public void setIndexService(IndexService indexService) {
+       public void setIndexService(final IndexService indexService) {
                _indexService = indexService;
        }
 
@@ -387,7 +1425,7 @@ public class ScenarioServiceImpl implements ScenarioService {
         * @param scenarioDAO
         *            the scenarioDAO to set
         */
-       public void setScenarioDAO(ScenarioDAO scenarioDAO) {
+       public void setScenarioDAO(final ScenarioDAO scenarioDAO) {
                _scenarioDAO = scenarioDAO;
        }
 
@@ -406,7 +1444,7 @@ public class ScenarioServiceImpl implements ScenarioService {
         * @param studyDAO
         *            the studyDAO to set
         */
-       public void setStudyDAO(StudyDAO studyDAO) {
+       public void setStudyDAO(final StudyDAO studyDAO) {
                _studyDAO = studyDAO;
        }
 
@@ -426,12 +1464,13 @@ public class ScenarioServiceImpl implements ScenarioService {
         *            the knowledgeElementTypeService to set
         */
        public void setKnowledgeElementTypeService(
-                       KnowledgeElementTypeService knowledgeElementTypeService) {
+                       final KnowledgeElementTypeService knowledgeElementTypeService) {
                _knowledgeElementTypeService = knowledgeElementTypeService;
        }
 
        /**
         * Get the studyService.
+        * 
         * @return the studyService
         */
        public StudyService getStudyService() {
@@ -440,10 +1479,228 @@ public class ScenarioServiceImpl implements ScenarioService {
 
        /**
         * Set the studyService.
-        * @param studyService the studyService to set
+        * 
+        * @param studyService
+        *            the studyService to set
         */
-       public void setStudyService(StudyService studyService) {
+       public void setStudyService(final StudyService studyService) {
                _studyService = studyService;
        }
 
+       /**
+        * Get the userService.
+        * 
+        * @return the userService
+        */
+       public UserService getUserService() {
+               return _userService;
+       }
+
+       /**
+        * Set the userService.
+        * 
+        * @param userService
+        *            the userService to set
+        */
+       public void setUserService(final UserService userService) {
+               _userService = userService;
+       }
+
+       /**
+        * Get the userDAO.
+        * 
+        * @return the userDAO
+        */
+       public UserDAO getUserDAO() {
+               return _userDAO;
+       }
+
+       /**
+        * Set the userDAO.
+        * 
+        * @param userDAO
+        *            the userDAO to set
+        */
+       public void setUserDAO(final UserDAO userDAO) {
+               _userDAO = userDAO;
+       }
+
+       /**
+        * Get the knowledgeElementTypeDAO.
+        * 
+        * @return the knowledgeElementTypeDAO
+        */
+       public KnowledgeElementTypeDAO getKnowledgeElementTypeDAO() {
+               return _knowledgeElementTypeDAO;
+       }
+
+       /**
+        * Set the knowledgeElementTypeDAO.
+        * 
+        * @param knowledgeElementTypeDAO
+        *            the knowledgeElementTypeDAO to set
+        */
+       public void setKnowledgeElementTypeDAO(
+                       final KnowledgeElementTypeDAO knowledgeElementTypeDAO) {
+               _knowledgeElementTypeDAO = knowledgeElementTypeDAO;
+       }
+
+       /**
+        * Get the simulationContextService.
+        * 
+        * @return the simulationContextService
+        */
+       public SimulationContextService getSimulationContextService() {
+               return _simulationContextService;
+       }
+
+       /**
+        * Set the simulationContextService.
+        * 
+        * @param simulationContextService
+        *            the simulationContextService to set
+        */
+       public void setSimulationContextService(
+                       final SimulationContextService simulationContextService) {
+               _simulationContextService = simulationContextService;
+       }
+
+       /**
+        * Get project settings.
+        * 
+        * @return Project settings service
+        */
+       private ProjectSettingsService getProjectSettings() {
+               return _projectSettings;
+       }
+
+       /**
+        * Set project settings service.
+        * 
+        * @param projectSettingsService
+        *            project settings service
+        */
+       public void setProjectSettings(
+                       final ProjectSettingsService projectSettingsService) {
+               _projectSettings = projectSettingsService;
+       }
+
+       /**
+        * Get the documentTypeService.
+        * 
+        * @return the documentTypeService
+        */
+       public DocumentTypeService getDocumentTypeService() {
+               return _documentTypeService;
+       }
+
+       /**
+        * Set the documentTypeService.
+        * 
+        * @param documentTypeService
+        *            the documentTypeService to set
+        */
+       public void setDocumentTypeService(
+                       final DocumentTypeService documentTypeService) {
+               _documentTypeService = documentTypeService;
+       }
+
+       /**
+        * Get the roleDAO.
+        * 
+        * @return the roleDAO
+        */
+       public RoleDAO getRoleDAO() {
+               return _roleDAO;
+       }
+
+       /**
+        * Set the roleDAO.
+        * 
+        * @param roleDAO
+        *            the roleDAO to set
+        */
+       public void setRoleDAO(final RoleDAO roleDAO) {
+               _roleDAO = roleDAO;
+       }
+
+       /**
+        * Get the simulationContextTypeService.
+        * 
+        * @return the simulationContextTypeService
+        */
+       public SimulationContextTypeService getSimulationContextTypeService() {
+               return _simulationContextTypeService;
+       }
+
+       /**
+        * Set the simulationContextTypeService.
+        * 
+        * @param simulationContextTypeService
+        *            the simulationContextTypeService to set
+        */
+       public void setSimulationContextTypeService(
+                       final SimulationContextTypeService simulationContextTypeService) {
+               _simulationContextTypeService = simulationContextTypeService;
+       }
+
+       /**
+        * Get the validationCycleDAO.
+        * 
+        * @return the validationCycleDAO
+        */
+       public ValidationCycleDAO getValidationCycleDAO() {
+               return _validationCycleDAO;
+       }
+
+       /**
+        * Set the validationCycleDAO.
+        * 
+        * @param validationCycleDAO
+        *            the validationCycleDAO to set
+        */
+       public void setValidationCycleDAO(
+                       final ValidationCycleDAO validationCycleDAO) {
+               _validationCycleDAO = validationCycleDAO;
+       }
+
+       /**
+        * Get steps config.
+        * 
+        * @return steps config service
+        */
+       private StepsConfigService getStepsConfigService() {
+               return _stepsConfigService;
+       }
+
+       /**
+        * Set steps config service.
+        * 
+        * @param stepsConfigService
+        *            steps config service
+        */
+       public void setStepsConfigService(
+                       final StepsConfigService stepsConfigService) {
+               _stepsConfigService = stepsConfigService;
+       }
+
+       /**
+        * Get the repositoryService.
+        * 
+        * @return the repositoryService
+        */
+       public RepositoryService getRepositoryService() {
+               return _repositoryService;
+       }
+
+       /**
+        * Set the repositoryService.
+        * 
+        * @param repositoryService
+        *            the repositoryService to set
+        */
+       public void setRepositoryService(final RepositoryService repositoryService) {
+               _repositoryService = repositoryService;
+       }
+
 }