Salome HOME
7fb730ba70bb0d6210f438641b1b4fc7997c9138
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / PublicationServiceImpl.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.FileNotFoundException;
13 import java.util.ArrayList;
14 import java.util.Date;
15 import java.util.Iterator;
16 import java.util.List;
17
18 import org.hibernate.Session;
19 import org.splat.dal.bo.kernel.User;
20 import org.splat.dal.bo.som.Document;
21 import org.splat.dal.bo.som.DocumentType;
22 import org.splat.dal.bo.som.ProgressState;
23 import org.splat.dal.bo.som.ProjectElement;
24 import org.splat.dal.bo.som.Publication;
25 import org.splat.dal.bo.som.SimulationContext;
26 import org.splat.dal.bo.som.SimulationContextType;
27 import org.splat.dal.bo.som.Study;
28 import org.splat.dal.bo.som.Timestamp;
29 import org.splat.dal.bo.som.ValidationCycle;
30 import org.splat.dal.bo.som.ValidationStep;
31 import org.splat.dal.dao.som.Database;
32 import org.splat.kernel.NotApplicableException;
33 import org.splat.manox.Reader;
34 import org.splat.manox.Toolbox;
35 import org.splat.som.DocumentRights;
36 import org.splat.som.Revision;
37 import org.splat.som.Step;
38
39 /**
40  * @author RKV
41  * 
42  */
43 public class PublicationServiceImpl implements PublicationService {
44
45         private StudyService _studyService;
46         private StepService _stepService;
47         private DocumentTypeService _documentTypeService;
48         private ProjectElementService _projectElementService;
49
50         public Publication copy(Publication aPublication, ProjectElement publisher) {
51                 // -----------------------------------------------------
52                 Publication copy = new Publication();
53                 copy.setValue(aPublication.value());
54                 copy.setStep(aPublication.getStep()); // May not be initialized yet
55                 copy.setOwner(publisher);
56                 copy.setIsnew(aPublication.getIsnew());
57                 if (!copy.getOwnerStudy().equals(aPublication.getOwnerStudy())) {
58                         copy.setIsnew('N'); // The referenced document is not new for the given study
59                 }
60                 return copy;
61         }
62
63         /**
64          * Promotes the document referenced by this publication from In-Check to Approved state, if not out-dated, and attaches the
65          * corresponding time-stamp to the document.</br> If the promoted document is the final result of the owner study, the study is itself
66          * is promoted as well.</br> </br> Limitation: the way this promotion is propagated to the study supposes that the study has only ONE
67          * final result document.
68          * 
69          * @param adate
70          *            the date of approval
71          * @return true if the approval succeeded
72          * @see #getProgressState()
73          * @see DocumentRights#canApprove()
74          * @see DocumentType#isStudyResult()
75          * @see Study#getApproverOf(Publication)
76          */
77         public Timestamp approve(Publication aPublication, Date adate) {
78                 // -------------------------------------
79                 if (aPublication.isOutdated())
80                         return null;
81                 else if (aPublication.value().getProgressState() != ProgressState.inCHECK)
82                         return null; // This statement must conform to the corresponding right
83
84                 DocumentType type = aPublication.value().getType();
85                 Study owner = aPublication.getOwnerStudy();
86                 ValidationCycle cycle = owner.getValidationCycleOf(type);
87                 User approver = cycle.getActor(ValidationStep.APPROVAL);
88                 Timestamp stamp = new Timestamp(ValidationStep.APPROVAL,
89                                 aPublication.value(), approver, adate);
90                 if (!aPublication.value().promote(stamp))
91                         return null;
92                 if (getDocumentTypeService().isStudyResult(type)
93                                 && owner.getProgressState() == ProgressState.inCHECK)
94                         getStudyService().promote(owner);
95                 return stamp; // Hoping that promotion of the study succeeded
96         }
97
98         /**
99          * Demotes the document referenced by this publication to In-Work state, and removes the Promoter of the document, if exist.</br> The
100          * In-Draft state is skipped (direct demotion to In-Work) if the validation cycle of the document does not include the review step.</br>
101          * If the demoted document is the final result of the owner study, the study is itself is demoted as well.</br> </br> Limitation: the
102          * way this demotion is propagated to the study supposes that the study has only ONE final result document.
103          * 
104          * @return true if the demotion succeeded
105          * @see #getProgressState()
106          * @see DocumentRights#canDemote()
107          * @see DocumentType#isStudyResult()
108          */
109         public boolean demote(Publication aPublication) {
110                 // ------------------------
111                 DocumentType type = aPublication.value().getType();
112                 Study owner = aPublication.getOwnerStudy();
113
114                 if (aPublication.value().getProgressState() == ProgressState.inCHECK) {
115                         ValidationCycle cycle = owner.getValidationCycleOf(type);
116                         if (cycle.enables(ValidationStep.REVIEW)) {
117                                 if (!aPublication.value().demote())
118                                         return false;
119                         } else {
120                                 if (!aPublication.value().demote())
121                                         return false;
122                                 aPublication.value().demote();
123                         }
124                 } else if (aPublication.value().getProgressState() == ProgressState.inDRAFT) {
125                         if (!aPublication.value().demote())
126                                 return false;
127                 } else {
128                         return false;
129                 }
130                 if (getDocumentTypeService().isStudyResult(type)
131                                 && owner.getProgressState() != ProgressState.inWORK)
132                         getStudyService().demote(owner);
133                 return true;
134         }
135
136         /**
137          * Undo the review operation by demoting the document referenced by this publication from In-Check to In-Draft state and removing the
138          * Reviewer.</br> If the demoted document is the final result of the owner study, the study is itself is demoted as well.</br> </br>
139          * Limitation: the way this demotion is propagated to the study supposes that the study has only ONE final result document.
140          * 
141          * @return true if the demotion succeeded
142          * @see #getProgressState()
143          * @see #review()
144          * @see DocumentRights#canInvalidate()
145          * @see DocumentType#isStudyResult()
146          */
147         public boolean invalidate(Publication aPublication) {
148                 // ----------------------------
149                 if (aPublication.value().getProgressState() != ProgressState.inCHECK)
150                         return false;
151                 if (!aPublication.value().demote()) // Removes the reviewer if this document is In-Check
152                         return false;
153                 DocumentType type = aPublication.value().getType();
154                 Study owner = aPublication.getOwnerStudy();
155                 if (getDocumentTypeService().isStudyResult(type)
156                                 && owner.getProgressState() == ProgressState.inCHECK)
157                         getStudyService().demote(owner);
158                 return true;
159         }
160
161         /**
162          * Promotes the document referenced by this publication from In-Work to In-Draft or In-Check state, if not out-dated, and attaches the
163          * corresponding time-stamp to the document.</br> The In-Draft state is skipped (direct promotion to In-Check) if the validation cycle
164          * of the document does not include the review step.</br> Also, if the promoted document is the final result of the owner study, the
165          * study is itself promoted as well.</br> This operation can be undo-ed by demote().</br> </br> Limitation: the way this promotion is
166          * propagated to the study supposes that the study has only ONE final result document.
167          * 
168          * @return true if the promotion succeeded
169          * @see #getProgressState()
170          * @see #demote()
171          * @see DocumentRights#canPromote()
172          * @see DocumentType#isStudyResult()
173          */
174         public Timestamp promote(Publication aPublication, Date pdate) {
175                 if (aPublication.isOutdated())
176                         return null;
177                 else if (aPublication.value().getProgressState() != ProgressState.inWORK)
178                         return null; // This statement must conform to the corresponding right
179                 else {
180                         DocumentType type = aPublication.value().getType();
181                         Study owner = aPublication.getOwnerStudy();
182                         ValidationCycle cycle = owner.getValidationCycleOf(type);
183                         User promoter = cycle.getActor(ValidationStep.PROMOTION);
184                         if (promoter == null)
185                                 promoter = getInvolvedStep(aPublication).getActor();
186                         if (promoter == null)
187                                 promoter = owner.getAuthor();
188                         Timestamp stamp = new Timestamp(ValidationStep.PROMOTION,
189                                         aPublication.value(), promoter, pdate);
190
191                         if (!aPublication.value().promote(stamp)) // Promotion to being reviewed
192                                 return null;
193                         if (!cycle.enables(ValidationStep.REVIEW)) {
194                                 aPublication.value().promote(null);
195                         }
196                         if (getDocumentTypeService().isStudyResult(type)
197                                         && owner.getProgressState() == ProgressState.inWORK)
198                                 getStudyService().promote(owner);
199                         return stamp; // Hoping that promotion of the study succeeded
200                 }
201         }
202
203         /**
204          * Promotes the document referenced by this publication from In-Draft to In-Check state, if not out-dated, and attaches the
205          * corresponding time-stamp to the document.</br> If the promoted document is the final result of the owner study, the study is itself
206          * is promoted as well.</br> This operation can be undo-ed by invalidate().</br> </br> Limitation: the way this promotion is propagated
207          * to the study supposes that the study has only ONE final result document.
208          * 
209          * @param rdate
210          *            the date of review
211          * @return true if the review succeeded
212          * @see #getProgressState()
213          * @see #invalidate()
214          * @see DocumentRights#canReview()
215          * @see DocumentType#isStudyResult()
216          * @see Study#getReviewerOf(Publication)
217          */
218         public Timestamp review(Publication aPublication, Date rdate) {
219                 if (aPublication.isOutdated())
220                         return null;
221                 else if (aPublication.value().getProgressState() != ProgressState.inDRAFT)
222                         return null; // This statement must conform to the corresponding right
223
224                 DocumentType type = aPublication.value().getType();
225                 Study owner = aPublication.getOwnerStudy();
226                 ValidationCycle cycle = owner.getValidationCycleOf(type);
227                 User reviewer = cycle.getActor(ValidationStep.REVIEW);
228                 Timestamp stamp = new Timestamp(ValidationStep.REVIEW,
229                                 aPublication.value(), reviewer, rdate);
230                 if (!aPublication.value().promote(stamp))
231                         return null;
232                 if (getDocumentTypeService().isStudyResult(type)
233                                 && owner.getProgressState() == ProgressState.inDRAFT)
234                         getStudyService().promote(owner);
235                 return stamp; // Hoping that promotion of the study succeeded
236         }
237
238         /**
239          * Publishes the document referenced by this publication into the owner Project Element under the given revision number.<br/>
240          * The state of the referenced document is supposed being automatically set according to the given revision number, but, due to the
241          * versioning scheme, as it is not possible to differentiate In-Work and In-Draft states, this function has been deprecated (it is
242          * currently used only for the need of integration of Microsoft Office which anyway has to be redesigned). <br/>
243          * Note: in the context of branch versioning, the given revision may be modified by an update of the branch name.
244          * 
245          * @param newvers
246          *            the required revision number
247          * @throws FileNotFoundException
248          *             If the referenced document is empty
249          * @throws NotApplicableException
250          *             If the referenced document is undefined
251          * @deprecated
252          */
253         public void saveAs(Publication aPublication, Revision newvers)
254                         throws FileNotFoundException, NotApplicableException {
255                 // -------------------------------------
256                 if (aPublication.value().isUndefined())
257                         throw new NotApplicableException(
258                                         "Cannot save a Publication object refering an undefined Document");
259                 if (!aPublication.value().getSourceFile().exists())
260                         throw new FileNotFoundException();
261
262                 Database.getSession().save(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
263                 aPublication.value().updateAs(newvers); // May change the branch name of given revision
264                 updateOwner(aPublication);
265         }
266
267         /**
268          * Publishes the document referenced by this publication into the owner Project Element under the given state, the revision number of
269          * the document being automatically set accordingly. If the given state is In-Draft and the document is final result of the owner study,
270          * this automatically promotes the study to In-Draft.
271          * 
272          * @param state
273          *            the required progress state
274          * @throws FileNotFoundException
275          *             If the referenced document is empty
276          * @throws NotApplicableException
277          *             If the referenced document is undefined
278          */
279         public void saveAs(Publication aPublication, ProgressState state)
280                         throws FileNotFoundException, NotApplicableException {
281                 // ----------------------------------------
282                 if (aPublication.value().isUndefined())
283                         throw new NotApplicableException(
284                                         "Cannot save a Publication object refering an undefined Document");
285                 if (!aPublication.value().getSourceFile().exists())
286                         throw new FileNotFoundException();
287
288                 if (state == ProgressState.inWORK || state == ProgressState.EXTERN) {
289                         Database.getSession().save(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
290                         aPublication.value().updateAs(state);
291                 } else {
292                         DocumentType mytype = aPublication.value().getType();
293                         Study owner = aPublication.getOwnerStudy();
294                         ValidationCycle cycle = owner.getValidationCycleOf(mytype);
295                         boolean review = cycle.enables(ValidationStep.REVIEW);
296                         if (!(state == ProgressState.inDRAFT && review)
297                                         && !(state == ProgressState.inCHECK && !review)) {
298                                 throw new NotApplicableException(
299                                                 "Cannot save a result document in " + state.toString()
300                                                                 + " state");
301                         }
302                         Database.getSession().save(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
303                                                                                                                 // hascode
304                         aPublication.value().updateAs(ProgressState.inWORK);
305
306                         promote(aPublication, aPublication.value()
307                                         .getLastModificationDate()); // Promotes to the appropriate state in accordance to the validation cycle
308                 }
309                 updateOwner(aPublication);
310         }
311
312         public void updateOwner(Publication aPublication) {
313                 // ---------------------------
314                 Session session = Database.getSession();
315                 Step step = getInvolvedStep(aPublication);
316
317                 // Update of involved step
318                 Document previous = aPublication.value().getPreviousVersion();
319                 if (previous != null) {
320                         Publication oldoc = step.getDocument(previous.getIndex());
321                         boolean done = step.remove(oldoc); // Decrements the configuration tag count of document
322                         if (done)
323                                 session.delete(oldoc); // WARNING: Potential problem because it's not automatically done as orphan object
324                 }
325                 step.add(aPublication); // Increments the configuration tag count of document
326
327                 // Import the document properties and update of the study
328                 forwardProperties(aPublication, aPublication.value().getSourceFile()
329                                 .asFile(), step);
330                 session.update(aPublication.getOwner());
331         }
332
333         private void forwardProperties(Publication aPublication, java.io.File from,
334                         Step to) {
335                 // -----------------------------------------------------------
336                 Reader tool = Toolbox.getReader(from);
337                 if (tool == null)
338                         return; // No properties extractor available for this type of document
339
340                 SimulationContextType.Properties sprop = new SimulationContextType.Properties()
341                                 .setStep(to.getStep()).setState(ProgressState.APPROVED);
342                 List<SimulationContextType> contype = SimulationContext
343                                 .selectTypesWhere(sprop);
344                 if (contype.isEmpty())
345                         return; // No approved property type configured at this step
346
347                 SimulationContext.Properties cprop = new SimulationContext.Properties();
348                 List<SimulationContext> context = to.getAllSimulationContexts();
349
350                 context = new ArrayList<SimulationContext>(context.size());
351                 context.addAll(to.getAllSimulationContexts());
352                 cprop.disableCheck();
353                 for (Iterator<SimulationContextType> i = contype.iterator(); i
354                                 .hasNext();) {
355                         SimulationContextType property = i.next();
356                         for (Iterator<SimulationContext> j = context.iterator(); j
357                                         .hasNext();) {
358                                 SimulationContext existing = j.next();
359                                 if (!existing.getType().equals(property))
360                                         continue;
361                                 property = null; // Forget this property as it is already set
362                                 break;
363                         }
364                         if (property != null)
365                                 try {
366                                         String value = tool.extractProperty(property.getName());
367                                         if (value == null)
368                                                 continue; // Property not defined into the document
369
370                                         cprop.setType(property).setValue(value);
371                                         if (aPublication.getOwner() instanceof Study)
372                                                 getStudyService().addProjectContext(
373                                                                 (Study) aPublication.getOwner(), cprop); // Re-indexes knowledges and the study
374                                         else
375                                                 getStepService().addSimulationContext(to, cprop); // Re-indexes knowledges only
376                                 } catch (Exception e) {
377                                         break;
378                                 }
379                 }
380         }
381
382         /**
383          * Returns the study Step into which the document version referenced by this publication has been published.
384          */
385         public Step getInvolvedStep(Publication aPublication) {
386                 if (aPublication.getStep() == null) {
387                         Step[] step = getProjectElementService().getSteps(aPublication.getOwner());
388                         for (int i = 0; i < step.length; i++) {
389                                 aPublication.setStep(step[i]); // The involved step necessarily exists
390                                 if (aPublication.value().isInto(aPublication.getStep()))
391                                         break;
392                         }
393                 }
394                 return aPublication.getStep();
395         }
396
397         /**
398          * @return
399          */
400         private StepService getStepService() {
401                 return _stepService;
402         }
403
404         public void setStepService(StepService stepService) {
405                 _stepService = stepService;
406         }
407
408         /**
409          * @return
410          */
411         public StudyService getStudyService() {
412                 return _studyService;
413         }
414
415         public void setStudyService(StudyService studyService) {
416                 _studyService = studyService;
417         }
418
419         /**
420          * @return
421          */
422         public DocumentTypeService getDocumentTypeService() {
423                 return _documentTypeService;
424         }
425
426         public void setDocumentTypeService(DocumentTypeService documentTypeService) {
427                 _documentTypeService = documentTypeService;
428         }
429
430         /**
431          * Get the projectElementService.
432          * @return the projectElementService
433          */
434         public ProjectElementService getProjectElementService() {
435                 return _projectElementService;
436         }
437
438         /**
439          * Set the projectElementService.
440          * @param projectElementService the projectElementService to set
441          */
442         public void setProjectElementService(ProjectElementService projectElementService) {
443                 _projectElementService = projectElementService;
444         }
445 }