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