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