1 /*****************************************************************************
5 * Creation date 02.10.2012
6 * @author Author: Maria KRUCHININA
8 *****************************************************************************/
10 package org.splat.service;
12 import java.io.IOException;
13 import java.util.Date;
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.List;
18 import org.apache.log4j.Logger;
19 import org.hibernate.Session;
20 import org.hibernate.Transaction;
21 import org.splat.dal.bo.kernel.Relation;
22 import org.splat.dal.bo.kernel.User;
23 import org.splat.dal.bo.som.ActorRelation;
24 import org.splat.dal.bo.som.ContributorRelation;
25 import org.splat.dal.bo.som.DescriptionAttribute;
26 import org.splat.dal.bo.som.Document;
27 import org.splat.dal.bo.som.DocumentType;
28 import org.splat.dal.bo.som.IDBuilder;
29 import org.splat.dal.bo.som.KnowledgeElement;
30 import org.splat.dal.bo.som.KnowledgeElementType;
31 import org.splat.dal.bo.som.ProgressState;
32 import org.splat.dal.bo.som.Publication;
33 import org.splat.dal.bo.som.Scenario;
34 import org.splat.dal.bo.som.SimulationContext;
35 import org.splat.dal.bo.som.SimulationContextType;
36 import org.splat.dal.bo.som.Study;
37 import org.splat.dal.bo.som.ValidationCycle;
38 import org.splat.dal.bo.som.ValidationCycleRelation;
39 import org.splat.dal.bo.som.Visibility;
40 import org.splat.dal.bo.som.Study.Properties;
41 import org.splat.dal.dao.som.Database;
42 import org.splat.kernel.InvalidPropertyException;
43 import org.splat.kernel.MissedPropertyException;
44 import org.splat.kernel.MultiplyDefinedException;
45 import org.splat.kernel.UserDirectory;
46 import org.splat.service.technical.IndexService;
47 import org.splat.service.technical.ProjectSettingsService;
48 import org.splat.som.Revision;
51 * This class defines all methods for creation, modification the study.
52 * @author Maria KRUCHININA
55 public class StudyServiceImpl implements StudyService {
58 * logger for the service.
60 public final static Logger logger = Logger.getLogger(org.splat.service.StudyServiceImpl.class);
62 private IndexService _indexService;
64 private StepService _stepService;
66 private ScenarioService _scenarioService;
68 private ProjectSettingsService _projectSettingsService;
70 private ProjectElementService _projectElementService;
73 * Get the simulation context list for displaying drop-down list values populating
74 * on the "Create new study" screen.
76 * @see org.splat.service.StudyService#getSimulationContextList()
78 public List<SimulationContext> getSimulationContextList() {
79 //TODO: remove the commit transaction ...
80 Session connex = Database.getSession();
81 Transaction transax = connex.beginTransaction();
83 SimulationContext.Properties cprop = new SimulationContext.Properties();
84 SimulationContextType product = SimulationContext.selectType("product");
85 List<SimulationContext> resList = Database.selectSimulationContextsWhere(cprop.setType(product));
92 public Study selectStudy(int index) {
93 // -------------------------------------------
94 StringBuffer query = new StringBuffer("from Study where rid='").append(
96 Study result = (Study) Database.getSession().createQuery(
97 query.toString()).uniqueResult();
99 result.loadWorkflow();
103 public Study selectStudy(String refid) {
104 // ----------------------------------------------
105 StringBuffer query = new StringBuffer("from Study where sid='").append(
107 Study result = (Study) Database.getSession().createQuery(
108 query.toString()).uniqueResult();
110 result.loadWorkflow();
114 public Study createStudy(Study.Properties sprop)
115 throws MissedPropertyException, InvalidPropertyException,
116 MultiplyDefinedException, RuntimeException {
117 sprop.setReference(getProjectSettings().getReferencePattern());
118 Study study = new Study(sprop);
120 buildReference(study);
121 Database.getSession().save(study); // TODO: use StudyDAO and throw out Database.
123 IndexService lucin = getIndex();
125 } catch (IOException error) {
126 logger.error("Unable to index the study '" + study.getIndex()
127 + "', reason:", error);
128 // Continue and try to index later
133 public IndexService getIndex() throws IOException {
134 IndexService lucin = getIndexService();
136 lucin.create(); // Happens when re-indexing all studies
140 public SimulationContext addProjectContext(Study aStudy,
141 SimulationContext.Properties cprop) throws MissedPropertyException,
142 InvalidPropertyException, MultiplyDefinedException,
144 // -------------------------------------------------------------------------------
145 SimulationContext added = getStepService().addSimulationContext(
146 getProjectElementService().getFirstStep(aStudy), cprop);
151 public SimulationContext addProjectContext(Study aStudy,
152 SimulationContext context) {
153 // ----------------------------------------------------------------------
154 SimulationContext added = getStepService().addSimulationContext(
155 getProjectElementService().getFirstStep(aStudy), context);
160 public boolean addContributor(Study aStudy, User user) {
161 // -----------------------------------------
162 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
163 for (Iterator<User> i = contributor.iterator(); i.hasNext();) {
164 User present = i.next();
165 if (present.equals(user))
168 boolean absent = aStudy.getModifiableActors().add(user); // User may already be a reviewer or an approver
170 aStudy.addRelation(new ContributorRelation(aStudy, user));
172 update(aStudy); // Else, useless to re-index the study
173 contributor.add(user);
178 * Moves this study from the Public to the Reference area of the repository. For being moved to the Reference area, the study must
179 * previously be approved.
181 * @return true if the move succeeded.
182 * @see #moveToPublic()
184 * @see Publication#approve(Date)
186 public boolean moveToReference(Study aStudy) {
187 // ---------------------------------
188 if (aStudy.getProgressState() != ProgressState.APPROVED)
190 if (aStudy.getVisibility() != Visibility.PUBLIC)
193 aStudy.setVisibility(Visibility.REFERENCE);
194 if (update(aStudy)) {
195 return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
200 public boolean update(Study aStudy, Properties sprop)
201 throws InvalidPropertyException {
202 if (sprop.getTitle() != null)
203 aStudy.setTitle(sprop.getTitle());
204 if (sprop.getSummary() != null)
205 aStudy.setAttribute(new DescriptionAttribute(aStudy, sprop
207 // TODO: To be completed
208 return update(aStudy);
211 public boolean buildReference(Study aStudy) {
212 String pattern = aStudy.getReference(); // The study being supposed just created, its reference is the reference pattern
213 IDBuilder tool = Database.selectIDBuilder(aStudy.getDate());
215 tool = new IDBuilder(aStudy.getDate());
216 Database.getSession().save(tool);
218 aStudy.setReference(tool.buildReference(pattern, aStudy));
222 public boolean publishes(Study aStudy, Document doc) {
223 // ---------------------------------------
224 if (!aStudy.publishes(doc)) {
225 Scenario[] scene = aStudy.getScenarii();
226 for (int i = 0; i < scene.length; i++) {
227 if (scene[i].publishes(doc))
234 public boolean removeContributor(Study aStudy, User... users) {
235 // ------------------------------------------------
236 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
237 Boolean done = false;
238 for (int i = 0; i < users.length; i++) {
239 User user = users[i];
240 for (Iterator<User> j = contributor.iterator(); j.hasNext();) {
241 User present = j.next();
242 if (!present.equals(user))
245 aStudy.removeRelation(ContributorRelation.class, user);
246 j.remove(); // Updates the contributor shortcut
256 public boolean removeProjectContext(Study aStudy, SimulationContext context) {
257 // ---------------------------------------------------------------
258 boolean done = getStepService().removeSimulationContext(
259 getProjectElementService().getFirstStep(aStudy), context);
264 public void setValidationCycle(Study aStudy, DocumentType type,
265 ValidationCycle.Properties vprop) {
266 HashMap<String, ValidationCycle> validactor = aStudy
267 .getValidationCycles();
268 if (validactor == null)
269 aStudy.setShortCuts(); // Initializes validactor and actor
271 String cname = type.getName();
272 ValidationCycle cycle = validactor.get(cname);
274 if (cycle != null && cycle.isAssigned()) {
275 cycle.resetActors(vprop);
278 cycle = new ValidationCycle(aStudy, vprop.setDocumentType(type));
280 ValidationCycleRelation link = cycle.getContext();
281 aStudy.addRelation(link);
282 validactor.put(cname, link.getTo()); // Replaces the cycle if exists as default,
283 } catch (Exception error) {
284 logger.error("Unable to re-index Knowledge Elements, reason:",
288 resetActorsShortCut(aStudy);
289 update(aStudy); // Re-index the study, just in case
292 private void resetActorsShortCut(Study aStudy) {
293 aStudy.getModifiableActors().clear();
294 // Get all actors involved in validation cycles
295 for (Iterator<ValidationCycle> i = aStudy.getValidationCycles()
296 .values().iterator(); i.hasNext();) {
297 ValidationCycle cycle = i.next();
298 User[] user = cycle.getAllActors();
299 for (int j = 0; j < user.length; j++)
300 aStudy.getModifiableActors().add(user[j]);
302 // Get all other actors
303 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
305 Relation link = i.next();
306 Class<?> kindof = link.getClass().getSuperclass();
307 if (!kindof.equals(ActorRelation.class))
309 aStudy.getModifiableActors().add(((ActorRelation) link).getTo());
314 * Demotes this study from In-Check to In-Draft then In-Work states. This function is called internally when demoting the final result
315 * document of the study.
317 * @return true if the demotion succeeded.
319 public boolean demote(Study aStudy) {
320 // ---------------------------
321 if (aStudy.getProgressState() == ProgressState.inCHECK)
322 aStudy.setProgressState(ProgressState.inDRAFT);
323 else if (aStudy.getProgressState() == ProgressState.inDRAFT)
324 aStudy.setProgressState(ProgressState.inWORK);
327 return update(aStudy);
330 public int generateLocalIndex(Study aStudy) {
331 aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1);
332 Database.getSession().update(aStudy);
333 return aStudy.getLastLocalIndex();
336 // ==============================================================================================================================
337 // Public member functions
338 // ==============================================================================================================================
340 public Scenario addScenario(Study aStudy, Scenario.Properties sprop)
341 throws MissedPropertyException, InvalidPropertyException,
342 MultiplyDefinedException, RuntimeException {
343 // -------------------------------------------------------
344 if (sprop.getManager() == null)
345 sprop.setManager(aStudy.getAuthor());
347 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
348 if (sprop.getBaseStep() != null)
350 .copyContentsUpTo(scenario, sprop.getBaseStep());
351 Scenario previous = sprop.getInsertAfter();
352 Session session = Database.getSession();
354 if (previous == null) {
355 aStudy.getScenariiList().add(scenario);
357 aStudy.getScenariiList().add(
358 aStudy.getScenariiList().indexOf(previous) + 1, scenario);
360 session.update(aStudy); // No need to update the Lucene index
361 session.save(scenario); // Must be done after updating this study because of the back reference to the study
362 if (sprop.getBaseStep() != null) {
363 // No need to update the Knowledge Element index as Knowledge Elements are not copied
364 scenario.refresh(); // Because saving the scenario changes the hashcode of copied Publications
366 KnowledgeElementType ucase = KnowledgeElement.selectType("usecase");
367 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
368 User admin = UserDirectory.selectUser(1); // First user created when creating the database
369 kprop.setType(ucase).setTitle(aStudy.getTitle())
370 .setValue(scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
372 getScenarioService().addKnowledgeElement(scenario, kprop);
379 private ScenarioService getScenarioService() {
380 return _scenarioService;
383 public void setScenarioService(ScenarioService scenarioService) {
384 _scenarioService = scenarioService;
388 * Promotes this study from In-Work to In-Draft then In-Check and APPROVED states. This function is called internally when promoting the
389 * final result document of the study.
391 * @return true if the demotion succeeded.
393 public boolean promote(Study aStudy) {
394 // ----------------------------
395 if (aStudy.getProgressState() == ProgressState.inWORK) {
396 aStudy.setProgressState(ProgressState.inDRAFT);
397 } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
398 aStudy.setProgressState(ProgressState.inCHECK);
399 Revision myvers = new Revision(aStudy.getVersion());
400 if (myvers.isMinor()) {
401 aStudy.setVersion(myvers.incrementAs(aStudy.getProgressState())
404 } else if (aStudy.getProgressState() == ProgressState.inCHECK) {
405 aStudy.setProgressState(ProgressState.APPROVED);
409 return update(aStudy);
413 * Moves this study from the Private to the Public area of the repository.
415 * @return true if the move succeeded.
418 public boolean moveToPublic(Study aStudy) {
419 // ------------------------------
420 if (aStudy.getVisibility() != Visibility.PRIVATE)
423 aStudy.setVisibility(Visibility.PUBLIC);
424 if (update(aStudy)) {
425 return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
430 private boolean update(Study aStudy) {
432 Database.getSession().update(aStudy); // Update of relational base
433 getIndex().update(aStudy); // Update of Lucene index
435 } catch (Exception error) {
436 logger.error("Unable to re-index the study '" + aStudy.getIndex()
437 + "', reason:", error);
442 private boolean updateKnowledgeElementsIndex(Study aStudy) {
443 // ----------------------------------------------
445 IndexService lucin = getIndex();
447 for (Iterator<Scenario> i = aStudy.getScenariiList().iterator(); i
449 Scenario scene = i.next();
450 for (Iterator<KnowledgeElement> j = scene
451 .getAllKnowledgeElements().iterator(); j.hasNext();) {
452 KnowledgeElement kelm = j.next();
457 } catch (Exception error) {
458 logger.error("Unable to re-index Knowledge Elements, reason:",
467 public IndexService getIndexService() {
468 return _indexService;
471 public void setIndexService(IndexService indexService) {
472 _indexService = indexService;
476 * Get project settings.
478 * @return Project settings service
480 private ProjectSettingsService getProjectSettings() {
481 return _projectSettingsService;
485 * Set project settings service.
487 * @param projectSettingsService
488 * project settings service
490 public void setProjectSettings(ProjectSettingsService projectSettingsService) {
491 _projectSettingsService = projectSettingsService;
495 * Get the projectElementService.
497 * @return the projectElementService
499 public ProjectElementService getProjectElementService() {
500 return _projectElementService;
504 * Set the projectElementService.
506 * @param projectElementService
507 * the projectElementService to set
509 public void setProjectElementService(
510 ProjectElementService projectElementService) {
511 _projectElementService = projectElementService;
515 * Get the stepService.
516 * @return the stepService
518 public StepService getStepService() {
523 * Set the stepService.
524 * @param stepService the stepService to set
526 public void setStepService(StepService stepService) {
527 _stepService = stepService;