Salome HOME
Studies comparison functionality is implemented.
[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.File;
13 import java.io.FileNotFoundException;
14 import java.io.IOException;
15 import java.text.ParseException;
16 import java.util.ArrayList;
17 import java.util.Date;
18 import java.util.HashSet;
19 import java.util.Iterator;
20 import java.util.List;
21
22 import org.apache.log4j.Logger;
23 import org.splat.common.properties.MessageKeyEnum;
24 import org.splat.dal.bo.kernel.User;
25 import org.splat.dal.bo.som.ConvertsRelation;
26 import org.splat.dal.bo.som.Document;
27 import org.splat.dal.bo.som.DocumentType;
28 import org.splat.dal.bo.som.ProgressState;
29 import org.splat.dal.bo.som.ProjectElement;
30 import org.splat.dal.bo.som.Publication;
31 import org.splat.dal.bo.som.SimulationContext;
32 import org.splat.dal.bo.som.SimulationContextType;
33 import org.splat.dal.bo.som.Study;
34 import org.splat.dal.bo.som.Timestamp;
35 import org.splat.dal.bo.som.UsedByRelation;
36 import org.splat.dal.bo.som.ValidationCycle;
37 import org.splat.dal.bo.som.ValidationStep;
38 import org.splat.dal.dao.som.ProjectElementDAO;
39 import org.splat.dal.dao.som.PublicationDAO;
40 import org.splat.dal.dao.som.TimestampDAO;
41 import org.splat.exception.InvalidParameterException;
42 import org.splat.kernel.InvalidPropertyException;
43 import org.splat.kernel.MismatchException;
44 import org.splat.kernel.MissedPropertyException;
45 import org.splat.kernel.MultiplyDefinedException;
46 import org.splat.kernel.NotApplicableException;
47 import org.splat.manox.Reader;
48 import org.splat.manox.Toolbox;
49 import org.splat.service.dto.DocToCompareDTO;
50 import org.splat.service.technical.RepositoryService;
51 import org.splat.som.DocumentRights;
52 import org.splat.som.Revision;
53 import org.splat.som.Step;
54 import org.springframework.transaction.annotation.Transactional;
55
56 /**
57  * Publication service implementation.
58  * 
59  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
60  */
61 public class PublicationServiceImpl implements PublicationService {
62
63         /**
64          * Logger for this class.
65          */
66         protected final static Logger LOG = Logger
67                         .getLogger(PublicationServiceImpl.class);
68
69         /**
70          * Injected study service.
71          */
72         private StudyService _studyService;
73         /**
74          * Injected step service.
75          */
76         private StepService _stepService;
77         /**
78          * Injected document service.
79          */
80         private DocumentService _documentService;
81         /**
82          * Injected document type service.
83          */
84         private DocumentTypeService _documentTypeService;
85         /**
86          * Injected user service.
87          */
88         private UserService _userService;
89         /**
90          * Injected project element service.
91          */
92         private ProjectElementService _projectElementService;
93         /**
94          * Injected simulation context service.
95          */
96         private SimulationContextService _simulationContextService;
97         /**
98          * Injected publication DAO.
99          */
100         private PublicationDAO _publicationDAO;
101         /**
102          * Injected timestamp DAO.
103          */
104         private TimestampDAO _timestampDAO;
105         /**
106          * Injected project element DAO.
107          */
108         private ProjectElementDAO _projectElementDAO;
109         /**
110          * Injected repository service.
111          */
112         private RepositoryService _repositoryService;
113
114         /**
115          * {@inheritDoc}
116          * 
117          * @see org.splat.service.PublicationService#copy(org.splat.dal.bo.som.Publication, org.splat.dal.bo.som.ProjectElement)
118          */
119         public Publication copy(final Publication aPublication,
120                         final ProjectElement publisher) {
121                 Publication copy = new Publication();
122                 copy.setValue(aPublication.value());
123                 copy.setStep(aPublication.getStep()); // May not be initialized yet
124                 copy.setOwner(publisher);
125                 copy.setIsnew(aPublication.getIsnew());
126                 if (!copy.getOwnerStudy().equals(aPublication.getOwnerStudy())) {
127                         copy.setIsnew('N'); // The referenced document is not new for the given study
128                 }
129                 return copy;
130         }
131
132         /**
133          * {@inheritDoc}
134          * 
135          * @see org.splat.service.PublicationService#createDoc(long, org.splat.som.Step, long, long, java.lang.String, java.lang.String,
136          *      org.splat.dal.bo.som.ProgressState, java.lang.String, java.lang.String, java.util.Date, java.util.List)
137          */
138         @Transactional
139         public Publication createDoc(final long ownerId, final Step step,
140                         final long documentTypeId, final long userId, final String fname,
141                         final String doctitle, final ProgressState docstate,
142                         final String reference, final String version, final Date docDate,
143                         final List<Long> docuses) throws MissedPropertyException,
144                         InvalidPropertyException, MultiplyDefinedException, IOException,
145                         NotApplicableException, InterruptedException, ParseException {
146                 DocumentType type = getDocumentTypeService().selectType(
147                                 (int) documentTypeId);
148                 User user = getUserService().selectUser(userId);
149                 File updir = getRepositoryService().getDownloadDirectory(user);
150                 File upfile = new File(updir.getPath() + "/" + fname);
151                 String[] table = fname.split("\\x2E");
152
153                 // Creation of the document
154                 Document.Properties dprop = new Document.Properties();
155                 dprop.setLocalPath(upfile.getPath());
156                 Publication addoc;
157
158                 if (reference.length() == 0) { // Importation of a foreign document
159                         // TODO: Extract property of supported documents (DOCX, ODT...)
160                         addoc = getStepService().createDocument(
161                                         step,
162                                         dprop.setName(doctitle).setType(type).setFormat(
163                                                         table[table.length - 1]).setAuthor(user));
164                         updir = addoc.getSourceFile().asFile();
165                         if (LOG.isInfoEnabled()) {
166                                 LOG.info("Moving \"" + upfile.getAbsolutePath() + "\" to \""
167                                                 + updir.getPath() + "\".");
168                         }
169                         upfile.renameTo(updir);
170                         try {
171                                 saveAs(addoc, docstate); // May throw FileNotFound if rename was not done
172                         } catch (FileNotFoundException saverror) {
173                                 Thread.sleep(1000);
174                                 LOG.info("Waiting for the file.");
175                                 upfile.renameTo(updir);
176                                 saveAs(addoc, docstate); // Forget it if throw again FileNotFound
177                         }
178                 } else { // Importation of a previously created template-based document
179                         if (docDate != null) {
180                                 dprop.setDate(docDate);
181                         }
182                         addoc = getStepService().assignDocument(step,
183                                         dprop.setReference(reference).setName(doctitle));
184                         updir = addoc.getSourceFile().asFile();
185                         if (LOG.isInfoEnabled()) {
186                                 LOG.info("Moving \"" + upfile.getName() + "\" to \""
187                                                 + updir.getPath() + "\".");
188                         }
189                         upfile.renameTo(updir);
190                         try {
191                                 if (version.length() > 0) {
192                                         saveAs(addoc, new Revision(version));
193                                 } else {
194                                         saveAs(addoc, docstate);
195                                 }
196                         } catch (FileNotFoundException saverror) {
197                                 Thread.sleep(1000);
198                                 LOG.info("Waiting for the file.");
199                                 upfile.renameTo(updir);
200                                 if (version.length() > 0) {
201                                         saveAs(addoc, new Revision(version));
202                                 } else {
203                                         saveAs(addoc, docstate);
204                                 }
205                         }
206                 }
207                 // Creation of uses relations
208                 if (docuses != null) {
209                         for (Long index : docuses) {
210                                 Document used = getDocumentService().selectDocument(index);
211                                 addoc.addDependency(used);
212                         }
213                 }
214                 return addoc;
215         }
216
217         /**
218          * {@inheritDoc}
219          * 
220          * @see org.splat.service.PublicationService#versionDocument(org.splat.som.Step, org.splat.dal.bo.kernel.User, java.lang.String, long,
221          *      java.lang.String, java.lang.String, org.splat.dal.bo.som.ProgressState, java.util.Date, java.lang.String[], long[])
222          */
223         @Transactional
224         public void versionDocument(final Step step, final User user,
225                         final String filename, final long docIndex, final String docver,
226                         final String summary, final ProgressState state, final Date date,
227                         final String[] docuses, final long[] docusedby)
228                         throws MissedPropertyException, InvalidPropertyException,
229                         MultiplyDefinedException, IOException, MismatchException,
230                         NotApplicableException, InterruptedException {
231                 File updir = getRepositoryService().getDownloadDirectory(user);
232                 File upfile = new File(updir.getPath() + "/" + filename);
233
234                 // Versioning of the document
235                 Document.Properties dprop = new Document.Properties();
236                 dprop.setLocalPath(upfile.getPath());
237                 Publication current = step.getDocument(docIndex);
238                 Publication next;
239
240                 if ((docver.length() != 0) && // Importation of a not foreign document
241                                 (date != null)) {
242                         dprop.setDate(date);
243                 }
244                 if ((summary != null) && (summary.length() > 0)) {
245                         dprop.setDescription(summary);
246                 }
247                 next = getStepService().versionDocument(step, current,
248                                 dprop.setAuthor(user));
249                 updir = next.getSourceFile().asFile();
250                 if (LOG.isInfoEnabled()) {
251                         LOG.info("Moving \"" + upfile.getName() + "\" to \""
252                                         + updir.getPath() + "\".");
253                 }
254                 upfile.renameTo(updir);
255
256                 try {
257                         if (docver.length() == 0) { // Importation of a foreign document
258                                 saveAs(next, state); // May throw FileNotFound if rename was not done
259                         } else {
260                                 saveAs(next, new Revision(docver));
261                         }
262                 } catch (FileNotFoundException saverror) {
263                         Thread.sleep(1000);
264                         LOG.info("Waiting for the file.");
265                         upfile.renameTo(updir);
266                         saveAs(next, state);
267                 }
268                 // TODO: Remove current document details from the contents of open study
269
270                 // Creation of uses relations
271                 updateRelations(current, next, docuses, docusedby);
272         }
273
274         /**
275          * Update relations after creation of a new document version.
276          * 
277          * @param current
278          *            the current version
279          * @param next
280          *            the new version
281          * @param docuses
282          *            ids of used documents
283          * @param docusedby
284          *            ids of documents used by the versioned one.
285          */
286         private void updateRelations(final Publication current,
287                         final Publication next, final String[] docuses,
288                         final long[] docusedby) {
289                 if (docuses != null) {
290                         for (int i = 0; i < docuses.length; i++) {
291                                 Long index = Long.valueOf(docuses[i].trim());
292                                 Document used = getDocumentService().selectDocument(index);// RKV: getPublication(index, steps);
293                                 next.addDependency(used);
294                         }
295                 }
296                 // Outdating impacted document
297                 HashSet<Long> compatible = new HashSet<Long>();
298                 if (docusedby != null) {
299                         for (int i = 0; i < docusedby.length; i++) {
300                                 compatible.add(docusedby[i]);
301                         }
302                 }
303                 List<Publication> relist = current.getRelations(UsedByRelation.class);
304                 for (Iterator<Publication> i = relist.iterator(); i.hasNext();) {
305                         Publication using = i.next();
306                         if (!compatible.contains(using.getIndex())) {
307                                 outdate(using);
308                         }
309                 }
310         }
311
312         /*
313          * protected Publication getPublication(int index, List<Step> steps) { for (Iterator<Step> i = steps.iterator(); i.hasNext();) { List<Publication>
314          * published = i.next().getAllDocuments(); for (Iterator<Publication> j = published.iterator(); j.hasNext();) { Publication found =
315          * j.next(); // In a given study step, if (found.value().getIndex() == index) return found; // there is only one publication of a given
316          * document } } return null; }
317          */
318         /**
319          * {@inheritDoc}
320          * 
321          * @see org.splat.service.PublicationService#approve(org.splat.dal.bo.som.Publication, java.util.Date)
322          */
323         @Transactional
324         public Timestamp approve(final Publication aPublication, final Date adate) {
325                 Timestamp res = null;
326                 if (!(aPublication.isOutdated() || (aPublication.value()
327                                 .getProgressState() != ProgressState.inCHECK))) {
328                         DocumentType type = aPublication.value().getType();
329                         Study owner = aPublication.getOwnerStudy();
330                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
331                                         owner, type);
332                         User approver = cycle.getActor(ValidationStep.APPROVAL);
333                         Timestamp stamp = new Timestamp(ValidationStep.APPROVAL,
334                                         aPublication.value(), approver, adate);
335                         getTimestampDAO().create(stamp);
336
337                         if (getDocumentService().promote(aPublication.value(), stamp)) {
338                                 res = stamp;
339                                 if (getDocumentService().isStudyResult(type)
340                                                 && owner.getProgressState() == ProgressState.inCHECK) {
341                                         getStudyService().promote(owner);
342                                 }
343                         }
344                 }
345                 return res; // Hoping that promotion of the study succeeded
346         }
347
348         /**
349          * {@inheritDoc}
350          * 
351          * @see org.splat.service.PublicationService#demote(org.splat.dal.bo.som.Publication)
352          */
353         @Transactional
354         public boolean demote(final Publication aPublication) {
355                 boolean res = false;
356                 DocumentType type = aPublication.value().getType();
357                 Study owner = aPublication.getOwnerStudy();
358
359                 if (aPublication.value().getProgressState() == ProgressState.inCHECK) {
360                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
361                                         owner, type);
362                         if (cycle.enables(ValidationStep.REVIEW)) {
363                                 res = getDocumentService().demote(aPublication.value());
364                         } else {
365                                 res = getDocumentService().demote(aPublication.value());
366                                 if (res) {
367                                         getDocumentService().demote(aPublication.value());
368                                 }
369                         }
370                 } else if (aPublication.value().getProgressState() == ProgressState.inDRAFT) {
371                         res = getDocumentService().demote(aPublication.value());
372                 }
373                 if (res && getDocumentService().isStudyResult(type)
374                                 && owner.getProgressState() != ProgressState.inWORK) {
375                         getStudyService().demote(owner);
376                 }
377                 return res;
378         }
379
380         /**
381          * {@inheritDoc}
382          * 
383          * @see org.splat.service.PublicationService#invalidate(org.splat.dal.bo.som.Publication)
384          */
385         @Transactional
386         public boolean invalidate(final Publication aPublication) {
387                 boolean res = false;
388                 if ((aPublication.value().getProgressState() == ProgressState.inCHECK)) {
389                         DocumentType type = aPublication.value().getType();
390                         Study owner = aPublication.getOwnerStudy();
391
392                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
393                                         owner, type);
394                         // Check if the validation cycle allows the review step
395                         if (cycle.enables(ValidationStep.REVIEW)) {
396                                 if (getDocumentService().demote(aPublication.value())
397                                                 && getDocumentService().isStudyResult(type)
398                                                 && owner.getProgressState() == ProgressState.inCHECK) {
399                                         getStudyService().demote(owner);
400                                 }
401                                 res = true;
402                         } else { // If the validation cycle has no inDraft step
403                                 res = demote(aPublication);
404                         }
405                 }
406                 return res;
407         }
408
409         /**
410          * {@inheritDoc}
411          * 
412          * @see org.splat.service.PublicationService#promote(org.splat.dal.bo.som.Publication, java.util.Date)
413          */
414         @Transactional
415         public Timestamp promote(final Publication aPublication, final Date pdate) {
416                 Timestamp res = null;
417                 if ((!aPublication.isOutdated())
418                                 && (aPublication.value().getProgressState() == ProgressState.inWORK)) {
419                         DocumentType type = aPublication.value().getType();
420                         Study owner = aPublication.getOwnerStudy();
421                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
422                                         owner, type);
423                         User promoter = cycle.getActor(ValidationStep.PROMOTION);
424                         if (promoter == null) {
425                                 promoter = getInvolvedStep(aPublication).getActor();
426                         }
427                         if (promoter == null) {
428                                 promoter = owner.getAuthor();
429                         }
430                         Timestamp stamp = new Timestamp(ValidationStep.PROMOTION,
431                                         aPublication.value(), promoter, pdate);
432                         getTimestampDAO().create(stamp);
433
434                         if (getDocumentService().promote(aPublication.value(), stamp)) {
435                                 res = stamp;
436                                 if (!cycle.enables(ValidationStep.REVIEW)) {
437                                         getDocumentService().promote(aPublication.value(), null);
438                                 }
439                                 if (getDocumentService().isStudyResult(type)
440                                                 && owner.getProgressState() == ProgressState.inWORK) {
441                                         getStudyService().promote(owner);
442                                 }
443                         }
444                 }
445                 return res; // Hoping that promotion of the study succeeded
446         }
447
448         /**
449          * {@inheritDoc}
450          * 
451          * @see org.splat.service.PublicationService#review(org.splat.dal.bo.som.Publication, java.util.Date)
452          */
453         @Transactional
454         public Timestamp review(final Publication aPublication, final Date rdate) {
455                 Timestamp res = null;
456                 if (!aPublication.isOutdated()
457                                 && !(aPublication.value().getProgressState() != ProgressState.inDRAFT)) {
458
459                         DocumentType type = aPublication.value().getType();
460                         Study owner = aPublication.getOwnerStudy();
461                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
462                                         owner, type);
463                         User reviewer = cycle.getActor(ValidationStep.REVIEW);
464                         Timestamp stamp = new Timestamp(ValidationStep.REVIEW, aPublication
465                                         .value(), reviewer, rdate);
466                         getTimestampDAO().create(stamp);
467
468                         if (getDocumentService().promote(aPublication.value(), stamp)) {
469                                 res = stamp;
470                                 if (getDocumentService().isStudyResult(type)
471                                                 && owner.getProgressState() == ProgressState.inDRAFT) {
472                                         getStudyService().promote(owner);
473                                 }
474                         }
475                 }
476                 return res; // Hoping that promotion of the study succeeded
477         }
478
479         /**
480          * {@inheritDoc}
481          * 
482          * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.som.Revision)
483          * @deprecated
484          */
485         @Deprecated
486         @Transactional
487         public void saveAs(final Publication aPublication, final Revision newvers)
488                         throws FileNotFoundException, NotApplicableException {
489                 if (aPublication.value().isUndefined()) {
490                         throw new NotApplicableException(
491                                         "Cannot save a Publication object refering an undefined Document");
492                 }
493                 if (!aPublication.value().getSourceFile().exists()) {
494                         throw new FileNotFoundException();
495                 }
496
497                 getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
498                 getDocumentService().updateAs(aPublication.value(), newvers); // May change the branch name of given revision
499                 updateOwner(aPublication);
500         }
501
502         /**
503          * {@inheritDoc}
504          * 
505          * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.dal.bo.som.ProgressState)
506          */
507         @Transactional
508         public void saveAs(final Publication aPublication, final ProgressState state)
509                         throws FileNotFoundException, NotApplicableException {
510                 if (aPublication.value().isUndefined()) {
511                         throw new NotApplicableException(
512                                         "Cannot save a Publication object refering an undefined Document");
513                 }
514                 if (!aPublication.value().getSourceFile().exists()) {
515                         throw new FileNotFoundException(aPublication.value()
516                                         .getSourceFile().asFile().getAbsolutePath());
517                 }
518
519                 if (state == ProgressState.inWORK || state == ProgressState.EXTERN) {
520                         getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
521                         // hascode
522                         getDocumentService().updateAs(aPublication.value(), state);
523                 } else {
524                         // Check that the state is applicable for the validation cycle
525                         DocumentType mytype = aPublication.value().getType();
526                         Study owner = aPublication.getOwnerStudy();
527                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
528                                         owner, mytype);
529                         boolean review = cycle.enables(ValidationStep.REVIEW);
530                         if (!(state == ProgressState.inDRAFT && review)
531                                         && !(state == ProgressState.inCHECK && !review)) {
532                                 throw new NotApplicableException(MessageKeyEnum.DCT_000003
533                                                 .toString(), state.toString());
534                         }
535                         getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
536                         // hascode
537                         getDocumentService().updateAs(aPublication.value(),
538                                         ProgressState.inWORK);
539
540                         promote(aPublication, aPublication.value()
541                                         .getLastModificationDate()); // Promotes to the appropriate state in accordance to the validation cycle
542                 }
543                 updateOwner(aPublication);
544         }
545
546         /**
547          * Update an owner of the publication.
548          * 
549          * @param aPublication
550          *            the document publication
551          */
552         @Transactional
553         private void updateOwner(final Publication aPublication) {
554                 Step step = getInvolvedStep(aPublication);
555
556                 // Update of involved step
557                 Document previous = aPublication.value().getPreviousVersion();
558                 if (previous != null) {
559                         Publication oldoc = step.getDocument(previous.getIndex());
560                         getStepService().remove(step, oldoc); // Decrements the configuration tag count of document
561                 }
562                 getStepService().add(step, aPublication); // Increments the configuration tag count of document
563
564                 // Import the document properties and update of the study
565                 forwardProperties(aPublication, aPublication.value().getSourceFile()
566                                 .asFile(), step);
567                 getProjectElementDAO().merge(aPublication.getOwner());
568         }
569
570         /**
571          * Propagate simulation contexts from the given config file to the publication's owner (study or step).
572          * 
573          * @param aPublication
574          *            the document publication
575          * @param from
576          *            the config file
577          * @param to
578          *            the study step
579          */
580         private void forwardProperties(final Publication aPublication,
581                         final java.io.File from, final Step to) {
582                 Reader tool = Toolbox.getReader(from);
583                 if (tool != null) { // Properties extractor available for this type of document
584                         SimulationContextType.Properties sprop = new SimulationContextType.Properties()
585                                         .setStep(to.getStep()).setProgressState(
586                                                         ProgressState.APPROVED);
587                         List<SimulationContextType> contype = getSimulationContextService()
588                                         .selectTypesWhere(sprop);
589                         if (!contype.isEmpty()) { // There is an approved property type configured at this step
590
591                                 SimulationContext.Properties cprop = new SimulationContext.Properties();
592                                 List<SimulationContext> context = to.getAllSimulationContexts();
593
594                                 context = new ArrayList<SimulationContext>(context.size());
595                                 context.addAll(to.getAllSimulationContexts());
596                                 cprop.disableCheck();
597                                 for (Iterator<SimulationContextType> i = contype.iterator(); i
598                                                 .hasNext();) {
599                                         SimulationContextType property = i.next();
600                                         boolean isFound = false;
601                                         for (Iterator<SimulationContext> j = context.iterator(); j
602                                                         .hasNext();) {
603                                                 SimulationContext existing = j.next();
604                                                 isFound = existing.getType().equals(property);
605                                                 if (isFound) {
606                                                         // Forget this property as it is already set
607                                                         break;
608                                                 }
609                                         }
610                                         if (!isFound) {
611                                                 try {
612                                                         String value = tool.extractProperty(property
613                                                                         .getName());
614                                                         if (value == null) {
615                                                                 continue; // Property not defined into the document
616                                                         }
617
618                                                         cprop.setType(property).setValue(value);
619                                                         if (aPublication.getOwner() instanceof Study) {
620                                                                 getStudyService().addProjectContext(
621                                                                                 (Study) aPublication.getOwner(), cprop); // Re-indexes knowledges and the study
622                                                         } else {
623                                                                 getStepService()
624                                                                                 .addSimulationContext(to, cprop); // Re-indexes knowledges only
625                                                         }
626                                                 } catch (Exception e) {
627                                                         break;
628                                                 }
629                                         }
630                                 }
631                         }
632                 }
633         }
634
635         /**
636          * Returns the study Step into which the document version referenced by this publication has been published.
637          * 
638          * @param aPublication
639          *            the document publication
640          * @return the study step where the document is published
641          */
642         public Step getInvolvedStep(final Publication aPublication) {
643                 if (aPublication.getStep() == null) {
644                         Step[] step = getProjectElementService().getSteps(
645                                         aPublication.getOwner());
646                         for (int i = 0; i < step.length; i++) {
647                                 aPublication.setStep(step[i]); // The involved step necessarily exists
648                                 if (aPublication.value().isInto(aPublication.getStep())) {
649                                         break;
650                                 }
651                         }
652                 }
653                 return aPublication.getStep();
654         }
655
656         /**
657          * Undo the out-date operation.
658          * 
659          * @param aPublication
660          *            the publication
661          * @return true if the acceptance succeeds
662          * @see #outdate()
663          * @see DocumentRights#canAccept()
664          */
665         @Transactional
666         public boolean actualize(final Publication aPublication) {
667                 boolean res = aPublication.isOutdated();
668                 if (res) {
669                         aPublication.setIsnew('Y');
670                         getPublicationDAO().update(aPublication);
671                 }
672                 return res;
673         }
674
675         /**
676          * Out-dates this publication and recursively all publications using this one. Typically, a publication is out-dated when modifying a
677          * document to which it depends.
678          * 
679          * @param aPublication
680          *            the publication
681          * @see #isOutdated()
682          * @see #getProgressState()
683          * @see #actualize()
684          */
685         public void outdate(final Publication aPublication) {
686                 if (aPublication.isOutdated()) {
687                         return;
688                 }
689
690                 List<Publication> relist = aPublication
691                                 .getRelations(UsedByRelation.class);
692                 for (Iterator<Publication> i = relist.iterator(); i.hasNext();) {
693                         outdate(i.next());
694                 }
695                 aPublication.setIsnew('O');
696                 getPublicationDAO().update(aPublication);
697         }
698
699         /**
700          * Create "Converts" relation for the given document publication and format.
701          * 
702          * @param aPublication
703          *            the document publication
704          * @param format
705          *            the format
706          * @return the created "Converts" relation
707          */
708         @Transactional
709         public ConvertsRelation attach(final Publication aPublication,
710                         final String format) {
711                 return getDocumentService().attach(aPublication.value(), format);
712         }
713
714         /**
715          * Create "Converts" relation for the given document publication, format and description.
716          * 
717          * @param aPublication
718          *            the document publication
719          * @param format
720          *            the format
721          * @param description
722          *            the description of the relation
723          * @return the created "Converts" relation
724          */
725         @Transactional
726         public ConvertsRelation attach(final Publication aPublication,
727                         final String format, final String description) {
728                 return getDocumentService().attach(aPublication.value(), format,
729                                 description);
730         }
731
732         /**
733          * Rename the published document.
734          * 
735          * @param aPublication
736          *            the publication of the document
737          * @param title
738          *            the new document title
739          * @throws InvalidPropertyException
740          *             if the new title is empty
741          */
742         public void rename(final Publication aPublication, final String title)
743                         throws InvalidPropertyException {
744                 getDocumentService().rename(aPublication.value(), title);
745         }
746
747         /** 
748          * {@inheritDoc}
749          * @see org.splat.service.PublicationService#getDocToCompareDTO(long)
750          */
751         @Transactional(readOnly = true)
752         @Override
753         public DocToCompareDTO getDocToCompareDTO(final long publicationId) throws InvalidParameterException {
754                 DocToCompareDTO res = new DocToCompareDTO();
755                 Publication pub = _publicationDAO.get(Long.valueOf(publicationId));
756                 if(pub == null) {
757                         throw new InvalidParameterException("id", String.valueOf(publicationId));
758                 }
759                 
760                 res.setDocumentTitle(pub.value().getTitle());
761                 res.setPathToFile(pub.value().getFile().asFile().getAbsolutePath());
762                 res.setScenarioTitle(pub.getOwner().getTitle());
763                 res.setStudyTitle(pub.getOwnerStudy().getTitle());
764                 return res;
765         }
766
767         /**
768          * Get the projectElementService.
769          * 
770          * @return the projectElementService
771          */
772         public ProjectElementService getProjectElementService() {
773                 return _projectElementService;
774         }
775
776         /**
777          * Set the projectElementService.
778          * 
779          * @param projectElementService
780          *            the projectElementService to set
781          */
782         public void setProjectElementService(
783                         final ProjectElementService projectElementService) {
784                 _projectElementService = projectElementService;
785         }
786
787         /**
788          * Get the simulationContextService.
789          * 
790          * @return the simulationContextService
791          */
792         public SimulationContextService getSimulationContextService() {
793                 return _simulationContextService;
794         }
795
796         /**
797          * Set the simulationContextService.
798          * 
799          * @param simulationContextService
800          *            the simulationContextService to set
801          */
802         public void setSimulationContextService(
803                         final SimulationContextService simulationContextService) {
804                 _simulationContextService = simulationContextService;
805         }
806
807         /**
808          * Get the studyService.
809          * 
810          * @return the studyService
811          */
812         public StudyService getStudyService() {
813                 return _studyService;
814         }
815
816         /**
817          * Set the studyService.
818          * 
819          * @param studyService
820          *            the studyService to set
821          */
822         public void setStudyService(final StudyService studyService) {
823                 _studyService = studyService;
824         }
825
826         /**
827          * Get the stepService.
828          * 
829          * @return the stepService
830          */
831         public StepService getStepService() {
832                 return _stepService;
833         }
834
835         /**
836          * Set the stepService.
837          * 
838          * @param stepService
839          *            the stepService to set
840          */
841         public void setStepService(final StepService stepService) {
842                 _stepService = stepService;
843         }
844
845         /**
846          * Get the documentService.
847          * 
848          * @return the documentService
849          */
850         public DocumentService getDocumentService() {
851                 return _documentService;
852         }
853
854         /**
855          * Set the documentService.
856          * 
857          * @param documentService
858          *            the documentService to set
859          */
860         public void setDocumentService(final DocumentService documentService) {
861                 _documentService = documentService;
862         }
863
864         /**
865          * Get the publicationDAO.
866          * 
867          * @return the publicationDAO
868          */
869         public PublicationDAO getPublicationDAO() {
870                 return _publicationDAO;
871         }
872
873         /**
874          * Set the publicationDAO.
875          * 
876          * @param publicationDAO
877          *            the publicationDAO to set
878          */
879         public void setPublicationDAO(final PublicationDAO publicationDAO) {
880                 _publicationDAO = publicationDAO;
881         }
882
883         /**
884          * Get the projectElementDAO.
885          * 
886          * @return the projectElementDAO
887          */
888         public ProjectElementDAO getProjectElementDAO() {
889                 return _projectElementDAO;
890         }
891
892         /**
893          * Set the projectElementDAO.
894          * 
895          * @param projectElementDAO
896          *            the projectElementDAO to set
897          */
898         public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
899                 _projectElementDAO = projectElementDAO;
900         }
901
902         /**
903          * Get the repositoryService.
904          * 
905          * @return the repositoryService
906          */
907         public RepositoryService getRepositoryService() {
908                 return _repositoryService;
909         }
910
911         /**
912          * Set the repositoryService.
913          * 
914          * @param repositoryService
915          *            the repositoryService to set
916          */
917         public void setRepositoryService(final RepositoryService repositoryService) {
918                 _repositoryService = repositoryService;
919         }
920
921         /**
922          * Get the timestampDAO.
923          * 
924          * @return the timestampDAO
925          */
926         public TimestampDAO getTimestampDAO() {
927                 return _timestampDAO;
928         }
929
930         /**
931          * Set the timestampDAO.
932          * 
933          * @param timestampDAO
934          *            the timestampDAO to set
935          */
936         public void setTimestampDAO(final TimestampDAO timestampDAO) {
937                 _timestampDAO = timestampDAO;
938         }
939
940         /**
941          * Get the documentTypeService.
942          * 
943          * @return the documentTypeService
944          */
945         public DocumentTypeService getDocumentTypeService() {
946                 return _documentTypeService;
947         }
948
949         /**
950          * Set the documentTypeService.
951          * 
952          * @param documentTypeService
953          *            the documentTypeService to set
954          */
955         public void setDocumentTypeService(
956                         final DocumentTypeService documentTypeService) {
957                 _documentTypeService = documentTypeService;
958         }
959
960         /**
961          * Get the userService.
962          * 
963          * @return the userService
964          */
965         public UserService getUserService() {
966                 return _userService;
967         }
968
969         /**
970          * Set the userService.
971          * 
972          * @param userService
973          *            the userService to set
974          */
975         public void setUserService(final UserService userService) {
976                 _userService = userService;
977         }
978 }