]> SALOME platform Git repositories - tools/siman.git/commitdiff
Salome HOME
Study validation cycle operations are implemented according to the specification.
authorrkv <rkv@opencascade.com>
Fri, 12 Apr 2013 14:32:00 +0000 (14:32 +0000)
committerrkv <rkv@opencascade.com>
Fri, 12 Apr 2013 14:32:00 +0000 (14:32 +0000)
15 files changed:
Workspace/Siman-Common/src/org/splat/dal/dao/kernel/AbstractGenericDAOImpl.java
Workspace/Siman-Common/src/org/splat/dal/dao/kernel/GenericDAO.java
Workspace/Siman-Common/src/org/splat/service/ProjectElementService.java
Workspace/Siman-Common/src/org/splat/service/ProjectElementServiceImpl.java
Workspace/Siman-Common/src/org/splat/service/PublicationServiceImpl.java
Workspace/Siman-Common/src/org/splat/service/StudyService.java
Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java
Workspace/Siman-Common/src/org/splat/som/DocumentRights.java
Workspace/Siman-Common/src/org/splat/som/StudyRights.java
Workspace/Siman-Common/src/spring/businessServiceContext.xml
Workspace/Siman/src/labels.properties
Workspace/Siman/src/labels_en.properties
Workspace/Siman/src/org/splat/simer/ApplicationSettings.java
Workspace/Siman/src/org/splat/simer/EditStudyAction.java
Workspace/Siman/src/org/splat/simer/OpenStudy.java

index 778ac116ae7be19c48bc66cff16788506f309880..83405d94bfdf951af0859d664a03dbe2eb1424c1 100644 (file)
@@ -143,6 +143,19 @@ public abstract class AbstractGenericDAOImpl<T, PK extends Serializable>
                return aDetachedCriteria.getExecutableCriteria(getSession()).list();
        }
 
+       /**
+        * Retrieve a first found object in the database using the given criteria.
+        * 
+        * @param aDetachedCriteria
+        *            search criteria
+        * @return a first found object filtered according to the given criteria
+        */
+       @SuppressWarnings(Constants.UNCHECKED)
+       public T getFirstResult(final DetachedCriteria aDetachedCriteria) {
+               return (T) aDetachedCriteria.getExecutableCriteria(getSession())
+                               .setMaxResults(1).uniqueResult();
+       }
+
        /**
         * Retrieve a list of DTO objects using the given criteria.
         * 
index 477ab48ae5c6a90b3d941f1e6b1d9bb927cd396d..6a45c1eadbb3a81949fffa67e28e3b85dd72ed81 100644 (file)
@@ -155,6 +155,15 @@ public interface GenericDAO<T, PK extends Serializable> {
         */
        public List<T> getFilteredList(final DetachedCriteria aDetachedCriteria);
 
+       /**
+        * Retrieve a first found object in the database using the given criteria.
+        * 
+        * @param aDetachedCriteria
+        *            search criteria
+        * @return a first found object filtered according to the given criteria
+        */
+       public T getFirstResult(final DetachedCriteria aDetachedCriteria);
+       
        /**
         * Retrieve a list of DTO objects using the given criteria.
         * 
index 722703166f56dca8cb77704281423163f2050add..214af6664a33a44661ae6b0c15e54c458101bbd7 100644 (file)
@@ -31,6 +31,15 @@ public interface ProjectElementService {
         */
        Step getFirstStep(ProjectElement elem);
 
+       /**
+        * Get the last activity of the project element.
+        * 
+        * @param elem
+        *            a study or a scenario
+        * @return the last activity (step) of the project element
+        */
+       Step getLastStep(ProjectElement elem);
+
        /**
         * Get activities of the project element.
         * 
index d01bdd6d7b42e89825aae00a12847a4440e0aefc..7de02b24f6f7ff3aebec2a7ad6f5f942c44941f1 100644 (file)
@@ -48,6 +48,10 @@ public class ProjectElementServiceImpl implements ProjectElementService {
                return getSteps(elem)[0];
        }
 
+       /** 
+        * {@inheritDoc}
+        * @see org.splat.service.ProjectElementService#getLastStep(org.splat.dal.bo.som.ProjectElement)
+        */
        public Step getLastStep(final ProjectElement elem) {
                Step[] mystep = getSteps(elem); // For getting the folders length, if null
                return mystep[mystep.length - 1];
index e2693f68e81f8f6a089d7ff8336a63b3c9288107..119a4fc29bde714727feda9f0152f9cd410a6fc6 100644 (file)
@@ -339,10 +339,10 @@ public class PublicationServiceImpl implements PublicationService {
 
                        if (getDocumentService().promote(aPublication.value(), stamp)) {
                                res = stamp;
-                               if (getDocumentService().isStudyResult(type)
-                                               && owner.getProgressState() == ProgressState.inCHECK) {
-                                       getStudyService().promote(owner);
-                               }
+//                             if (getDocumentService().isStudyResult(type)
+//                                             && owner.getProgressState() == ProgressState.inCHECK) {
+//                                     getStudyService().promote(owner);
+//                             }
                        }
                }
                return res; // Hoping that promotion of the study succeeded
@@ -373,10 +373,10 @@ public class PublicationServiceImpl implements PublicationService {
                } else if (aPublication.value().getProgressState() == ProgressState.inDRAFT) {
                        res = getDocumentService().demote(aPublication.value());
                }
-               if (res && getDocumentService().isStudyResult(type)
-                               && owner.getProgressState() != ProgressState.inWORK) {
-                       getStudyService().demote(owner);
-               }
+//             if (res && getDocumentService().isStudyResult(type)
+//                             && owner.getProgressState() != ProgressState.inWORK) {
+//                     getStudyService().demote(owner);
+//             }
                return res;
        }
 
@@ -396,11 +396,11 @@ public class PublicationServiceImpl implements PublicationService {
                                        owner, type);
                        // Check if the validation cycle allows the review step
                        if (cycle.enables(ValidationStep.REVIEW)) {
-                               if (getDocumentService().demote(aPublication.value())
-                                               && getDocumentService().isStudyResult(type)
-                                               && owner.getProgressState() == ProgressState.inCHECK) {
-                                       getStudyService().demote(owner);
-                               }
+//                             if (getDocumentService().demote(aPublication.value())
+//                                             && getDocumentService().isStudyResult(type)
+//                                             && owner.getProgressState() == ProgressState.inCHECK) {
+//                                     getStudyService().demote(owner);
+//                             }
                                res = true;
                        } else { // If the validation cycle has no inDraft step
                                res = demote(aPublication);
@@ -439,10 +439,10 @@ public class PublicationServiceImpl implements PublicationService {
                                if (!cycle.enables(ValidationStep.REVIEW)) {
                                        getDocumentService().promote(aPublication.value(), null);
                                }
-                               if (getDocumentService().isStudyResult(type)
-                                               && owner.getProgressState() == ProgressState.inWORK) {
-                                       getStudyService().promote(owner);
-                               }
+//                             if (getDocumentService().isStudyResult(type)
+//                                             && owner.getProgressState() == ProgressState.inWORK) {
+//                                     getStudyService().promote(owner);
+//                             }
                        }
                }
                return res; // Hoping that promotion of the study succeeded
@@ -470,10 +470,10 @@ public class PublicationServiceImpl implements PublicationService {
 
                        if (getDocumentService().promote(aPublication.value(), stamp)) {
                                res = stamp;
-                               if (getDocumentService().isStudyResult(type)
-                                               && owner.getProgressState() == ProgressState.inDRAFT) {
-                                       getStudyService().promote(owner);
-                               }
+//                             if (getDocumentService().isStudyResult(type)
+//                                             && owner.getProgressState() == ProgressState.inDRAFT) {
+//                                     getStudyService().promote(owner);
+//                             }
                        }
                }
                return res; // Hoping that promotion of the study succeeded
index 73d498da2e2bd6d533e8015b91e0ef70049cfcc3..7185cef30fec027a98cec84eabe079459cda8652 100644 (file)
@@ -13,7 +13,6 @@ import java.util.List;
 
 import org.splat.dal.bo.kernel.User;
 import org.splat.dal.bo.som.DocumentType;
-import org.splat.dal.bo.som.Publication;
 import org.splat.dal.bo.som.SimulationContext;
 import org.splat.dal.bo.som.Study;
 import org.splat.dal.bo.som.ValidationCycle;
@@ -38,6 +37,42 @@ import org.splat.service.dto.StudyFacadeDTO.ScenarioDTO;
  */
 public interface StudyService {
 
+       /**
+        * Check if the study can be promoted taking into account its documents states.
+        * 
+        * @param study
+        *            the study to be checked
+        * @return true if states of study documents allows the operation
+        */
+       boolean canBePromoted(final Study study);
+
+       /**
+        * Check if the study can be validated taking into account its documents states.
+        * 
+        * @param study
+        *            the study to be checked
+        * @return true if states of study documents allows the operation
+        */
+       boolean canBeReviewed(final Study study);
+
+       /**
+        * Check if the study can be approved taking into account its documents states.
+        * 
+        * @param study
+        *            the study to be checked
+        * @return true if states of study documents allows the operation
+        */
+       boolean canBeApproved(final Study study);
+
+       /**
+        * Get the study result document type.
+        * 
+        * @param aStudy
+        *            the study
+        * @return document type
+        */
+       DocumentType getStudyResultType(final Study aStudy);
+
        /**
         * Increment total number of study documents including versions (docount) and update it in the study.
         * 
@@ -122,21 +157,21 @@ public interface StudyService {
        boolean removeProjectContext(Study aStudy, SimulationContext context);
 
        /**
-        * Demotes this study from In-Check to In-Draft then In-Work states. This function is called internally when demoting the final result
-        * document of the study.
+        * Demotes this study from In-Check or In-Draft to In-Work states.
         * 
         * @param aStudy
-        *            the study to demote
+        *            a study to demote
         * @return true if the demotion succeeded.
         */
        boolean demote(Study aStudy);
 
        /**
-        * Promotes this study from In-Work to In-Draft then In-Check and APPROVED states. This function is called internally when promoting the
-        * final result document of the study.
+        * Promotes this study from In-Work to In-Draft then In-Check and APPROVED <BR>
+        * states. This function takes into account statuses of final result<BR>
+        * documents of the study.
         * 
         * @param aStudy
-        *            the study to promote
+        *            a study to promote
         * @return true if the promotion succeeded.
         */
        boolean promote(Study aStudy);
@@ -195,19 +230,6 @@ public interface StudyService {
         */
        boolean moveToPrivate(Study aStudy);
 
-       /**
-        * Moves this study from the Public to the Reference area of the repository. For being moved to the Reference area, the study must
-        * previously be approved.
-        * 
-        * @param aStudy
-        *            the study to move
-        * @return true if the move succeeded.
-        * @see #moveToPublic()
-        * @see #isPublic()
-        * @see Publication#approve(Date)
-        */
-       boolean moveToReference(Study aStudy);
-
        /**
         * Update a study.
         * 
@@ -275,12 +297,13 @@ public interface StudyService {
        List<User> getContributors(Study aStudy);
 
        /**
-        * Mark study as reference.
+        * Mark this study as Reference. The study must previously be approved.
         * 
         * @param aStudy -
         *            the Study
+        * @return true if succeeded
         */
-       void markStudyAsReference(Study aStudy);
+       boolean markStudyAsReference(Study aStudy);
 
        /**
         * Remove study as reference. This operation is inverse one to Mark as reference.
@@ -291,16 +314,19 @@ public interface StudyService {
        void removeStudyAsReference(Study aStudy);
 
        /**
-        * Get studies, scenarios and publications available for comparison.
-        * <br><b> DocumentDto.id are actually filled in with Publication ids.</b>
-        * @param userId id of the user to to whom visible studies will be returned.
-        * @return list of {@link StudyFacadeDTO} containing lists of {@link ScenarioDTO} containing list of 
-        *              {@link DocumentDTO}, corresponding to to the publications available for comparison,
-        *              with ids and titles filled in.
-        * @throws MismatchException if some configurations considering postprocessing step are invalid.
+        * Get studies, scenarios and publications available for comparison. <br>
+        * <b> DocumentDto.id are actually filled in with Publication ids.</b>
+        * 
+        * @param userId
+        *            id of the user to to whom visible studies will be returned.
+        * @return list of {@link StudyFacadeDTO} containing lists of {@link ScenarioDTO} containing list of {@link DocumentDTO}, corresponding
+        *         to to the publications available for comparison, with ids and titles filled in.
+        * @throws MismatchException
+        *             if some configurations considering postprocessing step are invalid.
         */
-       List<StudyFacadeDTO> getComparableStudies(final long userId) throws MismatchException;
-       
+       List<StudyFacadeDTO> getComparableStudies(final long userId)
+                       throws MismatchException;
+
        /**
         * Get the description attribute related to the study (there supposed to be the only one such attribute in the database).
         * 
@@ -351,30 +377,44 @@ public interface StudyService {
         */
        String compare(List<DocToCompareDTO> docsList, final String userName)
                        throws IncompatibleDataException;
-       
+
        /**
         * Get readers of a given study.
-        * @param studyId the study id.
+        * 
+        * @param studyId
+        *            the study id.
         * @return list of user DTO corresponding to the study readers.
-        * @throws InvalidParameterException if no study with such id has been found in the database.
+        * @throws InvalidParameterException
+        *             if no study with such id has been found in the database.
         */
-       List<UserDTO> getReaders(final long studyId) throws InvalidParameterException;
-       
+       List<UserDTO> getReaders(final long studyId)
+                       throws InvalidParameterException;
+
        /**
         * Add reader to a given study.
-        * @param studyId the study id.
-        * @param userId the user id.
+        * 
+        * @param studyId
+        *            the study id.
+        * @param userId
+        *            the user id.
         * @return true if the user has been added as a reader
-        * @throws InvalidParameterException if no study or user with such id has been found in the database.
+        * @throws InvalidParameterException
+        *             if no study or user with such id has been found in the database.
         */
-       boolean addReader(final long studyId, final long userId) throws InvalidParameterException;
+       boolean addReader(final long studyId, final long userId)
+                       throws InvalidParameterException;
 
        /**
         * Remove reader from a given study.
-        * @param studyId the study id.
-        * @param userId the user id.
+        * 
+        * @param studyId
+        *            the study id.
+        * @param userId
+        *            the user id.
         * @return true if the relation has been found and removed
-        * @throws InvalidParameterException if no study or user with such id has been found in the database.
+        * @throws InvalidParameterException
+        *             if no study or user with such id has been found in the database.
         */
-       boolean removeReader(final long studyId, final long userId) throws InvalidParameterException;
+       boolean removeReader(final long studyId, final long userId)
+                       throws InvalidParameterException;
 }
index d75d3ccfa29cd440919d9bd6ac10de208b6a8753..86863e9829f107c5e9f56ea976c906ceb4ff4cac 100644 (file)
@@ -33,6 +33,7 @@ import org.apache.lucene.store.FSDirectory;
 import org.hibernate.Criteria;
 import org.hibernate.Hibernate;
 import org.hibernate.criterion.DetachedCriteria;
+import org.hibernate.criterion.Order;
 import org.hibernate.criterion.Restrictions;
 import org.hibernate.proxy.HibernateProxy;
 import org.jfree.chart.ChartFactory;
@@ -48,6 +49,7 @@ import org.splat.dal.bo.som.ContributorRelation;
 import org.splat.dal.bo.som.DescriptionAttribute;
 import org.splat.dal.bo.som.DocumentType;
 import org.splat.dal.bo.som.IDBuilder;
+import org.splat.dal.bo.som.KnowledgeElement;
 import org.splat.dal.bo.som.ProgressState;
 import org.splat.dal.bo.som.ProjectElement;
 import org.splat.dal.bo.som.Publication;
@@ -63,6 +65,7 @@ import org.splat.dal.bo.som.Study.Properties;
 import org.splat.dal.bo.som.ValidationCycle.Actor;
 import org.splat.dal.dao.som.DescriptionAttributeDAO;
 import org.splat.dal.dao.som.DocumentDAO;
+import org.splat.dal.dao.som.DocumentTypeDAO;
 import org.splat.dal.dao.som.IDBuilderDAO;
 import org.splat.dal.dao.som.PublicationDAO;
 import org.splat.dal.dao.som.ScenarioDAO;
@@ -190,6 +193,10 @@ public class StudyServiceImpl implements StudyService {
         * Injected description attribute DAO.
         */
        private DescriptionAttributeDAO _descriptionAttributeDAO;
+       /**
+        * Injected document type DAO.
+        */
+       private DocumentTypeDAO _documentTypeDAO;
 
        /**
         * {@inheritDoc}
@@ -339,24 +346,24 @@ public class StudyServiceImpl implements StudyService {
        @Transactional
        public boolean addContributor(final Study aStudy, final User user) {
                List<User> contributors = getModifiableContributors(aStudy); // Initializes contributor
-               
-               if(contributors.contains(user)) {
+
+               if (contributors.contains(user)) {
                        return false;
                }
-               
-               //Remove user from readers
+
+               // Remove user from readers
                try {
                        List<UserDTO> readers = getReaders(aStudy.getIndex());
-                       for(UserDTO reader : readers) {
-                               if(reader.getIndex() == user.getIndex()) {
-                                       //user must be the actual user in the relationship object in the aStudy object for this to work
+                       for (UserDTO reader : readers) {
+                               if (reader.getIndex() == user.getIndex()) {
+                                       // user must be the actual user in the relationship object in the aStudy object for this to work
                                        aStudy.removeRelation(ReaderRelation.class, user);
                                }
                        }
-               } catch(InvalidParameterException e) {
-                       LOG.error(e.getMessage(), e);   
+               } catch (InvalidParameterException e) {
+                       LOG.error(e.getMessage(), e);
                }
-               
+
                boolean absent = getModifiableActors(aStudy).add(user); // User may already be a reviewer or an approver
 
                aStudy.addRelation(new ContributorRelation(aStudy, user));
@@ -366,33 +373,6 @@ public class StudyServiceImpl implements StudyService {
                return true;
        }
 
-       /**
-        * Moves this study from the Public to the Reference area of the repository. For being moved to the Reference area, the study must
-        * previously be approved.
-        * 
-        * @param aStudy
-        *            the study to move
-        * @return true if the move succeeded.
-        * @see #moveToPublic()
-        * @see #isPublic()
-        * @see Publication#approve(Date)
-        */
-       @Transactional
-       public boolean moveToReference(final Study aStudy) {
-               if (aStudy.getProgressState() != ProgressState.APPROVED) {
-                       return false;
-               }
-               if (aStudy.getVisibility() != Visibility.PUBLIC) {
-                       return false;
-               }
-
-               aStudy.setVisibility(Visibility.REFERENCE);
-               if (update(aStudy)) {
-                       return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
-               }
-               return false;
-       }
-
        /**
         * {@inheritDoc}
         * 
@@ -434,8 +414,8 @@ public class StudyServiceImpl implements StudyService {
        public boolean removeContributor(final Study aStudy, final User... users) {
                List<User> contributors = getModifiableContributors(aStudy); // Initializes contributor
                Boolean done = false;
-               for(User user : users) {
-                       if(contributors.contains(user)) {
+               for (User user : users) {
+                       if (contributors.contains(user)) {
                                aStudy.removeRelation(ContributorRelation.class, user);
                                contributors.remove(user);
                                done = true;
@@ -504,26 +484,6 @@ public class StudyServiceImpl implements StudyService {
                update(aStudy); // Re-index the study, just in case
        }
 
-       /**
-        * Demotes this study from In-Check to In-Draft then In-Work states. This function is called internally when demoting the final result
-        * document of the study.
-        * 
-        * @param aStudy
-        *            a study to demote
-        * @return true if the demotion succeeded.
-        */
-       @Transactional
-       public boolean demote(final Study aStudy) {
-               if (aStudy.getProgressState() == ProgressState.inCHECK) {
-                       aStudy.setProgressState(ProgressState.inDRAFT);
-               } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
-                       aStudy.setProgressState(ProgressState.inWORK);
-               } else {
-                       return false;
-               }
-               return update(aStudy);
-       }
-
        /**
         * {@inheritDoc}
         * 
@@ -536,31 +496,60 @@ public class StudyServiceImpl implements StudyService {
        }
 
        /**
-        * Promotes this study from In-Work to In-Draft then In-Check and APPROVED states. This function is called internally when promoting the
-        * final result document of the study.
+        * Promotes this study from In-Work to In-Draft then In-Check and APPROVED <BR>
+        * states. This function takes into account statuses of final result<BR>
+        * documents of the study.
         * 
         * @param aStudy
         *            a study to promote
-        * @return true if the demotion succeeded.
+        * @return true if the promotion succeeded.
         */
        @Transactional
        public boolean promote(final Study aStudy) {
-               if (aStudy.getProgressState() == ProgressState.inWORK) {
+               boolean res = true;
+               if (aStudy.getProgressState() == ProgressState.inWORK
+                               && canBePromoted(aStudy)) {
                        aStudy.setProgressState(ProgressState.inDRAFT);
-               } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
+               } else if (aStudy.getProgressState() == ProgressState.inDRAFT
+                               && canBeReviewed(aStudy)) {
                        aStudy.setProgressState(ProgressState.inCHECK);
                        Revision myvers = new Revision(aStudy.getVersion());
                        if (myvers.isMinor()) {
                                aStudy.setVersion(myvers.incrementAs(aStudy.getProgressState())
                                                .toString());
                        }
-               } else if (aStudy.getProgressState() == ProgressState.inCHECK) {
+               } else if (aStudy.getProgressState() == ProgressState.inCHECK
+                               && canBeApproved(aStudy)) {
                        aStudy.setProgressState(ProgressState.APPROVED);
+                       updateKnowledgeElementsState(aStudy);
                } else {
-                       return false;
+                       res = false;
+               }
+               if (res) {
+                       res = update(aStudy);
                }
 
-               return update(aStudy);
+               return res;
+       }
+
+       /**
+        * Demotes this study from In-Check or In-Draft to In-Work states.
+        * 
+        * @param aStudy
+        *            a study to demote
+        * @return true if the demotion succeeded.
+        */
+       @Transactional
+       public boolean demote(final Study aStudy) {
+               boolean res;
+               if (aStudy.getProgressState() == ProgressState.inCHECK
+                               || aStudy.getProgressState() == ProgressState.inDRAFT) {
+                       aStudy.setProgressState(ProgressState.inWORK);
+                       res = update(aStudy);
+               } else {
+                       res = false;
+               }
+               return res;
        }
 
        /**
@@ -577,7 +566,7 @@ public class StudyServiceImpl implements StudyService {
                if (aStudy.getVisibility() == Visibility.PRIVATE) {
                        aStudy.setVisibility(Visibility.PUBLIC);
                        if (update(aStudy)) {
-                               isOk = updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
+                               isOk = updateKnowledgeElementsState(aStudy); // If fails, the database roll-back is under responsibility of the caller
                        }
                }
                return isOk;
@@ -596,7 +585,7 @@ public class StudyServiceImpl implements StudyService {
                if (aStudy.getVisibility() == Visibility.PUBLIC) {
                        aStudy.setVisibility(Visibility.PRIVATE);
                        if (update(aStudy)) {
-                               isOk = updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
+                               isOk = updateKnowledgeElementsState(aStudy); // If fails, the database roll-back is under responsibility of the caller
                        }
                }
                return isOk;
@@ -614,7 +603,7 @@ public class StudyServiceImpl implements StudyService {
                try {
                        getStudyDAO().merge(aStudy); // Update of relational base
                        setShortCuts(aStudy); // RKV: initialize transient actors set
-                       //RKV: getIndex().update(aStudy); // Update of Lucene index
+                       // RKV: getIndex().update(aStudy); // Update of Lucene index
                        isOk = true;
                } catch (Exception e) {
                        LOG.error("STD-000001", e, aStudy.getIndex(), e.getMessage());
@@ -755,27 +744,18 @@ public class StudyServiceImpl implements StudyService {
        }
 
        /**
-        * Update lucene index for the study knowledge elements.
+        * Update knowledge elements states.
         * 
         * @param aStudy
         *            the study
-        * @return true if reindexing succeeded
-        */
-       private boolean updateKnowledgeElementsIndex(final Study aStudy) {
-//             boolean isOk = false;
-//              try {
-//                      IndexService lucin = getIndex();
-//                      for(Scenario scenario : aStudy.getScenariiList()) {
-//                              for (KnowledgeElement element : scenario.getAllKnowledgeElements()) {
-//                                      lucin.update(element);
-//                              }
-//                      }
-//                      isOk = true;
-//              } catch (Exception error) {
-//                      LOG.error("Unable to re-index Knowledge Elements, reason:",
-//                      error);
-//              }
-//              return isOk;
+        * @return true if succeeded
+        */
+       private boolean updateKnowledgeElementsState(final Study aStudy) {
+               for (Scenario scenario : aStudy.getScenariiList()) {
+                       for (KnowledgeElement element : scenario.getAllKnowledgeElements()) {
+                               element.setProgressState(aStudy.getProgressState());
+                       }
+               }
                return true;
        }
 
@@ -997,14 +977,18 @@ public class StudyServiceImpl implements StudyService {
         */
        public ValidationCycle getValidationCycleOf(final Study aStudy,
                        final DocumentType type) {
-               if (aStudy.getValidationCycles() == null
-                               || aStudy.getValidationCycles().isEmpty()) {
-                       setShortCuts(aStudy);
+               ValidationCycle result = null;
+               if (aStudy != null) {
+                       if (aStudy.getValidationCycles() == null
+                                       || aStudy.getValidationCycles().isEmpty()) {
+                               setShortCuts(aStudy);
+                       }
+                       if (type != null) {
+                               result = aStudy.getValidationCycles().get(type.getName());
+                       }
                }
-               ValidationCycle result = aStudy.getValidationCycles().get(
-                               type.getName());
-               if (result == null) {
-                       if (type.isStepResult()) {
+               if ((result == null) && (aStudy != null)) {
+                       if ((type == null) || type.isStepResult()) {
                                result = aStudy.getValidationCycles().get("default"); // "default" validation cycle defined in the configuration, if exist
                        }
                        if (result == null) {
@@ -1142,11 +1126,15 @@ public class StudyServiceImpl implements StudyService {
         * @see org.splat.service.StudyService#markStudyAsReference(org.splat.dal.bo.som.Study)
         */
        @Transactional
-       public void markStudyAsReference(final Study aStudy) {
-
-               aStudy.setMarkreference(1);
-               aStudy.setProgressState(ProgressState.TEMPLATE);
-               getStudyDAO().merge(aStudy);
+       public boolean markStudyAsReference(final Study aStudy) {
+               boolean res = false;
+               if (aStudy.getProgressState() == ProgressState.APPROVED) {
+                       aStudy.setMarkreference(1);
+                       aStudy.setProgressState(ProgressState.TEMPLATE);
+                       res = updateKnowledgeElementsState(aStudy);
+                       getStudyDAO().merge(aStudy);
+               }
+               return res;
        }
 
        /**
@@ -1157,9 +1145,9 @@ public class StudyServiceImpl implements StudyService {
         */
        @Transactional
        public void removeStudyAsReference(final Study aStudy) {
-
                aStudy.setMarkreference(0);
                aStudy.setProgressState(ProgressState.APPROVED);
+               updateKnowledgeElementsState(aStudy);
                getStudyDAO().merge(aStudy);
        }
 
@@ -1349,45 +1337,52 @@ public class StudyServiceImpl implements StudyService {
                } catch (DocumentException e) {
                        LOG.error("Sorry, the DocumentException is thrown.", e);
                }
-       
+
                return resultPath;
        }
-       
-       /** 
+
+       /**
         * {@inheritDoc}
+        * 
         * @see org.splat.service.StudyService#getReaders(long)
         */
        @Transactional(readOnly = true)
-       public List<UserDTO> getReaders(final long studyId) throws InvalidParameterException {
+       public List<UserDTO> getReaders(final long studyId)
+                       throws InvalidParameterException {
                Study aStudy = selectStudy(studyId);
-               if(aStudy == null){
-                       throw new InvalidParameterException(PARAM_STUDY_ID, String.valueOf(studyId));
+               if (aStudy == null) {
+                       throw new InvalidParameterException(PARAM_STUDY_ID, String
+                                       .valueOf(studyId));
                }
                List<Relation> relations = aStudy.getRelations(ReaderRelation.class);
                List<UserDTO> result = new ArrayList<UserDTO>();
-               for(Relation relation : relations){
+               for (Relation relation : relations) {
                        result.add(BeanHelper.copyBean(relation.getTo(), UserDTO.class));
                }
                return Collections.unmodifiableList(result);
        }
-       
-       /** 
+
+       /**
         * {@inheritDoc}
+        * 
         * @see org.splat.service.StudyService#addReader(long, long)
         */
        @Transactional
-       public boolean addReader(final long studyId, final long userId) throws InvalidParameterException {
+       public boolean addReader(final long studyId, final long userId)
+                       throws InvalidParameterException {
                Study aStudy = selectStudy(studyId);
-               if(aStudy == null){
-                       throw new InvalidParameterException(PARAM_STUDY_ID, String.valueOf(studyId));
+               if (aStudy == null) {
+                       throw new InvalidParameterException(PARAM_STUDY_ID, String
+                                       .valueOf(studyId));
                }
                User user = _userService.selectUser(userId);
-               if(user == null){
-                       throw new InvalidParameterException("userId", String.valueOf(userId));
+               if (user == null) {
+                       throw new InvalidParameterException("userId", String
+                                       .valueOf(userId));
                }
 
-               for(Relation relation : aStudy.getRelations(ReaderRelation.class)) {
-                       if(user.equals(relation.getTo())) {
+               for (Relation relation : aStudy.getRelations(ReaderRelation.class)) {
+                       if (user.equals(relation.getTo())) {
                                return false;
                        }
                }
@@ -1396,26 +1391,30 @@ public class StudyServiceImpl implements StudyService {
                return true;
        }
 
-       /** 
+       /**
         * {@inheritDoc}
+        * 
         * @see org.splat.service.StudyService#removeReader(long, long)
         */
        @Transactional
-       public boolean removeReader(final long studyId, final long userId) throws InvalidParameterException {
+       public boolean removeReader(final long studyId, final long userId)
+                       throws InvalidParameterException {
                Study aStudy = selectStudy(studyId);
-               if(aStudy == null){
-                       throw new InvalidParameterException(PARAM_STUDY_ID, String.valueOf(studyId));
+               if (aStudy == null) {
+                       throw new InvalidParameterException(PARAM_STUDY_ID, String
+                                       .valueOf(studyId));
                }
                User user = _userService.selectUser(userId);
-               if(user == null){
-                       throw new InvalidParameterException("userId", String.valueOf(userId));
+               if (user == null) {
+                       throw new InvalidParameterException("userId", String
+                                       .valueOf(userId));
                }
 
                Relation relation = aStudy.removeRelation(ReaderRelation.class, user);
                update(aStudy);
                return relation != null;
        }
-       
+
        /**
         * Get project settings.
         * 
@@ -1808,4 +1807,91 @@ public class StudyServiceImpl implements StudyService {
                _usedByRelationDAO = usedByRelationDAO;
        }
 
+       /**
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.StudyService#getStudyResultType(org.splat.dal.bo.som.Study)
+        */
+       @Override
+       @Transactional(readOnly = true)
+       public DocumentType getStudyResultType(final Study study) {
+               DetachedCriteria query = DetachedCriteria.forClass(DocumentType.class)
+                               .addOrder(Order.desc("result"));
+               return getDocumentTypeDAO().getFirstResult(query);
+       }
+
+       /**
+        * Get the documentTypeDAO.
+        * 
+        * @return the documentTypeDAO
+        */
+       public DocumentTypeDAO getDocumentTypeDAO() {
+               return _documentTypeDAO;
+       }
+
+       /**
+        * Set the documentTypeDAO.
+        * 
+        * @param documentTypeDAO
+        *            the documentTypeDAO to set
+        */
+       public void setDocumentTypeDAO(final DocumentTypeDAO documentTypeDAO) {
+               _documentTypeDAO = documentTypeDAO;
+       }
+
+       /**
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.StudyService#canBeApproved(org.splat.dal.bo.som.Study)
+        */
+       @Override
+       @Transactional(readOnly = true)
+       public boolean canBeApproved(final Study study) {
+               return resultDocsAtLeast(study, ProgressState.APPROVED);
+       }
+
+       /**
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.StudyService#canBePromoted(org.splat.dal.bo.som.Study)
+        */
+       @Override
+       @Transactional(readOnly = true)
+       public boolean canBePromoted(final Study study) {
+               return resultDocsAtLeast(study, ProgressState.inDRAFT);
+       }
+
+       /**
+        * {@inheritDoc}
+        * 
+        * @see org.splat.service.StudyService#canBeReviewed(org.splat.dal.bo.som.Study)
+        */
+       @Override
+       @Transactional(readOnly = true)
+       public boolean canBeReviewed(final Study study) {
+               return resultDocsAtLeast(study, ProgressState.inCHECK);
+       }
+
+       /**
+        * Check that all result documents of the study are at least in the given state.
+        * 
+        * @param study
+        *            the study to check
+        * @param state
+        *            the minimal acceptable state
+        * @return true if study result documents have acceptable states
+        */
+       private boolean resultDocsAtLeast(final Study study,
+                       final ProgressState state) {
+               boolean res = true;
+               // Check that all study result documents have the state APPROVED or more.
+               for (Publication pub : getProjectElementService().getLastStep(study)
+                               .getResultDocuments()) {
+                       res = pub.getProgressState().compareTo(ProgressState.APPROVED) >= 0;
+                       if (!res) {
+                               break;
+                       }
+               }
+               return res;
+       }
 }
index 73a295025098bbd920280acc44796b7f768794d2..cb2e3fc6f06fe465a8cf202767f63138710c1d18 100644 (file)
@@ -25,36 +25,64 @@ import org.splat.dal.bo.som.ValidationCycle;
 import org.splat.dal.bo.som.ValidationStep;
 import org.splat.dal.bo.som.VersionsRelation;
 import org.splat.service.ServiceLocatorImpl;
+import org.splat.service.StudyService;
 
+/**
+ * The class defining user rights to the document.
+ */
 public class DocumentRights {
 
+       /**
+        * The connected user.
+        */
        private transient final User _user;
+       /**
+        * The document publication.
+        */
        private transient Publication _operand;
+       /**
+        * The document validation cycle.
+        */
        private transient final ValidationCycle _cycle;
-       private transient boolean _isauthor; // True if the user is author of the document
+       /**
+        * True if the user is author of the document.
+        */
+       private final transient boolean _isauthor;
 
        // ==============================================================================================================================
        // Constructors
        // ==============================================================================================================================
 
+       /**
+        * The constructor.
+        * 
+        * @param user
+        *            the current user
+        * @param tag
+        *            the document publication
+        */
        public DocumentRights(final User user, final Publication tag) {
                this._user = user;
                this._operand = tag;
                // RKV this.cycle = operand.getOwnerStudy().getValidationCycleOf(operand.value().getType());
-               this._cycle = ServiceLocatorImpl.getInstance().getStudyService()
-                               .getValidationCycleOf(_operand.getOwnerStudy(),
-                                               _operand.value().getType());
+               this._cycle = getStudyService().getValidationCycleOf(
+                               _operand.getOwnerStudy(), _operand.value().getType());
                this._isauthor = _operand.value().getAuthor().equals(user);
                // TODO: all contributors of the given document (when supported) must also behave as author
        }
 
+       /**
+        * The constructor in the case when the user is an author of the document.
+        * 
+        * @param tag
+        *            the document publication
+        */
        protected DocumentRights(final Publication tag) {
                this._operand = tag;
                this._user = _operand.value().getAuthor();
                this._operand = tag;
-               this._cycle = ServiceLocatorImpl.getInstance().getStudyService()
-                               .getValidationCycleOf(_operand.getOwnerStudy(),
-                                               _operand.value().getType());
+               this._cycle = getStudyService().getValidationCycleOf(
+                               _operand.getOwnerStudy(), _operand.value().getType());
                this._isauthor = true; // In order to ignore the author state in the context of any user
                // TODO: all contributors of the given document (when supported) must also behave as author
        }
@@ -214,6 +242,9 @@ public class DocumentRights {
                User publisher = _cycle.getActor(ValidationStep.PROMOTION); // Null if the default users are involved
 
                if (_operand.getProgressState() != ProgressState.inWORK) {
+                       if (_operand.getProgressState() == ProgressState.inDRAFT) {
+                               return canReview();
+                       }
                        return false;
                }
                if (publisher == null) {
@@ -421,13 +452,12 @@ public class DocumentRights {
                                return true;
                        }
 
-               }
-               else if (state == ProgressState.EXTERN) { 
-                       if (_isauthor || _user.equals(manager)) { 
-                               return true; 
+               } else if (state == ProgressState.EXTERN) {
+                       if (_isauthor || _user.equals(manager)) {
+                               return true;
                        }
                }
-                        
+
                return false;
        }
 
@@ -443,4 +473,13 @@ public class DocumentRights {
        public Document getOperand() {
                return _operand.value();
        }
+
+       /**
+        * Get the study service.
+        * 
+        * @return the study service
+        */
+       private StudyService getStudyService() {
+               return ServiceLocatorImpl.getInstance().getStudyService();
+       }
 }
\ No newline at end of file
index d90863d02263a91b0bdd81e1726cea33a3f45306..049f88f9835e5e0ea34caab8560864e6ef68b01f 100644 (file)
@@ -1,4 +1,5 @@
 package org.splat.som;
+
 /**
  * Class defining the default rights related to operations on studies.
  * On the contrary of documents, a study cannot directly be reviewed or approved. It is reviewed or approved through
@@ -10,58 +11,103 @@ package org.splat.som;
 
 import org.splat.dal.bo.kernel.User;
 import org.splat.dal.bo.som.ProgressState;
+import org.splat.dal.bo.som.Publication;
 import org.splat.dal.bo.som.Study;
+import org.splat.dal.bo.som.ValidationCycle;
+import org.splat.dal.bo.som.ValidationStep;
 import org.splat.service.ServiceLocatorImpl;
+import org.splat.service.StudyService;
 
-
+/**
+ * The class representing user rights for a selected study.
+ */
 public class StudyRights {
 
-    private final transient User     _user;
-    private final transient Study    _operand;
-    private transient boolean  _author = false;                    // For optimizing 
-       public StudyRights (final User user, final Study study) {
-//  -------------------------------------------
-      this._user    = user;
-      this._operand = study;
-
-      if (_operand != null && _operand.getAuthor() != null) {
-         this._author  = _operand.getAuthor().equals(user);  // user may be null
-      }
-    }
-    public StudyRights (final Study study) {
-//  --------------------------------
-      this._user    = study.getAuthor();
-      this._operand = study;
-      this._author  = true;                              // In order to ignore the author in this context
-    }
-
-//  ==============================================================================================================================
-//  Public member functions
-//  ==============================================================================================================================
-
-    public boolean canAddScenario () {
-//  --------------------------------
-      if (_operand.getProgressState() != ProgressState.inWORK && _operand.getProgressState() != ProgressState.inDRAFT) {
-               return false;
-       }
-      return ServiceLocatorImpl.getInstance().getStudyService().isStaffedBy(_operand, _user);
-    }
+       /**
+        * The connected user.
+        */
+       private final transient User _user;
+       /**
+        * The selected study.
+        */
+       private final transient Study _operand;
+       /**
+        * True if the current user is the author of the selected study.
+        */
+       private transient boolean _isauthor = false; // For optimizing
+       /**
+        * The study validation cycle according to the validation cycle of a study result document.
+        */
+       private transient final ValidationCycle _cycle;
 
-/**
- * Checks if the user has right to edit the description of the study.
- * All actors of the study have such right, including the author, contributors, reviewers and approvers.
- * 
- * @return true if the user has right to edit the description.
- */
-    public boolean canEditDescription () {
-//  ------------------------------------
-      return (_operand.getAuthor().equals(_user) || ServiceLocatorImpl.getInstance().getStudyService().hasActor(_operand, _user));
-    }
+       /**
+        * The constructor.
+        * 
+        * @param user
+        *            the current user
+        * @param study
+        *            the selected study
+        */
+       public StudyRights(final User user, final Study study) {
+               this._user = user;
+               this._operand = study;
+               this._cycle = getStudyService().getValidationCycleOf(_operand,
+                               getStudyService().getStudyResultType(_operand));
+
+               if (_operand != null && _operand.getAuthor() != null) {
+                       this._isauthor = _operand.getAuthor().equals(user); // user may be null
+               }
+       }
+
+       /**
+        * The constructor for the case when the user is the author of the study.
+        * 
+        * @param study
+        *            the selected study
+        */
+       public StudyRights(final Study study) {
+               this._user = study.getAuthor();
+               this._operand = study;
+               this._isauthor = true; // In order to ignore the author in this context
+               this._cycle = getStudyService().getValidationCycleOf(_operand,
+                               getStudyService().getStudyResultType(_operand));
+       }
+
+       // ==============================================================================================================================
+       // Public member functions
+       // ==============================================================================================================================
+
+       /**
+        * Check if the user can add a new scenario to the study.
+        * 
+        * @return true if the user can add a new scenario to the study
+        */
+       public boolean canAddScenario() {
+               return (_operand.getProgressState() == ProgressState.inWORK || _operand
+                               .getProgressState() == ProgressState.inDRAFT)
+                               && getStudyService().isStaffedBy(_operand, _user);
+       }
+
+       /**
+        * Checks if the user has right to edit the description of the study. <BR>
+        * All actors of the study have such right, including the author, contributors,<BR>
+        * reviewers and approvers.
+        * 
+        * @return true if the user has right to edit the description.
+        */
+       public boolean canEditDescription() {
+               return (_operand.getAuthor().equals(_user) || getStudyService()
+                               .hasActor(_operand, _user));
+       }
 
-    public boolean canEditProperties () {
-//  -----------------------------------
-      return _author;
-    }
+       /**
+        * Check if the user can configure the study.
+        * 
+        * @return true if the user can configure the study.
+        */
+       public boolean canEditProperties() {
+               return _isauthor;
+       }
 
        /**
         * Checks if the user has right to move the study from the Private to the Public area of the repository. Only the author of the study
@@ -70,12 +116,8 @@ public class StudyRights {
         * @return true if the user has right to edit the description.
         */
        public boolean canPublish() {
-               // ----------------------------
-               if (_operand.getProgressState() == ProgressState.APPROVED
-                               && !_operand.isPublic()/* && "knowledgineer".equals(_user.getRole().getName()) */) {
-                       return true;
-               }
-               return false;
+               return (_operand.getProgressState() == ProgressState.APPROVED && !_operand
+                               .isPublic()/* && "knowledgineer".equals(_user.getRole().getName()) */);
        }
 
        /**
@@ -85,68 +127,190 @@ public class StudyRights {
         * @return true if the user has right to edit the description.
         */
        public boolean canProtect() {
-               // ----------------------------
-               if (_operand.getProgressState() == ProgressState.APPROVED
-                               && _operand.isPublic()/* && "knowledgineer".equals(_user.getRole().getName()) */) {
-                       return true;
+               return (_operand.getProgressState() == ProgressState.APPROVED && _operand
+                               .isPublic()/* && "knowledgineer".equals(_user.getRole().getName()) */);
+       }
+
+       /**
+        * Check if the user can remove old versions.
+        * 
+        * @return true if the user can remove old versions
+        */
+       public boolean canPurge() {
+               return (_isauthor && _operand.isVersioned());
+       }
+
+       /**
+        * Check if the user can remove the study.
+        * 
+        * @return true if the user can remove the study
+        */
+       public boolean canRemove() {
+               return (_operand.getProgressState() == ProgressState.inWORK || _operand
+                               .getProgressState() == ProgressState.inDRAFT)
+                               && _isauthor;
+       }
+
+       /**
+        * Check if the user can version the study.
+        * 
+        * @return true if the user can version the study
+        */
+       public boolean canVersion() {
+               return (_operand.getProgressState() == ProgressState.inWORK || _operand
+                               .getProgressState() == ProgressState.inDRAFT)
+                               && getStudyService().isStaffedBy(_operand, _user);
+       }
+
+       /**
+        * Can the given study be marked as reference or not.
+        * 
+        * @return true/false.
+        */
+       public boolean canMarkStudyAsReference() {
+               return (_operand.getProgressState() == ProgressState.APPROVED /* && "knowledgineer".equals(_user.getRole().getName()) */);
+       }
+
+       /**
+        * Can the given study be unmarked as reference or not.
+        * 
+        * @return true/false.
+        */
+       public boolean canRemoveStudyAsReference() {
+               return (_operand.getProgressState() == ProgressState.TEMPLATE /* && "knowledgineer".equals(_user.getRole().getName()) */);
+       }
+
+       // ==========================================================================
+       // Operations from document validation cycle
+       // ==========================================================================
+
+       /**
+        * Checks if the user has right to approve the selected document. Only the approver of the type of selected document has such right,
+        * providing that the document is candidate for approval and all document dependencies have already been approved.
+        * 
+        * @return true if the user has right to approve the document.
+        * @see Publication#approve()
+        * @see ValidationCycle
+        */
+       public boolean canApprove() {
+               User approver = _cycle.getActor(ValidationStep.APPROVAL); // May be null if not approvable
+               return (_user.equals(approver))
+                               && getStudyService().canBeApproved(_operand);
+       }
+
+       /**
+        * Checks if the user has right to demote the selected document. A document can be demoted providing that it is In-Draft or In-Check and
+        * all documents using it have previously been demoted. In-Draft documents can be demoted by default by both, the author of the document
+        * and the responsible of study, while documents in approval process can be demoted by their approver only.
+        * 
+        * @return true if the user has right to demote the document.
+        * @see #canInvalidate()
+        * @see #canPromote()
+        * @see Publication#demote()
+        * @see ValidationCycle
+        */
+       public boolean canDemote() {
+               User manager = _operand.getOwnerStudy().getAuthor();
+               User publisher = _cycle.getActor(ValidationStep.PROMOTION); // Null if the default users are involved
+               User reviewer = _cycle.getActor(ValidationStep.REVIEW); // May be null if not reviewable
+               User approver = _cycle.getActor(ValidationStep.APPROVAL); // May be null if not approvable
+               ProgressState mystate = _operand.getProgressState();
+
+               if (mystate == ProgressState.inDRAFT) {
+                       if (publisher == null) {
+                               if ((!_isauthor) && (!_user.equals(manager))
+                                               && (!_user.equals(reviewer))) {
+                                       return false;
+                               }
+                       } else if ((!_user.equals(publisher)) && (!_user.equals(reviewer))) {
+                               return false;
+                       }
+               } else if (mystate == ProgressState.inCHECK) {
+                       if (!_user.equals(approver)) {
+                               return false;
+                       }
+               } else {
+                       return false;
                }
-               return false;
-       }
-
-    public boolean canPurge () {
-//  --------------------------
-      if (!_author) {
-               return false;
-       }
-      return _operand.isVersioned();
-    }
-
-    public boolean canRemove () {
-//  ---------------------------
-      if (_operand.getProgressState() != ProgressState.inWORK && _operand.getProgressState() != ProgressState.inDRAFT) {
-               return false;
-       }
-      return _author;
-    }
-
-    public boolean canVersion () {
-//  ----------------------------
-      if (_operand.getProgressState() != ProgressState.inWORK && _operand.getProgressState() != ProgressState.inDRAFT) {
-               return false;
-       }
-      return ServiceLocatorImpl.getInstance().getStudyService().isStaffedBy(_operand, _user);
-    }
-    
-    /**
-     * Can the given study be marked as reference or not.
-     * @return true/false.
-     */
-    public boolean canMarkStudyAsReference() {
-       
-       if (_operand.getProgressState() == ProgressState.APPROVED /*&& "knowledgineer".equals(_user.getRole().getName())*/) {
-               return true;
-       }
-       return false;
-    }
-    
-    /**
-     * Can the given study be unmarked as reference or not.
-     * @return true/false.
-     */
-    public boolean canRemoveStudyAsReference() {
-       
-       if (_operand.getProgressState() == ProgressState.TEMPLATE /*&& "knowledgineer".equals(_user.getRole().getName())*/) {
-               return true;
-       }
-       return false;
-    }
-
-//  ==============================================================================================================================
-//  Getter
-//  ==============================================================================================================================
-
-    public Study getOperand () {
-//  --------------------------
-      return _operand;
-    }
+
+               return true;
+       }
+
+       /**
+        * Checks if the user has right to promote the selected document. A document can be promoted providing that it is In-Work and all its
+        * dependencies have previously been promoted. By default, both the author of the document and the responsible of study has right to
+        * promote such document. Otherwise, only the user involved in the Promotion step of validation cycle of the selected document has such
+        * right.
+        * 
+        * @return true if the user has right to promote the document.
+        * @see #canDemote()
+        * @see Publication#promote()
+        * @see ValidationCycle
+        */
+       public boolean canPromote() {
+               User manager = _operand.getOwnerStudy().getAuthor();
+               User publisher = _cycle.getActor(ValidationStep.PROMOTION); // Null if the default users are involved
+
+               if (_operand.getProgressState() != ProgressState.inWORK) {
+                       if (_operand.getProgressState() == ProgressState.inDRAFT) {
+                               return canReview();
+                       }
+                       return false;
+               }
+               if (publisher == null) {
+                       if (!_isauthor && !_user.equals(manager)) {
+                               return false;
+                       }
+               } else {
+                       if (!_user.equals(publisher)) {
+                               return false;
+                       }
+               }
+               return getStudyService().canBePromoted(_operand);
+       }
+
+       /**
+        * Checks if the user has right to validate the selected document. Only the reviewer of the type of selected document has such right,
+        * providing that the document is being reviewed and all document dependencies have already been validated.
+        * 
+        * @return true if the user has right to validate the document
+        * @see #canUnvalidate()
+        * @see Publication#review()
+        * @see ValidationCycle
+        */
+       public boolean canReview() {
+               User reviewer = _cycle.getActor(ValidationStep.REVIEW); // May be null if not reviewable
+
+               if (!_user.equals(reviewer)) {
+                       return false;
+               }
+               if (_operand.getProgressState() != ProgressState.inDRAFT) {
+                       return false;
+               }
+
+               return getStudyService().canBeReviewed(_operand);
+       }
+
+       // ==============================================================================================================================
+       // Getter
+       // ==============================================================================================================================
+
+       /**
+        * Get the selected study.
+        * 
+        * @return the selected study
+        */
+       public Study getOperand() {
+               return _operand;
+       }
+
+       /**
+        * Get the study service.
+        * 
+        * @return the study service
+        */
+       private StudyService getStudyService() {
+               return ServiceLocatorImpl.getInstance().getStudyService();
+       }
+
 }
\ No newline at end of file
index 8c62f8c18a3d6ae377f8dcf769f8d21e0ff1c990..b27d984d7476772a08419bb728c9f116783d80fe 100644 (file)
@@ -150,6 +150,7 @@ http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
 
        <bean id="studyService"
                class="org.splat.service.StudyServiceImpl">
+        <property name="documentTypeDAO" ref="documentTypeDAO" />
                <property name="indexService" ref="indexService" />
                <property name="projectElementService"
                        ref="projectElementService" />
index eaf2630c0697a84ea21f065f68666b9057f3799e..8b310a4dc9f1d4264c1e5c80208f7f288c2e0bbd 100644 (file)
@@ -276,6 +276,11 @@ message.noindex           = Aucune 
 message.nocontext         = Aucun contexte de simulation n''est en attente d''approbation.
 message.emptydocument     = Aucun document n''a été créé à cette étape.
 message.accept.document   = Voulez-vous accepter les modifications des documents utilisés ?
+message.promote.study     = Voulez-vous avancer l&#146;état de cette étude ?
+message.review.study      = Voulez-vous valider cette étude ?
+message.demote.study      = Voulez-vous reculer l&#146;état de cette étude ?
+message.disapprove.study  = Voulez-vous vraiment refuser l'approbation de cette étude?
+message.approve.study     = All knowledge attached to the study will also be approved. Did you review these knowledge ?
 message.publish.study     = All knowledge attached to the study will also be published. Did you review these knowledge ?
 message.protect.study     = Do you really want to protect the study ?
 message.promote.document  = Voulez-vous promouvoir ce document ?
index 3f2c96e8caadb1710a7a14036421b2997cf64fbf..e4f035cf9d276224d6dbe3b6b5c97edc51ebcbdb 100644 (file)
@@ -277,6 +277,11 @@ message.noindex           = All existing studies are already indexed.
 message.nocontext         = No simulation context is pending for approval.
 message.emptydocument     = No document has been created at this step.
 message.accept.document   = Do you really want to accept the modifications of dependent documents ?
+message.promote.study     = Do you really want to promote this study ?
+message.review.study      = Do you really want to validate this study ?
+message.demote.study      = Do you really want to demote this study ?
+message.disapprove.study  = Do you really want to refuse approval of this study ?
+message.approve.study     = All knowledge attached to the study will also be approved. Did you review these knowledge ?
 message.publish.study     = All knowledge attached to the study will also be published. Did you review these knowledge ?
 message.protect.study     = Do you really want to protect the study ?
 message.promote.document  = Do you really want to promote this document ?
index 6fb1c238eb52d1491f7ab0d385370184facfbb9d..b1772117fd199adda2e85015795f1e3a24b3a88c 100644 (file)
@@ -148,6 +148,15 @@ public class ApplicationSettings {
         * Delete icon file name.
         */
        private static final String IMG_DELETE = "icon.delete.png";
+       /**
+        * Promote icon file name.
+        */
+       private static final String IMG_PROMOTE = "image.publish.png";
+       /**
+        * Demote icon file name.
+        */
+       private static final String IMG_DEMOTE = "image.demote.png";
+       
        /**
         * Attach menu item name.
         */
@@ -269,7 +278,11 @@ public class ApplicationSettings {
         * Remove as reference action name.
         */
        private static final String ACT_REMOVE_AS_REFERENCE = "removeasref-study";
-
+       /**
+        * Promote the study action name.
+        */
+       private static final String ACT_PROMOTE_STUDY = "edit-study?action=promote";
+       
        /**
         * Siman application server name.
         */
@@ -505,51 +518,18 @@ public class ApplicationSettings {
 
        // Resources relative to studies
        /**
-        * Study popup menu.
+        * Base study popup menu.
         */
-       private static class EditableMarkedStudyPopup extends PopupMenu {
+       private static class StudyPopup extends PopupMenu {
                /**
                 * User rights for the selected study.
                 */
-               private transient StudyRights _user = null;
+               protected transient StudyRights _user = null;
 
                /**
-                * Study popup menu constructor.
-                * 
-                * @param isPublic
-                *            public study flag
-                * @param isMarked
-                *            "marked as reference" study flag
+                * Add items which are common for all study popup menus.
                 */
-               private EditableMarkedStudyPopup(final boolean isPublic,
-                               final boolean isMarked) {
-                       super();
-
-                       if (isMarked) {
-                               addItem(MNU_MARK_AS_REFERENCE, new PopupItem(
-                                               MNU_NAME_REMOVE_AS_REFERENCE).action(
-                                               ACT_REMOVE_AS_REFERENCE).confirmation(
-                                               "message.removeasreference.study"));
-                       } else {
-                               addItem(MNU_MARK_AS_REFERENCE, new PopupItem(
-                                               MNU_NAME_MARK_AS_REFERENCE).action(
-                                               ACT_MARK_AS_REFERENCE).confirmation(
-                                               "message.markasreference.study"));
-                       }
-
-                       if (isPublic) {
-                               addItem(MNU_PUBLISH, new PopupItem(MNU_NAME_PROTECT).icon(
-                                               "image.publish.png")
-                                               .action("edit-study?action=protect").confirmation(
-                                                               "message.protect.study"));
-                       } else {
-                               addItem(MNU_PUBLISH, new PopupItem(MNU_NAME_PUBLISH).icon(
-                                               "image.publish.png")
-                                               .action("edit-study?action=publish").confirmation(
-                                                               "message.publish.study"));
-                       }
-
-                       /* addItem(MNU_PROMOTE, new PopupItem("menu.archive")); */
+               protected void addCommonItems() {
                        addSeparator();
                        addItem(MNU_EDIT, new PopupItem("menu.properties").icon(
                                        "icon.ed.png").action(
@@ -599,9 +579,15 @@ public class ApplicationSettings {
                                        case remove:
                                                res = _user.canRemove();
                                                break;
-                                       /*
-                                        * case purge: res = _user.canPurge(); break;
-                                        */
+                                       case promote:
+                                               res = _user.canPromote();
+                                               break;
+                                       case demote:
+                                               res = _user.canDemote();
+                                               break;
+                                       case approve:
+                                               res = _user.canApprove();
+                                               break;
                                        case markasreference:
                                                if (_user.getOperand().getMarkreference() == 0) {
                                                        res = _user.canMarkStudyAsReference();
@@ -636,6 +622,116 @@ public class ApplicationSettings {
                }
        }
 
+       /**
+        * Approved study popup menu.
+        */
+       private static class EditableMarkedStudyPopup extends StudyPopup {
+
+               /**
+                * Study popup menu constructor.
+                * 
+                * @param isPublic
+                *            public study flag
+                * @param isMarked
+                *            "marked as reference" study flag
+                */
+               private EditableMarkedStudyPopup(final boolean isPublic,
+                               final boolean isMarked) {
+                       super();
+
+                       if (isMarked) {
+                               addItem(MNU_MARK_AS_REFERENCE, new PopupItem(
+                                               MNU_NAME_REMOVE_AS_REFERENCE).action(
+                                               ACT_REMOVE_AS_REFERENCE).confirmation(
+                                               "message.removeasreference.study"));
+                       } else {
+                               addItem(MNU_MARK_AS_REFERENCE, new PopupItem(
+                                               MNU_NAME_MARK_AS_REFERENCE).action(
+                                               ACT_MARK_AS_REFERENCE).confirmation(
+                                               "message.markasreference.study"));
+                       }
+
+                       if (isPublic) {
+                               addItem(MNU_PUBLISH, new PopupItem(MNU_NAME_PROTECT).icon(
+                                               IMG_PROMOTE)
+                                               .action("edit-study?action=protect").confirmation(
+                                                               "message.protect.study"));
+                       } else {
+                               addItem(MNU_PUBLISH, new PopupItem(MNU_NAME_PUBLISH).icon(
+                                               IMG_PROMOTE)
+                                               .action("edit-study?action=publish").confirmation(
+                                                               "message.publish.study"));
+                       }
+
+                       addCommonItems();
+               }
+
+       }
+
+       /**
+        * In-Work study popup menu.
+        */
+       private static class EditableStudyPopup extends StudyPopup {
+               /**
+                * Study popup menu constructor.
+                */
+               private EditableStudyPopup() {
+                       super();
+
+                       addItem(MNU_PROMOTE, new PopupItem(MNU_NAME_PROMOTE).icon(
+                                       IMG_PROMOTE).action(ACT_PROMOTE_STUDY)
+                                       .confirmation("message.promote.study"));
+
+                       addCommonItems();
+               }
+       }
+
+       /**
+        * In-Work study popup menu.
+        */
+       private static class ReviewableStudyPopup extends StudyPopup {
+               /**
+                * Study popup menu constructor.
+                */
+               private ReviewableStudyPopup() {
+                       super();
+
+                       addItem(MNU_DEMOTE, new PopupItem(MNU_NAME_DEMOTE).icon(
+                                       IMG_DEMOTE).action("edit-study?action=demote")
+                                       .confirmation("message.demote.study"));
+                       addItem(MNU_PROMOTE, new PopupItem("menu.review").icon(
+                                       "image.review.png").action(ACT_PROMOTE_STUDY)
+                                       .confirmation("message.review.study"));
+
+                       addCommonItems();
+               }
+       }
+
+       /**
+        * In-Work study popup menu.
+        */
+       private static class ApprovableStudyPopup extends StudyPopup {
+               /**
+                * Study popup menu constructor.
+                */
+               private ApprovableStudyPopup() {
+                       super();
+
+                       addItem(MNU_PROMOTE, new PopupItem(MNU_NAME_PROMOTE).icon(
+                                       IMG_PROMOTE).action(ACT_PROMOTE_STUDY)
+                                       .confirmation("message.promote.study"));
+                       // Refuse
+                       addItem(MNU_DEMOTE, new PopupItem("menu.disapprove").icon(
+                                       IMG_DEMOTE).action("edit-study?action=demote")
+                                       .confirmation("message.disapprove.study"));
+                       addItem("approve", new PopupItem("menu.approve").icon(
+                                       "icon.APPROVED.png").action(ACT_PROMOTE_STUDY)
+                                       .confirmation("message.approve.study"));
+
+                       addCommonItems();
+               }
+       }
+
        // Resources relative to documents
        /**
         * Popup of a document.
@@ -735,7 +831,7 @@ public class ApplicationSettings {
                         * .confirmation("message.accept.document"));
                         */
                        addItem(MNU_PROMOTE, new PopupItem(MNU_NAME_PROMOTE).icon(
-                                       "image.publish.png").action("setDocument?action=promote")
+                                       IMG_PROMOTE).action("setDocument?action=promote")
                                        .confirmation("message.promote.document"));
                        addSeparator();
                        addItem(MNU_RENAME, new PopupItem(MNU_NAME_RENAME)
@@ -768,7 +864,7 @@ public class ApplicationSettings {
                private ReviewableDocumentPopup() {
                        super();
                        addItem(MNU_DEMOTE, new PopupItem(MNU_NAME_DEMOTE).icon(
-                                       "image.demote.png").action("setDocument?action=demote")
+                                       IMG_DEMOTE).action("setDocument?action=demote")
                                        .confirmation("message.demote.document"));
                        addItem(MNU_PROMOTE, new PopupItem("menu.review").icon(
                                        "image.review.png").action("setDocument?action=review")
@@ -796,7 +892,7 @@ public class ApplicationSettings {
                private NotResultDocumentPopup() {
                        super();
                        addItem(MNU_DEMOTE, new PopupItem(MNU_NAME_DEMOTE).icon(
-                                       "image.demote.png").action("setDocument?action=demote")
+                                       IMG_DEMOTE).action("setDocument?action=demote")
                                        .confirmation("message.demote.document"));
                        addSeparator();
                        addItem(MNU_ATTACH, new PopupItem(MNU_NAME_ATTACH).icon(IMG_ATTACH)
@@ -828,7 +924,7 @@ public class ApplicationSettings {
                                        "setDocument?action=invalidate").confirmation(
                                        "message.demote.document"));
                        addItem(MNU_DEMOTE, new PopupItem("menu.disapprove").icon(
-                                       "image.demote.png").action("setDocument?action=disapprove")
+                                       IMG_DEMOTE).action("setDocument?action=disapprove")
                                        .confirmation("message.disapprove.document"));
                        addItem("approve", new PopupItem("menu.approve").icon(
                                        "icon.APPROVED.png").action("setDocument?action=approve")
@@ -1080,6 +1176,10 @@ public class ApplicationSettings {
                                false));
                _popups.put("steditableunmarkprivate", new EditableMarkedStudyPopup(
                                true, true));
+               _popups.put("steditable", new EditableStudyPopup());
+               _popups.put("streviewable", new ReviewableStudyPopup());
+               _popups.put("stapprovable", new ApprovableStudyPopup());
+
                _popups.put("editable", new EditableDocumentPopup());
                _popups.put("notresult", new NotResultDocumentPopup());
                _popups.put("reviewable", new ReviewableDocumentPopup());
index c666c042fb0f273dcf44f7937623408ee61993de..73c5c95f364bd76734e69447a4096823aee117e3 100644 (file)
@@ -9,14 +9,37 @@ public class EditStudyAction extends DisplayStudyStepAction {
         */
        private static final long serialVersionUID = -4865668290514118396L;
 
+       /**
+        * Possible operations on a study.
+        */
        private enum Execute {
-               publish, protect, promote
+               /**
+                * Publish a study.
+                */
+               publish,
+               /**
+                * Make published study private.
+                */
+               protect,
+               /**
+                * Promote a study to the next state.
+                */
+               promote,
+               /**
+                * Demote a study from In-Draft or In-Check to In-Work.
+                */
+               demote
        }
 
-       // ==============================================================================================================================
+       // =========================================================================
        // Action methods
-       // ==============================================================================================================================
+       // =========================================================================
 
+       /**
+        * Perform operation on the selected study.
+        * 
+        * @return SUCCESS
+        */
        public String doEdition() {
                _openStudy = getOpenStudy();
 
@@ -28,48 +51,53 @@ public class EditStudyAction extends DisplayStudyStepAction {
                } else if (todo == Execute.protect) {
                        getStudyService().moveToPrivate(study);
                } else if (todo == Execute.promote) {
-                       getStudyService().moveToReference(study);
+                       getStudyService().promote(study);
+               } else if (todo == Execute.demote) {
+                       getStudyService().demote(study);
                }
+//             _openStudy.getMenu().refreshSelectedItem(); // Updates the menu icon, in case of other documents in approved state
                _openStudy.getPopup().setContext("study", _openStudy.getStudyRights()); // The context has changed
 
                setMenu();
 
                _myindex = null;
-               _selection = _openStudy.getSelection(); //actually, value doesn't matter, it just has to be not null
+               _selection = _openStudy.getSelection(); // actually, value doesn't matter, it just has to be not null
                doOpen();
                return SUCCESS;
        }
-       
+
        /**
         * Mark study as reference functionality.
+        * 
         * @return SUCCESS
         */
        public String doMarkAsReference() {
-               
+
                _openStudy = getOpenStudy();
                Study study = _openStudy.getStudyObject();
-               
+
                getStudyService().markStudyAsReference(study);
 
                _myindex = null;
-               _selection = _openStudy.getSelection(); //actually, value doesn't matter, it just has to be not null
+               _selection = _openStudy.getSelection(); // actually, value doesn't matter, it just has to be not null
                doOpen();
                return SUCCESS;
        }
-       
+
        /**
         * Remove study as reference functionality.
+        * 
         * @return SUCCESS
         */
        public String doRemoveAsReference() {
-               
+
                _openStudy = getOpenStudy();
                Study study = _openStudy.getStudyObject();
-               
+
                getStudyService().removeStudyAsReference(study);
 
                _myindex = null;
-               _selection = _openStudy.getSelection(); //actually, value doesn't matter, it just has to be not null
+               _selection = _openStudy.getSelection(); // actually, value doesn't matter, it just has to be not null
                doOpen();
                return SUCCESS;
        }
index 420ac861a7ca2db66265fdef93ae2a00153a9cf4..e6190801bf1d92edd4f670094ac5fc78ea7cc00d 100644 (file)
@@ -152,8 +152,19 @@ public class OpenStudy extends AbstractOpenObject implements OpenStudyServices {
                                        _popup = getApplicationSettings().getPopupMenu(
                                                        "steditablemarkprivate");
                                } else {
-                                       _popup = getApplicationSettings().getPopupMenu(
-                                                       "steditablemarkpublic");
+                                       if (_mystudy.getProgressState() == ProgressState.inWORK) {
+                                               _popup = getApplicationSettings().getPopupMenu(
+                                                               "steditable");
+                                       } else if (_mystudy.getProgressState() == ProgressState.inDRAFT) {
+                                               _popup = getApplicationSettings().getPopupMenu(
+                                                               "streviewable");
+                                       } else if (_mystudy.getProgressState() == ProgressState.inCHECK) {
+                                               _popup = getApplicationSettings().getPopupMenu(
+                                                               "stapprovable");
+                                       } else { // APPROVED
+                                               _popup = getApplicationSettings().getPopupMenu(
+                                                               "steditablemarkpublic");
+                                       }
                                }
 
                        }