Salome HOME
e5a6634855878a2646d3aa8bf72b22320dab9763
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / PublicationServiceImpl.java
1 /*****************************************************************************
2  * Company         OPEN CASCADE
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.splat.dal.bo.kernel.User;
19 import org.splat.dal.bo.som.ConvertsRelation;
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.UsedByRelation;
30 import org.splat.dal.bo.som.ValidationCycle;
31 import org.splat.dal.bo.som.ValidationStep;
32 import org.splat.dal.dao.som.Database;
33 import org.splat.dal.dao.som.ProjectElementDAO;
34 import org.splat.dal.dao.som.PublicationDAO;
35 import org.splat.kernel.InvalidPropertyException;
36 import org.splat.kernel.NotApplicableException;
37 import org.splat.manox.Reader;
38 import org.splat.manox.Toolbox;
39 import org.splat.som.DocumentRights;
40 import org.splat.som.Revision;
41 import org.splat.som.Step;
42 import org.springframework.transaction.annotation.Transactional;
43
44 /**
45  * Publication service implementation.
46  * 
47  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
48  */
49 public class PublicationServiceImpl implements PublicationService {
50
51         /**
52          * Injected study service.
53          */
54         private StudyService _studyService;
55         /**
56          * Injected step service.
57          */
58         private StepService _stepService;
59         /**
60          * Injected document service.
61          */
62         private DocumentService _documentService;
63         /**
64          * Injected project element service.
65          */
66         private ProjectElementService _projectElementService;
67         /**
68          * Injected simulation context service.
69          */
70         private SimulationContextService _simulationContextService;
71         /**
72          * Injected publication DAO.
73          */
74         private PublicationDAO _publicationDAO;
75         /**
76          * Injected project element DAO.
77          */
78         private ProjectElementDAO _projectElementDAO;
79
80         /**
81          * {@inheritDoc}
82          * 
83          * @see org.splat.service.PublicationService#copy(org.splat.dal.bo.som.Publication, org.splat.dal.bo.som.ProjectElement)
84          */
85         public Publication copy(Publication aPublication, ProjectElement publisher) {
86                 Publication copy = new Publication();
87                 copy.setValue(aPublication.value());
88                 copy.setStep(aPublication.getStep()); // May not be initialized yet
89                 copy.setOwner(publisher);
90                 copy.setIsnew(aPublication.getIsnew());
91                 if (!copy.getOwnerStudy().equals(aPublication.getOwnerStudy())) {
92                         copy.setIsnew('N'); // The referenced document is not new for the given study
93                 }
94                 return copy;
95         }
96
97         /**
98          * {@inheritDoc}
99          * 
100          * @see org.splat.service.PublicationService#approve(org.splat.dal.bo.som.Publication, java.util.Date)
101          */
102         public Timestamp approve(Publication aPublication, Date adate) {
103                 if (aPublication.isOutdated())
104                         return null;
105                 else if (aPublication.value().getProgressState() != ProgressState.inCHECK)
106                         return null; // This statement must conform to the corresponding right
107
108                 DocumentType type = aPublication.value().getType();
109                 Study owner = aPublication.getOwnerStudy();
110                 ValidationCycle cycle = getStudyService().getValidationCycleOf(owner,
111                                 type);
112                 User approver = cycle.getActor(ValidationStep.APPROVAL);
113                 Timestamp stamp = new Timestamp(ValidationStep.APPROVAL,
114                                 aPublication.value(), approver, adate);
115                 if (!getDocumentService().promote(aPublication.value(), stamp))
116                         return null;
117                 if (getDocumentService().isStudyResult(type)
118                                 && owner.getProgressState() == ProgressState.inCHECK)
119                         getStudyService().promote(owner);
120                 return stamp; // Hoping that promotion of the study succeeded
121         }
122
123         /**
124          * {@inheritDoc}
125          * 
126          * @see org.splat.service.PublicationService#demote(org.splat.dal.bo.som.Publication)
127          */
128         public boolean demote(Publication aPublication) {
129                 DocumentType type = aPublication.value().getType();
130                 Study owner = aPublication.getOwnerStudy();
131
132                 if (aPublication.value().getProgressState() == ProgressState.inCHECK) {
133                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
134                                         owner, type);
135                         if (cycle.enables(ValidationStep.REVIEW)) {
136                                 if (!getDocumentService().demote(aPublication.value()))
137                                         return false;
138                         } else {
139                                 if (!getDocumentService().demote(aPublication.value()))
140                                         return false;
141                                 getDocumentService().demote(aPublication.value());
142                         }
143                 } else if (aPublication.value().getProgressState() == ProgressState.inDRAFT) {
144                         if (!getDocumentService().demote(aPublication.value()))
145                                 return false;
146                 } else {
147                         return false;
148                 }
149                 if (getDocumentService().isStudyResult(type)
150                                 && owner.getProgressState() != ProgressState.inWORK)
151                         getStudyService().demote(owner);
152                 return true;
153         }
154
155         /**
156          * {@inheritDoc}
157          * 
158          * @see org.splat.service.PublicationService#invalidate(org.splat.dal.bo.som.Publication)
159          */
160         public boolean invalidate(Publication aPublication) {
161                 if (aPublication.value().getProgressState() != ProgressState.inCHECK)
162                         return false;
163                 if (!getDocumentService().demote(aPublication.value())) // Removes the reviewer if this document is In-Check
164                         return false;
165                 DocumentType type = aPublication.value().getType();
166                 Study owner = aPublication.getOwnerStudy();
167                 if (getDocumentService().isStudyResult(type)
168                                 && owner.getProgressState() == ProgressState.inCHECK)
169                         getStudyService().demote(owner);
170                 return true;
171         }
172
173         /**
174          * {@inheritDoc}
175          * 
176          * @see org.splat.service.PublicationService#promote(org.splat.dal.bo.som.Publication, java.util.Date)
177          */
178         public Timestamp promote(Publication aPublication, Date pdate) {
179                 if (aPublication.isOutdated())
180                         return null;
181                 else if (aPublication.value().getProgressState() != ProgressState.inWORK)
182                         return null; // This statement must conform to the corresponding right
183                 else {
184                         DocumentType type = aPublication.value().getType();
185                         Study owner = aPublication.getOwnerStudy();
186                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
187                                         owner, type);
188                         User promoter = cycle.getActor(ValidationStep.PROMOTION);
189                         if (promoter == null)
190                                 promoter = getInvolvedStep(aPublication).getActor();
191                         if (promoter == null)
192                                 promoter = owner.getAuthor();
193                         Timestamp stamp = new Timestamp(ValidationStep.PROMOTION,
194                                         aPublication.value(), promoter, pdate);
195
196                         if (!getDocumentService().promote(aPublication.value(), stamp)) // Promotion to being reviewed
197                                 return null;
198                         if (!cycle.enables(ValidationStep.REVIEW)) {
199                                 getDocumentService().promote(aPublication.value(), null);
200                         }
201                         if (getDocumentService().isStudyResult(type)
202                                         && owner.getProgressState() == ProgressState.inWORK)
203                                 getStudyService().promote(owner);
204                         return stamp; // Hoping that promotion of the study succeeded
205                 }
206         }
207
208         /**
209          * {@inheritDoc}
210          * 
211          * @see org.splat.service.PublicationService#review(org.splat.dal.bo.som.Publication, java.util.Date)
212          */
213         public Timestamp review(Publication aPublication, Date rdate) {
214                 if (aPublication.isOutdated())
215                         return null;
216                 else if (aPublication.value().getProgressState() != ProgressState.inDRAFT)
217                         return null; // This statement must conform to the corresponding right
218
219                 DocumentType type = aPublication.value().getType();
220                 Study owner = aPublication.getOwnerStudy();
221                 ValidationCycle cycle = getStudyService().getValidationCycleOf(owner,
222                                 type);
223                 User reviewer = cycle.getActor(ValidationStep.REVIEW);
224                 Timestamp stamp = new Timestamp(ValidationStep.REVIEW,
225                                 aPublication.value(), reviewer, rdate);
226                 if (!getDocumentService().promote(aPublication.value(), stamp))
227                         return null;
228                 if (getDocumentService().isStudyResult(type)
229                                 && owner.getProgressState() == ProgressState.inDRAFT)
230                         getStudyService().promote(owner);
231                 return stamp; // Hoping that promotion of the study succeeded
232         }
233
234         /**
235          * {@inheritDoc}
236          * 
237          * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.som.Revision)
238          * @deprecated
239          */
240         @Transactional
241         public void saveAs(Publication aPublication, Revision newvers)
242                         throws FileNotFoundException, NotApplicableException {
243                 if (aPublication.value().isUndefined())
244                         throw new NotApplicableException(
245                                         "Cannot save a Publication object refering an undefined Document");
246                 if (!aPublication.value().getSourceFile().exists())
247                         throw new FileNotFoundException();
248
249                 getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
250                 getDocumentService().updateAs(aPublication.value(), newvers); // May change the branch name of given revision
251                 updateOwner(aPublication);
252         }
253
254         /**
255          * {@inheritDoc}
256          * 
257          * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.dal.bo.som.ProgressState)
258          */
259         @Transactional
260         public void saveAs(Publication aPublication, ProgressState state)
261                         throws FileNotFoundException, NotApplicableException {
262                 if (aPublication.value().isUndefined())
263                         throw new NotApplicableException(
264                                         "Cannot save a Publication object refering an undefined Document");
265                 if (!aPublication.value().getSourceFile().exists())
266                         throw new FileNotFoundException();
267
268                 if (state == ProgressState.inWORK || state == ProgressState.EXTERN) {
269                         getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
270                         // hascode
271                         getDocumentService().updateAs(aPublication.value(), state);
272                 } else {
273                         DocumentType mytype = aPublication.value().getType();
274                         Study owner = aPublication.getOwnerStudy();
275                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
276                                         owner, mytype);
277                         boolean review = cycle.enables(ValidationStep.REVIEW);
278                         if (!(state == ProgressState.inDRAFT && review)
279                                         && !(state == ProgressState.inCHECK && !review)) {
280                                 throw new NotApplicableException(
281                                                 "Cannot save a result document in " + state.toString()
282                                                                 + " state");
283                         }
284                         getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
285                         // hascode
286                         getDocumentService().updateAs(aPublication.value(),
287                                         ProgressState.inWORK);
288
289                         promote(aPublication, aPublication.value()
290                                         .getLastModificationDate()); // Promotes to the appropriate state in accordance to the validation cycle
291                 }
292                 updateOwner(aPublication);
293         }
294
295         /**
296          * Update an owner of the publication.
297          * 
298          * @param aPublication
299          *            the document publication
300          */
301         @Transactional
302         private void updateOwner(Publication aPublication) {
303                 Step step = getInvolvedStep(aPublication);
304
305                 // Update of involved step
306                 Document previous = aPublication.value().getPreviousVersion();
307                 if (previous != null) {
308                         Publication oldoc = step.getDocument(previous.getIndex());
309                         boolean done = getStepService().remove(step, oldoc); // Decrements the configuration tag count of document
310                         if (done)
311                                 getPublicationDAO().delete(oldoc); // WARNING: Potential problem because it's not automatically done as orphan object
312                 }
313                 getStepService().add(step, aPublication); // Increments the configuration tag count of document
314
315                 // Import the document properties and update of the study
316                 forwardProperties(aPublication, aPublication.value().getSourceFile()
317                                 .asFile(), step);
318                 getProjectElementDAO().update(aPublication.getOwner());
319         }
320
321         /**
322          * Propagate simulation contexts from the given config file to the publication's owner (study or step).
323          * 
324          * @param aPublication
325          *            the document publication
326          * @param from
327          *            the config file
328          * @param to
329          *            the study step
330          */
331         private void forwardProperties(Publication aPublication, java.io.File from,
332                         Step to) {
333                 Reader tool = Toolbox.getReader(from);
334                 if (tool == null)
335                         return; // No properties extractor available for this type of document
336
337                 SimulationContextType.Properties sprop = new SimulationContextType.Properties()
338                                 .setStep(to.getStep()).setProgressState(ProgressState.APPROVED);
339                 List<SimulationContextType> contype = getSimulationContextService()
340                                 .selectTypesWhere(sprop);
341                 if (contype.isEmpty())
342                         return; // No approved property type configured at this step
343
344                 SimulationContext.Properties cprop = new SimulationContext.Properties();
345                 List<SimulationContext> context = to.getAllSimulationContexts();
346
347                 context = new ArrayList<SimulationContext>(context.size());
348                 context.addAll(to.getAllSimulationContexts());
349                 cprop.disableCheck();
350                 for (Iterator<SimulationContextType> i = contype.iterator(); i
351                                 .hasNext();) {
352                         SimulationContextType property = i.next();
353                         for (Iterator<SimulationContext> j = context.iterator(); j
354                                         .hasNext();) {
355                                 SimulationContext existing = j.next();
356                                 if (!existing.getType().equals(property))
357                                         continue;
358                                 property = null; // Forget this property as it is already set
359                                 break;
360                         }
361                         if (property != null)
362                                 try {
363                                         String value = tool.extractProperty(property.getName());
364                                         if (value == null)
365                                                 continue; // Property not defined into the document
366
367                                         cprop.setType(property).setValue(value);
368                                         if (aPublication.getOwner() instanceof Study)
369                                                 getStudyService().addProjectContext(
370                                                                 (Study) aPublication.getOwner(), cprop); // Re-indexes knowledges and the study
371                                         else
372                                                 getStepService().addSimulationContext(to, cprop); // Re-indexes knowledges only
373                                 } catch (Exception e) {
374                                         break;
375                                 }
376                 }
377         }
378
379         /**
380          * Returns the study Step into which the document version referenced by this publication has been published.
381          * 
382          * @param aPublication
383          *            the document publication
384          * @return the study step where the document is published
385          */
386         public Step getInvolvedStep(Publication aPublication) {
387                 if (aPublication.getStep() == null) {
388                         Step[] step = getProjectElementService().getSteps(
389                                         aPublication.getOwner());
390                         for (int i = 0; i < step.length; i++) {
391                                 aPublication.setStep(step[i]); // The involved step necessarily exists
392                                 if (aPublication.value().isInto(aPublication.getStep()))
393                                         break;
394                         }
395                 }
396                 return aPublication.getStep();
397         }
398
399         /**
400          * Undo the out-date operation.
401          * 
402          * @param aPublication
403          *            the publication
404          * @return true if the acceptance succeeds
405          * @see #outdate()
406          * @see DocumentRights#canAccept()
407          */
408         public boolean actualize(Publication aPublication) {
409                 if (!aPublication.isOutdated())
410                         return false;
411                 aPublication.setIsnew('Y');
412                 getPublicationDAO().update(aPublication);
413                 return true;
414         }
415
416         /**
417          * Out-dates this publication and recursively all publications using this one. Typically, a publication is out-dated when modifying a
418          * document to which it depends.
419          * 
420          * @param aPublication
421          *            the publication
422          * @see #isOutdated()
423          * @see #getProgressState()
424          * @see #actualize()
425          */
426         public void outdate(Publication aPublication) {
427                 if (aPublication.isOutdated())
428                         return;
429
430                 List<Publication> relist = aPublication
431                                 .getRelations(UsedByRelation.class);
432                 for (Iterator<Publication> i = relist.iterator(); i.hasNext();) {
433                         outdate(i.next());
434                 }
435                 aPublication.setIsnew('O');
436                 getPublicationDAO().update(aPublication);
437         }
438
439         /**
440          * Create "Converts" relation for the given document publication and format.
441          * 
442          * @param aPublication
443          *            the document publication
444          * @param format
445          *            the format
446          * @return the created "Converts" relation
447          */
448         public ConvertsRelation attach(Publication aPublication, String format) {
449                 return getDocumentService().attach(aPublication.value(), format);
450         }
451
452         /**
453          * Create "Converts" relation for the given document publication, format and description.
454          * 
455          * @param aPublication
456          *            the document publication
457          * @param format
458          *            the format
459          * @param description
460          *            the description of the relation
461          * @return the created "Converts" relation
462          */
463         public ConvertsRelation attach(Publication aPublication, String format,
464                         String description) {
465                 return getDocumentService().attach(aPublication.value(), format,
466                                 description);
467         }
468
469         /**
470          * Rename the published document.
471          * 
472          * @param aPublication
473          *            the publication of the document
474          * @param title
475          *            the new document title
476          * @throws InvalidPropertyException
477          *             if the new title is empty
478          */
479         public void rename(Publication aPublication, String title)
480                         throws InvalidPropertyException {
481                 getDocumentService().rename(aPublication.value(), title);
482         }
483
484         /**
485          * Get the projectElementService.
486          * 
487          * @return the projectElementService
488          */
489         public ProjectElementService getProjectElementService() {
490                 return _projectElementService;
491         }
492
493         /**
494          * Set the projectElementService.
495          * 
496          * @param projectElementService
497          *            the projectElementService to set
498          */
499         public void setProjectElementService(
500                         ProjectElementService projectElementService) {
501                 _projectElementService = projectElementService;
502         }
503
504         /**
505          * Get the simulationContextService.
506          * 
507          * @return the simulationContextService
508          */
509         public SimulationContextService getSimulationContextService() {
510                 return _simulationContextService;
511         }
512
513         /**
514          * Set the simulationContextService.
515          * 
516          * @param simulationContextService
517          *            the simulationContextService to set
518          */
519         public void setSimulationContextService(
520                         SimulationContextService simulationContextService) {
521                 _simulationContextService = simulationContextService;
522         }
523
524         /**
525          * Get the studyService.
526          * 
527          * @return the studyService
528          */
529         public StudyService getStudyService() {
530                 return _studyService;
531         }
532
533         /**
534          * Set the studyService.
535          * 
536          * @param studyService
537          *            the studyService to set
538          */
539         public void setStudyService(StudyService studyService) {
540                 _studyService = studyService;
541         }
542
543         /**
544          * Get the stepService.
545          * 
546          * @return the stepService
547          */
548         public StepService getStepService() {
549                 return _stepService;
550         }
551
552         /**
553          * Set the stepService.
554          * 
555          * @param stepService
556          *            the stepService to set
557          */
558         public void setStepService(StepService stepService) {
559                 _stepService = stepService;
560         }
561
562         /**
563          * Get the documentService.
564          * 
565          * @return the documentService
566          */
567         public DocumentService getDocumentService() {
568                 return _documentService;
569         }
570
571         /**
572          * Set the documentService.
573          * 
574          * @param documentService
575          *            the documentService to set
576          */
577         public void setDocumentService(DocumentService documentService) {
578                 _documentService = documentService;
579         }
580
581         /**
582          * Get the publicationDAO.
583          * 
584          * @return the publicationDAO
585          */
586         public PublicationDAO getPublicationDAO() {
587                 return _publicationDAO;
588         }
589
590         /**
591          * Set the publicationDAO.
592          * 
593          * @param publicationDAO
594          *            the publicationDAO to set
595          */
596         public void setPublicationDAO(PublicationDAO publicationDAO) {
597                 _publicationDAO = publicationDAO;
598         }
599
600         /**
601          * Get the projectElementDAO.
602          * 
603          * @return the projectElementDAO
604          */
605         public ProjectElementDAO getProjectElementDAO() {
606                 return _projectElementDAO;
607         }
608
609         /**
610          * Set the projectElementDAO.
611          * 
612          * @param projectElementDAO
613          *            the projectElementDAO to set
614          */
615         public void setProjectElementDAO(ProjectElementDAO projectElementDAO) {
616                 _projectElementDAO = projectElementDAO;
617         }
618 }