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