Salome HOME
Id now is Long instead of Integer. First unit test is created. hibernate-3.5.jar...
[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   02.10.2012
6  * @author         Author: Maria KRUCHININA
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.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;
50
51 /**
52  * This class defines all methods for creation, modification the study.
53  * @author Maria KRUCHININA
54  *
55  */
56 public class StudyServiceImpl implements StudyService {
57
58         /**
59          * logger for the service.
60          */
61         public final static AppLogger logger = AppLogger.getLogger(StudyServiceImpl.class);
62
63         private IndexService _indexService;
64
65         private StepService _stepService;
66
67         private ScenarioService _scenarioService;
68
69         private ProjectSettingsService _projectSettingsService;
70
71         private ProjectElementService _projectElementService;
72         
73         /**
74          * Get the simulation context list for displaying drop-down list values populating
75          * on the "Create new study" screen.
76          * {@inheritDoc}
77          * @see org.splat.service.StudyService#getSimulationContextList()
78          */
79         public List<SimulationContext> getSimulationContextList() {
80                 //TODO: remove the commit transaction ...
81                 Session      connex  = Database.getSession();
82                 Transaction  transax = connex.beginTransaction();
83                 
84                 SimulationContext.Properties cprop   = new SimulationContext.Properties();
85             SimulationContextType        product = SimulationContext.selectType("product");
86             List<SimulationContext> resList = Database.selectSimulationContextsWhere(cprop.setType(product));
87             
88             transax.commit();
89                   
90             return resList;
91         }
92         
93         public Study selectStudy(long index) {
94                 // -------------------------------------------
95                 StringBuffer query = new StringBuffer("from Study where rid='").append(
96                                 index).append("'");
97                 Study result = (Study) Database.getSession().createQuery(
98                                 query.toString()).uniqueResult();
99
100                 result.loadWorkflow();
101                 return result;
102         }
103
104         public Study selectStudy(String refid) {
105                 // ----------------------------------------------
106                 StringBuffer query = new StringBuffer("from Study where sid='").append(
107                                 refid).append("'");
108                 Study result = (Study) Database.getSession().createQuery(
109                                 query.toString()).uniqueResult();
110
111                 result.loadWorkflow();
112                 return result;
113         }
114
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);
120
121                 buildReference(study);
122                 Database.getSession().save(study); // TODO: use StudyDAO and throw out Database.
123                 try {
124                         IndexService lucin = getIndex();
125                         lucin.add(study);
126                 } catch (IOException error) {
127                         logger.error("Unable to index the study '" + study.getIndex()
128                                         + "', reason:", error);
129                         // Continue and try to index later
130                 }
131                 return study;
132         }
133
134         public IndexService getIndex() throws IOException {
135                 IndexService lucin = getIndexService();
136                 if (!lucin.exists())
137                         lucin.create(); // Happens when re-indexing all studies
138                 return lucin;
139         }
140
141         public SimulationContext addProjectContext(Study aStudy,
142                         SimulationContext.Properties cprop) throws MissedPropertyException,
143                         InvalidPropertyException, MultiplyDefinedException,
144                         RuntimeException {
145                 // -------------------------------------------------------------------------------
146                 SimulationContext added = getStepService().addSimulationContext(
147                                 getProjectElementService().getFirstStep(aStudy), cprop);
148                 update(aStudy);
149                 return added;
150         }
151
152         public SimulationContext addProjectContext(Study aStudy,
153                         SimulationContext context) {
154                 // ----------------------------------------------------------------------
155                 SimulationContext added = getStepService().addSimulationContext(
156                                 getProjectElementService().getFirstStep(aStudy), context);
157                 update(aStudy);
158                 return added;
159         }
160
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))
167                                 return false;
168                 }
169                 boolean absent = aStudy.getModifiableActors().add(user); // User may already be a reviewer or an approver
170
171                 aStudy.addRelation(new ContributorRelation(aStudy, user));
172                 if (absent)
173                         update(aStudy); // Else, useless to re-index the study
174                 contributor.add(user);
175                 return true;
176         }
177
178         /**
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.
181          * 
182          * @return true if the move succeeded.
183          * @see #moveToPublic()
184          * @see #isPublic()
185          * @see Publication#approve(Date)
186          */
187         public boolean moveToReference(Study aStudy) {
188                 // ---------------------------------
189                 if (aStudy.getProgressState() != ProgressState.APPROVED)
190                         return false;
191                 if (aStudy.getVisibility() != Visibility.PUBLIC)
192                         return false;
193
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
197                 }
198                 return false;
199         }
200
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
207                                         .getSummary()));
208                 // TODO: To be completed
209                 return update(aStudy);
210         }
211
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());
215                 if (tool == null) {
216                         tool = new IDBuilder(aStudy.getDate());
217                         Database.getSession().save(tool);
218                 }
219                 aStudy.setReference(tool.buildReference(pattern, aStudy));
220                 return true;
221         }
222
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))
229                                         return true;
230                         }
231                 }
232                 return false;
233         }
234
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))
244                                         continue;
245
246                                 aStudy.removeRelation(ContributorRelation.class, user);
247                                 j.remove(); // Updates the contributor shortcut
248                                 done = true;
249                                 break;
250                         }
251                 }
252                 if (done)
253                         update(aStudy);
254                 return done;
255         }
256
257         public boolean removeProjectContext(Study aStudy, SimulationContext context) {
258                 // ---------------------------------------------------------------
259                 boolean done = getStepService().removeSimulationContext(
260                                 getProjectElementService().getFirstStep(aStudy), context);
261                 update(aStudy);
262                 return done;
263         }
264
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
271
272                 String cname = type.getName();
273                 ValidationCycle cycle = validactor.get(cname);
274
275                 if (cycle != null && cycle.isAssigned()) {
276                         cycle.resetActors(vprop);
277                 } else
278                         try {
279                                 cycle = new ValidationCycle(aStudy, vprop.setDocumentType(type));
280
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:",
286                                                 error);
287                                 return;
288                         }
289                 resetActorsShortCut(aStudy);
290                 update(aStudy); // Re-index the study, just in case
291         }
292
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]);
302                 }
303                 // Get all other actors
304                 for (Iterator<Relation> i = aStudy.getAllRelations().iterator(); i
305                                 .hasNext();) {
306                         Relation link = i.next();
307                         Class<?> kindof = link.getClass().getSuperclass();
308                         if (!kindof.equals(ActorRelation.class))
309                                 continue;
310                         aStudy.getModifiableActors().add(((ActorRelation) link).getTo());
311                 }
312         }
313
314         /**
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.
317          * 
318          * @return true if the demotion succeeded.
319          */
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);
326                 else
327                         return false;
328                 return update(aStudy);
329         }
330
331         public int generateLocalIndex(Study aStudy) {
332                 aStudy.setLastLocalIndex(aStudy.getLastLocalIndex() + 1);
333                 Database.getSession().update(aStudy);
334                 return aStudy.getLastLocalIndex();
335         }
336
337         // ==============================================================================================================================
338         // Public member functions
339         // ==============================================================================================================================
340
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());
347
348                 Scenario scenario = new Scenario(sprop.setOwnerStudy(aStudy));
349                 if (sprop.getBaseStep() != null)
350                         getScenarioService()
351                                         .copyContentsUpTo(scenario, sprop.getBaseStep());
352                 Scenario previous = sprop.getInsertAfter();
353                 Session session = Database.getSession();
354
355                 if (previous == null) {
356                         aStudy.getScenariiList().add(scenario);
357                 } else {
358                         aStudy.getScenariiList().add(
359                                         aStudy.getScenariiList().indexOf(previous) + 1, scenario);
360                 }
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
366                 }
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
372                                                                                                                                         // knowledges
373                 getScenarioService().addKnowledgeElement(scenario, kprop);
374                 return scenario;
375         }
376
377         /**
378          * @return
379          */
380         private ScenarioService getScenarioService() {
381                 return _scenarioService;
382         }
383
384         public void setScenarioService(ScenarioService scenarioService) {
385                 _scenarioService = scenarioService;
386         }
387
388         /**
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.
391          * 
392          * @return true if the demotion succeeded.
393          */
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())
403                                                 .toString());
404                         }
405                 } else if (aStudy.getProgressState() == ProgressState.inCHECK) {
406                         aStudy.setProgressState(ProgressState.APPROVED);
407                 } else
408                         return false;
409
410                 return update(aStudy);
411         }
412
413         /**
414          * Moves this study from the Private to the Public area of the repository.
415          * 
416          * @return true if the move succeeded.
417          * @see #isPublic()
418          */
419         public boolean moveToPublic(Study aStudy) {
420                 // ------------------------------
421                 if (aStudy.getVisibility() != Visibility.PRIVATE)
422                         return false;
423
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
427                 }
428                 return false;
429         }
430
431         private boolean update(Study aStudy) {
432                 try {
433                         Database.getSession().update(aStudy); // Update of relational base
434                         getIndex().update(aStudy); // Update of Lucene index
435                         return true;
436                 } catch (Exception error) {
437                         logger.error("Unable to re-index the study '" + aStudy.getIndex()
438                                         + "', reason:", error);
439                         return false;
440                 }
441         }
442
443         private boolean updateKnowledgeElementsIndex(Study aStudy) {
444                 // ----------------------------------------------
445                 try {
446                         IndexService lucin = getIndex();
447
448                         for (Iterator<Scenario> i = aStudy.getScenariiList().iterator(); i
449                                         .hasNext();) {
450                                 Scenario scene = i.next();
451                                 for (Iterator<KnowledgeElement> j = scene
452                                                 .getAllKnowledgeElements().iterator(); j.hasNext();) {
453                                         KnowledgeElement kelm = j.next();
454                                         lucin.update(kelm);
455                                 }
456                         }
457                         return true;
458                 } catch (Exception error) {
459                         logger.error("Unable to re-index Knowledge Elements, reason:",
460                                         error);
461                         return false;
462                 }
463         }
464
465         /**
466          * @return
467          */
468         public IndexService getIndexService() {
469                 return _indexService;
470         }
471
472         public void setIndexService(IndexService indexService) {
473                 _indexService = indexService;
474         }
475
476         /**
477          * Get project settings.
478          * 
479          * @return Project settings service
480          */
481         private ProjectSettingsService getProjectSettings() {
482                 return _projectSettingsService;
483         }
484
485         /**
486          * Set project settings service.
487          * 
488          * @param projectSettingsService
489          *            project settings service
490          */
491         public void setProjectSettings(ProjectSettingsService projectSettingsService) {
492                 _projectSettingsService = projectSettingsService;
493         }
494
495         /**
496          * Get the projectElementService.
497          * 
498          * @return the projectElementService
499          */
500         public ProjectElementService getProjectElementService() {
501                 return _projectElementService;
502         }
503
504         /**
505          * Set the projectElementService.
506          * 
507          * @param projectElementService
508          *            the projectElementService to set
509          */
510         public void setProjectElementService(
511                         ProjectElementService projectElementService) {
512                 _projectElementService = projectElementService;
513         }
514
515         /**
516          * Get the stepService.
517          * @return the stepService
518          */
519         public StepService getStepService() {
520                 return _stepService;
521         }
522
523         /**
524          * Set the stepService.
525          * @param stepService the stepService to set
526          */
527         public void setStepService(StepService stepService) {
528                 _stepService = stepService;
529         }
530 }