Salome HOME
6a10e4c9c2d3581d070c81cfc79f524e8aa4e3cb
[tools/siman.git] / Workspace / Siman-Common / src / org / splat / service / StepServiceImpl.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.IOException;
13 import java.util.ArrayList;
14 import java.util.Iterator;
15 import java.util.List;
16
17 import org.splat.dal.bo.kernel.Relation;
18 import org.splat.dal.bo.som.ConvertsRelation;
19 import org.splat.dal.bo.som.Document;
20 import org.splat.dal.bo.som.DocumentType;
21 import org.splat.dal.bo.som.File;
22 import org.splat.dal.bo.som.KnowledgeElement;
23 import org.splat.dal.bo.som.Publication;
24 import org.splat.dal.bo.som.Scenario;
25 import org.splat.dal.bo.som.SimulationContext;
26 import org.splat.dal.bo.som.UsedByRelation;
27 import org.splat.dal.bo.som.UsesRelation;
28 import org.splat.dal.bo.som.VersionsRelation;
29 import org.splat.dal.dao.kernel.RelationDAO;
30 import org.splat.dal.dao.som.DocumentDAO;
31 import org.splat.dal.dao.som.FileDAO;
32 import org.splat.dal.dao.som.ProjectElementDAO;
33 import org.splat.dal.dao.som.PublicationDAO;
34 import org.splat.dal.dao.som.SimulationContextDAO;
35 import org.splat.dal.dao.som.VersionsRelationDAO;
36 import org.splat.exception.DocumentIsUsedException;
37 import org.splat.kernel.InvalidPropertyException;
38 import org.splat.kernel.MismatchException;
39 import org.splat.kernel.MissedPropertyException;
40 import org.splat.kernel.MultiplyDefinedException;
41 import org.splat.kernel.NotApplicableException;
42 import org.splat.log.AppLogger;
43 import org.splat.service.technical.IndexService;
44 import org.splat.service.technical.ProjectSettingsService;
45 import org.splat.som.Revision;
46 import org.splat.som.Step;
47 import org.springframework.transaction.annotation.Transactional;
48
49 /**
50  * Step service implementation.
51  * 
52  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
53  */
54 public class StepServiceImpl implements StepService {
55
56         /**
57          * logger for the service.
58          */
59         public final static AppLogger LOG = AppLogger
60                         .getLogger(StepServiceImpl.class);
61         /**
62          * Injected index service.
63          */
64         private IndexService _indexService;
65         /**
66          * Injected document service.
67          */
68         private DocumentService _documentService;
69         /**
70          * Injected document type service.
71          */
72         private DocumentTypeService _documentTypeService;
73         /**
74          * Injected document DAO.
75          */
76         private DocumentDAO _documentDAO;
77         /**
78          * Injected relation DAO.
79          */
80         private RelationDAO _relationDAO;
81         /**
82          * Injected file DAO.
83          */
84         private FileDAO _fileDAO;
85         /**
86          * Injected simulation context service.
87          */
88         private SimulationContextService _simulationContextService;
89         /**
90          * Injected simulation context DAO.
91          */
92         private SimulationContextDAO _simulationContextDAO;
93         /**
94          * Injected project element DAO.
95          */
96         private ProjectElementDAO _projectElementDAO;
97         /**
98          * Injected versions relation DAO.
99          */
100         private VersionsRelationDAO _versionsRelationDAO;
101         /**
102          * Injected project service.
103          */
104         private ProjectSettingsService _projectSettings;
105         /**
106          * Injected publication DAO.
107          */
108         private PublicationDAO _publicationDAO;
109
110         /**
111          * {@inheritDoc}
112          * 
113          * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext.Properties)
114          */
115         public SimulationContext addSimulationContext(final Step aStep,
116                         final SimulationContext.Properties dprop)
117                         throws MissedPropertyException, InvalidPropertyException,
118                         MultiplyDefinedException {
119                 SimulationContext context = new SimulationContext(dprop.setStep(aStep
120                                 .getStep()));
121                 return addSimulationContext(aStep, context);
122         }
123
124         /**
125          * {@inheritDoc}
126          * 
127          * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
128          */
129         @Transactional
130         public SimulationContext addSimulationContext(final Step aStep,
131                         final SimulationContext context) {
132                 SimulationContext res = null;
133                 getSimulationContextService().hold(context); // Increments the reference count of simulation context
134                 if (aStep.getOwner().isSaved()) {
135                         try {
136                                 if (!context.isSaved()) {
137                                         getSimulationContextDAO().create(context);
138                                 }
139                                 aStep.getOwner().add(context);
140                                 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
141                                 getProjectElementDAO().update(aStep.getOwner());
142                                 updateKnowledgeElementsIndex(aStep);
143                                 res = context;
144                         } catch (Exception error) {
145                                 LOG.debug(error.getMessage(), error);
146                         }
147                 } else { // Happens when copying a scenario
148                         aStep.getOwner().add(context);
149                         aStep.getContex().add(context); // The context is also referenced from this (transient) Step
150                         // In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
151                         res = context;
152                 }
153                 return res;
154         }
155
156         /**
157          * Update lucene index of knowledge elements of a scenario or a study which the given step is related to.
158          * 
159          * @param aStep
160          *            the step (activity)
161          */
162         private void updateKnowledgeElementsIndex(final Step aStep) {
163                 Scenario[] scenarii;
164                 if (aStep.getOwner() instanceof Scenario) {
165                         scenarii = new Scenario[1];
166                         scenarii[0] = (Scenario) aStep.getOwner();
167                 } else {
168                         scenarii = aStep.getOwnerStudy().getScenarii();
169                 }
170                 try {
171                         for (int i = 0; i < scenarii.length; i++) {
172                                 Scenario scene = scenarii[i];
173                                 List<KnowledgeElement> knelm = scene.getAllKnowledgeElements();
174                                 for (Iterator<KnowledgeElement> j = knelm.iterator(); j
175                                                 .hasNext();) {
176                                         KnowledgeElement kelm = j.next();
177                                         getIndexService().update(kelm);
178                                 }
179                                 updateScenarioIndex(scene);
180                         }
181                 } catch (Exception error) {
182                         LOG.error("Unable to re-index Knowledge Elements, reason:", error);
183                 }
184         }
185
186         /**
187          * Update lucene index for knowledge elements of the scenario.
188          * 
189          * @param scene
190          *            the scenario
191          * @throws IOException
192          *             if can't update lucene index
193          */
194         private void updateScenarioIndex(final Scenario scene) throws IOException {
195                 if (scene.getUcase() == null) {
196                         for (Iterator<KnowledgeElement> i = scene.getKnowledgeElements()
197                                         .iterator(); i.hasNext();) {
198                                 KnowledgeElement kelm = i.next();
199                                 if (!kelm.getType().equals("usecase")) {
200                                         continue;
201                                 }
202                                 scene.setUcase(kelm);
203                                 break;
204                         }
205                 }
206                 getIndexService().update(scene.getUcase());
207         }
208
209         /**
210          * {@inheritDoc}
211          * 
212          * @see org.splat.service.StepService#removeSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
213          */
214         @Transactional
215         public boolean removeSimulationContext(final Step aStep,
216                         final SimulationContext context) {
217                 SimulationContext torem = aStep
218                                 .getSimulationContext(context.getIndex());
219
220                 boolean isOk = (torem != null) && (aStep.getOwner().remove(torem));
221                 if (isOk) {
222
223                         aStep.getContex().remove(torem);
224                         getProjectElementDAO().update(aStep.getOwner());
225                         if (torem.isShared()) {
226                                 getSimulationContextService().release(torem);
227                                 getSimulationContextDAO().update(torem);
228                         } else {
229                                 getSimulationContextDAO().delete(torem);
230                         }
231                 }
232                 return isOk;
233         }
234
235         /**
236          * {@inheritDoc}
237          * 
238          * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
239          */
240         @Transactional
241         public Publication createDocument(final Step aStep,
242                         final Document.Properties dprop) throws MissedPropertyException,
243                         InvalidPropertyException, MultiplyDefinedException, IOException {
244                 if (LOG.isDebugEnabled()) {
245                         LOG.debug("Local index before: "
246                                         + aStep.getOwnerStudy().getLastLocalIndex());
247                 }
248                 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
249                                 .setStep(aStep.getStep()));
250                 getDocumentService().generateDocumentId(newdoc, dprop);
251
252                 // Creation of the save directory
253                 java.io.File wdir = getDocumentService().getSaveDirectory(newdoc);
254                 if ((!wdir.exists()) && (!wdir.mkdirs())) {
255                         throw new IOException(
256                                         "Cannot create the repository vault directory");
257                 }
258
259                 // Identification and save
260                 if (LOG.isDebugEnabled()) {
261                         LOG.debug("Local index after: "
262                                         + aStep.getOwnerStudy().getLastLocalIndex());
263                 }
264                 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwnerStudy());
265                 getDocumentDAO().create(newdoc);
266
267                 return new Publication(newdoc, aStep.getOwner());
268         }
269
270         /**
271          * {@inheritDoc}
272          * 
273          * @see org.splat.service.StepService#assignDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
274          */
275         public Publication assignDocument(final Step aStep,
276                         final Document.Properties dprop) throws MissedPropertyException,
277                         InvalidPropertyException, NotApplicableException {
278                 String refid = dprop.getReference();
279                 Publication res = null;
280                 if (refid != null) {
281                         Document slot = getDocumentService().selectDocument(refid,
282                                         new Revision().toString());
283                         if ((slot != null) && (slot.isUndefined())) {
284                                 getDocumentService().initialize(slot,
285                                                 dprop.setOwner(aStep.getOwnerStudy()));
286                                 res = new Publication(slot, aStep.getOwner());
287                         }
288                 }
289                 return res;
290         }
291
292         /**
293          * Create a new version of a document in the given study step.
294          * 
295          * @param aStep
296          *            the study step
297          * @param base
298          *            the base document published version
299          * @return the new version publication
300          * @throws MissedPropertyException
301          *             if a mandatory property is missed
302          * @throws InvalidPropertyException
303          *             if some property doesn't exist
304          * @throws MultiplyDefinedException
305          *             if some property is defined several times
306          * @throws IOException
307          *             if a file system error occurs
308          * @throws MismatchException
309          *             if the document is not applicable to the given study step
310          */
311         public Publication versionDocument(final Step aStep, final Publication base)
312                         throws MissedPropertyException, InvalidPropertyException,
313                         MultiplyDefinedException, IOException, MismatchException {
314                 return versionDocument(aStep, base, new Document.Properties());
315         }
316
317         /**
318          * Create a new version of a document in the given study step.
319          * 
320          * @param aStep
321          *            the study step
322          * @param base
323          *            the base document published version
324          * @param reason
325          *            the comment for the new version
326          * @return the new version publication
327          * @throws MissedPropertyException
328          *             if a mandatory property is missed
329          * @throws InvalidPropertyException
330          *             if some property doesn't exist
331          * @throws MultiplyDefinedException
332          *             if some property is defined several times
333          * @throws IOException
334          *             if a file system error occurs
335          * @throws MismatchException
336          *             if the document is not applicable to the given study step
337          */
338         public Publication versionDocument(final Step aStep,
339                         final Publication base, final String reason)
340                         throws MissedPropertyException, InvalidPropertyException,
341                         MultiplyDefinedException, IOException, MismatchException {
342                 return versionDocument(aStep, base, new Document.Properties()
343                                 .setDescription(reason));
344         }
345
346         /**
347          * Create a new version of a document in the given study step.
348          * 
349          * @param aStep
350          *            the study step
351          * @param base
352          *            the base document published version
353          * @param dprop
354          *            properties of the new version
355          * @return the new version publication
356          * @throws MissedPropertyException
357          *             if a mandatory property is missed
358          * @throws InvalidPropertyException
359          *             if some property doesn't exist
360          * @throws MultiplyDefinedException
361          *             if some property is defined several times
362          * @throws IOException
363          *             if a file system error occurs
364          * @throws MismatchException
365          *             if the document is not applicable to the given study step
366          */
367         @Transactional
368         public Publication versionDocument(final Step aStep,
369                         final Publication base, final Document.Properties dprop)
370                         throws MissedPropertyException, InvalidPropertyException,
371                         MultiplyDefinedException, IOException, MismatchException {
372                 Document previous = base.value();
373
374                 // RKV: Keep the new file format if it is related to the same document type on this step.
375                 String newFormat = dprop.getFormat();
376
377                 dprop.setDocument(previous, getProjectSettings().getStep(
378                                 base.getStep().getNumber())); // Initializes the Step property
379                 if (dprop.getStep().getNumber() != aStep.getNumber()) {
380                         throw new MismatchException();
381                 }
382
383                 if (newFormat != null
384                                 && previous.getType().equals(
385                                                 getProjectSettings().getDefaultDocumentType(
386                                                                 aStep.getStep(), newFormat))) {
387                         dprop.setFormat(newFormat);
388                 }
389
390                 if (dprop.getAuthor() == null) {
391                         dprop.setAuthor(previous.getAuthor());
392                 }
393                 String summary = dprop.getDescription();
394
395                 // Creation of the document
396                 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
397                                 .setStep(aStep.getStep()));
398                 getDocumentService().generateDocumentId(newdoc, dprop);
399                 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwner(),
400                                 previous);
401                 getDocumentDAO().create(newdoc);
402
403                 // Versioning
404                 VersionsRelation aRel;
405                 aRel = new VersionsRelation(newdoc, previous, summary);
406                 // getVersionsRelationDAO().create(aRel);
407                 newdoc.addRelation(aRel);
408
409                 // Update of usedby relations, if exist
410                 /*
411                  * RKV: Consider the new version as not used by old dependent documents. So these documents must be marked as outdated then. List<Relation>
412                  * relist = previous.getRelations(UsedByRelation.class); Study scope = aStep.getOwnerStudy(); for (Iterator<Relation> i =
413                  * relist.iterator(); i.hasNext();) { UsedByRelation relation = (UsedByRelation) i.next(); Document relatedoc = relation.getTo(); if
414                  * (scope.shares(relatedoc)) { relatedoc.addRelation(new UsesRelation(relatedoc, newdoc)); } else { relation.moveTo(newdoc); } }
415                  */
416                 return new Publication(newdoc, aStep.getOwner());
417         }
418
419         /**
420          * Get document types which are applicable for the given study step (activity).
421          * 
422          * @param aStep
423          *            the study step
424          * @return the list of document types
425          */
426         public List<DocumentType> getValidDocumentTypes(final Step aStep) {
427                 return getDocumentTypeService().selectTypesOf(aStep.getStep());
428         }
429
430         /**
431          * Add a document publication to the given step.
432          * 
433          * @param aStep
434          *            the target study step
435          * @param newdoc
436          *            the document publication to add
437          * @return true if publication succeeded
438          */
439         public boolean add(final Step aStep, final Publication newdoc) {
440                 boolean res = aStep.getOwner().add(newdoc); // Updates the study in memory
441                 if (res) {
442                         aStep.getDocuments().add(0, newdoc); // Updates this step
443                         getDocumentService().hold(newdoc.value()); // Increments the configuration tag count of document
444                         // If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
445                         // database (it will be saved later by cascading the update of owner scenario).
446                 }
447                 return res;
448         }
449
450         /**
451          * Remove a document publication from the given step.
452          * 
453          * @param aStep
454          *            the study step
455          * @param oldoc
456          *            the document publication to remove
457          * @return true if removing of the publication succeeded
458          */
459         public boolean remove(final Step aStep, final Publication oldoc) {
460                 aStep.getDocuments().remove(oldoc); // Updates this step
461                 aStep.getOwner().remove(oldoc); // remove from the parent project element
462                 getProjectElementDAO().merge(aStep.getOwner());
463                 getDocumentService().release(oldoc.value()); // Decrements the configuration tag count of document
464                 // The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
465                 return true;
466         }
467
468         /**
469          * Remove a document from the given step and from the database if it is no more used.
470          * 
471          * @param aStep
472          *            the study step
473          * @param docId
474          *            the document id
475          * @return true if removing of the document succeeded
476          * @throws DocumentIsUsedException
477          *             if the document is used by other documents
478          */
479         @Transactional
480         public boolean removeDocument(final Step aStep, final long docId)
481                         throws DocumentIsUsedException {
482                 Publication torem = aStep.getDocument(docId);
483                 boolean res = (torem != null);
484                 if (res) {
485                         if (!torem.value().getRelations(UsedByRelation.class).isEmpty()) {
486                                 throw new DocumentIsUsedException(torem.value().getTitle());
487                         }
488                         remove(aStep, torem);
489                         Document value = torem.value();
490                         if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
491                                 List<Document> using = new ArrayList<Document>();
492                                 List<File> files = new ArrayList<File>();
493                                 for (Relation link : value.getAllRelations()) {
494                                         if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
495                                                 files.add((File) link.getTo());
496                                         } else if (link.getClass().equals(UsesRelation.class)) { // Document dependency
497                                                 using.add((Document) link.getTo());
498                                         }
499                                 }
500                                 // Remove relations from depending documents
501                                 if (LOG.isDebugEnabled()) {
502                                         LOG.debug("Remove " + using.size() + " UsedByRelation(s).");
503                                 }
504                                 for (Document doc : using) {
505                                         if (LOG.isDebugEnabled()) {
506                                                 LOG.debug("Remove UsedByRelation from "
507                                                                 + doc.getTitle() + " to " + value.getTitle());
508                                                 LOG.debug("Nb relations of doc " + doc.getTitle()
509                                                                 + " before: " + doc.getAllRelations().size());
510                                         }
511                                         doc.removeRelation(UsedByRelation.class, value);
512                                         if (LOG.isDebugEnabled()) {
513                                                 LOG.debug("Nb relations of doc " + doc.getTitle()
514                                                                 + " after: " + doc.getAllRelations().size());
515                                         }
516                                         getDocumentDAO().merge(doc);
517                                 }
518                                 // Synchronize deleted objects with the database to avoid hibernate exception
519                                 // org.hibernate.PropertyValueException: not-null property references a null or transient value
520                                 getDocumentDAO().flush();
521                                 // The corresponding physical file is not removed from the vault
522                                 getDocumentDAO().delete(getDocumentDAO().merge(torem.value()));
523                                 // Delete document's files
524                                 for (File file : files) {
525                                         getFileDAO().delete(getFileDAO().merge(file)); // The corresponding physical file is not removed from the vault
526                                 }
527                         }
528                 }
529                 return res;
530         }
531
532         /**
533          * Get the documentService.
534          * 
535          * @return the documentService
536          */
537         public DocumentService getDocumentService() {
538                 return _documentService;
539         }
540
541         /**
542          * Set the documentService.
543          * 
544          * @param documentService
545          *            the documentService to set
546          */
547         public void setDocumentService(final DocumentService documentService) {
548                 _documentService = documentService;
549         }
550
551         /**
552          * Get the simulationContextService.
553          * 
554          * @return the simulationContextService
555          */
556         public SimulationContextService getSimulationContextService() {
557                 return _simulationContextService;
558         }
559
560         /**
561          * Set the simulationContextService.
562          * 
563          * @param simulationContextService
564          *            the simulationContextService to set
565          */
566         public void setSimulationContextService(
567                         final SimulationContextService simulationContextService) {
568                 _simulationContextService = simulationContextService;
569         }
570
571         /**
572          * Get the documentDAO.
573          * 
574          * @return the documentDAO
575          */
576         public DocumentDAO getDocumentDAO() {
577                 return _documentDAO;
578         }
579
580         /**
581          * Set the documentDAO.
582          * 
583          * @param documentDAO
584          *            the documentDAO to set
585          */
586         public void setDocumentDAO(final DocumentDAO documentDAO) {
587                 _documentDAO = documentDAO;
588         }
589
590         /**
591          * Get the simulationContextDAO.
592          * 
593          * @return the simulationContextDAO
594          */
595         public SimulationContextDAO getSimulationContextDAO() {
596                 return _simulationContextDAO;
597         }
598
599         /**
600          * Set the simulationContextDAO.
601          * 
602          * @param simulationContextDAO
603          *            the simulationContextDAO to set
604          */
605         public void setSimulationContextDAO(
606                         final SimulationContextDAO simulationContextDAO) {
607                 _simulationContextDAO = simulationContextDAO;
608         }
609
610         /**
611          * Get the projectElementDAO.
612          * 
613          * @return the projectElementDAO
614          */
615         public ProjectElementDAO getProjectElementDAO() {
616                 return _projectElementDAO;
617         }
618
619         /**
620          * Set the projectElementDAO.
621          * 
622          * @param projectElementDAO
623          *            the projectElementDAO to set
624          */
625         public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
626                 _projectElementDAO = projectElementDAO;
627         }
628
629         /**
630          * Get the indexService.
631          * 
632          * @return the indexService
633          */
634         public IndexService getIndexService() {
635                 return _indexService;
636         }
637
638         /**
639          * Set the indexService.
640          * 
641          * @param indexService
642          *            the indexService to set
643          */
644         public void setIndexService(final IndexService indexService) {
645                 _indexService = indexService;
646         }
647
648         /**
649          * Get the fileDAO.
650          * 
651          * @return the fileDAO
652          */
653         public FileDAO getFileDAO() {
654                 return _fileDAO;
655         }
656
657         /**
658          * Set the fileDAO.
659          * 
660          * @param fileDAO
661          *            the fileDAO to set
662          */
663         public void setFileDAO(final FileDAO fileDAO) {
664                 _fileDAO = fileDAO;
665         }
666
667         /**
668          * Get the documentTypeService.
669          * 
670          * @return the documentTypeService
671          */
672         public DocumentTypeService getDocumentTypeService() {
673                 return _documentTypeService;
674         }
675
676         /**
677          * Set the documentTypeService.
678          * 
679          * @param documentTypeService
680          *            the documentTypeService to set
681          */
682         public void setDocumentTypeService(
683                         final DocumentTypeService documentTypeService) {
684                 _documentTypeService = documentTypeService;
685         }
686
687         /**
688          * Get the versionsRelationDAO.
689          * 
690          * @return the versionsRelationDAO
691          */
692         public VersionsRelationDAO getVersionsRelationDAO() {
693                 return _versionsRelationDAO;
694         }
695
696         /**
697          * Set the versionsRelationDAO.
698          * 
699          * @param versionsRelationDAO
700          *            the versionsRelationDAO to set
701          */
702         public void setVersionsRelationDAO(
703                         final VersionsRelationDAO versionsRelationDAO) {
704                 _versionsRelationDAO = versionsRelationDAO;
705         }
706
707         /**
708          * Get project settings.
709          * 
710          * @return Project settings service
711          */
712         private ProjectSettingsService getProjectSettings() {
713                 return _projectSettings;
714         }
715
716         /**
717          * Set project settings service.
718          * 
719          * @param projectSettingsService
720          *            project settings service
721          */
722         public void setProjectSettings(
723                         final ProjectSettingsService projectSettingsService) {
724                 _projectSettings = projectSettingsService;
725         }
726
727         /**
728          * Get the publicationDAO.
729          * 
730          * @return the publicationDAO
731          */
732         public PublicationDAO getPublicationDAO() {
733                 return _publicationDAO;
734         }
735
736         /**
737          * Set the publicationDAO.
738          * 
739          * @param publicationDAO
740          *            the publicationDAO to set
741          */
742         public void setPublicationDAO(final PublicationDAO publicationDAO) {
743                 this._publicationDAO = publicationDAO;
744         }
745
746         /**
747          * Get the relationDAO.
748          * 
749          * @return the relationDAO
750          */
751         public RelationDAO getRelationDAO() {
752                 return _relationDAO;
753         }
754
755         /**
756          * Set the relationDAO.
757          * 
758          * @param relationDAO
759          *            the relationDAO to set
760          */
761         public void setRelationDAO(final RelationDAO relationDAO) {
762                 _relationDAO = relationDAO;
763         }
764 }