]> SALOME platform Git repositories - tools/siman.git/blob - Workspace/Siman-Common/src/org/splat/service/PublicationServiceImpl.java
Salome HOME
Fix of document popup menu refreshing after document import, delete and version....
[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                 Publication syncronizedCurrent = _publicationDAO.get(current.getIndex());
275                 updateRelations(syncronizedCurrent, next, docuses, docusedby);
276         }
277
278         /**
279          * Update relations after creation of a new document version.
280          * 
281          * @param current
282          *            the current version
283          * @param next
284          *            the new version
285          * @param docuses
286          *            ids of used documents
287          * @param docusedby
288          *            ids of documents used by the versioned one.
289          */
290         private void updateRelations(final Publication current,
291                         final Publication next, final String[] docuses,
292                         final long[] docusedby) {
293                 if (docuses != null) {
294                         for (int i = 0; i < docuses.length; i++) {
295                                 Long index = Long.valueOf(docuses[i].trim());
296                                 Document used = getDocumentService().selectDocument(index);// RKV: getPublication(index, steps);
297                                 next.addDependency(used);
298                         }
299                 }
300                 // Outdating impacted document
301                 HashSet<Long> compatible = new HashSet<Long>();
302                 if (docusedby != null) {
303                         for (int i = 0; i < docusedby.length; i++) {
304                                 compatible.add(docusedby[i]);
305                         }
306                 }
307                 for (Publication using : current.getRelations(UsedByRelation.class)) {
308                         if (!compatible.contains(using.getIndex())) {
309                                 outdate(using);
310                         }
311                 }
312         }
313
314         /*
315          * protected Publication getPublication(int index, List<Step> steps) { for (Iterator<Step> i = steps.iterator(); i.hasNext();) { List<Publication>
316          * published = i.next().getAllDocuments(); for (Iterator<Publication> j = published.iterator(); j.hasNext();) { Publication found =
317          * j.next(); // In a given study step, if (found.value().getIndex() == index) return found; // there is only one publication of a given
318          * document } } return null; }
319          */
320         /**
321          * {@inheritDoc}
322          * 
323          * @see org.splat.service.PublicationService#approve(org.splat.dal.bo.som.Publication, java.util.Date)
324          */
325         @Transactional
326         public Timestamp approve(final Publication aPublication, final Date adate) {
327                 Timestamp res = null;
328                 if (!(aPublication.isOutdated() || (aPublication.value()
329                                 .getProgressState() != ProgressState.inCHECK))) {
330                         DocumentType type = aPublication.value().getType();
331                         Study owner = aPublication.getOwnerStudy();
332                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
333                                         owner, type);
334                         User approver = cycle.getActor(ValidationStep.APPROVAL);
335                         Timestamp stamp = new Timestamp(ValidationStep.APPROVAL,
336                                         aPublication.value(), approver, adate);
337                         getTimestampDAO().create(stamp);
338
339                         if (getDocumentService().promote(aPublication.value(), stamp)) {
340                                 res = stamp;
341 //                              if (getDocumentService().isStudyResult(type)
342 //                                              && owner.getProgressState() == ProgressState.inCHECK) {
343 //                                      getStudyService().promote(owner);
344 //                              }
345                         }
346                 }
347                 return res; // Hoping that promotion of the study succeeded
348         }
349
350         /**
351          * {@inheritDoc}
352          * 
353          * @see org.splat.service.PublicationService#demote(org.splat.dal.bo.som.Publication)
354          */
355         @Transactional
356         public boolean demote(final Publication aPublication) {
357                 boolean res = false;
358                 DocumentType type = aPublication.value().getType();
359                 Study owner = aPublication.getOwnerStudy();
360
361                 if (aPublication.value().getProgressState() == ProgressState.inCHECK) {
362                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
363                                         owner, type);
364                         if (cycle.enables(ValidationStep.REVIEW)) {
365                                 res = getDocumentService().demote(aPublication.value());
366                         } else {
367                                 res = getDocumentService().demote(aPublication.value());
368                                 if (res) {
369                                         getDocumentService().demote(aPublication.value());
370                                 }
371                         }
372                 } else if (aPublication.value().getProgressState() == ProgressState.inDRAFT) {
373                         res = getDocumentService().demote(aPublication.value());
374                 }
375 //              if (res && getDocumentService().isStudyResult(type)
376 //                              && owner.getProgressState() != ProgressState.inWORK) {
377 //                      getStudyService().demote(owner);
378 //              }
379                 return res;
380         }
381
382         /**
383          * {@inheritDoc}
384          * 
385          * @see org.splat.service.PublicationService#invalidate(org.splat.dal.bo.som.Publication)
386          */
387         @Transactional
388         public boolean invalidate(final Publication aPublication) {
389                 boolean res = false;
390                 if ((aPublication.value().getProgressState() == ProgressState.inCHECK)) {
391                         DocumentType type = aPublication.value().getType();
392                         Study owner = aPublication.getOwnerStudy();
393
394                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
395                                         owner, type);
396                         // Check if the validation cycle allows the review step
397                         if (cycle.enables(ValidationStep.REVIEW)) {
398 //                              if (getDocumentService().demote(aPublication.value())
399 //                                              && getDocumentService().isStudyResult(type)
400 //                                              && owner.getProgressState() == ProgressState.inCHECK) {
401 //                                      getStudyService().demote(owner);
402 //                              }
403                                 res = true;
404                         } else { // If the validation cycle has no inDraft step
405                                 res = demote(aPublication);
406                         }
407                 }
408                 return res;
409         }
410
411         /**
412          * {@inheritDoc}
413          * 
414          * @see org.splat.service.PublicationService#promote(org.splat.dal.bo.som.Publication, java.util.Date)
415          */
416         @Transactional
417         public Timestamp promote(final Publication aPublication, final Date pdate) {
418                 Timestamp res = null;
419                 if ((!aPublication.isOutdated())
420                                 && (aPublication.value().getProgressState() == ProgressState.inWORK)) {
421                         DocumentType type = aPublication.value().getType();
422                         Study owner = aPublication.getOwnerStudy();
423                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
424                                         owner, type);
425                         User promoter = cycle.getActor(ValidationStep.PROMOTION);
426                         if (promoter == null) {
427                                 promoter = getInvolvedStep(aPublication).getActor();
428                         }
429                         if (promoter == null) {
430                                 promoter = owner.getAuthor();
431                         }
432                         Timestamp stamp = new Timestamp(ValidationStep.PROMOTION,
433                                         aPublication.value(), promoter, pdate);
434                         getTimestampDAO().create(stamp);
435
436                         if (getDocumentService().promote(aPublication.value(), stamp)) {
437                                 res = stamp;
438                                 if (!cycle.enables(ValidationStep.REVIEW)) {
439                                         getDocumentService().promote(aPublication.value(), null);
440                                 }
441 //                              if (getDocumentService().isStudyResult(type)
442 //                                              && owner.getProgressState() == ProgressState.inWORK) {
443 //                                      getStudyService().promote(owner);
444 //                              }
445                         }
446                 }
447                 return res; // Hoping that promotion of the study succeeded
448         }
449
450         /**
451          * {@inheritDoc}
452          * 
453          * @see org.splat.service.PublicationService#review(org.splat.dal.bo.som.Publication, java.util.Date)
454          */
455         @Transactional
456         public Timestamp review(final Publication aPublication, final Date rdate) {
457                 Timestamp res = null;
458                 if (!aPublication.isOutdated()
459                                 && !(aPublication.value().getProgressState() != ProgressState.inDRAFT)) {
460
461                         DocumentType type = aPublication.value().getType();
462                         Study owner = aPublication.getOwnerStudy();
463                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
464                                         owner, type);
465                         User reviewer = cycle.getActor(ValidationStep.REVIEW);
466                         Timestamp stamp = new Timestamp(ValidationStep.REVIEW, aPublication
467                                         .value(), reviewer, rdate);
468                         getTimestampDAO().create(stamp);
469
470                         if (getDocumentService().promote(aPublication.value(), stamp)) {
471                                 res = stamp;
472 //                              if (getDocumentService().isStudyResult(type)
473 //                                              && owner.getProgressState() == ProgressState.inDRAFT) {
474 //                                      getStudyService().promote(owner);
475 //                              }
476                         }
477                 }
478                 return res; // Hoping that promotion of the study succeeded
479         }
480
481         /**
482          * {@inheritDoc}
483          * 
484          * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.som.Revision)
485          * @deprecated
486          */
487         @Deprecated
488         @Transactional
489         public void saveAs(final Publication aPublication, final Revision newvers)
490                         throws FileNotFoundException, NotApplicableException {
491                 if (aPublication.value().isUndefined()) {
492                         throw new NotApplicableException(
493                                         "Cannot save a Publication object refering an undefined Document");
494                 }
495                 if (!aPublication.value().getSourceFile().exists()) {
496                         throw new FileNotFoundException();
497                 }
498
499                 getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
500                 getDocumentService().updateAs(aPublication.value(), newvers); // May change the branch name of given revision
501                 updateOwner(aPublication);
502         }
503
504         /**
505          * {@inheritDoc}
506          * 
507          * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.dal.bo.som.ProgressState)
508          */
509         @Transactional
510         public void saveAs(final Publication aPublication, final ProgressState state)
511                         throws FileNotFoundException, NotApplicableException {
512                 if (aPublication.value().isUndefined()) {
513                         throw new NotApplicableException(
514                                         "Cannot save a Publication object refering an undefined Document");
515                 }
516                 if (!aPublication.value().getSourceFile().exists()) {
517                         throw new FileNotFoundException(aPublication.value()
518                                         .getSourceFile().asFile().getAbsolutePath());
519                 }
520
521                 if (state == ProgressState.inWORK || state == ProgressState.EXTERN) {
522                         getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
523                         // hascode
524                         getDocumentService().updateAs(aPublication.value(), state);
525                 } else {
526                         // Check that the state is applicable for the validation cycle
527                         DocumentType mytype = aPublication.value().getType();
528                         Study owner = aPublication.getOwnerStudy();
529                         ValidationCycle cycle = getStudyService().getValidationCycleOf(
530                                         owner, mytype);
531                         boolean review = cycle.enables(ValidationStep.REVIEW);
532                         if (!(state == ProgressState.inDRAFT && review)
533                                         && !(state == ProgressState.inCHECK && !review)) {
534                                 throw new NotApplicableException(MessageKeyEnum.DCT_000003
535                                                 .toString(), state.toString());
536                         }
537                         getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
538                         // hascode
539                         getDocumentService().updateAs(aPublication.value(),
540                                         ProgressState.inWORK);
541
542                         promote(aPublication, aPublication.value()
543                                         .getLastModificationDate()); // Promotes to the appropriate state in accordance to the validation cycle
544                 }
545                 updateOwner(aPublication);
546         }
547
548         /**
549          * Update an owner of the publication.
550          * 
551          * @param aPublication
552          *            the document publication
553          */
554         @Transactional
555         private void updateOwner(final Publication aPublication) {
556                 Step step = getInvolvedStep(aPublication);
557
558                 // Update of involved step
559                 Document previous = aPublication.value().getPreviousVersion();
560                 if (previous != null) {
561                         Publication oldoc = step.getDocument(previous.getIndex());
562                         getStepService().remove(step, oldoc); // Decrements the configuration tag count of document
563                 }
564                 getStepService().add(step, aPublication); // Increments the configuration tag count of document
565
566                 // Import the document properties and update of the study
567                 forwardProperties(aPublication, aPublication.value().getSourceFile()
568                                 .asFile(), step);
569                 getProjectElementDAO().merge(aPublication.getOwner());
570         }
571
572         /**
573          * Propagate simulation contexts from the given config file to the publication's owner (study or step).
574          * 
575          * @param aPublication
576          *            the document publication
577          * @param from
578          *            the config file
579          * @param to
580          *            the study step
581          */
582         private void forwardProperties(final Publication aPublication,
583                         final java.io.File from, final Step to) {
584                 Reader tool = Toolbox.getReader(from);
585                 if (tool != null) { // Properties extractor available for this type of document
586                         SimulationContextType.Properties sprop = new SimulationContextType.Properties()
587                                         .setStep(to.getStep()).setProgressState(
588                                                         ProgressState.APPROVED);
589                         List<SimulationContextType> contype = getSimulationContextService()
590                                         .selectTypesWhere(sprop);
591                         if (!contype.isEmpty()) { // There is an approved property type configured at this step
592
593                                 SimulationContext.Properties cprop = new SimulationContext.Properties();
594                                 List<SimulationContext> context = to.getAllSimulationContexts();
595
596                                 context = new ArrayList<SimulationContext>(context.size());
597                                 context.addAll(to.getAllSimulationContexts());
598                                 cprop.disableCheck();
599                                 for (Iterator<SimulationContextType> i = contype.iterator(); i
600                                                 .hasNext();) {
601                                         SimulationContextType property = i.next();
602                                         boolean isFound = false;
603                                         for (Iterator<SimulationContext> j = context.iterator(); j
604                                                         .hasNext();) {
605                                                 SimulationContext existing = j.next();
606                                                 isFound = existing.getType().equals(property);
607                                                 if (isFound) {
608                                                         // Forget this property as it is already set
609                                                         break;
610                                                 }
611                                         }
612                                         if (!isFound) {
613                                                 try {
614                                                         String value = tool.extractProperty(property
615                                                                         .getName());
616                                                         if (value == null) {
617                                                                 continue; // Property not defined into the document
618                                                         }
619
620                                                         cprop.setType(property).setValue(value);
621                                                         if (aPublication.getOwner() instanceof Study) {
622                                                                 getStudyService().addProjectContext(
623                                                                                 (Study) aPublication.getOwner(), cprop); // Re-indexes knowledges and the study
624                                                         } else {
625                                                                 getStepService()
626                                                                                 .addSimulationContext(to, cprop); // Re-indexes knowledges only
627                                                         }
628                                                 } catch (Exception e) {
629                                                         break;
630                                                 }
631                                         }
632                                 }
633                         }
634                 }
635         }
636
637         /**
638          * Returns the study Step into which the document version referenced by this publication has been published.
639          * 
640          * @param aPublication
641          *            the document publication
642          * @return the study step where the document is published
643          */
644         public Step getInvolvedStep(final Publication aPublication) {
645                 if (aPublication.getStep() == null) {
646                         Step[] step = getProjectElementService().getSteps(
647                                         aPublication.getOwner());
648                         for (int i = 0; i < step.length; i++) {
649                                 aPublication.setStep(step[i]); // The involved step necessarily exists
650                                 if (aPublication.value().isInto(aPublication.getStep())) {
651                                         break;
652                                 }
653                         }
654                 }
655                 return aPublication.getStep();
656         }
657
658         /**
659          * Undo the out-date operation.
660          * 
661          * @param aPublication
662          *            the publication
663          * @return true if the acceptance succeeds
664          * @see #outdate()
665          * @see DocumentRights#canAccept()
666          */
667         @Transactional
668         public boolean actualize(final Publication aPublication) {
669                 boolean res = aPublication.isOutdated();
670                 if (res) {
671                         aPublication.setIsnew('Y');
672                         getPublicationDAO().update(aPublication);
673                 }
674                 return res;
675         }
676
677         /**
678          * Out-dates this publication and recursively all publications using this one. Typically, a publication is out-dated when modifying a
679          * document to which it depends.
680          * 
681          * @param aPublication
682          *            the publication
683          * @see #isOutdated()
684          * @see #getProgressState()
685          * @see #actualize()
686          */
687         public void outdate(final Publication aPublication) {
688                 if (aPublication.isOutdated()) {
689                         return;
690                 }
691
692                 List<Publication> relist = aPublication
693                                 .getRelations(UsedByRelation.class);
694                 for (Iterator<Publication> i = relist.iterator(); i.hasNext();) {
695                         outdate(i.next());
696                 }
697                 aPublication.setIsnew('O');
698                 getPublicationDAO().update(aPublication);
699         }
700
701         /**
702          * Create "Converts" relation for the given document publication and format.
703          * 
704          * @param aPublication
705          *            the document publication
706          * @param format
707          *            the format
708          * @return the created "Converts" relation
709          */
710         @Transactional
711         public ConvertsRelation attach(final Publication aPublication,
712                         final String format) {
713                 return getDocumentService().attach(aPublication.value(), format);
714         }
715
716         /**
717          * Create "Converts" relation for the given document publication, format and description.
718          * 
719          * @param aPublication
720          *            the document publication
721          * @param format
722          *            the format
723          * @param description
724          *            the description of the relation
725          * @return the created "Converts" relation
726          */
727         @Transactional
728         public ConvertsRelation attach(final Publication aPublication,
729                         final String format, final String description) {
730                 return getDocumentService().attach(aPublication.value(), format,
731                                 description);
732         }
733
734         /**
735          * Rename the published document.
736          * 
737          * @param aPublication
738          *            the publication of the document
739          * @param title
740          *            the new document title
741          * @throws InvalidPropertyException
742          *             if the new title is empty
743          */
744         public void rename(final Publication aPublication, final String title)
745                         throws InvalidPropertyException {
746                 getDocumentService().rename(aPublication.value(), title);
747         }
748
749         /**
750          * {@inheritDoc}
751          * 
752          * @see org.splat.service.PublicationService#getDocToCompareDTO(long)
753          */
754         @Transactional(readOnly = true)
755         @Override
756         public DocToCompareDTO getDocToCompareDTO(final long publicationId)
757                         throws InvalidParameterException {
758                 DocToCompareDTO res = new DocToCompareDTO();
759                 Publication pub = _publicationDAO.get(Long.valueOf(publicationId));
760                 if (pub == null) {
761                         throw new InvalidParameterException("id", String
762                                         .valueOf(publicationId));
763                 }
764
765                 res.setDocumentTitle(pub.value().getTitle());
766                 res.setPathToFile(pub.value().getFile().asFile().getAbsolutePath());
767                 res.setScenarioTitle(pub.getOwner().getTitle());
768                 res.setStudyTitle(pub.getOwnerStudy().getTitle());
769                 return res;
770         }
771
772         /**
773          * Get the projectElementService.
774          * 
775          * @return the projectElementService
776          */
777         public ProjectElementService getProjectElementService() {
778                 return _projectElementService;
779         }
780
781         /**
782          * Set the projectElementService.
783          * 
784          * @param projectElementService
785          *            the projectElementService to set
786          */
787         public void setProjectElementService(
788                         final ProjectElementService projectElementService) {
789                 _projectElementService = projectElementService;
790         }
791
792         /**
793          * Get the simulationContextService.
794          * 
795          * @return the simulationContextService
796          */
797         public SimulationContextService getSimulationContextService() {
798                 return _simulationContextService;
799         }
800
801         /**
802          * Set the simulationContextService.
803          * 
804          * @param simulationContextService
805          *            the simulationContextService to set
806          */
807         public void setSimulationContextService(
808                         final SimulationContextService simulationContextService) {
809                 _simulationContextService = simulationContextService;
810         }
811
812         /**
813          * Get the studyService.
814          * 
815          * @return the studyService
816          */
817         public StudyService getStudyService() {
818                 return _studyService;
819         }
820
821         /**
822          * Set the studyService.
823          * 
824          * @param studyService
825          *            the studyService to set
826          */
827         public void setStudyService(final StudyService studyService) {
828                 _studyService = studyService;
829         }
830
831         /**
832          * Get the stepService.
833          * 
834          * @return the stepService
835          */
836         public StepService getStepService() {
837                 return _stepService;
838         }
839
840         /**
841          * Set the stepService.
842          * 
843          * @param stepService
844          *            the stepService to set
845          */
846         public void setStepService(final StepService stepService) {
847                 _stepService = stepService;
848         }
849
850         /**
851          * Get the documentService.
852          * 
853          * @return the documentService
854          */
855         public DocumentService getDocumentService() {
856                 return _documentService;
857         }
858
859         /**
860          * Set the documentService.
861          * 
862          * @param documentService
863          *            the documentService to set
864          */
865         public void setDocumentService(final DocumentService documentService) {
866                 _documentService = documentService;
867         }
868
869         /**
870          * Get the publicationDAO.
871          * 
872          * @return the publicationDAO
873          */
874         public PublicationDAO getPublicationDAO() {
875                 return _publicationDAO;
876         }
877
878         /**
879          * Set the publicationDAO.
880          * 
881          * @param publicationDAO
882          *            the publicationDAO to set
883          */
884         public void setPublicationDAO(final PublicationDAO publicationDAO) {
885                 _publicationDAO = publicationDAO;
886         }
887
888         /**
889          * Get the projectElementDAO.
890          * 
891          * @return the projectElementDAO
892          */
893         public ProjectElementDAO getProjectElementDAO() {
894                 return _projectElementDAO;
895         }
896
897         /**
898          * Set the projectElementDAO.
899          * 
900          * @param projectElementDAO
901          *            the projectElementDAO to set
902          */
903         public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
904                 _projectElementDAO = projectElementDAO;
905         }
906
907         /**
908          * Get the repositoryService.
909          * 
910          * @return the repositoryService
911          */
912         public RepositoryService getRepositoryService() {
913                 return _repositoryService;
914         }
915
916         /**
917          * Set the repositoryService.
918          * 
919          * @param repositoryService
920          *            the repositoryService to set
921          */
922         public void setRepositoryService(final RepositoryService repositoryService) {
923                 _repositoryService = repositoryService;
924         }
925
926         /**
927          * Get the timestampDAO.
928          * 
929          * @return the timestampDAO
930          */
931         public TimestampDAO getTimestampDAO() {
932                 return _timestampDAO;
933         }
934
935         /**
936          * Set the timestampDAO.
937          * 
938          * @param timestampDAO
939          *            the timestampDAO to set
940          */
941         public void setTimestampDAO(final TimestampDAO timestampDAO) {
942                 _timestampDAO = timestampDAO;
943         }
944
945         /**
946          * Get the documentTypeService.
947          * 
948          * @return the documentTypeService
949          */
950         public DocumentTypeService getDocumentTypeService() {
951                 return _documentTypeService;
952         }
953
954         /**
955          * Set the documentTypeService.
956          * 
957          * @param documentTypeService
958          *            the documentTypeService to set
959          */
960         public void setDocumentTypeService(
961                         final DocumentTypeService documentTypeService) {
962                 _documentTypeService = documentTypeService;
963         }
964
965         /**
966          * Get the userService.
967          * 
968          * @return the userService
969          */
970         public UserService getUserService() {
971                 return _userService;
972         }
973
974         /**
975          * Set the userService.
976          * 
977          * @param userService
978          *            the userService to set
979          */
980         public void setUserService(final UserService userService) {
981                 _userService = userService;
982         }
983
984         /**
985          * {@inheritDoc}
986          * 
987          * @see org.splat.service.PublicationService#replace(long, java.io.File)
988          */
989         @Override
990         @Transactional
991         public boolean replace(final Publication pub, final File newFile,
992                         final Date modifTime) throws IncompatibleDataException {
993                 if (!(ProgressState.EXTERN.equals(pub.getProgressState()) || ProgressState.inWORK
994                                 .equals(pub.getProgressState()))) {
995                         throw new IncompatibleDataException(MessageKeyEnum.DCT_000004
996                                         .toString());
997                 }
998                 Document doc = getDocumentService().selectDocument(
999                                 pub.value().getIndex());
1000                 if (LOG.isInfoEnabled()) {
1001                         LOG.info("Moving \"" + newFile.getName() + "\" to \""
1002                                         + doc.getSourceFile().asFile().getAbsolutePath() + "\".");
1003                 }
1004                 // Save a temporary copy of the original file as <old file name>.backup
1005                 String oldFilePath = doc.getSourceFile().asFile().getAbsolutePath();
1006                 File oldFile = new File(oldFilePath);
1007                 File backupFile = new File(oldFilePath + ".backup");
1008                 oldFile.renameTo(backupFile);
1009                 boolean res = newFile.renameTo(oldFile);
1010                 if (res) {
1011                         // Delete the temporary copy of the old file
1012                         // if the new one is moved into the repository.
1013                         backupFile.delete();
1014                         // Update the document modification date.
1015                         doc.setLastModificationDate(modifTime);
1016                         // Update presentation data
1017                         pub.value().setLastModificationDate(modifTime);
1018                 } else {
1019                         // Restore the original file if replacing is failed
1020                         backupFile.renameTo(oldFile);
1021                 }
1022                 return res;
1023         }
1024 }