+ * 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 (IndexWriter.isLocked(FSDirectory.open(getRepositoryService()
+ .getRepositoryIndexDirectory()))) {
+ IndexWriter.unlock(FSDirectory.open(getRepositoryService()
+ .getRepositoryIndexDirectory()));
+ }
+ 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<User> manager = getUserService().selectUsersWhere(
+ uprop.setOrganizationName("Nx1"));
+ if (manager.size() == 1) {
+ actor = manager.get(0);
+ }
+ } else if (actype[i] == Actor.Nx2) {
+ List<User> 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().merge(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<User> 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<User> 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<User> 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<User> 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
+ || aStudy.getValidationCycles().isEmpty()) {
+ 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<User> i = getActors(aStudy).iterator(); i.hasNext();) {
+ User involved = i.next();
+ if (involved.equals(user)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 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 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<User> i = getContributors(aStudy).iterator(); i.hasNext();) {
+ if (i.next().equals(user)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 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<Relation> 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<Relation> 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<ProjectSettingsServiceImpl.ProjectSettingsValidationCycle> 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<ValidationCycle> 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<Relation> 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());
+ }
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ *
+ * @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);
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ *
+ * @see org.splat.service.StudyService#removeStudyAsReference(org.splat.dal.bo.som.Study)
+ */
+ @Transactional
+ public void removeStudyAsReference(final Study aStudy) {
+
+ aStudy.setMarkreference(0);
+ aStudy.setProgressState(ProgressState.APPROVED);
+ getStudyDAO().merge(aStudy);
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.splat.service.StudyService#getDescription(java.lang.Long)
+ */
+ @Override
+ @Transactional(readOnly = true)
+ public String getDescription(final Long studyId)
+ throws InvalidParameterException {
+ if (studyId == null) {
+ throw new InvalidParameterException(PARAM_STUDY_ID, "null");
+ }
+ Study study = _studyDAO.get(studyId);
+ if (study == null) {
+ throw new InvalidParameterException(PARAM_STUDY_ID, studyId
+ .toString());
+ }
+ return study.getDescription();
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.splat.service.StudyService#setDescription(java.lang.Long, java.lang.String)
+ */
+ @Transactional
+ public void setDescription(final Long studyId, final String descriptionText)
+ throws InvalidParameterException {
+ if (studyId == null) {
+ throw new InvalidParameterException(PARAM_STUDY_ID, "null");
+ }
+ Study study = _studyDAO.get(studyId);
+ if (study == null) {
+ throw new InvalidParameterException(PARAM_STUDY_ID, studyId
+ .toString());
+ }
+ study.setAttribute(new DescriptionAttribute(study, descriptionText));
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.splat.service.StudyService#removeStudyDescription(java.lang.Long)
+ */
+ @Transactional
+ public boolean removeDescription(final Long studyId)
+ throws InvalidParameterException {
+ if (studyId == null) {
+ throw new InvalidParameterException(PARAM_STUDY_ID, String
+ .valueOf(studyId));
+ }
+ Study study = _studyDAO.get(studyId);
+ if (study == null) {
+ throw new InvalidParameterException(PARAM_STUDY_ID, String
+ .valueOf(studyId));
+ }
+ return study.removeAttribute(study
+ .getAttribute(DescriptionAttribute.class));
+ }
+
+ /**
+ *
+ * {@inheritDoc}
+ *
+ * @see org.splat.service.StudyService#compare(java.util.List)
+ */
+ @Override
+ public String compare(final List<DocToCompareDTO> docsList,
+ final String userName) throws IncompatibleDataException {
+
+ String axis1Name = "";
+ String axis2Name = "";
+ String chartTitle = "";
+ String resultPath = "";
+
+ XYSeriesCollection dataset = new XYSeriesCollection();
+
+ Iterator<DocToCompareDTO> docListIter = docsList.iterator();
+
+ for (; docListIter.hasNext();) {
+
+ DocToCompareDTO docDTO = docListIter.next();
+ String pathToFile = docDTO.getPathToFile();
+ File compDocFile = new File(pathToFile);
+
+ resultPath = pathToFile.substring(0, pathToFile.indexOf("vault"))
+ + "downloads" + File.separator + userName + File.separator
+ + "ComparisonResult.pdf";
+
+ XYSeries series = new XYSeries("Study: " + docDTO.getStudyTitle()
+ + " Scenario: " + docDTO.getScenarioTitle() + " Document: "
+ + docDTO.getDocumentTitle());
+
+ // read the file and get points information.
+ try {
+ Scanner input = new Scanner(compDocFile);
+
+ // get the title of the chart.
+ if (input.hasNext()) {
+ chartTitle = input.nextLine();
+ }
+
+ // get the name of the axis.
+ if (input.hasNext()) {
+ String[] tokens = input.nextLine().split(",");
+
+ if (tokens.length < 2) {
+ throw new IncompatibleDataException(
+ MessageKeyEnum.IDT_000001.toString());
+ }
+
+ if ("".equals(axis1Name)) {
+ axis1Name = tokens[0];
+ } else if (!axis1Name.equals(tokens[0])) {
+ LOG.debug("Axis must be the same for all documents");
+ throw new IncompatibleDataException(
+ MessageKeyEnum.IDT_000001.toString());
+ }
+
+ if ("".equals(axis2Name)) {
+ axis2Name = tokens[1];
+ } else if (!axis2Name.equals(tokens[1])) {
+ LOG.debug("Axis must be the same for all documents");
+ throw new IncompatibleDataException(
+ MessageKeyEnum.IDT_000001.toString());
+ }
+ }
+
+ // Get the XY points series.
+ while (input.hasNext()) {
+
+ String currentString = input.nextLine();
+
+ if (!("".equals(currentString))) {
+ String[] tokens = currentString.split(" ");
+ series.add(Double.valueOf(tokens[0]), Double
+ .valueOf(tokens[1]));
+ }
+
+ } // while
+
+ dataset.addSeries(series);
+
+ } catch (FileNotFoundException e) {
+ LOG.error("Sorry, the file is not found.", e);
+ }
+ } // for
+
+ JFreeChart chart = ChartFactory.createXYLineChart(chartTitle, // Title
+ axis1Name, // x-axis Label
+ axis2Name, // y-axis Label
+ dataset, // Dataset
+ PlotOrientation.VERTICAL, // Plot Orientation
+ true, // Show Legend
+ true, // Use tooltips
+ false // Configure chart to generate URLs?
+ );
+
+ // export to PDF - file.
+ int x = 500;
+ int y = 300;
+ Rectangle pagesize = new Rectangle(x, y);
+ Document document = new Document(pagesize, 50, 50, 50, 50);
+ PdfWriter writer;
+ try {
+ File resFile = new File(resultPath);
+ File resFolder = new File(resultPath.substring(0, resultPath
+ .lastIndexOf(File.separator)));
+ resFolder.mkdirs();
+ writer = PdfWriter.getInstance(document, new FileOutputStream(
+ resFile));
+
+ document.open();
+ PdfContentByte cb = writer.getDirectContent();
+ PdfTemplate tp = cb.createTemplate(x, y);
+ Graphics2D g2 = tp.createGraphics(x, y, new DefaultFontMapper());
+ chart.draw(g2, new java.awt.Rectangle(x, y));
+ g2.dispose();
+ cb.addTemplate(tp, 0, 0);
+ document.close();
+
+ } catch (FileNotFoundException e) {
+ LOG.error("Sorry, the file is not found.", e);
+ } catch (DocumentException e) {
+ LOG.error("Sorry, the DocumentException is thrown.", e);
+ }
+
+ return resultPath;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.splat.service.StudyService#getReaders(long)
+ */
+ @Transactional(readOnly = true)
+ public List<UserDTO> getReaders(final long studyId) throws InvalidParameterException {
+ Study aStudy = selectStudy(studyId);
+ if(aStudy == null){
+ throw new InvalidParameterException(PARAM_STUDY_ID, String.valueOf(studyId));
+ }
+ List<Relation> relations = aStudy.getRelations(ReaderRelation.class);
+ List<UserDTO> result = new ArrayList<UserDTO>();
+ for(Relation relation : relations){
+ 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 {
+ Study aStudy = selectStudy(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));
+ }
+
+ for(Relation relation : aStudy.getRelations(ReaderRelation.class)) {
+ if(user.equals(relation.getTo())) {
+ return false;
+ }
+ }
+ aStudy.addRelation(new ReaderRelation(aStudy, user));
+ update(aStudy);
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.splat.service.StudyService#removeReader(long, long)
+ */
+ @Transactional
+ 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));
+ }
+ User user = _userService.selectUser(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.
+ *
+ * @return Project settings service
+ */
+ private ProjectSettingsService getProjectSettings() {
+ return _projectSettings;
+ }
+
+ /**
+ * Set project settings service.
+ *
+ * @param projectSettingsService
+ * project settings service
+ */
+ public void setProjectSettings(
+ final ProjectSettingsService projectSettingsService) {
+ _projectSettings = projectSettingsService;
+ }
+
+ /**
+ * Get the projectElementService.
+ *
+ * @return the projectElementService
+ */
+ public ProjectElementService getProjectElementService() {
+ return _projectElementService;
+ }
+
+ /**
+ * Set the projectElementService.
+ *
+ * @param projectElementService
+ * the projectElementService to set
+ */
+ public void setProjectElementService(
+ final ProjectElementService projectElementService) {
+ _projectElementService = projectElementService;
+ }
+
+ /**
+ * Get the stepService.
+ *
+ * @return the stepService