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.log.AppLogger;
47 import org.splat.service.technical.IndexService;
48 import org.splat.service.technical.ProjectSettingsService;
49 import org.splat.som.Revision;
52 * This class defines all methods for creation, modification the study.
53 * @author Maria KRUCHININA
56 public class StudyServiceImpl implements StudyService {
59 * logger for the service.
61 public final static AppLogger logger = AppLogger.getLogger(StudyServiceImpl.class);
63 private IndexService _indexService;
65 private StepService _stepService;
67 private ScenarioService _scenarioService;
69 private ProjectSettingsService _projectSettingsService;
71 private ProjectElementService _projectElementService;
74 * Get the simulation context list for displaying drop-down list values populating
75 * on the "Create new study" screen.
77 * @see org.splat.service.StudyService#getSimulationContextList()
79 public List<SimulationContext> getSimulationContextList() {
80 //TODO: remove the commit transaction ...
81 Session connex = Database.getSession();
82 Transaction transax = connex.beginTransaction();
84 SimulationContext.Properties cprop = new SimulationContext.Properties();
85 SimulationContextType product = SimulationContext.selectType("product");
86 List<SimulationContext> resList = Database.selectSimulationContextsWhere(cprop.setType(product));
93 public Study selectStudy(long index) {
94 // -------------------------------------------
95 StringBuffer query = new StringBuffer("from Study where rid='").append(
97 Study result = (Study) Database.getSession().createQuery(
98 query.toString()).uniqueResult();
100 result.loadWorkflow();
104 public Study selectStudy(String refid) {
105 // ----------------------------------------------
106 StringBuffer query = new StringBuffer("from Study where sid='").append(
108 Study result = (Study) Database.getSession().createQuery(
109 query.toString()).uniqueResult();
111 result.loadWorkflow();
115 public Study createStudy(Study.Properties sprop)
116 throws MissedPropertyException, InvalidPropertyException,
117 MultiplyDefinedException, RuntimeException {
118 sprop.setReference(getProjectSettings().getReferencePattern());
119 Study study = new Study(sprop);
121 buildReference(study);
122 Database.getSession().save(study); // TODO: use StudyDAO and throw out Database.
124 IndexService lucin = getIndex();
126 } catch (IOException error) {
127 logger.error("Unable to index the study '" + study.getIndex()
128 + "', reason:", error);
129 // Continue and try to index later
134 public IndexService getIndex() throws IOException {
135 IndexService lucin = getIndexService();
137 lucin.create(); // Happens when re-indexing all studies
141 public SimulationContext addProjectContext(Study aStudy,
142 SimulationContext.Properties cprop) throws MissedPropertyException,
143 InvalidPropertyException, MultiplyDefinedException,
145 // -------------------------------------------------------------------------------
146 SimulationContext added = getStepService().addSimulationContext(
147 getProjectElementService().getFirstStep(aStudy), cprop);
152 public SimulationContext addProjectContext(Study aStudy,
153 SimulationContext context) {
154 // ----------------------------------------------------------------------
155 SimulationContext added = getStepService().addSimulationContext(
156 getProjectElementService().getFirstStep(aStudy), context);
161 public boolean addContributor(Study aStudy, User user) {
162 // -----------------------------------------
163 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
164 for (Iterator<User> i = contributor.iterator(); i.hasNext();) {
165 User present = i.next();
166 if (present.equals(user))
169 boolean absent = aStudy.getModifiableActors().add(user); // User may already be a reviewer or an approver
171 aStudy.addRelation(new ContributorRelation(aStudy, user));
173 update(aStudy); // Else, useless to re-index the study
174 contributor.add(user);
179 * Moves this study from the Public to the Reference area of the repository. For being moved to the Reference area, the study must
180 * previously be approved.
182 * @return true if the move succeeded.
183 * @see #moveToPublic()
185 * @see Publication#approve(Date)
187 public boolean moveToReference(Study aStudy) {
188 // ---------------------------------
189 if (aStudy.getProgressState() != ProgressState.APPROVED)
191 if (aStudy.getVisibility() != Visibility.PUBLIC)
194 aStudy.setVisibility(Visibility.REFERENCE);
195 if (update(aStudy)) {
196 return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
201 public boolean update(Study aStudy, Properties sprop)
202 throws InvalidPropertyException {
203 if (sprop.getTitle() != null)
204 aStudy.setTitle(sprop.getTitle());
205 if (sprop.getSummary() != null)
206 aStudy.setAttribute(new DescriptionAttribute(aStudy, sprop
208 // TODO: To be completed
209 return update(aStudy);
212 public boolean buildReference(Study aStudy) {
213 String pattern = aStudy.getReference(); // The study being supposed just created, its reference is the reference pattern
214 IDBuilder tool = Database.selectIDBuilder(aStudy.getDate());
216 tool = new IDBuilder(aStudy.getDate());
217 Database.getSession().save(tool);
219 aStudy.setReference(tool.buildReference(pattern, aStudy));
223 public boolean publishes(Study aStudy, Document doc) {
224 // ---------------------------------------
225 if (!aStudy.publishes(doc)) {
226 Scenario[] scene = aStudy.getScenarii();
227 for (int i = 0; i < scene.length; i++) {
228 if (scene[i].publishes(doc))
235 public boolean removeContributor(Study aStudy, User... users) {
236 // ------------------------------------------------
237 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
238 Boolean done = false;
239 for (int i = 0; i < users.length; i++) {
240 User user = users[i];
241 for (Iterator<User> j = contributor.iterator(); j.hasNext();) {
242 User present = j.next();
243 if (!present.equals(user))
246 aStudy.removeRelation(ContributorRelation.class, user);
247 j.remove(); // Updates the contributor shortcut
257 public boolean removeProjectContext(Study aStudy, SimulationContext context) {
258 // ---------------------------------------------------------------
259 boolean done = getStepService().removeSimulationContext(
260 getProjectElementService().getFirstStep(aStudy), context);
265 public void setValidationCycle(Study aStudy, DocumentType type,
266 ValidationCycle.Properties vprop) {
267 HashMap<String, ValidationCycle> validactor = aStudy
268 .getValidationCycles();
269 if (validactor == null)
270 aStudy.setShortCuts(); // Initializes validactor and actor
272 String cname = type.getName();
273 ValidationCycle cycle = validactor.get(cname);
275 if (cycle != null && cycle.isAssigned()) {
276 cycle.resetActors(vprop);
279 cycle = new ValidationCycle(aStudy, vprop.setDocumentType(type));
281 ValidationCycleRelation link = cycle.getContext();
282 aStudy.addRelation(link);
283 validactor.put(cname, link.getTo()); // Replaces the cycle if exists as default,
284 } catch (Exception error) {
285 logger.error("Unable to re-index Knowledge Elements, reason:",
289 resetActorsShortCut(aStudy);
290 update(aStudy); // Re-index the study, just in case
293 private void resetActorsShortCut(Study aStudy) {
294 aStudy.getModifiableActors().clear();
295 // Get all actors involved in validation cycles
296 for (Iterator<ValidationCycle> i = aStudy.getValidationCycles()
297 .values().iterator(); i.hasNext();) {
298 ValidationCycle cycle = i.next();
299 User[] user = cycle.getAllActors();
300 for (int j = 0; j < user.length; j++)
301 aStudy.getModifiableActors().add(user[j]);
303 // Get all other actors
304 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
306 Relation link = i.next();
307 Class<?> kindof = link.getClass().getSuperclass();
308 if (!kindof.equals(ActorRelation.class))
310 aStudy.getModifiableActors().add(((ActorRelation) link).getTo());
315 * Demotes this study from In-Check to In-Draft then In-Work states. This function is called internally when demoting the final result
316 * document of the study.
318 * @return true if the demotion succeeded.
320 public boolean demote(Study aStudy) {
321 // ---------------------------
322 if (aStudy.getProgressState() == ProgressState.inCHECK)
323 aStudy.setProgressState(ProgressState.inDRAFT);
324 else if (aStudy.getProgressState() == ProgressState.inDRAFT)
325 aStudy.setProgressState(ProgressState.inWORK);
328 return update(aStudy);
331 public int generateLocalIndex(Study aStudy) {
332 aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1);
333 Database.getSession().update(aStudy);
334 return aStudy.getLastLocalIndex();
337 // ==============================================================================================================================
338 // Public member functions
339 // ==============================================================================================================================
341 public Scenario addScenario(Study aStudy, Scenario.Properties sprop)
342 throws MissedPropertyException, InvalidPropertyException,
343 MultiplyDefinedException, RuntimeException {
344 // -------------------------------------------------------
345 if (sprop.getManager() == null)
346 sprop.setManager(aStudy.getAuthor());
348 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
349 if (sprop.getBaseStep() != null)
351 .copyContentsUpTo(scenario, sprop.getBaseStep());
352 Scenario previous = sprop.getInsertAfter();
353 Session session = Database.getSession();
355 if (previous == null) {
356 aStudy.getScenariiList().add(scenario);
358 aStudy.getScenariiList().add(
359 aStudy.getScenariiList().indexOf(previous) + 1, scenario);
361 session.update(aStudy); // No need to update the Lucene index
362 session.save(scenario); // Must be done after updating this study because of the back reference to the study
363 if (sprop.getBaseStep() != null) {
364 // No need to update the Knowledge Element index as Knowledge Elements are not copied
365 scenario.refresh(); // Because saving the scenario changes the hashcode of copied Publications
367 KnowledgeElementType ucase = KnowledgeElement.selectType("usecase");
368 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
369 User admin = UserDirectory.selectUser(1); // First user created when creating the database
370 kprop.setType(ucase).setTitle(aStudy.getTitle())
371 .setValue(scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
373 getScenarioService().addKnowledgeElement(scenario, kprop);
380 private ScenarioService getScenarioService() {
381 return _scenarioService;
384 public void setScenarioService(ScenarioService scenarioService) {
385 _scenarioService = scenarioService;
389 * Promotes this study from In-Work to In-Draft then In-Check and APPROVED states. This function is called internally when promoting the
390 * final result document of the study.
392 * @return true if the demotion succeeded.
394 public boolean promote(Study aStudy) {
395 // ----------------------------
396 if (aStudy.getProgressState() == ProgressState.inWORK) {
397 aStudy.setProgressState(ProgressState.inDRAFT);
398 } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
399 aStudy.setProgressState(ProgressState.inCHECK);
400 Revision myvers = new Revision(aStudy.getVersion());
401 if (myvers.isMinor()) {
402 aStudy.setVersion(myvers.incrementAs(aStudy.getProgressState())
405 } else if (aStudy.getProgressState() == ProgressState.inCHECK) {
406 aStudy.setProgressState(ProgressState.APPROVED);
410 return update(aStudy);
414 * Moves this study from the Private to the Public area of the repository.
416 * @return true if the move succeeded.
419 public boolean moveToPublic(Study aStudy) {
420 // ------------------------------
421 if (aStudy.getVisibility() != Visibility.PRIVATE)
424 aStudy.setVisibility(Visibility.PUBLIC);
425 if (update(aStudy)) {
426 return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
431 private boolean update(Study aStudy) {
433 Database.getSession().update(aStudy); // Update of relational base
434 getIndex().update(aStudy); // Update of Lucene index
436 } catch (Exception error) {
437 logger.error("Unable to re-index the study '" + aStudy.getIndex()
438 + "', reason:", error);
443 private boolean updateKnowledgeElementsIndex(Study aStudy) {
444 // ----------------------------------------------
446 IndexService lucin = getIndex();
448 for (Iterator<Scenario> i = aStudy.getScenariiList().iterator(); i
450 Scenario scene = i.next();
451 for (Iterator<KnowledgeElement> j = scene
452 .getAllKnowledgeElements().iterator(); j.hasNext();) {
453 KnowledgeElement kelm = j.next();
458 } catch (Exception error) {
459 logger.error("Unable to re-index Knowledge Elements, reason:",
468 public IndexService getIndexService() {
469 return _indexService;
472 public void setIndexService(IndexService indexService) {
473 _indexService = indexService;
477 * Get project settings.
479 * @return Project settings service
481 private ProjectSettingsService getProjectSettings() {
482 return _projectSettingsService;
486 * Set project settings service.
488 * @param projectSettingsService
489 * project settings service
491 public void setProjectSettings(ProjectSettingsService projectSettingsService) {
492 _projectSettingsService = projectSettingsService;
496 * Get the projectElementService.
498 * @return the projectElementService
500 public ProjectElementService getProjectElementService() {
501 return _projectElementService;
505 * Set the projectElementService.
507 * @param projectElementService
508 * the projectElementService to set
510 public void setProjectElementService(
511 ProjectElementService projectElementService) {
512 _projectElementService = projectElementService;
516 * Get the stepService.
517 * @return the stepService
519 public StepService getStepService() {
524 * Set the stepService.
525 * @param stepService the stepService to set
527 public void setStepService(StepService stepService) {
528 _stepService = stepService;