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