]> SALOME platform Git repositories - tools/siman.git/blob - Workspace/Siman-Common/src/org/splat/service/StudyServiceImpl.java
Salome HOME
New study creation is fixed. Search page is also accessible now.
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / StudyServiceImpl.java
1 /*****************************************************************************
2  * Company         EURIWARE
3  * Application     SIMAN
4  * File            $Id$ 
5  * Creation date   06.10.2012
6  * @author         $Author$
7  * @version        $Revision$
8  *****************************************************************************/
9
10 package org.splat.service;
11
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;
17
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;
47
48 /**
49  * @author RKV
50  * 
51  */
52 public class StudyServiceImpl implements StudyService {
53
54         public final static Logger logger = Logger.getLogger(org.splat.service.StudyServiceImpl.class);
55
56         private IndexService _indexService;
57
58         private StepService _stepService;
59
60         private ScenarioService _scenarioService;
61
62         private ProjectSettingsService _projectSettingsService;
63
64         private ProjectElementService _projectElementService;
65
66         public Study selectStudy(int index) {
67                 // -------------------------------------------
68                 StringBuffer query = new StringBuffer("from Study where rid='").append(
69                                 index).append("'");
70                 Study result = (Study) Database.getSession().createQuery(
71                                 query.toString()).uniqueResult();
72
73                 result.loadWorkflow();
74                 return result;
75         }
76
77         public Study selectStudy(String refid) {
78                 // ----------------------------------------------
79                 StringBuffer query = new StringBuffer("from Study where sid='").append(
80                                 refid).append("'");
81                 Study result = (Study) Database.getSession().createQuery(
82                                 query.toString()).uniqueResult();
83
84                 result.loadWorkflow();
85                 return result;
86         }
87
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);
93
94                 buildReference(study);
95                 Database.getSession().save(study); // TODO: use StudyDAO and throw out Database.
96                 try {
97                         IndexService lucin = getIndex();
98                         lucin.add(study);
99                 } catch (IOException error) {
100                         logger.error("Unable to index the study '" + study.getIndex()
101                                         + "', reason:", error);
102                         // Continue and try to index later
103                 }
104                 return study;
105         }
106
107         public IndexService getIndex() throws IOException {
108                 IndexService lucin = getIndexService();
109                 if (!lucin.exists())
110                         lucin.create(); // Happens when re-indexing all studies
111                 return lucin;
112         }
113
114         public SimulationContext addProjectContext(Study aStudy,
115                         SimulationContext.Properties cprop) throws MissedPropertyException,
116                         InvalidPropertyException, MultiplyDefinedException,
117                         RuntimeException {
118                 // -------------------------------------------------------------------------------
119                 SimulationContext added = getStepService().addSimulationContext(
120                                 getProjectElementService().getFirstStep(aStudy), cprop);
121                 update(aStudy);
122                 return added;
123         }
124
125         /**
126          * @return
127          */
128         public StepService getStepService() {
129                 return _stepService;
130         }
131
132         public void setStepService(StepService stepService) {
133                 _stepService = stepService;
134         }
135
136         public SimulationContext addProjectContext(Study aStudy,
137                         SimulationContext context) {
138                 // ----------------------------------------------------------------------
139                 SimulationContext added = getStepService().addSimulationContext(
140                                 getProjectElementService().getFirstStep(aStudy), context);
141                 update(aStudy);
142                 return added;
143         }
144
145         public boolean addContributor(Study aStudy, User user) {
146                 // -----------------------------------------
147                 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
148                 for (Iterator<User> i = contributor.iterator(); i.hasNext();) {
149                         User present = i.next();
150                         if (present.equals(user))
151                                 return false;
152                 }
153                 boolean absent = aStudy.getModifiableActors().add(user); // User may already be a reviewer or an approver
154
155                 aStudy.addRelation(new ContributorRelation(aStudy, user));
156                 if (absent)
157                         update(aStudy); // Else, useless to re-index the study
158                 contributor.add(user);
159                 return true;
160         }
161
162         /**
163          * Moves this study from the Public to the Reference area of the repository. For being moved to the Reference area, the study must
164          * previously be approved.
165          * 
166          * @return true if the move succeeded.
167          * @see #moveToPublic()
168          * @see #isPublic()
169          * @see Publication#approve(Date)
170          */
171         public boolean moveToReference(Study aStudy) {
172                 // ---------------------------------
173                 if (aStudy.getProgressState() != ProgressState.APPROVED)
174                         return false;
175                 if (aStudy.getVisibility() != Visibility.PUBLIC)
176                         return false;
177
178                 aStudy.setVisibility(Visibility.REFERENCE);
179                 if (update(aStudy)) {
180                         return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
181                 }
182                 return false;
183         }
184
185         public boolean update(Study aStudy, Properties sprop)
186                         throws InvalidPropertyException {
187                 if (sprop.getTitle() != null)
188                         aStudy.setTitle(sprop.getTitle());
189                 if (sprop.getSummary() != null)
190                         aStudy.setAttribute(new DescriptionAttribute(aStudy, sprop
191                                         .getSummary()));
192                 // TODO: To be completed
193                 return update(aStudy);
194         }
195
196         public boolean buildReference(Study aStudy) {
197                 String pattern = aStudy.getReference(); // The study being supposed just created, its reference is the reference pattern
198                 IDBuilder tool = Database.selectIDBuilder(aStudy.getDate());
199                 if (tool == null) {
200                         tool = new IDBuilder(aStudy.getDate());
201                         Database.getSession().save(tool);
202                 }
203                 aStudy.setReference(tool.buildReference(pattern, aStudy));
204                 return true;
205         }
206
207         public boolean publishes(Study aStudy, Document doc) {
208                 // ---------------------------------------
209                 if (!aStudy.publishes(doc)) {
210                         Scenario[] scene = aStudy.getScenarii();
211                         for (int i = 0; i < scene.length; i++) {
212                                 if (scene[i].publishes(doc))
213                                         return true;
214                         }
215                 }
216                 return false;
217         }
218
219         public boolean removeContributor(Study aStudy, User... users) {
220                 // ------------------------------------------------
221                 List<User> contributor = aStudy.getModifiableContributors(); // Initializes contributor
222                 Boolean done = false;
223                 for (int i = 0; i < users.length; i++) {
224                         User user = users[i];
225                         for (Iterator<User> j = contributor.iterator(); j.hasNext();) {
226                                 User present = j.next();
227                                 if (!present.equals(user))
228                                         continue;
229
230                                 aStudy.removeRelation(ContributorRelation.class, user);
231                                 j.remove(); // Updates the contributor shortcut
232                                 done = true;
233                                 break;
234                         }
235                 }
236                 if (done)
237                         update(aStudy);
238                 return done;
239         }
240
241         public boolean removeProjectContext(Study aStudy, SimulationContext context) {
242                 // ---------------------------------------------------------------
243                 boolean done = getStepService().removeSimulationContext(
244                                 getProjectElementService().getFirstStep(aStudy), context);
245                 update(aStudy);
246                 return done;
247         }
248
249         public void setValidationCycle(Study aStudy, DocumentType type,
250                         ValidationCycle.Properties vprop) {
251                 HashMap<String, ValidationCycle> validactor = aStudy
252                                 .getValidationCycles();
253                 if (validactor == null)
254                         aStudy.setShortCuts(); // Initializes validactor and actor
255
256                 String cname = type.getName();
257                 ValidationCycle cycle = validactor.get(cname);
258
259                 if (cycle != null && cycle.isAssigned()) {
260                         cycle.resetActors(vprop);
261                 } else
262                         try {
263                                 cycle = new ValidationCycle(aStudy, vprop.setDocumentType(type));
264
265                                 ValidationCycleRelation link = cycle.getContext();
266                                 aStudy.addRelation(link);
267                                 validactor.put(cname, link.getTo()); // Replaces the cycle if exists as default,
268                         } catch (Exception error) {
269                                 logger.error("Unable to re-index Knowledge Elements, reason:",
270                                                 error);
271                                 return;
272                         }
273                 resetActorsShortCut(aStudy);
274                 update(aStudy); // Re-index the study, just in case
275         }
276
277         private void resetActorsShortCut(Study aStudy) {
278                 aStudy.getModifiableActors().clear();
279                 // Get all actors involved in validation cycles
280                 for (Iterator<ValidationCycle> i = aStudy.getValidationCycles()
281                                 .values().iterator(); i.hasNext();) {
282                         ValidationCycle cycle = i.next();
283                         User[] user = cycle.getAllActors();
284                         for (int j = 0; j < user.length; j++)
285                                 aStudy.getModifiableActors().add(user[j]);
286                 }
287                 // Get all other actors
288                 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
289                                 .hasNext();) {
290                         Relation link = i.next();
291                         Class<?> kindof = link.getClass().getSuperclass();
292                         if (!kindof.equals(ActorRelation.class))
293                                 continue;
294                         aStudy.getModifiableActors().add(((ActorRelation) link).getTo());
295                 }
296         }
297
298         /**
299          * Demotes this study from In-Check to In-Draft then In-Work states. This function is called internally when demoting the final result
300          * document of the study.
301          * 
302          * @return true if the demotion succeeded.
303          */
304         public boolean demote(Study aStudy) {
305                 // ---------------------------
306                 if (aStudy.getProgressState() == ProgressState.inCHECK)
307                         aStudy.setProgressState(ProgressState.inDRAFT);
308                 else if (aStudy.getProgressState() == ProgressState.inDRAFT)
309                         aStudy.setProgressState(ProgressState.inWORK);
310                 else
311                         return false;
312                 return update(aStudy);
313         }
314
315         public int generateLocalIndex(Study aStudy) {
316                 aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1);
317                 Database.getSession().update(aStudy);
318                 return aStudy.getLastLocalIndex();
319         }
320
321         // ==============================================================================================================================
322         // Public member functions
323         // ==============================================================================================================================
324
325         public Scenario addScenario(Study aStudy, Scenario.Properties sprop)
326                         throws MissedPropertyException, InvalidPropertyException,
327                         MultiplyDefinedException, RuntimeException {
328                 // -------------------------------------------------------
329                 if (sprop.getManager() == null)
330                         sprop.setManager(aStudy.getAuthor());
331
332                 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
333                 if (sprop.getBaseStep() != null)
334                         getScenarioService()
335                                         .copyContentsUpTo(scenario, sprop.getBaseStep());
336                 Scenario previous = sprop.getInsertAfter();
337                 Session session = Database.getSession();
338
339                 if (previous == null) {
340                         aStudy.getScenariiList().add(scenario);
341                 } else {
342                         aStudy.getScenariiList().add(
343                                         aStudy.getScenariiList().indexOf(previous) + 1, scenario);
344                 }
345                 session.update(aStudy); // No need to update the Lucene index
346                 session.save(scenario); // Must be done after updating this study because of the back reference to the study
347                 if (sprop.getBaseStep() != null) {
348                         // No need to update the Knowledge Element index as Knowledge Elements are not copied
349                         scenario.refresh(); // Because saving the scenario changes the hashcode of copied Publications
350                 }
351                 KnowledgeElementType ucase = KnowledgeElement.selectType("usecase");
352                 KnowledgeElement.Properties kprop = new KnowledgeElement.Properties();
353                 User admin = UserDirectory.selectUser(1); // First user created when creating the database
354                 kprop.setType(ucase).setTitle(aStudy.getTitle())
355                                 .setValue(scenario.getTitle()).setAuthor(admin); // Internal Knowledge Element required by the validation process of
356                                                                                                                                         // knowledges
357                 getScenarioService().addKnowledgeElement(scenario, kprop);
358                 return scenario;
359         }
360
361         /**
362          * @return
363          */
364         private ScenarioService getScenarioService() {
365                 return _scenarioService;
366         }
367
368         public void setScenarioService(ScenarioService scenarioService) {
369                 _scenarioService = scenarioService;
370         }
371
372         /**
373          * Promotes this study from In-Work to In-Draft then In-Check and APPROVED states. This function is called internally when promoting the
374          * final result document of the study.
375          * 
376          * @return true if the demotion succeeded.
377          */
378         public boolean promote(Study aStudy) {
379                 // ----------------------------
380                 if (aStudy.getProgressState() == ProgressState.inWORK) {
381                         aStudy.setProgressState(ProgressState.inDRAFT);
382                 } else if (aStudy.getProgressState() == ProgressState.inDRAFT) {
383                         aStudy.setProgressState(ProgressState.inCHECK);
384                         Revision myvers = new Revision(aStudy.getVersion());
385                         if (myvers.isMinor()) {
386                                 aStudy.setVersion(myvers.incrementAs(aStudy.getProgressState())
387                                                 .toString());
388                         }
389                 } else if (aStudy.getProgressState() == ProgressState.inCHECK) {
390                         aStudy.setProgressState(ProgressState.APPROVED);
391                 } else
392                         return false;
393
394                 return update(aStudy);
395         }
396
397         /**
398          * Moves this study from the Private to the Public area of the repository.
399          * 
400          * @return true if the move succeeded.
401          * @see #isPublic()
402          */
403         public boolean moveToPublic(Study aStudy) {
404                 // ------------------------------
405                 if (aStudy.getVisibility() != Visibility.PRIVATE)
406                         return false;
407
408                 aStudy.setVisibility(Visibility.PUBLIC);
409                 if (update(aStudy)) {
410                         return updateKnowledgeElementsIndex(aStudy); // If fails, the database roll-back is under responsibility of the caller
411                 }
412                 return false;
413         }
414
415         private boolean update(Study aStudy) {
416                 try {
417                         Database.getSession().update(aStudy); // Update of relational base
418                         getIndex().update(aStudy); // Update of Lucene index
419                         return true;
420                 } catch (Exception error) {
421                         logger.error("Unable to re-index the study '" + aStudy.getIndex()
422                                         + "', reason:", error);
423                         return false;
424                 }
425         }
426
427         private boolean updateKnowledgeElementsIndex(Study aStudy) {
428                 // ----------------------------------------------
429                 try {
430                         IndexService lucin = getIndex();
431
432                         for (Iterator<Scenario> i = aStudy.getScenariiList().iterator(); i
433                                         .hasNext();) {
434                                 Scenario scene = i.next();
435                                 for (Iterator<KnowledgeElement> j = scene
436                                                 .getAllKnowledgeElements().iterator(); j.hasNext();) {
437                                         KnowledgeElement kelm = j.next();
438                                         lucin.update(kelm);
439                                 }
440                         }
441                         return true;
442                 } catch (Exception error) {
443                         logger.error("Unable to re-index Knowledge Elements, reason:",
444                                         error);
445                         return false;
446                 }
447         }
448
449         /**
450          * @return
451          */
452         public IndexService getIndexService() {
453                 return _indexService;
454         }
455
456         public void setIndexService(IndexService indexService) {
457                 _indexService = indexService;
458         }
459
460         /**
461          * Get project settings.
462          * 
463          * @return Project settings service
464          */
465         private ProjectSettingsService getProjectSettings() {
466                 return _projectSettingsService;
467         }
468
469         /**
470          * Set project settings service.
471          * 
472          * @param projectSettingsService
473          *            project settings service
474          */
475         public void setProjectSettings(ProjectSettingsService projectSettingsService) {
476                 _projectSettingsService = projectSettingsService;
477         }
478
479         /**
480          * Get the projectElementService.
481          * 
482          * @return the projectElementService
483          */
484         public ProjectElementService getProjectElementService() {
485                 return _projectElementService;
486         }
487
488         /**
489          * Set the projectElementService.
490          * 
491          * @param projectElementService
492          *            the projectElementService to set
493          */
494         public void setProjectElementService(
495                         ProjectElementService projectElementService) {
496                 _projectElementService = projectElementService;
497         }
498 }