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 createStudy(Study.Properties sprop)
67 throws MissedPropertyException, InvalidPropertyException,
68 MultiplyDefinedException, RuntimeException {
69 sprop.setReference(getProjectSettings().getReferencePattern());
70 Study study = new Study(sprop);
72 buildReference(study);
73 Database.getSession().save(study); // TODO: use StudyDAO and throw out Database.
75 IndexService lucin = getIndex();
77 } catch (IOException error) {
78 logger.error("Unable to index the study '" + study.getIndex()
79 + "', reason:", error);
80 // Continue and try to index later
85 public IndexService getIndex() throws IOException {
86 IndexService lucin = getIndexService();
88 lucin.create(); // Happens when re-indexing all studies
92 public SimulationContext addProjectContext(Study aStudy,
93 SimulationContext.Properties cprop) throws MissedPropertyException,
94 InvalidPropertyException, MultiplyDefinedException,
96 // -------------------------------------------------------------------------------
97 SimulationContext added = getStepService().addSimulationContext(
98 getProjectElementService().getFirstStep(aStudy), cprop);
106 public StepService getStepService() {
110 public void setStepService(StepService stepService) {
111 _stepService = stepService;
114 public SimulationContext addProjectContext(Study aStudy,
115 SimulationContext context) {
116 // ----------------------------------------------------------------------
117 SimulationContext added = getStepService().addSimulationContext(
118 getProjectElementService().getFirstStep(aStudy), context);
123 public boolean addContributor(Study aStudy, User user) {
124 // -----------------------------------------
125 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
126 for (Iterator<User> i = contributor.iterator(); i.hasNext();) {
127 User present = i.next();
128 if (present.equals(user))
131 boolean absent = aStudy.getModifiableActors().add(user); // User may already be a reviewer or an approver
133 aStudy.addRelation(new ContributorRelation(aStudy, user));
135 update(aStudy); // Else, useless to re-index the study
136 contributor.add(user);
141 * Moves this study from the Public to the Reference area of the repository. For being moved to the Reference area, the study must
142 * previously be approved.
144 * @return true if the move succeeded.
145 * @see #moveToPublic()
147 * @see Publication#approve(Date)
149 public boolean moveToReference(Study aStudy) {
150 // ---------------------------------
151 if (aStudy.getProgressState() != ProgressState.APPROVED)
153 if (aStudy.getVisibility() != Visibility.PUBLIC)
156 aStudy.setVisibility(Visibility.REFERENCE);
157 if (update(aStudy)) {
158 return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
163 public boolean update(Study aStudy, Properties sprop)
164 throws InvalidPropertyException {
165 if (sprop.getTitle() != null)
166 aStudy.setTitle(sprop.getTitle());
167 if (sprop.getSummary() != null)
168 aStudy.setAttribute(new DescriptionAttribute(aStudy, sprop
170 // TODO: To be completed
171 return update(aStudy);
174 public boolean buildReference(Study aStudy) {
175 String pattern = aStudy.getReference(); // The study being supposed just created, its reference is the reference pattern
176 IDBuilder tool = Database.selectIDBuilder(aStudy.getDate());
178 tool = new IDBuilder(aStudy.getDate());
179 Database.getSession().save(tool);
181 aStudy.setReference(tool.buildReference(pattern, aStudy));
185 public boolean publishes(Study aStudy, Document doc) {
186 // ---------------------------------------
187 if (!aStudy.publishes(doc)) {
188 Scenario[] scene = aStudy.getScenarii();
189 for (int i = 0; i < scene.length; i++) {
190 if (scene[i].publishes(doc))
197 public boolean removeContributor(Study aStudy, User... users) {
198 // ------------------------------------------------
199 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
200 Boolean done = false;
201 for (int i = 0; i < users.length; i++) {
202 User user = users[i];
203 for (Iterator<User> j = contributor.iterator(); j.hasNext();) {
204 User present = j.next();
205 if (!present.equals(user))
208 aStudy.removeRelation(ContributorRelation.class, user);
209 j.remove(); // Updates the contributor shortcut
219 public boolean removeProjectContext(Study aStudy, SimulationContext context) {
220 // ---------------------------------------------------------------
221 boolean done = getStepService().removeSimulationContext(
222 getProjectElementService().getFirstStep(aStudy), context);
227 public void setValidationCycle(Study aStudy, DocumentType type,
228 ValidationCycle.Properties vprop) {
229 HashMap<String, ValidationCycle> validactor = aStudy
230 .getValidationCycles();
231 if (validactor == null)
232 aStudy.setShortCuts(); // Initializes validactor and actor
234 String cname = type.getName();
235 ValidationCycle cycle = validactor.get(cname);
237 if (cycle != null && cycle.isAssigned()) {
238 cycle.resetActors(vprop);
241 cycle = new ValidationCycle(aStudy, vprop.setDocumentType(type));
243 ValidationCycleRelation link = cycle.getContext();
244 aStudy.addRelation(link);
245 validactor.put(cname, link.getTo()); // Replaces the cycle if exists as default,
246 } catch (Exception error) {
247 logger.error("Unable to re-index Knowledge Elements, reason:",
251 resetActorsShortCut(aStudy);
252 update(aStudy); // Re-index the study, just in case
255 private void resetActorsShortCut(Study aStudy) {
256 aStudy.getModifiableActors().clear();
257 // Get all actors involved in validation cycles
258 for (Iterator<ValidationCycle> i = aStudy.getValidationCycles()
259 .values().iterator(); i.hasNext();) {
260 ValidationCycle cycle = i.next();
261 User[] user = cycle.getAllActors();
262 for (int j = 0; j < user.length; j++)
263 aStudy.getModifiableActors().add(user[j]);
265 // Get all other actors
266 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
268 Relation link = i.next();
269 Class<?> kindof = link.getClass().getSuperclass();
270 if (!kindof.equals(ActorRelation.class))
272 aStudy.getModifiableActors().add(((ActorRelation) link).getTo());
277 * Demotes this study from In-Check to In-Draft then In-Work states. This function is called internally when demoting the final result
278 * document of the study.
280 * @return true if the demotion succeeded.
282 public boolean demote(Study aStudy) {
283 // ---------------------------
284 if (aStudy.getProgressState() == ProgressState.inCHECK)
285 aStudy.setProgressState(ProgressState.inDRAFT);
286 else if (aStudy.getProgressState() == ProgressState.inDRAFT)
287 aStudy.setProgressState(ProgressState.inWORK);
290 return update(aStudy);
293 public int generateLocalIndex(Study aStudy) {
294 aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1);
295 Database.getSession().update(this);
296 return aStudy.getLastLocalIndex();
299 // ==============================================================================================================================
300 // Public member functions
301 // ==============================================================================================================================
303 public Scenario addScenario(Study aStudy, Scenario.Properties sprop)
304 throws MissedPropertyException, InvalidPropertyException,
305 MultiplyDefinedException, RuntimeException {
306 // -------------------------------------------------------
307 if (sprop.getManager() == null)
308 sprop.setManager(aStudy.getAuthor());
310 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
311 if (sprop.getBaseStep() != null)
313 .copyContentsUpTo(scenario, sprop.getBaseStep());
314 Scenario previous = sprop.getInsertAfter();
315 Session session = Database.getSession();
317 if (previous == null) {
318 aStudy.getScenariiList().add(scenario);
320 aStudy.getScenariiList().add(
321 aStudy.getScenariiList().indexOf(previous) + 1, scenario);
323 session.update(this); // No need to update the Lucene index
324 session.save(scenario); // Must be done after updating this study because of the back reference to the study
325 if (sprop.getBaseStep() != null) {
326 // No need to update the Knowledge Element index as Knowledge Elements are not copied
327 scenario.refresh(); // Because saving the scenario changes the hashcode of copied Publications
329 KnowledgeElementType ucase = KnowledgeElement.selectType("usecase");
330 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
331 User admin = UserDirectory.selectUser(1); // First user created when creating the database
332 kprop.setType(ucase).setTitle(aStudy.getTitle())
333 .setValue(scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
335 getScenarioService().addKnowledgeElement(scenario, kprop);
342 private ScenarioService getScenarioService() {
343 return _scenarioService;
346 public void setScenarioService(ScenarioService scenarioService) {
347 _scenarioService = scenarioService;
351 * Promotes this study from In-Work to In-Draft then In-Check and APPROVED states. This function is called internally when promoting the
352 * final result document of the study.
354 * @return true if the demotion succeeded.
356 public boolean promote(Study aStudy) {
357 // ----------------------------
358 if (aStudy.getProgressState() == ProgressState.inWORK) {
359 aStudy.setProgressState(ProgressState.inDRAFT);
360 } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
361 aStudy.setProgressState(ProgressState.inCHECK);
362 Revision myvers = new Revision(aStudy.getVersion());
363 if (myvers.isMinor()) {
364 aStudy.setVersion(myvers.incrementAs(aStudy.getProgressState())
367 } else if (aStudy.getProgressState() == ProgressState.inCHECK) {
368 aStudy.setProgressState(ProgressState.APPROVED);
372 return update(aStudy);
376 * Moves this study from the Private to the Public area of the repository.
378 * @return true if the move succeeded.
381 public boolean moveToPublic(Study aStudy) {
382 // ------------------------------
383 if (aStudy.getVisibility() != Visibility.PRIVATE)
386 aStudy.setVisibility(Visibility.PUBLIC);
387 if (update(aStudy)) {
388 return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
393 private boolean update(Study aStudy) {
395 Database.getSession().update(aStudy); // Update of relational base
396 getIndex().update(aStudy); // Update of Lucene index
398 } catch (Exception error) {
399 logger.error("Unable to re-index the study '" + aStudy.getIndex()
400 + "', reason:", error);
405 private boolean updateKnowledgeElementsIndex(Study aStudy) {
406 // ----------------------------------------------
408 IndexService lucin = getIndex();
410 for (Iterator<Scenario> i = aStudy.getScenariiList().iterator(); i
412 Scenario scene = i.next();
413 for (Iterator<KnowledgeElement> j = scene
414 .getAllKnowledgeElements().iterator(); j.hasNext();) {
415 KnowledgeElement kelm = j.next();
420 } catch (Exception error) {
421 logger.error("Unable to re-index Knowledge Elements, reason:",
430 public IndexService getIndexService() {
431 return _indexService;
434 public void setIndexService(IndexService indexService) {
435 _indexService = indexService;
439 * Get project settings.
441 * @return Project settings service
443 private ProjectSettingsService getProjectSettings() {
444 return _projectSettingsService;
448 * Set project settings service.
450 * @param projectSettingsService
451 * project settings service
453 public void setProjectSettings(ProjectSettingsService projectSettingsService) {
454 _projectSettingsService = projectSettingsService;
458 * Get the projectElementService.
460 * @return the projectElementService
462 public ProjectElementService getProjectElementService() {
463 return _projectElementService;
467 * Set the projectElementService.
469 * @param projectElementService
470 * the projectElementService to set
472 public void setProjectElementService(
473 ProjectElementService projectElementService) {
474 _projectElementService = projectElementService;