From eb90d68aafe1fbc1307dd1121500a97ffd940d21 Mon Sep 17 00:00:00 2001 From: rkv Date: Fri, 12 Apr 2013 14:32:00 +0000 Subject: [PATCH] Study validation cycle operations are implemented according to the specification. --- .../dao/kernel/AbstractGenericDAOImpl.java | 13 + .../org/splat/dal/dao/kernel/GenericDAO.java | 9 + .../splat/service/ProjectElementService.java | 9 + .../service/ProjectElementServiceImpl.java | 4 + .../splat/service/PublicationServiceImpl.java | 42 +- .../src/org/splat/service/StudyService.java | 128 ++++-- .../org/splat/service/StudyServiceImpl.java | 334 +++++++++------ .../src/org/splat/som/DocumentRights.java | 63 ++- .../src/org/splat/som/StudyRights.java | 392 +++++++++++++----- .../src/spring/businessServiceContext.xml | 1 + Workspace/Siman/src/labels.properties | 5 + Workspace/Siman/src/labels_en.properties | 5 + .../org/splat/simer/ApplicationSettings.java | 192 +++++++-- .../src/org/splat/simer/EditStudyAction.java | 54 ++- .../Siman/src/org/splat/simer/OpenStudy.java | 15 +- 15 files changed, 890 insertions(+), 376 deletions(-) diff --git a/Workspace/Siman-Common/src/org/splat/dal/dao/kernel/AbstractGenericDAOImpl.java b/Workspace/Siman-Common/src/org/splat/dal/dao/kernel/AbstractGenericDAOImpl.java index 778ac11..83405d9 100644 --- a/Workspace/Siman-Common/src/org/splat/dal/dao/kernel/AbstractGenericDAOImpl.java +++ b/Workspace/Siman-Common/src/org/splat/dal/dao/kernel/AbstractGenericDAOImpl.java @@ -143,6 +143,19 @@ public abstract class AbstractGenericDAOImpl 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. * diff --git a/Workspace/Siman-Common/src/org/splat/dal/dao/kernel/GenericDAO.java b/Workspace/Siman-Common/src/org/splat/dal/dao/kernel/GenericDAO.java index 477ab48..6a45c1e 100644 --- a/Workspace/Siman-Common/src/org/splat/dal/dao/kernel/GenericDAO.java +++ b/Workspace/Siman-Common/src/org/splat/dal/dao/kernel/GenericDAO.java @@ -155,6 +155,15 @@ public interface GenericDAO { */ public List 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. * diff --git a/Workspace/Siman-Common/src/org/splat/service/ProjectElementService.java b/Workspace/Siman-Common/src/org/splat/service/ProjectElementService.java index 7227031..214af66 100644 --- a/Workspace/Siman-Common/src/org/splat/service/ProjectElementService.java +++ b/Workspace/Siman-Common/src/org/splat/service/ProjectElementService.java @@ -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. * diff --git a/Workspace/Siman-Common/src/org/splat/service/ProjectElementServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/ProjectElementServiceImpl.java index d01bdd6..7de02b2 100644 --- a/Workspace/Siman-Common/src/org/splat/service/ProjectElementServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/ProjectElementServiceImpl.java @@ -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]; diff --git a/Workspace/Siman-Common/src/org/splat/service/PublicationServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/PublicationServiceImpl.java index e2693f6..119a4fc 100644 --- a/Workspace/Siman-Common/src/org/splat/service/PublicationServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/PublicationServiceImpl.java @@ -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 diff --git a/Workspace/Siman-Common/src/org/splat/service/StudyService.java b/Workspace/Siman-Common/src/org/splat/service/StudyService.java index 73d498d..7185cef 100644 --- a/Workspace/Siman-Common/src/org/splat/service/StudyService.java +++ b/Workspace/Siman-Common/src/org/splat/service/StudyService.java @@ -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
+ * states. This function takes into account statuses of final result
+ * 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 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. - *
DocumentDto.id are actually filled in with Publication ids. - * @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.
+ * DocumentDto.id are actually filled in with Publication ids. + * + * @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 getComparableStudies(final long userId) throws MismatchException; - + List 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 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 getReaders(final long studyId) throws InvalidParameterException; - + List 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; } diff --git a/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java index d75d3cc..86863e9 100644 --- a/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java @@ -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 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 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 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
+ * states. This function takes into account statuses of final result
+ * 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 getReaders(final long studyId) throws InvalidParameterException { + public List 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 relations = aStudy.getRelations(ReaderRelation.class); List result = new ArrayList(); - 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; + } } diff --git a/Workspace/Siman-Common/src/org/splat/som/DocumentRights.java b/Workspace/Siman-Common/src/org/splat/som/DocumentRights.java index 73a2950..cb2e3fc 100644 --- a/Workspace/Siman-Common/src/org/splat/som/DocumentRights.java +++ b/Workspace/Siman-Common/src/org/splat/som/DocumentRights.java @@ -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 diff --git a/Workspace/Siman-Common/src/org/splat/som/StudyRights.java b/Workspace/Siman-Common/src/org/splat/som/StudyRights.java index d90863d..049f88f 100644 --- a/Workspace/Siman-Common/src/org/splat/som/StudyRights.java +++ b/Workspace/Siman-Common/src/org/splat/som/StudyRights.java @@ -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.
+ * 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) || 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 diff --git a/Workspace/Siman-Common/src/spring/businessServiceContext.xml b/Workspace/Siman-Common/src/spring/businessServiceContext.xml index 8c62f8c..b27d984 100644 --- a/Workspace/Siman-Common/src/spring/businessServiceContext.xml +++ b/Workspace/Siman-Common/src/spring/businessServiceContext.xml @@ -150,6 +150,7 @@ http://www.springframework.org/schema/tx/spring-tx-3.0.xsd"> + diff --git a/Workspace/Siman/src/labels.properties b/Workspace/Siman/src/labels.properties index eaf2630..8b310a4 100644 --- a/Workspace/Siman/src/labels.properties +++ b/Workspace/Siman/src/labels.properties @@ -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’état de cette étude ? +message.review.study = Voulez-vous valider cette étude ? +message.demote.study = Voulez-vous reculer l’é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 ? diff --git a/Workspace/Siman/src/labels_en.properties b/Workspace/Siman/src/labels_en.properties index 3f2c96e..e4f035c 100644 --- a/Workspace/Siman/src/labels_en.properties +++ b/Workspace/Siman/src/labels_en.properties @@ -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 ? diff --git a/Workspace/Siman/src/org/splat/simer/ApplicationSettings.java b/Workspace/Siman/src/org/splat/simer/ApplicationSettings.java index 6fb1c23..b177211 100644 --- a/Workspace/Siman/src/org/splat/simer/ApplicationSettings.java +++ b/Workspace/Siman/src/org/splat/simer/ApplicationSettings.java @@ -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()); diff --git a/Workspace/Siman/src/org/splat/simer/EditStudyAction.java b/Workspace/Siman/src/org/splat/simer/EditStudyAction.java index c666c04..73c5c95 100644 --- a/Workspace/Siman/src/org/splat/simer/EditStudyAction.java +++ b/Workspace/Siman/src/org/splat/simer/EditStudyAction.java @@ -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; } diff --git a/Workspace/Siman/src/org/splat/simer/OpenStudy.java b/Workspace/Siman/src/org/splat/simer/OpenStudy.java index 420ac86..e619080 100644 --- a/Workspace/Siman/src/org/splat/simer/OpenStudy.java +++ b/Workspace/Siman/src/org/splat/simer/OpenStudy.java @@ -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"); + } } } -- 2.30.2