1 /*****************************************************************************
5 * Creation date 06.10.2012
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.splat.dal.bo.kernel.Relation;
21 import org.splat.dal.bo.kernel.User;
22 import org.splat.dal.bo.som.ActorRelation;
23 import org.splat.dal.bo.som.ContributorRelation;
24 import org.splat.dal.bo.som.DescriptionAttribute;
25 import org.splat.dal.bo.som.Document;
26 import org.splat.dal.bo.som.DocumentType;
27 import org.splat.dal.bo.som.IDBuilder;
28 import org.splat.dal.bo.som.KnowledgeElement;
29 import org.splat.dal.bo.som.KnowledgeElementType;
30 import org.splat.dal.bo.som.ProgressState;
31 import org.splat.dal.bo.som.Publication;
32 import org.splat.dal.bo.som.Scenario;
33 import org.splat.dal.bo.som.SimulationContext;
34 import org.splat.dal.bo.som.Study;
35 import org.splat.dal.bo.som.ValidationCycle;
36 import org.splat.dal.bo.som.ValidationCycleRelation;
37 import org.splat.dal.bo.som.Visibility;
38 import org.splat.dal.bo.som.Study.Properties;
39 import org.splat.dal.dao.som.Database;
40 import org.splat.kernel.InvalidPropertyException;
41 import org.splat.kernel.MissedPropertyException;
42 import org.splat.kernel.MultiplyDefinedException;
43 import org.splat.kernel.UserDirectory;
44 import org.splat.service.technical.IndexService;
45 import org.splat.service.technical.ProjectSettingsService;
46 import org.splat.som.Revision;
52 public class StudyServiceImpl implements StudyService {
54 public final static Logger logger = Logger.getLogger(org.splat.service.StudyServiceImpl.class);
56 private IndexService _indexService;
58 private StepService _stepService;
60 private ScenarioService _scenarioService;
62 private ProjectSettingsService _projectSettingsService;
64 private ProjectElementService _projectElementService;
66 public Study selectStudy(int index) {
67 // -------------------------------------------
68 StringBuffer query = new StringBuffer("from Study where rid='").append(
70 Study result = (Study) Database.getSession().createQuery(
71 query.toString()).uniqueResult();
73 result.loadWorkflow();
77 public Study selectStudy(String refid) {
78 // ----------------------------------------------
79 StringBuffer query = new StringBuffer("from Study where sid='").append(
81 Study result = (Study) Database.getSession().createQuery(
82 query.toString()).uniqueResult();
84 result.loadWorkflow();
88 public Study createStudy(Study.Properties sprop)
89 throws MissedPropertyException, InvalidPropertyException,
90 MultiplyDefinedException, RuntimeException {
91 sprop.setReference(getProjectSettings().getReferencePattern());
92 Study study = new Study(sprop);
94 buildReference(study);
95 Database.getSession().save(study); // TODO: use StudyDAO and throw out Database.
97 IndexService lucin = getIndex();
99 } catch (IOException error) {
100 logger.error("Unable to index the study '" + study.getIndex()
101 + "', reason:", error);
102 // Continue and try to index later
107 public IndexService getIndex() throws IOException {
108 IndexService lucin = getIndexService();
110 lucin.create(); // Happens when re-indexing all studies
114 public SimulationContext addProjectContext(Study aStudy,
115 SimulationContext.Properties cprop) throws MissedPropertyException,
116 InvalidPropertyException, MultiplyDefinedException,
118 // -------------------------------------------------------------------------------
119 SimulationContext added = getStepService().addSimulationContext(
120 getProjectElementService().getFirstStep(aStudy), cprop);
125 public SimulationContext addProjectContext(Study aStudy,
126 SimulationContext context) {
127 // ----------------------------------------------------------------------
128 SimulationContext added = getStepService().addSimulationContext(
129 getProjectElementService().getFirstStep(aStudy), context);
134 public boolean addContributor(Study aStudy, User user) {
135 // -----------------------------------------
136 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
137 for (Iterator<User> i = contributor.iterator(); i.hasNext();) {
138 User present = i.next();
139 if (present.equals(user))
142 boolean absent = aStudy.getModifiableActors().add(user); // User may already be a reviewer or an approver
144 aStudy.addRelation(new ContributorRelation(aStudy, user));
146 update(aStudy); // Else, useless to re-index the study
147 contributor.add(user);
152 * Moves this study from the Public to the Reference area of the repository. For being moved to the Reference area, the study must
153 * previously be approved.
155 * @return true if the move succeeded.
156 * @see #moveToPublic()
158 * @see Publication#approve(Date)
160 public boolean moveToReference(Study aStudy) {
161 // ---------------------------------
162 if (aStudy.getProgressState() != ProgressState.APPROVED)
164 if (aStudy.getVisibility() != Visibility.PUBLIC)
167 aStudy.setVisibility(Visibility.REFERENCE);
168 if (update(aStudy)) {
169 return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
174 public boolean update(Study aStudy, Properties sprop)
175 throws InvalidPropertyException {
176 if (sprop.getTitle() != null)
177 aStudy.setTitle(sprop.getTitle());
178 if (sprop.getSummary() != null)
179 aStudy.setAttribute(new DescriptionAttribute(aStudy, sprop
181 // TODO: To be completed
182 return update(aStudy);
185 public boolean buildReference(Study aStudy) {
186 String pattern = aStudy.getReference(); // The study being supposed just created, its reference is the reference pattern
187 IDBuilder tool = Database.selectIDBuilder(aStudy.getDate());
189 tool = new IDBuilder(aStudy.getDate());
190 Database.getSession().save(tool);
192 aStudy.setReference(tool.buildReference(pattern, aStudy));
196 public boolean publishes(Study aStudy, Document doc) {
197 // ---------------------------------------
198 if (!aStudy.publishes(doc)) {
199 Scenario[] scene = aStudy.getScenarii();
200 for (int i = 0; i < scene.length; i++) {
201 if (scene[i].publishes(doc))
208 public boolean removeContributor(Study aStudy, User... users) {
209 // ------------------------------------------------
210 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
211 Boolean done = false;
212 for (int i = 0; i < users.length; i++) {
213 User user = users[i];
214 for (Iterator<User> j = contributor.iterator(); j.hasNext();) {
215 User present = j.next();
216 if (!present.equals(user))
219 aStudy.removeRelation(ContributorRelation.class, user);
220 j.remove(); // Updates the contributor shortcut
230 public boolean removeProjectContext(Study aStudy, SimulationContext context) {
231 // ---------------------------------------------------------------
232 boolean done = getStepService().removeSimulationContext(
233 getProjectElementService().getFirstStep(aStudy), context);
238 public void setValidationCycle(Study aStudy, DocumentType type,
239 ValidationCycle.Properties vprop) {
240 HashMap<String, ValidationCycle> validactor = aStudy
241 .getValidationCycles();
242 if (validactor == null)
243 aStudy.setShortCuts(); // Initializes validactor and actor
245 String cname = type.getName();
246 ValidationCycle cycle = validactor.get(cname);
248 if (cycle != null && cycle.isAssigned()) {
249 cycle.resetActors(vprop);
252 cycle = new ValidationCycle(aStudy, vprop.setDocumentType(type));
254 ValidationCycleRelation link = cycle.getContext();
255 aStudy.addRelation(link);
256 validactor.put(cname, link.getTo()); // Replaces the cycle if exists as default,
257 } catch (Exception error) {
258 logger.error("Unable to re-index Knowledge Elements, reason:",
262 resetActorsShortCut(aStudy);
263 update(aStudy); // Re-index the study, just in case
266 private void resetActorsShortCut(Study aStudy) {
267 aStudy.getModifiableActors().clear();
268 // Get all actors involved in validation cycles
269 for (Iterator<ValidationCycle> i = aStudy.getValidationCycles()
270 .values().iterator(); i.hasNext();) {
271 ValidationCycle cycle = i.next();
272 User[] user = cycle.getAllActors();
273 for (int j = 0; j < user.length; j++)
274 aStudy.getModifiableActors().add(user[j]);
276 // Get all other actors
277 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
279 Relation link = i.next();
280 Class<?> kindof = link.getClass().getSuperclass();
281 if (!kindof.equals(ActorRelation.class))
283 aStudy.getModifiableActors().add(((ActorRelation) link).getTo());
288 * Demotes this study from In-Check to In-Draft then In-Work states. This function is called internally when demoting the final result
289 * document of the study.
291 * @return true if the demotion succeeded.
293 public boolean demote(Study aStudy) {
294 // ---------------------------
295 if (aStudy.getProgressState() == ProgressState.inCHECK)
296 aStudy.setProgressState(ProgressState.inDRAFT);
297 else if (aStudy.getProgressState() == ProgressState.inDRAFT)
298 aStudy.setProgressState(ProgressState.inWORK);
301 return update(aStudy);
304 public int generateLocalIndex(Study aStudy) {
305 aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1);
306 Database.getSession().update(aStudy);
307 return aStudy.getLastLocalIndex();
310 // ==============================================================================================================================
311 // Public member functions
312 // ==============================================================================================================================
314 public Scenario addScenario(Study aStudy, Scenario.Properties sprop)
315 throws MissedPropertyException, InvalidPropertyException,
316 MultiplyDefinedException, RuntimeException {
317 // -------------------------------------------------------
318 if (sprop.getManager() == null)
319 sprop.setManager(aStudy.getAuthor());
321 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
322 if (sprop.getBaseStep() != null)
324 .copyContentsUpTo(scenario, sprop.getBaseStep());
325 Scenario previous = sprop.getInsertAfter();
326 Session session = Database.getSession();
328 if (previous == null) {
329 aStudy.getScenariiList().add(scenario);
331 aStudy.getScenariiList().add(
332 aStudy.getScenariiList().indexOf(previous) + 1, scenario);
334 session.update(aStudy); // No need to update the Lucene index
335 session.save(scenario); // Must be done after updating this study because of the back reference to the study
336 if (sprop.getBaseStep() != null) {
337 // No need to update the Knowledge Element index as Knowledge Elements are not copied
338 scenario.refresh(); // Because saving the scenario changes the hashcode of copied Publications
340 KnowledgeElementType ucase = KnowledgeElement.selectType("usecase");
341 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
342 User admin = UserDirectory.selectUser(1); // First user created when creating the database
343 kprop.setType(ucase).setTitle(aStudy.getTitle())
344 .setValue(scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
346 getScenarioService().addKnowledgeElement(scenario, kprop);
353 private ScenarioService getScenarioService() {
354 return _scenarioService;
357 public void setScenarioService(ScenarioService scenarioService) {
358 _scenarioService = scenarioService;
362 * Promotes this study from In-Work to In-Draft then In-Check and APPROVED states. This function is called internally when promoting the
363 * final result document of the study.
365 * @return true if the demotion succeeded.
367 public boolean promote(Study aStudy) {
368 // ----------------------------
369 if (aStudy.getProgressState() == ProgressState.inWORK) {
370 aStudy.setProgressState(ProgressState.inDRAFT);
371 } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
372 aStudy.setProgressState(ProgressState.inCHECK);
373 Revision myvers = new Revision(aStudy.getVersion());
374 if (myvers.isMinor()) {
375 aStudy.setVersion(myvers.incrementAs(aStudy.getProgressState())
378 } else if (aStudy.getProgressState() == ProgressState.inCHECK) {
379 aStudy.setProgressState(ProgressState.APPROVED);
383 return update(aStudy);
387 * Moves this study from the Private to the Public area of the repository.
389 * @return true if the move succeeded.
392 public boolean moveToPublic(Study aStudy) {
393 // ------------------------------
394 if (aStudy.getVisibility() != Visibility.PRIVATE)
397 aStudy.setVisibility(Visibility.PUBLIC);
398 if (update(aStudy)) {
399 return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
404 private boolean update(Study aStudy) {
406 Database.getSession().update(aStudy); // Update of relational base
407 getIndex().update(aStudy); // Update of Lucene index
409 } catch (Exception error) {
410 logger.error("Unable to re-index the study '" + aStudy.getIndex()
411 + "', reason:", error);
416 private boolean updateKnowledgeElementsIndex(Study aStudy) {
417 // ----------------------------------------------
419 IndexService lucin = getIndex();
421 for (Iterator<Scenario> i = aStudy.getScenariiList().iterator(); i
423 Scenario scene = i.next();
424 for (Iterator<KnowledgeElement> j = scene
425 .getAllKnowledgeElements().iterator(); j.hasNext();) {
426 KnowledgeElement kelm = j.next();
431 } catch (Exception error) {
432 logger.error("Unable to re-index Knowledge Elements, reason:",
441 public IndexService getIndexService() {
442 return _indexService;
445 public void setIndexService(IndexService indexService) {
446 _indexService = indexService;
450 * Get project settings.
452 * @return Project settings service
454 private ProjectSettingsService getProjectSettings() {
455 return _projectSettingsService;
459 * Set project settings service.
461 * @param projectSettingsService
462 * project settings service
464 public void setProjectSettings(ProjectSettingsService projectSettingsService) {
465 _projectSettingsService = projectSettingsService;
469 * Get the projectElementService.
471 * @return the projectElementService
473 public ProjectElementService getProjectElementService() {
474 return _projectElementService;
478 * Set the projectElementService.
480 * @param projectElementService
481 * the projectElementService to set
483 public void setProjectElementService(
484 ProjectElementService projectElementService) {
485 _projectElementService = projectElementService;
489 * Get the stepService.
490 * @return the stepService
492 public StepService getStepService() {
497 * Set the stepService.
498 * @param stepService the stepService to set
500 public void setStepService(StepService stepService) {
501 _stepService = stepService;