Salome HOME
The checkin from SALOME operation is updated (ScenarioService.checkin()). Versioning...
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / PublicationServiceImpl.java
index e2e530214d12c71196bf1c657701e1edeff93e41..a47e1dc7ed43d554a45a61d0538399dbd81e8974 100644 (file)
@@ -1,5 +1,5 @@
 /*****************************************************************************
- * Company         EURIWARE
+ * Company         OPEN CASCADE
  * Application     SIMAN
  * File            $Id$ 
  * Creation date   06.10.2012
@@ -9,14 +9,18 @@
 
 package org.splat.service;
 
+import java.io.File;
 import java.io.FileNotFoundException;
+import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 
-import org.hibernate.Session;
+import org.apache.log4j.Logger;
 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.ProgressState;
@@ -26,14 +30,24 @@ 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.Timestamp;
+import org.splat.dal.bo.som.UsedByRelation;
 import org.splat.dal.bo.som.ValidationCycle;
 import org.splat.dal.bo.som.ValidationStep;
-import org.splat.dal.dao.som.Database;
+import org.splat.dal.dao.som.ProjectElementDAO;
+import org.splat.dal.dao.som.PublicationDAO;
+import org.splat.dal.dao.som.TimestampDAO;
+import org.splat.kernel.InvalidPropertyException;
+import org.splat.kernel.MismatchException;
+import org.splat.kernel.MissedPropertyException;
+import org.splat.kernel.MultiplyDefinedException;
 import org.splat.kernel.NotApplicableException;
 import org.splat.manox.Reader;
 import org.splat.manox.Toolbox;
+import org.splat.service.technical.RepositoryService;
+import org.splat.som.DocumentRights;
 import org.splat.som.Revision;
 import org.splat.som.Step;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * Publication service implementation.
@@ -42,33 +56,55 @@ import org.splat.som.Step;
  */
 public class PublicationServiceImpl implements PublicationService {
 
+       /**
+        * Logger for this class.
+        */
+       protected final static Logger LOG = Logger
+                       .getLogger(PublicationServiceImpl.class);
+
        /**
         * Injected study service.
         */
        private StudyService _studyService;
        /**
-        * Injected study service.
+        * Injected step service.
         */
        private StepService _stepService;
        /**
-        * Injected study service.
+        * Injected document service.
         */
-       private DocumentTypeService _documentTypeService;
+       private DocumentService _documentService;
        /**
-        * Injected study service.
+        * Injected project element service.
         */
        private ProjectElementService _projectElementService;
        /**
         * Injected simulation context service.
         */
        private SimulationContextService _simulationContextService;
+       /**
+        * Injected publication DAO.
+        */
+       private PublicationDAO _publicationDAO;
+       /**
+        * Injected timestamp DAO.
+        */
+       private TimestampDAO _timestampDAO;
+       /**
+        * Injected project element DAO.
+        */
+       private ProjectElementDAO _projectElementDAO;
+       /**
+        * Injected repository service.
+        */
+       private RepositoryService _repositoryService;
 
        /**
         * {@inheritDoc}
         * 
         * @see org.splat.service.PublicationService#copy(org.splat.dal.bo.som.Publication, org.splat.dal.bo.som.ProjectElement)
         */
-       public Publication copy(Publication aPublication, ProjectElement publisher) {
+       public Publication copy(final Publication aPublication, final ProjectElement publisher) {
                Publication copy = new Publication();
                copy.setValue(aPublication.value());
                copy.setStep(aPublication.getStep()); // May not be initialized yet
@@ -80,30 +116,134 @@ public class PublicationServiceImpl implements PublicationService {
                return copy;
        }
 
+       /** 
+        * {@inheritDoc}
+        * @see org.splat.service.PublicationService#versionDocument(org.splat.som.Step, org.splat.dal.bo.kernel.User, java.lang.String, long, java.lang.String, java.lang.String, org.splat.dal.bo.som.ProgressState, java.util.Date, java.lang.String[], long[])
+        */
+       @Transactional
+       public void versionDocument(final Step step, final User user,
+                       final String filename, final long docIndex, final String docver,
+                       final String summary, final ProgressState state, final Date date,
+                       final String[] docuses, final long[] docusedby)
+                       throws MissedPropertyException, InvalidPropertyException,
+                       MultiplyDefinedException, IOException, MismatchException,
+                       NotApplicableException, InterruptedException {
+               File updir = getRepositoryService().getDownloadDirectory(user);
+               File upfile = new File(updir.getPath() + "/" + filename);
+
+               // Versioning of the document
+               Document.Properties dprop = new Document.Properties();
+               Publication current = step.getDocument(docIndex);
+               Publication next;
+
+               if ((docver.length() != 0) && // Importation of a not foreign document
+                               (date != null)) {
+                       dprop.setDate(date);
+               }
+               next = getStepService().versionDocument(step, current,
+                               dprop.setAuthor(user).setDescription(summary));
+               updir = next.getSourceFile().asFile();
+               if (LOG.isInfoEnabled()) {
+                       LOG.info("Moving \"" + upfile.getName() + "\" to \""
+                                       + updir.getPath() + "\".");
+               }
+               upfile.renameTo(updir);
+
+               try {
+                       if (docver.length() == 0) { // Importation of a foreign document
+                               saveAs(next, state); // May throw FileNotFound if rename was not done
+                       } else {
+                               saveAs(next, new Revision(docver));
+                       }
+               } catch (FileNotFoundException saverror) {
+                       Thread.sleep(1000);
+                       LOG.info("Waiting for the file.");
+                       upfile.renameTo(updir);
+                       saveAs(next, state);
+               }
+               // TODO: Remove current document details from the contents of open study
+
+               // Creation of uses relations
+               updateRelations(current, next, docuses, docusedby);
+       }
+
+       /**
+        * Update relations after creation of a new document version.
+        * 
+        * @param current
+        *            the current version
+        * @param next
+        *            the new version
+        * @param docuses
+        *            ids of used documents
+        * @param docusedby
+        *            ids of documents used by the versioned one.
+        */
+       private void updateRelations(final Publication current,
+                       final Publication next, final String[] docuses,
+                       final long[] docusedby) {
+               if (docuses != null) {
+                       for (int i = 0; i < docuses.length; i++) {
+                               Long index = Long.valueOf(docuses[i].trim());
+                               Publication used = getPublicationDAO().get(index);// RKV: getPublication(index, steps);
+                               next.addDependency(used);
+                       }
+               }
+               // Outdating impacted document
+               HashSet<Long> compatible = new HashSet<Long>();
+               if (docusedby != null) {
+                       for (int i = 0; i < docusedby.length; i++) {
+                               compatible.add(docusedby[i]);
+                       }
+               }
+               List<Publication> relist = current.getRelations(UsedByRelation.class);
+               for (Iterator<Publication> i = relist.iterator(); i.hasNext();) {
+                       Publication using = i.next();
+                       if (!compatible.contains(using.getIndex())) {
+                               outdate(using);
+                       }
+               }
+       }
+
+/*     protected Publication getPublication(int index, List<Step> steps) {
+               for (Iterator<Step> i = steps.iterator(); i.hasNext();) {
+                       List<Publication> published = i.next().getAllDocuments();
+                       for (Iterator<Publication> j = published.iterator(); j.hasNext();) {
+                               Publication found = j.next(); // In a given study step,
+                               if (found.value().getIndex() == index)
+                                       return found; // there is only one publication of a given document
+                       }
+               }
+               return null;
+       }
+*/
        /**
         * {@inheritDoc}
         * 
         * @see org.splat.service.PublicationService#approve(org.splat.dal.bo.som.Publication, java.util.Date)
         */
-       public Timestamp approve(Publication aPublication, Date adate) {
-               // -------------------------------------
-               if (aPublication.isOutdated())
-                       return null;
-               else if (aPublication.value().getProgressState() != ProgressState.inCHECK)
-                       return null; // This statement must conform to the corresponding right
-
-               DocumentType type = aPublication.value().getType();
-               Study owner = aPublication.getOwnerStudy();
-               ValidationCycle cycle = owner.getValidationCycleOf(type);
-               User approver = cycle.getActor(ValidationStep.APPROVAL);
-               Timestamp stamp = new Timestamp(ValidationStep.APPROVAL, aPublication
-                               .value(), approver, adate);
-               if (!aPublication.value().promote(stamp))
-                       return null;
-               if (getDocumentTypeService().isStudyResult(type)
-                               && owner.getProgressState() == ProgressState.inCHECK)
-                       getStudyService().promote(owner);
-               return stamp; // Hoping that promotion of the study succeeded
+       @Transactional
+       public Timestamp approve(final Publication aPublication, final Date adate) {
+               Timestamp res = null;
+               if (!(aPublication.isOutdated() || (aPublication.value().getProgressState() != ProgressState.inCHECK))) {
+                       DocumentType type = aPublication.value().getType();
+                       Study owner = aPublication.getOwnerStudy();
+                       ValidationCycle cycle = getStudyService().getValidationCycleOf(owner,
+                                       type);
+                       User approver = cycle.getActor(ValidationStep.APPROVAL);
+                       Timestamp stamp = new Timestamp(ValidationStep.APPROVAL, aPublication
+                                       .value(), approver, adate);
+                       getTimestampDAO().create(stamp);
+                       
+                       if (getDocumentService().promote(aPublication.value(), stamp)) {
+                               res = stamp;
+                               if (getDocumentService().isStudyResult(type)
+                                               && owner.getProgressState() == ProgressState.inCHECK) {
+                                       getStudyService().promote(owner);
+                               }
+                       }
+               }
+               return res; // Hoping that promotion of the study succeeded
        }
 
        /**
@@ -111,31 +251,31 @@ public class PublicationServiceImpl implements PublicationService {
         * 
         * @see org.splat.service.PublicationService#demote(org.splat.dal.bo.som.Publication)
         */
-       public boolean demote(Publication aPublication) {
-               // ------------------------
+       @Transactional
+       public boolean demote(final Publication aPublication) {
+               boolean res = false;
                DocumentType type = aPublication.value().getType();
                Study owner = aPublication.getOwnerStudy();
 
                if (aPublication.value().getProgressState() == ProgressState.inCHECK) {
-                       ValidationCycle cycle = owner.getValidationCycleOf(type);
+                       ValidationCycle cycle = getStudyService().getValidationCycleOf(
+                                       owner, type);
                        if (cycle.enables(ValidationStep.REVIEW)) {
-                               if (!aPublication.value().demote())
-                                       return false;
+                               res = getDocumentService().demote(aPublication.value());
                        } else {
-                               if (!aPublication.value().demote())
-                                       return false;
-                               aPublication.value().demote();
+                               res = getDocumentService().demote(aPublication.value());
+                               if (res) {
+                                       getDocumentService().demote(aPublication.value());
+                               }
                        }
                } else if (aPublication.value().getProgressState() == ProgressState.inDRAFT) {
-                       if (!aPublication.value().demote())
-                               return false;
-               } else {
-                       return false;
+                       res = getDocumentService().demote(aPublication.value());
                }
-               if (getDocumentTypeService().isStudyResult(type)
-                               && owner.getProgressState() != ProgressState.inWORK)
+               if (res && getDocumentService().isStudyResult(type)
+                               && owner.getProgressState() != ProgressState.inWORK) {
                        getStudyService().demote(owner);
-               return true;
+               }
+               return res;
        }
 
        /**
@@ -143,18 +283,20 @@ public class PublicationServiceImpl implements PublicationService {
         * 
         * @see org.splat.service.PublicationService#invalidate(org.splat.dal.bo.som.Publication)
         */
-       public boolean invalidate(Publication aPublication) {
-               // ----------------------------
-               if (aPublication.value().getProgressState() != ProgressState.inCHECK)
-                       return false;
-               if (!aPublication.value().demote()) // Removes the reviewer if this document is In-Check
-                       return false;
-               DocumentType type = aPublication.value().getType();
-               Study owner = aPublication.getOwnerStudy();
-               if (getDocumentTypeService().isStudyResult(type)
-                               && owner.getProgressState() == ProgressState.inCHECK)
-                       getStudyService().demote(owner);
-               return true;
+       @Transactional
+       public boolean invalidate(final Publication aPublication) {
+               boolean res = false;
+               if ((aPublication.value().getProgressState() == ProgressState.inCHECK)
+                               && getDocumentService().demote(aPublication.value())) {
+                       DocumentType type = aPublication.value().getType();
+                       Study owner = aPublication.getOwnerStudy();
+                       if (getDocumentService().isStudyResult(type)
+                                       && owner.getProgressState() == ProgressState.inCHECK) {
+                               getStudyService().demote(owner);
+                       }
+                       res = true;
+               }
+               return res;
        }
 
        /**
@@ -162,33 +304,38 @@ public class PublicationServiceImpl implements PublicationService {
         * 
         * @see org.splat.service.PublicationService#promote(org.splat.dal.bo.som.Publication, java.util.Date)
         */
-       public Timestamp promote(Publication aPublication, Date pdate) {
-               if (aPublication.isOutdated())
-                       return null;
-               else if (aPublication.value().getProgressState() != ProgressState.inWORK)
-                       return null; // This statement must conform to the corresponding right
-               else {
+       @Transactional
+       public Timestamp promote(final Publication aPublication, final Date pdate) {
+               Timestamp res = null;
+               if ((!aPublication.isOutdated())
+                               && (aPublication.value().getProgressState() == ProgressState.inWORK)) {
                        DocumentType type = aPublication.value().getType();
                        Study owner = aPublication.getOwnerStudy();
-                       ValidationCycle cycle = owner.getValidationCycleOf(type);
+                       ValidationCycle cycle = getStudyService().getValidationCycleOf(
+                                       owner, type);
                        User promoter = cycle.getActor(ValidationStep.PROMOTION);
-                       if (promoter == null)
+                       if (promoter == null) {
                                promoter = getInvolvedStep(aPublication).getActor();
-                       if (promoter == null)
+                       }
+                       if (promoter == null) {
                                promoter = owner.getAuthor();
+                       }
                        Timestamp stamp = new Timestamp(ValidationStep.PROMOTION,
                                        aPublication.value(), promoter, pdate);
+                       getTimestampDAO().create(stamp);
 
-                       if (!aPublication.value().promote(stamp)) // Promotion to being reviewed
-                               return null;
-                       if (!cycle.enables(ValidationStep.REVIEW)) {
-                               aPublication.value().promote(null);
+                       if (getDocumentService().promote(aPublication.value(), stamp)) {
+                               res = stamp;
+                               if (!cycle.enables(ValidationStep.REVIEW)) {
+                                       getDocumentService().promote(aPublication.value(), null);
+                               }
+                               if (getDocumentService().isStudyResult(type)
+                                               && owner.getProgressState() == ProgressState.inWORK) {
+                                       getStudyService().promote(owner);
+                               }
                        }
-                       if (getDocumentTypeService().isStudyResult(type)
-                                       && owner.getProgressState() == ProgressState.inWORK)
-                               getStudyService().promote(owner);
-                       return stamp; // Hoping that promotion of the study succeeded
                }
+               return res; // Hoping that promotion of the study succeeded
        }
 
        /**
@@ -196,24 +343,30 @@ public class PublicationServiceImpl implements PublicationService {
         * 
         * @see org.splat.service.PublicationService#review(org.splat.dal.bo.som.Publication, java.util.Date)
         */
-       public Timestamp review(Publication aPublication, Date rdate) {
-               if (aPublication.isOutdated())
-                       return null;
-               else if (aPublication.value().getProgressState() != ProgressState.inDRAFT)
-                       return null; // This statement must conform to the corresponding right
+       @Transactional
+       public Timestamp review(final Publication aPublication, final Date rdate) {
+               Timestamp res = null;
+               if (!aPublication.isOutdated()
+                               && !(aPublication.value().getProgressState() != ProgressState.inDRAFT)) {
 
-               DocumentType type = aPublication.value().getType();
-               Study owner = aPublication.getOwnerStudy();
-               ValidationCycle cycle = owner.getValidationCycleOf(type);
-               User reviewer = cycle.getActor(ValidationStep.REVIEW);
-               Timestamp stamp = new Timestamp(ValidationStep.REVIEW, aPublication
-                               .value(), reviewer, rdate);
-               if (!aPublication.value().promote(stamp))
-                       return null;
-               if (getDocumentTypeService().isStudyResult(type)
-                               && owner.getProgressState() == ProgressState.inDRAFT)
-                       getStudyService().promote(owner);
-               return stamp; // Hoping that promotion of the study succeeded
+                       DocumentType type = aPublication.value().getType();
+                       Study owner = aPublication.getOwnerStudy();
+                       ValidationCycle cycle = getStudyService().getValidationCycleOf(
+                                       owner, type);
+                       User reviewer = cycle.getActor(ValidationStep.REVIEW);
+                       Timestamp stamp = new Timestamp(ValidationStep.REVIEW, aPublication
+                                       .value(), reviewer, rdate);
+                       getTimestampDAO().create(stamp);
+
+                       if (getDocumentService().promote(aPublication.value(), stamp)) {
+                               res = stamp;
+                               if (getDocumentService().isStudyResult(type)
+                                               && owner.getProgressState() == ProgressState.inDRAFT) {
+                                       getStudyService().promote(owner);
+                               }
+                       }
+               }
+               return res; // Hoping that promotion of the study succeeded
        }
 
        /**
@@ -222,17 +375,20 @@ public class PublicationServiceImpl implements PublicationService {
         * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.som.Revision)
         * @deprecated
         */
-       public void saveAs(Publication aPublication, Revision newvers)
+       @Deprecated
+       @Transactional
+       public void saveAs(final Publication aPublication, final Revision newvers)
                        throws FileNotFoundException, NotApplicableException {
-               // -------------------------------------
-               if (aPublication.value().isUndefined())
+               if (aPublication.value().isUndefined()) {
                        throw new NotApplicableException(
                                        "Cannot save a Publication object refering an undefined Document");
-               if (!aPublication.value().getSourceFile().exists())
+               }
+               if (!aPublication.value().getSourceFile().exists()) {
                        throw new FileNotFoundException();
+               }
 
-               Database.getSession().save(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
-               aPublication.value().updateAs(newvers); // May change the branch name of given revision
+               getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
+               getDocumentService().updateAs(aPublication.value(), newvers); // May change the branch name of given revision
                updateOwner(aPublication);
        }
 
@@ -241,23 +397,26 @@ public class PublicationServiceImpl implements PublicationService {
         * 
         * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.dal.bo.som.ProgressState)
         */
-       public void saveAs(Publication aPublication, ProgressState state)
+       @Transactional
+       public void saveAs(final Publication aPublication, final ProgressState state)
                        throws FileNotFoundException, NotApplicableException {
-               // ----------------------------------------
-               if (aPublication.value().isUndefined())
+               if (aPublication.value().isUndefined()) {
                        throw new NotApplicableException(
                                        "Cannot save a Publication object refering an undefined Document");
-               if (!aPublication.value().getSourceFile().exists())
+               }
+               if (!aPublication.value().getSourceFile().exists()) {
                        throw new FileNotFoundException();
+               }
 
                if (state == ProgressState.inWORK || state == ProgressState.EXTERN) {
-                       Database.getSession().save(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
+                       getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
                        // hascode
-                       aPublication.value().updateAs(state);
+                       getDocumentService().updateAs(aPublication.value(), state);
                } else {
                        DocumentType mytype = aPublication.value().getType();
                        Study owner = aPublication.getOwnerStudy();
-                       ValidationCycle cycle = owner.getValidationCycleOf(mytype);
+                       ValidationCycle cycle = getStudyService().getValidationCycleOf(
+                                       owner, mytype);
                        boolean review = cycle.enables(ValidationStep.REVIEW);
                        if (!(state == ProgressState.inDRAFT && review)
                                        && !(state == ProgressState.inCHECK && !review)) {
@@ -265,9 +424,10 @@ public class PublicationServiceImpl implements PublicationService {
                                                "Cannot save a result document in " + state.toString()
                                                                + " state");
                        }
-                       Database.getSession().save(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
+                       getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
                        // hascode
-                       aPublication.value().updateAs(ProgressState.inWORK);
+                       getDocumentService().updateAs(aPublication.value(),
+                                       ProgressState.inWORK);
 
                        promote(aPublication, aPublication.value()
                                        .getLastModificationDate()); // Promotes to the appropriate state in accordance to the validation cycle
@@ -281,24 +441,27 @@ public class PublicationServiceImpl implements PublicationService {
         * @param aPublication
         *            the document publication
         */
-       private void updateOwner(Publication aPublication) {
-               Session session = Database.getSession();
+       @Transactional
+       private void updateOwner(final Publication aPublication) {
                Step step = getInvolvedStep(aPublication);
 
                // Update of involved step
                Document previous = aPublication.value().getPreviousVersion();
                if (previous != null) {
                        Publication oldoc = step.getDocument(previous.getIndex());
-                       boolean done = step.remove(oldoc); // Decrements the configuration tag count of document
-                       if (done)
-                               session.delete(oldoc); // WARNING: Potential problem because it's not automatically done as orphan object
-               }
-               step.add(aPublication); // Increments the configuration tag count of document
+                       boolean done = getStepService().remove(step, oldoc); // Decrements the configuration tag count of document
+/*                     if (done) {
+                               oldoc = getPublicationDAO().merge(oldoc); //RKV: to avoid: NonUniqueObjectException: a different object with the same identifier value was already associated with the session
+                               //RKV: use delete-orphan by removing from project element, see StepService.remove
+                               //RKV: getPublicationDAO().delete(oldoc); // WARNING: Potential problem because it's not automatically done as orphan object
+                       }
+*/             }
+               getStepService().add(step, aPublication); // Increments the configuration tag count of document
 
                // Import the document properties and update of the study
                forwardProperties(aPublication, aPublication.value().getSourceFile()
                                .asFile(), step);
-               session.update(aPublication.getOwner());
+               getProjectElementDAO().merge(aPublication.getOwner());
        }
 
        /**
@@ -311,52 +474,58 @@ public class PublicationServiceImpl implements PublicationService {
         * @param to
         *            the study step
         */
-       private void forwardProperties(Publication aPublication, java.io.File from,
-                       Step to) {
-               // -----------------------------------------------------------
+       private void forwardProperties(final Publication aPublication,
+                       final java.io.File from, final Step to) {
                Reader tool = Toolbox.getReader(from);
-               if (tool == null)
-                       return; // No properties extractor available for this type of document
-
-               SimulationContextType.Properties sprop = new SimulationContextType.Properties()
-                               .setStep(to.getStep()).setState(ProgressState.APPROVED);
-               List<SimulationContextType> contype = getSimulationContextService()
-                               .selectTypesWhere(sprop);
-               if (contype.isEmpty())
-                       return; // No approved property type configured at this step
-
-               SimulationContext.Properties cprop = new SimulationContext.Properties();
-               List<SimulationContext> context = to.getAllSimulationContexts();
-
-               context = new ArrayList<SimulationContext>(context.size());
-               context.addAll(to.getAllSimulationContexts());
-               cprop.disableCheck();
-               for (Iterator<SimulationContextType> i = contype.iterator(); i
-                               .hasNext();) {
-                       SimulationContextType property = i.next();
-                       for (Iterator<SimulationContext> j = context.iterator(); j
-                                       .hasNext();) {
-                               SimulationContext existing = j.next();
-                               if (!existing.getType().equals(property))
-                                       continue;
-                               property = null; // Forget this property as it is already set
-                               break;
-                       }
-                       if (property != null)
-                               try {
-                                       String value = tool.extractProperty(property.getName());
-                                       if (value == null)
-                                               continue; // Property not defined into the document
-
-                                       cprop.setType(property).setValue(value);
-                                       if (aPublication.getOwner() instanceof Study)
-                                               getStudyService().addProjectContext(
-                                                               (Study) aPublication.getOwner(), cprop); // Re-indexes knowledges and the study
-                                       else
-                                               getStepService().addSimulationContext(to, cprop); // Re-indexes knowledges only
-                               } catch (Exception e) {
-                                       break;
+               if (tool != null) { // Properties extractor available for this type of document
+                       SimulationContextType.Properties sprop = new SimulationContextType.Properties()
+                                       .setStep(to.getStep()).setProgressState(
+                                                       ProgressState.APPROVED);
+                       List<SimulationContextType> contype = getSimulationContextService()
+                                       .selectTypesWhere(sprop);
+                       if (!contype.isEmpty()) { // There is an approved property type configured at this step
+
+                               SimulationContext.Properties cprop = new SimulationContext.Properties();
+                               List<SimulationContext> context = to.getAllSimulationContexts();
+
+                               context = new ArrayList<SimulationContext>(context.size());
+                               context.addAll(to.getAllSimulationContexts());
+                               cprop.disableCheck();
+                               for (Iterator<SimulationContextType> i = contype.iterator(); i
+                                               .hasNext();) {
+                                       SimulationContextType property = i.next();
+                                       boolean isFound = false;
+                                       for (Iterator<SimulationContext> j = context.iterator(); j
+                                                       .hasNext();) {
+                                               SimulationContext existing = j.next();
+                                               isFound = existing.getType().equals(property);
+                                               if (isFound) {
+                                                       // Forget this property as it is already set
+                                                       break;
+                                               }
+                                       }
+                                       if (!isFound) {
+                                               try {
+                                                       String value = tool.extractProperty(property
+                                                                       .getName());
+                                                       if (value == null) {
+                                                               continue; // Property not defined into the document
+                                                       }
+
+                                                       cprop.setType(property).setValue(value);
+                                                       if (aPublication.getOwner() instanceof Study) {
+                                                               getStudyService().addProjectContext(
+                                                                               (Study) aPublication.getOwner(), cprop); // Re-indexes knowledges and the study
+                                                       } else {
+                                                               getStepService()
+                                                                               .addSimulationContext(to, cprop); // Re-indexes knowledges only
+                                                       }
+                                               } catch (Exception e) {
+                                                       break;
+                                               }
+                                       }
                                }
+                       }
                }
        }
 
@@ -367,19 +536,108 @@ public class PublicationServiceImpl implements PublicationService {
         *            the document publication
         * @return the study step where the document is published
         */
-       public Step getInvolvedStep(Publication aPublication) {
+       public Step getInvolvedStep(final Publication aPublication) {
                if (aPublication.getStep() == null) {
                        Step[] step = getProjectElementService().getSteps(
                                        aPublication.getOwner());
                        for (int i = 0; i < step.length; i++) {
                                aPublication.setStep(step[i]); // The involved step necessarily exists
-                               if (aPublication.value().isInto(aPublication.getStep()))
+                               if (aPublication.value().isInto(aPublication.getStep())) {
                                        break;
+                               }
                        }
                }
                return aPublication.getStep();
        }
 
+       /**
+        * Undo the out-date operation.
+        * 
+        * @param aPublication
+        *            the publication
+        * @return true if the acceptance succeeds
+        * @see #outdate()
+        * @see DocumentRights#canAccept()
+        */
+       @Transactional
+       public boolean actualize(final Publication aPublication) {
+               boolean res = aPublication.isOutdated();
+               if (res) {
+                       aPublication.setIsnew('Y');
+                       getPublicationDAO().update(aPublication);
+               }
+               return res;
+       }
+
+       /**
+        * Out-dates this publication and recursively all publications using this one. Typically, a publication is out-dated when modifying a
+        * document to which it depends.
+        * 
+        * @param aPublication
+        *            the publication
+        * @see #isOutdated()
+        * @see #getProgressState()
+        * @see #actualize()
+        */
+       public void outdate(final Publication aPublication) {
+               if (aPublication.isOutdated()) {
+                       return;
+               }
+
+               List<Publication> relist = aPublication
+                               .getRelations(UsedByRelation.class);
+               for (Iterator<Publication> i = relist.iterator(); i.hasNext();) {
+                       outdate(i.next());
+               }
+               aPublication.setIsnew('O');
+               getPublicationDAO().update(aPublication);
+       }
+
+       /**
+        * Create "Converts" relation for the given document publication and format.
+        * 
+        * @param aPublication
+        *            the document publication
+        * @param format
+        *            the format
+        * @return the created "Converts" relation
+        */
+       public ConvertsRelation attach(final Publication aPublication, final String format) {
+               return getDocumentService().attach(aPublication.value(), format);
+       }
+
+       /**
+        * Create "Converts" relation for the given document publication, format and description.
+        * 
+        * @param aPublication
+        *            the document publication
+        * @param format
+        *            the format
+        * @param description
+        *            the description of the relation
+        * @return the created "Converts" relation
+        */
+       public ConvertsRelation attach(final Publication aPublication, final String format,
+                       final String description) {
+               return getDocumentService().attach(aPublication.value(), format,
+                               description);
+       }
+
+       /**
+        * Rename the published document.
+        * 
+        * @param aPublication
+        *            the publication of the document
+        * @param title
+        *            the new document title
+        * @throws InvalidPropertyException
+        *             if the new title is empty
+        */
+       public void rename(final Publication aPublication, final String title)
+                       throws InvalidPropertyException {
+               getDocumentService().rename(aPublication.value(), title);
+       }
+
        /**
         * Get the projectElementService.
         * 
@@ -396,7 +654,7 @@ public class PublicationServiceImpl implements PublicationService {
         *            the projectElementService to set
         */
        public void setProjectElementService(
-                       ProjectElementService projectElementService) {
+                       final ProjectElementService projectElementService) {
                _projectElementService = projectElementService;
        }
 
@@ -416,12 +674,13 @@ public class PublicationServiceImpl implements PublicationService {
         *            the simulationContextService to set
         */
        public void setSimulationContextService(
-                       SimulationContextService simulationContextService) {
+                       final SimulationContextService simulationContextService) {
                _simulationContextService = simulationContextService;
        }
 
        /**
         * Get the studyService.
+        * 
         * @return the studyService
         */
        public StudyService getStudyService() {
@@ -430,14 +689,17 @@ public class PublicationServiceImpl implements PublicationService {
 
        /**
         * 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 stepService.
+        * 
         * @return the stepService
         */
        public StepService getStepService() {
@@ -446,25 +708,103 @@ public class PublicationServiceImpl implements PublicationService {
 
        /**
         * Set the stepService.
-        * @param stepService the stepService to set
+        * 
+        * @param stepService
+        *            the stepService to set
         */
-       public void setStepService(StepService stepService) {
+       public void setStepService(final StepService stepService) {
                _stepService = stepService;
        }
 
        /**
-        * Get the documentTypeService.
-        * @return the documentTypeService
+        * Get the documentService.
+        * 
+        * @return the documentService
+        */
+       public DocumentService getDocumentService() {
+               return _documentService;
+       }
+
+       /**
+        * Set the documentService.
+        * 
+        * @param documentService
+        *            the documentService to set
+        */
+       public void setDocumentService(final DocumentService documentService) {
+               _documentService = documentService;
+       }
+
+       /**
+        * Get the publicationDAO.
+        * 
+        * @return the publicationDAO
+        */
+       public PublicationDAO getPublicationDAO() {
+               return _publicationDAO;
+       }
+
+       /**
+        * Set the publicationDAO.
+        * 
+        * @param publicationDAO
+        *            the publicationDAO to set
+        */
+       public void setPublicationDAO(final PublicationDAO publicationDAO) {
+               _publicationDAO = publicationDAO;
+       }
+
+       /**
+        * Get the projectElementDAO.
+        * 
+        * @return the projectElementDAO
+        */
+       public ProjectElementDAO getProjectElementDAO() {
+               return _projectElementDAO;
+       }
+
+       /**
+        * Set the projectElementDAO.
+        * 
+        * @param projectElementDAO
+        *            the projectElementDAO to set
+        */
+       public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
+               _projectElementDAO = projectElementDAO;
+       }
+
+       /**
+        * 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;
+       }
+
+       /**
+        * Get the timestampDAO.
+        * @return the timestampDAO
         */
-       public DocumentTypeService getDocumentTypeService() {
-               return _documentTypeService;
+       public TimestampDAO getTimestampDAO() {
+               return _timestampDAO;
        }
 
        /**
-        * Set the documentTypeService.
-        * @param documentTypeService the documentTypeService to set
+        * Set the timestampDAO.
+        * @param timestampDAO the timestampDAO to set
         */
-       public void setDocumentTypeService(DocumentTypeService documentTypeService) {
-               _documentTypeService = documentTypeService;
+       public void setTimestampDAO(final TimestampDAO timestampDAO) {
+               _timestampDAO = timestampDAO;
        }
 }