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