X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=Workspace%2FSiman-Common%2Fsrc%2Forg%2Fsplat%2Fservice%2FStudyServiceImpl.java;h=0d133d13705e5d41a4728ec67d398b3b64c9a006;hb=7b66979277235ebe345d8589701e3cfd0dce842a;hp=0af12a2baf98965dc31336e154ba1ebaa28b9a80;hpb=9a1c4c7c806a97eaa27baa9bb44257e91aca3117;p=tools%2Fsiman.git diff --git a/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java b/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java index 0af12a2..0d133d1 100644 --- a/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java +++ b/Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java @@ -1,5 +1,5 @@ /***************************************************************************** - * Company EURIWARE + * Company OPEN CASCADE * Application SIMAN * File Id: * Creation date 02.10.2012 @@ -10,167 +10,215 @@ package org.splat.service; import java.io.IOException; +import java.text.DecimalFormat; +import java.text.SimpleDateFormat; +import java.util.Calendar; +import java.util.Collections; import java.util.Date; -import java.util.HashMap; import java.util.Iterator; import java.util.List; +import java.util.Map; +import java.util.Set; -import org.apache.log4j.Logger; -import org.hibernate.Session; -import org.hibernate.Transaction; +import org.hibernate.criterion.Restrictions; import org.splat.dal.bo.kernel.Relation; import org.splat.dal.bo.kernel.User; import org.splat.dal.bo.som.ActorRelation; import org.splat.dal.bo.som.ContributorRelation; import org.splat.dal.bo.som.DescriptionAttribute; -import org.splat.dal.bo.som.Document; 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.KnowledgeElementType; import org.splat.dal.bo.som.ProgressState; import org.splat.dal.bo.som.Publication; import org.splat.dal.bo.som.Scenario; import org.splat.dal.bo.som.SimulationContext; -import org.splat.dal.bo.som.SimulationContextType; import org.splat.dal.bo.som.Study; import org.splat.dal.bo.som.ValidationCycle; import org.splat.dal.bo.som.ValidationCycleRelation; +import org.splat.dal.bo.som.ValidationStep; import org.splat.dal.bo.som.Visibility; import org.splat.dal.bo.som.Study.Properties; -import org.splat.dal.dao.som.Database; +import org.splat.dal.bo.som.ValidationCycle.Actor; +import org.splat.dal.dao.som.IDBuilderDAO; +import org.splat.dal.dao.som.ScenarioDAO; +import org.splat.dal.dao.som.StudyDAO; +import org.splat.dal.dao.som.ValidationCycleDAO; import org.splat.kernel.InvalidPropertyException; import org.splat.kernel.MissedPropertyException; import org.splat.kernel.MultiplyDefinedException; -import org.splat.kernel.UserDirectory; import org.splat.log.AppLogger; import org.splat.service.technical.IndexService; import org.splat.service.technical.ProjectSettingsService; +import org.splat.service.technical.ProjectSettingsServiceImpl; import org.splat.som.Revision; +import org.springframework.transaction.annotation.Transactional; /** * This class defines all methods for creation, modification the study. + * * @author Maria KRUCHININA - * + * */ public class StudyServiceImpl implements StudyService { /** * logger for the service. */ - public final static AppLogger logger = AppLogger.getLogger(StudyServiceImpl.class); + public final static AppLogger LOG = AppLogger + .getLogger(StudyServiceImpl.class); + /** + * Injected index service. + */ private IndexService _indexService; + /** + * Injected step service. + */ private StepService _stepService; - private ScenarioService _scenarioService; - + /** + * Injected project service. + */ private ProjectSettingsService _projectSettingsService; + /** + * Injected project element service. + */ private ProjectElementService _projectElementService; - + + /** + * Injected study DAO. + */ + private StudyDAO _studyDAO; + + /** + * Injected scenario DAO. + */ + private ScenarioDAO _scenarioDAO; + + /** + * Injected validation cycle DAO. + */ + private ValidationCycleDAO _validationCycleDAO; + + /** + * Injected IDBuilder DAO. + */ + private IDBuilderDAO _iDBuilderDAO; + + /** + * Injected document type service. + */ + private DocumentTypeService _documentTypeService; + + /** + * Injected user service. + */ + private UserService _userService; + /** - * Get the simulation context list for displaying drop-down list values populating - * on the "Create new study" screen. * {@inheritDoc} - * @see org.splat.service.StudyService#getSimulationContextList() + * + * @see org.splat.service.StudyService#selectStudy(long) */ - public List getSimulationContextList() { - //TODO: remove the commit transaction ... - Session connex = Database.getSession(); - Transaction transax = connex.beginTransaction(); - - SimulationContext.Properties cprop = new SimulationContext.Properties(); - SimulationContextType product = SimulationContext.selectType("product"); - List resList = Database.selectSimulationContextsWhere(cprop.setType(product)); - - transax.commit(); - - return resList; - } - - public Study selectStudy(int index) { - // ------------------------------------------- - StringBuffer query = new StringBuffer("from Study where rid='").append( - index).append("'"); - Study result = (Study) Database.getSession().createQuery( - query.toString()).uniqueResult(); - - result.loadWorkflow(); + @Transactional + public Study selectStudy(final long index) { + Study result = getStudyDAO().get(index); + loadWorkflow(result); return result; } - public Study selectStudy(String refid) { - // ---------------------------------------------- - StringBuffer query = new StringBuffer("from Study where sid='").append( - refid).append("'"); - Study result = (Study) Database.getSession().createQuery( - query.toString()).uniqueResult(); - - result.loadWorkflow(); + /** + * Get study by its reference. + * + * @param refid + * the study reference + * @return found study or null + */ + @Transactional(readOnly = true) + public Study selectStudy(final String refid) { + Study result = getStudyDAO().findByCriteria( + Restrictions.eq("sid", refid)); + loadWorkflow(result); return result; } - public Study createStudy(Study.Properties sprop) + /** + * {@inheritDoc} + * + * @see org.splat.service.StudyService#createStudy(org.splat.dal.bo.som.Study.Properties) + */ + @Transactional + public Study createStudy(final Study.Properties sprop) throws MissedPropertyException, InvalidPropertyException, - MultiplyDefinedException, RuntimeException { + MultiplyDefinedException { sprop.setReference(getProjectSettings().getReferencePattern()); Study study = new Study(sprop); buildReference(study); - Database.getSession().save(study); // TODO: use StudyDAO and throw out Database. + getStudyDAO().create(study); try { IndexService lucin = getIndex(); lucin.add(study); } catch (IOException error) { - logger.error("Unable to index the study '" + study.getIndex() + LOG.error("Unable to index the study '" + study.getIndex() + "', reason:", error); // Continue and try to index later } return study; } - public IndexService getIndex() throws IOException { - IndexService lucin = getIndexService(); - if (!lucin.exists()) - lucin.create(); // Happens when re-indexing all studies - return lucin; - } - - public SimulationContext addProjectContext(Study aStudy, - SimulationContext.Properties cprop) throws MissedPropertyException, - InvalidPropertyException, MultiplyDefinedException, - RuntimeException { - // ------------------------------------------------------------------------------- + /** + * {@inheritDoc} + * + * @see org.splat.service.StudyService#addProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext.Properties) + */ + @Transactional + public SimulationContext addProjectContext(final Study aStudy, + final SimulationContext.Properties cprop) + throws MissedPropertyException, InvalidPropertyException, + MultiplyDefinedException { SimulationContext added = getStepService().addSimulationContext( getProjectElementService().getFirstStep(aStudy), cprop); update(aStudy); return added; } - public SimulationContext addProjectContext(Study aStudy, - SimulationContext context) { - // ---------------------------------------------------------------------- + /** + * {@inheritDoc} + * + * @see org.splat.service.StudyService#addProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext) + */ + @Transactional + public SimulationContext addProjectContext(final Study aStudy, + final SimulationContext context) { SimulationContext added = getStepService().addSimulationContext( getProjectElementService().getFirstStep(aStudy), context); update(aStudy); return added; } - public boolean addContributor(Study aStudy, User user) { - // ----------------------------------------- - List contributor = aStudy.getModifiableContributors(); // Initializes contributor + /** + * {@inheritDoc} + * + * @see org.splat.service.StudyService#addContributor(org.splat.dal.bo.som.Study, org.splat.dal.bo.kernel.User) + */ + public boolean addContributor(final Study aStudy, final User user) { + List contributor = getModifiableContributors(aStudy); // Initializes contributor for (Iterator i = contributor.iterator(); i.hasNext();) { User present = i.next(); - if (present.equals(user)) + if (present.equals(user)) { return false; + } } - boolean absent = aStudy.getModifiableActors().add(user); // User may already be a reviewer or an approver + boolean absent = getModifiableActors(aStudy).add(user); // User may already be a reviewer or an approver aStudy.addRelation(new ContributorRelation(aStudy, user)); - if (absent) + if (absent) { update(aStudy); // Else, useless to re-index the study + } contributor.add(user); return true; } @@ -179,17 +227,20 @@ public class StudyServiceImpl implements StudyService { * 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) */ - public boolean moveToReference(Study aStudy) { - // --------------------------------- - if (aStudy.getProgressState() != ProgressState.APPROVED) + public boolean moveToReference(final Study aStudy) { + if (aStudy.getProgressState() != ProgressState.APPROVED) { return false; - if (aStudy.getVisibility() != Visibility.PUBLIC) + } + if (aStudy.getVisibility() != Visibility.PUBLIC) { return false; + } aStudy.setVisibility(Visibility.REFERENCE); if (update(aStudy)) { @@ -198,50 +249,60 @@ public class StudyServiceImpl implements StudyService { return false; } - public boolean update(Study aStudy, Properties sprop) + /** + * {@inheritDoc} + * + * @see org.splat.service.StudyService#update(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.Study.Properties) + */ + public boolean update(final Study aStudy, final Properties sprop) throws InvalidPropertyException { - if (sprop.getTitle() != null) + if (sprop.getTitle() != null) { aStudy.setTitle(sprop.getTitle()); - if (sprop.getSummary() != null) + } + if (sprop.getSummary() != null) { aStudy.setAttribute(new DescriptionAttribute(aStudy, sprop .getSummary())); + } // TODO: To be completed return update(aStudy); } - public boolean buildReference(Study aStudy) { - String pattern = aStudy.getReference(); // The study being supposed just created, its reference is the reference pattern - IDBuilder tool = Database.selectIDBuilder(aStudy.getDate()); - if (tool == null) { - tool = new IDBuilder(aStudy.getDate()); - Database.getSession().save(tool); - } - aStudy.setReference(tool.buildReference(pattern, aStudy)); - return true; - } - - public boolean publishes(Study aStudy, Document doc) { - // --------------------------------------- + /** + * Check if the document is published in the study. + * + * @param aStudy + * the study + * @param doc + * the document + * @return true if the document is published in the study + */ +/* private boolean publishes(final Study aStudy, final Document doc) { if (!aStudy.publishes(doc)) { Scenario[] scene = aStudy.getScenarii(); for (int i = 0; i < scene.length; i++) { - if (scene[i].publishes(doc)) + if (scene[i].publishes(doc)) { return true; + } } } return false; } - - public boolean removeContributor(Study aStudy, User... users) { - // ------------------------------------------------ - List contributor = aStudy.getModifiableContributors(); // Initializes contributor +*/ + /** + * {@inheritDoc} + * + * @see org.splat.service.StudyService#removeContributor(org.splat.dal.bo.som.Study, org.splat.dal.bo.kernel.User[]) + */ + public boolean removeContributor(final Study aStudy, final User... users) { + List contributor = getModifiableContributors(aStudy); // Initializes contributor Boolean done = false; for (int i = 0; i < users.length; i++) { User user = users[i]; for (Iterator j = contributor.iterator(); j.hasNext();) { User present = j.next(); - if (!present.equals(user)) + if (!present.equals(user)) { continue; + } aStudy.removeRelation(ContributorRelation.class, user); j.remove(); // Updates the contributor shortcut @@ -249,150 +310,107 @@ public class StudyServiceImpl implements StudyService { break; } } - if (done) + if (done) { update(aStudy); + } return done; } - public boolean removeProjectContext(Study aStudy, SimulationContext context) { - // --------------------------------------------------------------- + /** + * {@inheritDoc} + * + * @see org.splat.service.StudyService#removeProjectContext(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.SimulationContext) + */ + public boolean removeProjectContext(final Study aStudy, + final SimulationContext context) { boolean done = getStepService().removeSimulationContext( getProjectElementService().getFirstStep(aStudy), context); update(aStudy); return done; } - public void setValidationCycle(Study aStudy, DocumentType type, - ValidationCycle.Properties vprop) { - HashMap validactor = aStudy - .getValidationCycles(); - if (validactor == null) - aStudy.setShortCuts(); // Initializes validactor and actor + /** + * {@inheritDoc} + * + * @see org.splat.service.StudyService#setValidationCycle(org.splat.dal.bo.som.Study, org.splat.dal.bo.som.DocumentType, + * org.splat.dal.bo.som.ValidationCycle.Properties) + */ + @Transactional + public void setValidationCycle(final Study aStudyDTO, final DocumentType type, + final ValidationCycle.Properties vprop) { + Map validactor = aStudyDTO.getValidationCycles(); + if (validactor == null) { + setShortCuts(aStudyDTO); // Initializes validactor and actor + } + Study aStudy = selectStudy(aStudyDTO.getIndex()); + String cname = type.getName(); ValidationCycle cycle = validactor.get(cname); if (cycle != null && cycle.isAssigned()) { - cycle.resetActors(vprop); - } else + resetActors(cycle, vprop); + } else { try { cycle = new ValidationCycle(aStudy, vprop.setDocumentType(type)); + getValidationCycleDAO().create(cycle); // RKV + ValidationCycleRelation link = cycle.getContext(); - aStudy.addRelation(link); + // RKV: aStudy.addRelation(link); + aStudyDTO.getAllRelations().add(link); // RKV + validactor.put(cname, link.getTo()); // Replaces the cycle if exists as default, } catch (Exception error) { - logger.error("Unable to re-index Knowledge Elements, reason:", + LOG.error("Unable to re-index Knowledge Elements, reason:", error); return; } - resetActorsShortCut(aStudy); - update(aStudy); // Re-index the study, just in case - } - - private void resetActorsShortCut(Study aStudy) { - aStudy.getModifiableActors().clear(); - // Get all actors involved in validation cycles - for (Iterator i = aStudy.getValidationCycles() - .values().iterator(); i.hasNext();) { - ValidationCycle cycle = i.next(); - User[] user = cycle.getAllActors(); - for (int j = 0; j < user.length; j++) - aStudy.getModifiableActors().add(user[j]); - } - // Get all other actors - for (Iterator i = aStudy.getAllRelations().iterator(); i - .hasNext();) { - Relation link = i.next(); - Class kindof = link.getClass().getSuperclass(); - if (!kindof.equals(ActorRelation.class)) - continue; - aStudy.getModifiableActors().add(((ActorRelation) link).getTo()); } + resetActorsShortCut(aStudyDTO); + 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. */ - public boolean demote(Study aStudy) { - // --------------------------- - if (aStudy.getProgressState() == ProgressState.inCHECK) + public boolean demote(final Study aStudy) { + if (aStudy.getProgressState() == ProgressState.inCHECK) { aStudy.setProgressState(ProgressState.inDRAFT); - else if (aStudy.getProgressState() == ProgressState.inDRAFT) + } else if (aStudy.getProgressState() == ProgressState.inDRAFT) { aStudy.setProgressState(ProgressState.inWORK); - else - return false; - return update(aStudy); - } - - public int generateLocalIndex(Study aStudy) { - aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1); - Database.getSession().update(aStudy); - return aStudy.getLastLocalIndex(); - } - - // ============================================================================================================================== - // Public member functions - // ============================================================================================================================== - - public Scenario addScenario(Study aStudy, Scenario.Properties sprop) - throws MissedPropertyException, InvalidPropertyException, - MultiplyDefinedException, RuntimeException { - // ------------------------------------------------------- - if (sprop.getManager() == null) - sprop.setManager(aStudy.getAuthor()); - - Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy)); - if (sprop.getBaseStep() != null) - getScenarioService() - .copyContentsUpTo(scenario, sprop.getBaseStep()); - Scenario previous = sprop.getInsertAfter(); - Session session = Database.getSession(); - - if (previous == null) { - aStudy.getScenariiList().add(scenario); } else { - aStudy.getScenariiList().add( - aStudy.getScenariiList().indexOf(previous) + 1, scenario); - } - session.update(aStudy); // No need to update the Lucene index - session.save(scenario); // Must be done after updating this study because of the back reference to the study - if (sprop.getBaseStep() != null) { - // No need to update the Knowledge Element index as Knowledge Elements are not copied - scenario.refresh(); // Because saving the scenario changes the hashcode of copied Publications + return false; } - KnowledgeElementType ucase = KnowledgeElement.selectType("usecase"); - KnowledgeElement.Properties kprop = new KnowledgeElement.Properties(); - User admin = UserDirectory.selectUser(1); // First user created when creating the database - kprop.setType(ucase).setTitle(aStudy.getTitle()) - .setValue(scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of - // knowledges - getScenarioService().addKnowledgeElement(scenario, kprop); - return scenario; + return update(aStudy); } /** - * @return + * {@inheritDoc} + * + * @see org.splat.service.StudyService#generateLocalIndex(org.splat.dal.bo.som.Study) */ - private ScenarioService getScenarioService() { - return _scenarioService; - } - - public void setScenarioService(ScenarioService scenarioService) { - _scenarioService = scenarioService; + @Transactional + public int generateLocalIndex(final Study aStudy) { + aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1); + getStudyDAO().update(aStudy); + return aStudy.getLastLocalIndex(); } /** * 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. * + * @param aStudy + * a study to promote * @return true if the demotion succeeded. */ - public boolean promote(Study aStudy) { - // ---------------------------- + public boolean promote(final Study aStudy) { if (aStudy.getProgressState() == ProgressState.inWORK) { aStudy.setProgressState(ProgressState.inDRAFT); } else if (aStudy.getProgressState() == ProgressState.inDRAFT) { @@ -404,8 +422,9 @@ public class StudyServiceImpl implements StudyService { } } else if (aStudy.getProgressState() == ProgressState.inCHECK) { aStudy.setProgressState(ProgressState.APPROVED); - } else + } else { return false; + } return update(aStudy); } @@ -413,35 +432,184 @@ public class StudyServiceImpl implements StudyService { /** * Moves this study from the Private to the Public area of the repository. * + * @param aStudy + * a study to move * @return true if the move succeeded. * @see #isPublic() */ - public boolean moveToPublic(Study aStudy) { - // ------------------------------ - if (aStudy.getVisibility() != Visibility.PRIVATE) - return false; - - aStudy.setVisibility(Visibility.PUBLIC); - if (update(aStudy)) { - return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller + public boolean moveToPublic(final Study aStudy) { + boolean isOk = false; + 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 + } } - return false; + return isOk; } - private boolean update(Study aStudy) { + /** + * Update a study in the database. + * + * @param aStudy + * the study to update + * @return true if the study is updated successfully + */ + @Transactional + private boolean update(final Study aStudy) { + boolean isOk = false; try { - Database.getSession().update(aStudy); // Update of relational base + getStudyDAO().update(aStudy); // Update of relational base + setShortCuts(aStudy); // RKV: initialize transient actors set getIndex().update(aStudy); // Update of Lucene index - return true; - } catch (Exception error) { - logger.error("Unable to re-index the study '" + aStudy.getIndex() - + "', reason:", error); - return false; + isOk = true; + } catch (Exception e) { + LOG.error("STD-000001", e, aStudy.getIndex(), e.getMessage()); } + return isOk; } - private boolean updateKnowledgeElementsIndex(Study aStudy) { - // ---------------------------------------------- + /** + * Build reference for the study. The reference of the study is stored as a new reference pattern (IDBuilder). + * + * @param aStudy + * the study + * @return true if reference building is succeded + */ + @Transactional + private boolean buildReference(final Study aStudy) { + String pattern = aStudy.getReference(); // The study being supposed just created, its reference is the reference pattern + IDBuilder tool = selectIDBuilder(aStudy.getDate()); + if (tool == null) { + tool = new IDBuilder(aStudy.getDate()); + getIDBuilderDAO().create(tool); + } + aStudy.setReference(buildReference(tool, pattern, aStudy)); + return true; + } + + /** + * Build reference for the study. The reference of the study is stored as a new reference pattern (IDBuilder). + * + * @param aBuilder + * the id builder + * @param study + * the study + * @param pattern + * the reference pattern + * @return true if reference building is succeded + */ + @Transactional + public String buildReference(final IDBuilder aBuilder, + final String pattern, final Study study) { + char[] format = pattern.toCharArray(); + char[] ref = new char[80]; // Better evaluate the length of the generated string + int next = aBuilder.getBase() + 1; + + int count = 0; + for (int i = 0; i < format.length; i++) { + + // Insertion of attribute values + if (format[i] == '%') { + i += 1; + + if (format[i] == 'y') { // Insertion of year in format 2 (e.g. 09) or 4 (e.g. 2009) digits + int n = i; + while (format[i] == 'y') { + i += 1; + if (i == format.length) { + break; + } + } + SimpleDateFormat tostring = new SimpleDateFormat("yyyy"); //RKV: NOPMD: TODO: Use locale here? + String year = tostring.format(study.getDate()); + year = year.substring(4 - (i - n), 4); // 4-(i-n) must be equal to either 0 or 2 + for (int j = 0; j < year.length(); j++) { + ref[count] = year.charAt(j); + count += 1; + } + i -= 1; // Back to the last 'y' character + } else if (format[i] == '0') { // Insertion of the index + int n = i; + while (format[i] == '0') { + i += 1; + if (i == format.length) { + break; + } + } + DecimalFormat tostring = new DecimalFormat(pattern + .substring(n, i)); + String number = tostring.format(next); + for (int j = 0; j < number.length(); j++) { + ref[count] = number.charAt(j); + count += 1; + } + i -= 1; // Back to the last '0' character + } + // Keep the character + } else { + ref[count] = format[i]; + count += 1; + } + } + // Incrementation of the number of study + aBuilder.setBase(next); + getIDBuilderDAO().update(aBuilder); + return String.copyValueOf(ref, 0, count); + } + + /** + * Find an id builder by date. + * + * @param date + * the date + * @return found id builder + */ + private IDBuilder selectIDBuilder(final Date date) { + Calendar aDate = Calendar.getInstance(); + aDate.setTime(date); + return getIDBuilderDAO().findByCriteria( + Restrictions.eq("cycle", aDate.get(Calendar.YEAR))); + } + + /** + * Fill transient collection ModifiableActors of the study. + * + * @param aStudy + * the study + */ + private void resetActorsShortCut(final Study aStudy) { + getModifiableActors(aStudy).clear(); + // Get all actors involved in validation cycles + for (Iterator i = aStudy.getValidationCycles() + .values().iterator(); i.hasNext();) { + ValidationCycle cycle = i.next(); + User[] user = cycle.getAllActors(); + for (int j = 0; j < user.length; j++) { + getModifiableActors(aStudy).add(user[j]); + } + } + // Get all other actors + for (Iterator i = aStudy.getAllRelations().iterator(); i + .hasNext();) { + Relation link = i.next(); + Class kindof = link.getClass().getSuperclass(); + if (!kindof.equals(ActorRelation.class)) { + continue; + } + getModifiableActors(aStudy).add(((ActorRelation) link).getTo()); + } + } + + /** + * Update lucene index for the study knowledge elements. + * + * @param aStudy + * the study + * @return true if reindexing succeeded + */ + private boolean updateKnowledgeElementsIndex(final Study aStudy) { + boolean isOk = false; try { IndexService lucin = getIndex(); @@ -454,23 +622,362 @@ public class StudyServiceImpl implements StudyService { lucin.update(kelm); } } - return true; + isOk = true; } catch (Exception error) { - logger.error("Unable to re-index Knowledge Elements, reason:", + LOG.error("Unable to re-index Knowledge Elements, reason:", error); + } + return isOk; + } + + /** + * Get lucene index service. Create a lucene index if it does not exist. + * + * @return index service + * @throws IOException + * if error occurs during lucene index creation + */ + private IndexService getIndex() throws IOException { + IndexService lucin = getIndexService(); + if (!lucin.exists()) { + lucin.create(); // Happens when re-indexing all studies + } + return lucin; + } + + /** + * Create a new validation cycle for documents of the given study. + * + * @param from + * the study + * @param cycle + * the cycle description + * @return the new validation cycle + */ + protected ValidationCycle createValidationCycle( + final Study from, + final ProjectSettingsServiceImpl.ProjectSettingsValidationCycle cycle) { + Actor[] actype = cycle.getActorTypes(); + User.Properties uprop = new User.Properties(); + + ValidationCycle aValidationCycle = new ValidationCycle(); + aValidationCycle.setDocumentType(getDocumentTypeService().selectType( + cycle.getName())); // Null in case of default validation cycle + // context = new ValidationCycleRelation(from, vprop); + // RKV aValidationCycle.context = null; // Validation cycle defined in the workflow + for (int i = 0; i < actype.length; i++) { + User actor = null; + if (actype[i] != null) { + try { + if (actype[i] == Actor.manager) { + actor = from.getAuthor(); + } else if (actype[i] == Actor.Nx1) { + List manager = getUserService().selectUsersWhere( + uprop.setOrganizationName("Nx1")); + if (manager.size() == 1) { + actor = manager.get(0); + } + } else if (actype[i] == Actor.Nx2) { + List manager = getUserService().selectUsersWhere( + uprop.setOrganizationName("Nx2")); + if (manager.size() == 1) { + actor = manager.get(0); + } + } else { /* Actor.customer */ + actor = from.getAuthor(); + // TODO: Get the customer of the study, if exists + } + } catch (Exception e) { // Should not happen + actor = null; + } + } + if (i == 0) { + aValidationCycle.setReviewer(actor); + } else if (i == 1) { + aValidationCycle.setApprover(actor); + } else if (i == 2) { + aValidationCycle.setSignatory(actor); + } + } + return aValidationCycle; + } + + /** + * Remove a validation step from the validation cycle. + * + * @param aValidationCycle + * the validation cycle + * @param step + * the validation step to remove + */ + @Transactional + protected void remove(final ValidationCycle aValidationCycle, + final ValidationStep step) { + if (step == ValidationStep.REVIEW) { + aValidationCycle.setReviewer(null); + } else if (step == ValidationStep.APPROVAL) { + aValidationCycle.setApprover(null); + } else if (step == ValidationStep.ACCEPTANCE + || step == ValidationStep.REFUSAL) { + aValidationCycle.setSignatory(null); + } + if (aValidationCycle.isSaved()) { + getValidationCycleDAO().update(aValidationCycle); + } + } + + /** + * Reset actors for the validation cycle. + * + * @param aValidationCycle + * the validation cycle to update + * @param vprop + * new validation cycle properties containing new actors + */ + @Transactional + public void resetActors(final ValidationCycle aValidationCycle, + final ValidationCycle.Properties vprop) { + aValidationCycle.setPublisher(vprop.getPublisher()); // May be null + aValidationCycle.setReviewer(vprop.getReviewer()); // May be null + aValidationCycle.setApprover(vprop.getApprover()); // May be null + aValidationCycle.setSignatory(vprop.getSignatory()); // May be null + if (aValidationCycle.isSaved()) { + getValidationCycleDAO().update(aValidationCycle); + } + } + + /** + * Set actor for the given validation cycle and validation step. + * + * @param aValidationCycle + * the validation cycle + * @param step + * the validation step + * @param actor + * the actor to set + */ + @Transactional + protected void setActor(final ValidationCycle aValidationCycle, + final ValidationStep step, final User actor) { + if (step == ValidationStep.PROMOTION) { + aValidationCycle.setPublisher(actor); + } else if (step == ValidationStep.REVIEW) { + aValidationCycle.setReviewer(actor); + } else if (step == ValidationStep.APPROVAL) { + aValidationCycle.setApprover(actor); + } else if (step == ValidationStep.ACCEPTANCE + || step == ValidationStep.REFUSAL) { + aValidationCycle.setSignatory(actor); + } + if (aValidationCycle.isSaved()) { + getValidationCycleDAO().update(aValidationCycle); + } + } + + /** + * Returns all actors of this study other than the author, including contributors, reviewers and approvers. + * + * @param aStudy + * the study + * @return the actors of this study + * @see #hasActor(User) + */ + public Set getActors(final Study aStudy) { + if (aStudy.getActor() == null) { + setShortCuts(aStudy); + } + return Collections.unmodifiableSet(aStudy.getActor()); + } + + /** + * Returns all actors of this study other than the author, including contributors, reviewers and approvers. + * + * @param aStudy + * the study + * @return the modifiable set of actors of this study + * @see #hasActor(User) + */ + public Set getModifiableActors(final Study aStudy) { + if (aStudy.getActor() == null) { + setShortCuts(aStudy); + } + return aStudy.getActor(); + } + + /** + * Returns unmodifiable initialized transient list of contributors of this study. + * + * @param aStudy + * the study + * @return the unmodifiable not null transient list of contributors of this study + */ + public List getContributors(final Study aStudy) { + if (aStudy.getContributor() == null) { + setShortCuts(aStudy); + } + return Collections.unmodifiableList(aStudy.getContributor()); // May be empty + } + + /** + * Returns modifiable initialized transient list of contributors of this study. + * + * @param aStudy + * the study + * @return the modifiable not null transient list of contributors of this study + */ + public List getModifiableContributors(final Study aStudy) { + if (aStudy.getContributor() == null) { + setShortCuts(aStudy); + } + return aStudy.getContributor(); // May be empty + } + + /** + * Returns the validation cycle of the given document type. + * + * @param aStudy + * the study + * @param type + * the document type being subject of validation + * @return the validation cycle of the document, or null if not defined. + */ + public ValidationCycle getValidationCycleOf(final Study aStudy, + final DocumentType type) { + if (aStudy.getValidationCycles() == null) { + setShortCuts(aStudy); + } + ValidationCycle result = aStudy.getValidationCycles().get( + type.getName()); + if (result == null) { + if (type.isStepResult()) { + result = aStudy.getValidationCycles().get("default"); // "default" validation cycle defined in the configuration, if exist + } + if (result == null) { + result = aStudy.getValidationCycles().get("built-in"); + } + } + return result; + } + + /** + * Checks if the given user is actor of this study. Actors include contributors, reviewers and approvers. + * + * @param aStudy + * the study + * @param user + * the user to look for + * @return true if the given user is actor of this study. + * @see #getActors() + */ + public boolean hasActor(final Study aStudy, final User user) { + if (user == null) { return false; } + for (Iterator i = getActors(aStudy).iterator(); i.hasNext();) { + User involved = i.next(); + if (involved.equals(user)) { + return true; + } + } + return false; } /** - * @return + * Checks if the given user participates to this study. The Study staff includes the author and contributors. + * + * @param aStudy + * the study + * @param user + * the user to look for + * @return true if the given user is actor of this study. + * @see #getContributors() */ - public IndexService getIndexService() { - return _indexService; + public boolean isStaffedBy(final Study aStudy, final User user) { + if (user == null) { + return false; + } + if (aStudy == null) { + return false; + } + if (aStudy.getAuthor() == null) { + return false; + } + if (aStudy.getAuthor().equals(user)) { + return true; + } + for (Iterator i = getContributors(aStudy).iterator(); i.hasNext();) { + if (i.next().equals(user)) { + return true; + } + } + return false; } - public void setIndexService(IndexService indexService) { - _indexService = indexService; + /** + * Initialize shortcuts of the study as its transient collections. + * + * @param aStudy + * the study + */ + public void loadWorkflow(final Study aStudy) { + setShortCuts(aStudy); + } + + /** + * Initialize shortcuts of the study as its transient collections. + * + * @param aStudy + * the study + */ + public void setShortCuts(final Study aStudy) { + aStudy.getContributor().clear(); + aStudy.getValidationCycles().clear(); + aStudy.getActor().clear(); + + // Get the contributors + for (Iterator i = aStudy.getRelations( + ContributorRelation.class).iterator(); i.hasNext();) { + ContributorRelation link = (ContributorRelation) i.next(); + aStudy.getContributor().add(link.getTo()); + } + // Get the validation cycles specific to this study + for (Iterator i = aStudy.getRelations( + ValidationCycleRelation.class).iterator(); i.hasNext();) { + ValidationCycleRelation link = (ValidationCycleRelation) i.next(); + aStudy.getValidationCycles().put(link.getDocumentType().getName(), + link.getTo()); // The associated document type is necessarily not null in this + // context + } + // Get the validation cycles coming from the configured workflow and not overridden in this study + for (Iterator i = getProjectSettings() + .getAllValidationCycles().iterator(); i.hasNext();) { + ProjectSettingsServiceImpl.ProjectSettingsValidationCycle cycle = i + .next(); + String type = cycle.getName(); + if (!aStudy.getValidationCycles().containsKey(type)) { + aStudy.getValidationCycles().put(type, + createValidationCycle(aStudy, cycle)); + } + } + // Get all corresponding actors + for (Iterator i = aStudy.getValidationCycles() + .values().iterator(); i.hasNext();) { + ValidationCycle cycle = i.next(); + User[] user = cycle.getAllActors(); + for (int j = 0; j < user.length; j++) { + aStudy.getActor().add(user[j]); + } + } + // Get all other actors + for (Iterator i = aStudy.getAllRelations().iterator(); i + .hasNext();) { + Relation link = i.next(); + Class kindof = link.getClass().getSuperclass(); + if (!kindof.equals(ActorRelation.class)) { + continue; + } + aStudy.getActor().add(((ActorRelation) link).getTo()); + } } /** @@ -488,7 +995,8 @@ public class StudyServiceImpl implements StudyService { * @param projectSettingsService * project settings service */ - public void setProjectSettings(ProjectSettingsService projectSettingsService) { + public void setProjectSettings( + final ProjectSettingsService projectSettingsService) { _projectSettingsService = projectSettingsService; } @@ -508,12 +1016,13 @@ public class StudyServiceImpl implements StudyService { * the projectElementService to set */ public void setProjectElementService( - ProjectElementService projectElementService) { + final ProjectElementService projectElementService) { _projectElementService = projectElementService; } /** * Get the stepService. + * * @return the stepService */ public StepService getStepService() { @@ -522,9 +1031,146 @@ public class StudyServiceImpl implements StudyService { /** * Set the stepService. - * @param stepService the stepService to set + * + * @param stepService + * the stepService to set */ - public void setStepService(StepService stepService) { + public void setStepService(final StepService stepService) { _stepService = stepService; } + + /** + * Get the indexService. + * + * @return the indexService + */ + public IndexService getIndexService() { + return _indexService; + } + + /** + * Set the indexService. + * + * @param indexService + * the indexService to set + */ + public void setIndexService(final IndexService indexService) { + _indexService = indexService; + } + + /** + * Get the studyDAO. + * + * @return the studyDAO + */ + public StudyDAO getStudyDAO() { + return _studyDAO; + } + + /** + * Set the studyDAO. + * + * @param studyDAO + * the studyDAO to set + */ + public void setStudyDAO(final StudyDAO studyDAO) { + _studyDAO = studyDAO; + } + + /** + * Get the iDBuilderDAO. + * + * @return the iDBuilderDAO + */ + public IDBuilderDAO getIDBuilderDAO() { + return _iDBuilderDAO; + } + + /** + * Set the iDBuilderDAO. + * + * @param builderDAO + * the iDBuilderDAO to set + */ + public void setIDBuilderDAO(final IDBuilderDAO builderDAO) { + _iDBuilderDAO = builderDAO; + } + + /** + * Get the scenarioDAO. + * + * @return the scenarioDAO + */ + public ScenarioDAO getScenarioDAO() { + return _scenarioDAO; + } + + /** + * Set the scenarioDAO. + * + * @param scenarioDAO + * the scenarioDAO to set + */ + public void setScenarioDAO(final ScenarioDAO scenarioDAO) { + _scenarioDAO = scenarioDAO; + } + + /** + * Get the validationCycleDAO. + * + * @return the validationCycleDAO + */ + public ValidationCycleDAO getValidationCycleDAO() { + return _validationCycleDAO; + } + + /** + * Set the validationCycleDAO. + * + * @param validationCycleDAO + * the validationCycleDAO to set + */ + public void setValidationCycleDAO( + final ValidationCycleDAO validationCycleDAO) { + _validationCycleDAO = validationCycleDAO; + } + + /** + * Get the documentTypeService. + * + * @return the documentTypeService + */ + public DocumentTypeService getDocumentTypeService() { + return _documentTypeService; + } + + /** + * Set the documentTypeService. + * + * @param documentTypeService + * the documentTypeService to set + */ + public void setDocumentTypeService( + final DocumentTypeService documentTypeService) { + _documentTypeService = documentTypeService; + } + + /** + * Get the userService. + * + * @return the userService + */ + public UserService getUserService() { + return _userService; + } + + /** + * Set the userService. + * + * @param userService + * the userService to set + */ + public void setUserService(final UserService userService) { + _userService = userService; + } }