Salome HOME
Copyrights update 2015.
[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.List;
15
16 import org.hibernate.criterion.Restrictions;
17 import org.splat.dal.bo.kernel.Relation;
18 import org.splat.dal.bo.kernel.User;
19 import org.splat.dal.bo.som.ConvertsRelation;
20 import org.splat.dal.bo.som.Document;
21 import org.splat.dal.bo.som.DocumentType;
22 import org.splat.dal.bo.som.File;
23 import org.splat.dal.bo.som.KnowledgeElement;
24 import org.splat.dal.bo.som.ProjectElement;
25 import org.splat.dal.bo.som.Publication;
26 import org.splat.dal.bo.som.Scenario;
27 import org.splat.dal.bo.som.SimulationContext;
28 import org.splat.dal.bo.som.StepCommentAttribute;
29 import org.splat.dal.bo.som.UsedByRelation;
30 import org.splat.dal.bo.som.UsesRelation;
31 import org.splat.dal.bo.som.VersionsRelation;
32 import org.splat.dal.dao.kernel.RelationDAO;
33 import org.splat.dal.dao.kernel.UserDAO;
34 import org.splat.dal.dao.som.DocumentDAO;
35 import org.splat.dal.dao.som.FileDAO;
36 import org.splat.dal.dao.som.ProjectElementDAO;
37 import org.splat.dal.dao.som.PublicationDAO;
38 import org.splat.dal.dao.som.SimulationContextDAO;
39 import org.splat.dal.dao.som.StepCommentAttributeDAO;
40 import org.splat.dal.dao.som.VersionsRelationDAO;
41 import org.splat.exception.DocumentIsUsedException;
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.log.AppLogger;
49 import org.splat.service.dto.StepCommentDTO;
50 import org.splat.service.technical.IndexService;
51 import org.splat.service.technical.ProjectSettingsService;
52 import org.splat.som.Revision;
53 import org.splat.som.Step;
54 import org.splat.util.BeanHelper;
55 import org.springframework.transaction.annotation.Transactional;
56
57 /**
58  * Step service implementation.
59  * 
60  * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
61  */
62 public class StepServiceImpl implements StepService {
63
64         /**
65          * logger for the service.
66          */
67         public final static AppLogger LOG = AppLogger
68                         .getLogger(StepServiceImpl.class);
69         /**
70          * Injected index service.
71          */
72         private IndexService _indexService;
73         /**
74          * Injected document service.
75          */
76         private DocumentService _documentService;
77         /**
78          * Injected document type service.
79          */
80         private DocumentTypeService _documentTypeService;
81         /**
82          * Injected document DAO.
83          */
84         private DocumentDAO _documentDAO;
85         /**
86          * Injected relation DAO.
87          */
88         private RelationDAO _relationDAO;
89         /**
90          * Injected file DAO.
91          */
92         private FileDAO _fileDAO;
93         /**
94          * Injected simulation context service.
95          */
96         private SimulationContextService _simulationContextService;
97         /**
98          * Injected simulation context DAO.
99          */
100         private SimulationContextDAO _simulationContextDAO;
101         /**
102          * Injected project element DAO.
103          */
104         private ProjectElementDAO _projectElementDAO;
105         /**
106          * Injected versions relation DAO.
107          */
108         private VersionsRelationDAO _versionsRelationDAO;
109         /**
110          * Injected project service.
111          */
112         private ProjectSettingsService _projectSettings;
113         /**
114          * Injected publication DAO.
115          */
116         private PublicationDAO _publicationDAO;
117
118         /**
119          * Injected text attribute DAO.
120          */
121         private StepCommentAttributeDAO _stepCommentAttributeDAO;
122
123         /**
124          * Injected user DAO.
125          */
126         private UserDAO _userDAO;
127
128         /**
129          * {@inheritDoc}
130          * 
131          * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext.Properties)
132          */
133         @Override
134         @Transactional
135         public SimulationContext addSimulationContext(final Step aStep,
136                         final SimulationContext.Properties dprop)
137                         throws MissedPropertyException, InvalidPropertyException,
138                         MultiplyDefinedException {
139                 SimulationContext context = new SimulationContext(dprop.setStep(aStep
140                                 .getStep()));
141                 return addSimulationContext(aStep, context);
142         }
143
144         /**
145          * {@inheritDoc}
146          * 
147          * @see org.splat.service.StepService#addSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
148          */
149         @Override
150         @Transactional
151         public SimulationContext addSimulationContext(final Step aStep,
152                         final SimulationContext context) {
153                 SimulationContext res = null;
154                 getSimulationContextService().hold(context); // Increments the reference count of simulation context
155                 if (aStep.getOwner().isSaved()) {
156                         try {
157                                 if (!context.isSaved()) {
158                                         getSimulationContextDAO().create(context);
159                                 }
160                                 aStep.getOwner().add(context);
161                                 aStep.getContex().add(context); // The context is also referenced from this (transient) Step
162                                 getProjectElementDAO().update(aStep.getOwner());
163                                 updateKnowledgeElementsIndex(aStep);
164                                 res = context;
165                         } catch (Exception error) {
166                                 LOG.debug(error.getMessage(), error);
167                         }
168                 } else { // Happens when copying a scenario
169                         aStep.getOwner().add(context);
170                         aStep.getContex().add(context); // The context is also referenced from this (transient) Step
171                         // In case of owner scenario, the Knowledge Element index will be updated later, when saving the scenario
172                         res = context;
173                 }
174                 return res;
175         }
176
177         /**
178          * Update lucene index of knowledge elements of a scenario or a study which the given step is related to.
179          * 
180          * @param aStep
181          *            the step (activity)
182          */
183         private void updateKnowledgeElementsIndex(final Step aStep) {
184                 Scenario[] scenarii;
185                 if (aStep.getOwner() instanceof Scenario) {
186                         scenarii = new Scenario[1];
187                         scenarii[0] = (Scenario) aStep.getOwner();
188                 } else {
189                         scenarii = aStep.getOwnerStudy().getScenarii();
190                 }
191                 for (int i = 0; i < scenarii.length; i++) {
192                         Scenario scene = scenarii[i];
193                         updateScenarioIndex(scene);
194                 }
195         }
196
197         /**
198          * Update lucene index for knowledge elements of the scenario.
199          * 
200          * @param scene
201          *            the scenario
202          */
203         private void updateScenarioIndex(final Scenario scene) {
204                 if (scene.getUcase() == null) {
205                         for (KnowledgeElement kelm : scene.getKnowledgeElements()) {
206                                 if (kelm.getType().equals("usecase")) {
207                                         scene.setUcase(kelm);
208                                         break;
209                                 }
210                         }
211                 }
212         }
213
214         /**
215          * {@inheritDoc}
216          * 
217          * @see org.splat.service.StepService#removeSimulationContext(org.splat.som.Step, org.splat.dal.bo.som.SimulationContext)
218          */
219         @Override
220         @Transactional
221         public boolean removeSimulationContext(final Step aStep,
222                         final SimulationContext context) {
223                 SimulationContext torem = aStep
224                                 .getSimulationContext(context.getIndex());
225
226                 boolean isOk = (torem != null) && (aStep.getOwner().remove(torem));
227                 if (isOk) {
228
229                         aStep.getContex().remove(torem);
230                         getProjectElementDAO().update(aStep.getOwner());
231                         if (torem.isShared()) {
232                                 getSimulationContextService().release(torem);
233                                 getSimulationContextDAO().update(torem);
234                         } else {
235                                 getSimulationContextDAO().delete(torem);
236                         }
237                 }
238                 return isOk;
239         }
240
241         /**
242          * {@inheritDoc}
243          * 
244          * @see org.splat.service.StepService#createDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
245          */
246         @Override
247         @Transactional
248         public Publication createDocument(final Step aStep,
249                         final Document.Properties dprop) throws MissedPropertyException,
250                         InvalidPropertyException, MultiplyDefinedException, IOException {
251                 if (LOG.isDebugEnabled()) {
252                         LOG.debug("Local index before: "
253                                         + aStep.getOwnerStudy().getLastLocalIndex());
254                 }
255                 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
256                                 .setStep(aStep.getStep()));
257                 getDocumentService().generateDocumentId(newdoc, dprop);
258
259                 // Creation of the save directory
260                 java.io.File wdir = getDocumentService().getSaveDirectory(newdoc);
261                 if ((!wdir.exists()) && (!wdir.mkdirs())) {
262                         throw new IOException(
263                                         "Cannot create the repository vault directory");
264                 }
265
266                 // Identification and save
267                 if (LOG.isDebugEnabled()) {
268                         LOG.debug("Local index after: "
269                                         + aStep.getOwnerStudy().getLastLocalIndex());
270                 }
271                 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwnerStudy());
272                 getDocumentDAO().create(newdoc);
273
274                 return new Publication(newdoc, aStep.getOwner());
275         }
276
277         /**
278          * {@inheritDoc}
279          * 
280          * @see org.splat.service.StepService#assignDocument(org.splat.som.Step, org.splat.dal.bo.som.Document.Properties)
281          */
282         @Override
283         public Publication assignDocument(final Step aStep,
284                         final Document.Properties dprop) throws MissedPropertyException,
285                         InvalidPropertyException, NotApplicableException {
286                 String refid = dprop.getReference();
287                 Publication res = null;
288                 if (refid != null) {
289                         Document slot = getDocumentService().selectDocument(refid,
290                                         new Revision().toString());
291                         if ((slot != null) && (slot.isUndefined())) {
292                                 getDocumentService().initialize(slot,
293                                                 dprop.setOwner(aStep.getOwnerStudy()));
294                                 res = new Publication(slot, aStep.getOwner());
295                         }
296                 }
297                 return res;
298         }
299
300         /**
301          * Create a new version of a document in the given study step.
302          * 
303          * @param aStep
304          *            the study step
305          * @param base
306          *            the base document published version
307          * @return the new version publication
308          * @throws MissedPropertyException
309          *             if a mandatory property is missed
310          * @throws InvalidPropertyException
311          *             if some property doesn't exist
312          * @throws MultiplyDefinedException
313          *             if some property is defined several times
314          * @throws IOException
315          *             if a file system error occurs
316          * @throws MismatchException
317          *             if the document is not applicable to the given study step
318          */
319         public Publication versionDocument(final Step aStep, final Publication base)
320                         throws MissedPropertyException, InvalidPropertyException,
321                         MultiplyDefinedException, IOException, MismatchException {
322                 return versionDocument(aStep, base, new Document.Properties());
323         }
324
325         /**
326          * Create a new version of a document in the given study step.
327          * 
328          * @param aStep
329          *            the study step
330          * @param base
331          *            the base document published version
332          * @param reason
333          *            the comment for the new version
334          * @return the new version publication
335          * @throws MissedPropertyException
336          *             if a mandatory property is missed
337          * @throws InvalidPropertyException
338          *             if some property doesn't exist
339          * @throws MultiplyDefinedException
340          *             if some property is defined several times
341          * @throws IOException
342          *             if a file system error occurs
343          * @throws MismatchException
344          *             if the document is not applicable to the given study step
345          */
346         public Publication versionDocument(final Step aStep,
347                         final Publication base, final String reason)
348                         throws MissedPropertyException, InvalidPropertyException,
349                         MultiplyDefinedException, IOException, MismatchException {
350                 return versionDocument(aStep, base, new Document.Properties()
351                                 .setDescription(reason));
352         }
353
354         /**
355          * Create a new version of a document in the given study step.
356          * 
357          * @param aStep
358          *            the study step
359          * @param base
360          *            the base document published version
361          * @param dprop
362          *            properties of the new version
363          * @return the new version publication
364          * @throws MissedPropertyException
365          *             if a mandatory property is missed
366          * @throws InvalidPropertyException
367          *             if some property doesn't exist
368          * @throws MultiplyDefinedException
369          *             if some property is defined several times
370          * @throws IOException
371          *             if a file system error occurs
372          * @throws MismatchException
373          *             if the document is not applicable to the given study step
374          */
375         @Transactional
376         public Publication versionDocument(final Step aStep,
377                         final Publication base, final Document.Properties dprop)
378                         throws MissedPropertyException, InvalidPropertyException,
379                         MultiplyDefinedException, IOException, MismatchException {
380                 Document previous = base.value();
381
382                 // RKV: Keep the new file format if it is related to the same document type on this step.
383                 String newFormat = dprop.getFormat();
384
385                 dprop.setDocument(previous, getProjectSettings().getStep(
386                                 base.getStep().getNumber())); // Initializes the Step property
387                 if (dprop.getStep().getNumber() != aStep.getNumber()) {
388                         throw new MismatchException();
389                 }
390
391                 if (newFormat != null
392                 /*
393                  * && previous.getType().equals( getProjectSettings().getDefaultDocumentType( aStep.getStep(), newFormat))
394                  */) {
395                         dprop.setFormat(newFormat);
396                 }
397
398                 if (dprop.getAuthor() == null) {
399                         dprop.setAuthor(previous.getAuthor());
400                 }
401                 String summary = dprop.getDescription();
402
403                 // Creation of the document
404                 Document newdoc = new Document(dprop.setOwner(aStep.getOwner())
405                                 .setStep(aStep.getStep()));
406                 getDocumentService().generateDocumentId(newdoc, dprop);
407                 getDocumentService().buildReferenceFrom(newdoc, aStep.getOwner(),
408                                 previous);
409                 getDocumentDAO().create(newdoc);
410
411                 // Versioning
412                 VersionsRelation aRel;
413                 aRel = new VersionsRelation(newdoc, previous, summary);
414                 // getVersionsRelationDAO().create(aRel);
415                 newdoc.addRelation(aRel);
416
417                 // Update of usedby relations, if exist
418                 /*
419                  * RKV: Consider the new version as not used by old dependent documents. So these documents must be marked as outdated then. List<Relation>
420                  * relist = previous.getRelations(UsedByRelation.class); Study scope = aStep.getOwnerStudy(); for (Iterator<Relation> i =
421                  * relist.iterator(); i.hasNext();) { UsedByRelation relation = (UsedByRelation) i.next(); Document relatedoc = relation.getTo(); if
422                  * (scope.shares(relatedoc)) { relatedoc.addRelation(new UsesRelation(relatedoc, newdoc)); } else { relation.moveTo(newdoc); } }
423                  */
424                 return new Publication(newdoc, aStep.getOwner());
425         }
426
427         /**
428          * Get document types which are applicable for the given study step (activity).
429          * 
430          * @param aStep
431          *            the study step
432          * @return the list of document types
433          */
434         @Override
435         public List<DocumentType> getValidDocumentTypes(final Step aStep) {
436                 return getDocumentTypeService().selectTypesOf(aStep.getStep());
437         }
438
439         /**
440          * Add a document publication to the given step.
441          * 
442          * @param aStep
443          *            the target study step
444          * @param newdoc
445          *            the document publication to add
446          * @return true if publication succeeded
447          */
448         @Override
449         public boolean add(final Step aStep, final Publication newdoc) {
450                 boolean res = aStep.getOwner().add(newdoc); // Updates the study in memory
451                 if (res) {
452                         aStep.getDocuments().add(0, newdoc); // Updates this step
453                         getDocumentService().hold(newdoc.value()); // Increments the configuration tag count of document
454                         // If not yet saved, the Publication MUST NOT be saved here, although this creates a temporary inconsistent state into the
455                         // database (it will be saved later by cascading the update of owner scenario).
456                 }
457                 return res;
458         }
459
460         /**
461          * Remove a document publication from the given step.
462          * 
463          * @param aStep
464          *            the study step
465          * @param oldoc
466          *            the document publication to remove
467          * @return true if removing of the publication succeeded
468          */
469         @Override
470         public boolean remove(final Step aStep, final Publication oldoc) {
471                 aStep.getDocuments().remove(oldoc); // Updates this step
472                 aStep.getOwner().remove(oldoc); // remove from the parent project element
473                 getProjectElementDAO().merge(aStep.getOwner().getOwnerStudy());
474                 getDocumentService().release(oldoc.value()); // Decrements the configuration tag count of document
475                 // The publication becoming orphan, it should automatically be removed from the database when updating of owner scenario.
476                 return true;
477         }
478
479         /**
480          * Remove a document from the given step and from the database if it is no more used.
481          * 
482          * @param aStep
483          *            the study step
484          * @param docId
485          *            the document id
486          * @return true if removing of the document succeeded
487          * @throws DocumentIsUsedException
488          *             if the document is used by other documents
489          */
490         @Override
491         @Transactional
492         public boolean removeDocument(final Step aStep, final long docId)
493                         throws DocumentIsUsedException {
494                 Publication torem = aStep.getDocument(docId);
495                 boolean res = (torem != null);
496                 if (res) {
497                         if (!torem.value().getRelations(UsedByRelation.class).isEmpty()) {
498                                 throw new DocumentIsUsedException(torem.value().getTitle());
499                         }
500                         // Remove the document publication from the step
501                         remove(aStep, torem);
502                         // Republish the previous version if any to avoid it becoming an orphan
503                         Document prevVersion = torem.value().getPreviousVersion();
504                         if (prevVersion != null) {
505                                 prevVersion.setHistory(prevVersion.getHistory() - 1);
506                                 add(aStep, new Publication(prevVersion, aStep.getOwner()));
507                                 getProjectElementDAO().merge(aStep.getOwner());
508                         }
509                         // Delete the document if it is no more used
510                         Document value = torem.value();
511                         if (!value.isPublished() && !value.isVersioned()) { // The referenced document is no more used
512                                 List<Document> using = new ArrayList<Document>();
513                                 List<File> files = new ArrayList<File>();
514                                 files.add(value.getFile()); // To delete the source file physically at the end
515                                 for (Relation link : value.getAllRelations()) {
516                                         if (link.getClass().equals(ConvertsRelation.class)) { // File conversion
517                                                 files.add((File) link.getTo());
518                                         } else if (link.getClass().equals(UsesRelation.class)) { // Document dependency
519                                                 using.add((Document) link.getTo());
520                                         }
521                                 }
522                                 // Remove relations from depending documents
523                                 if (LOG.isDebugEnabled()) {
524                                         LOG.debug("Remove " + using.size() + " UsedByRelation(s).");
525                                 }
526                                 for (Document doc : using) {
527                                         if (LOG.isDebugEnabled()) {
528                                                 LOG.debug("Remove UsedByRelation from "
529                                                                 + doc.getTitle() + " to " + value.getTitle());
530                                                 LOG.debug("Nb relations of doc " + doc.getTitle()
531                                                                 + " before: " + doc.getAllRelations().size());
532                                         }
533                                         doc.removeRelation(UsedByRelation.class, value);
534                                         if (LOG.isDebugEnabled()) {
535                                                 LOG.debug("Nb relations of doc " + doc.getTitle()
536                                                                 + " after: " + doc.getAllRelations().size());
537                                         }
538                                         getDocumentDAO().merge(doc);
539                                 }
540                                 // Synchronize deleted objects with the database to avoid hibernate exception
541                                 // org.hibernate.PropertyValueException: not-null property references a null or transient value
542                                 getDocumentDAO().flush();
543                                 // The corresponding physical file is not removed from the vault
544                                 getDocumentDAO().delete(getDocumentDAO().merge(torem.value()));
545                                 // Delete document's files
546                                 // Delete files from file system
547                                 for (File file : files) {
548                                         // getFileDAO().delete(getFileDAO().merge(file)); // The corresponding physical file is not removed from the vault
549                                         LOG.info("Delete the file "
550                                                         + file.asFile().getAbsolutePath());
551                                         if (file.asFile().delete()) {
552                                                 LOG.info("File " + file.asFile().getAbsolutePath()
553                                                                 + " successfully deleted.");
554                                         } else {
555                                                 LOG.info("File " + file.asFile().getAbsolutePath()
556                                                                 + " can not be deleted.");
557                                         }
558                                 }
559                         }
560                 }
561                 return res;
562         }
563
564         /**
565          * {@inheritDoc}
566          * 
567          * @see org.splat.service.StepService#addComment(org.splat.som.Step, org.splat.dal.bo.som.CommentAttribute)
568          */
569         @Override
570         @Transactional
571         public void addStepComment(final StepCommentDTO comment)
572                         throws InvalidParameterException {
573
574                 if (comment.getId() != null) {
575                         throw new InvalidParameterException("id", String.valueOf(comment
576                                         .getId()));
577                 }
578                 User user = getUserDAO().get(comment.getUserId());
579                 if (user == null) {
580                         throw new InvalidParameterException("userId", String
581                                         .valueOf(comment.getUserId()));
582                 }
583                 ProjectElement projectElement = getProjectElementDAO().get(
584                                 comment.getProjectElementId());
585                 if (projectElement == null) {
586                         throw new InvalidParameterException("projectElementId", comment
587                                         .getProjectElementId().toString());
588                 }
589                 if (comment.getStep() == null || comment.getStep() < 0) {
590                         throw new InvalidParameterException("step", String.valueOf(comment
591                                         .getStep()));
592                 }
593                 if (comment.getDate() == null) {
594                         throw new InvalidParameterException("date", String.valueOf(comment
595                                         .getDate()));
596                 }
597                 if (comment.getTitle() == null) {
598                         throw new InvalidParameterException("title", String.valueOf(comment
599                                         .getTitle()));
600                 }
601
602                 StepCommentAttribute newComment = new StepCommentAttribute(
603                                 projectElement, comment.getText(), comment.getDate(), comment
604                                                 .getStep(), user, comment.getTitle());
605
606                 Long resultKey = getStepCommentAttributeDAO().create(newComment);
607                 comment.setId(resultKey);
608         }
609
610         /**
611          * {@inheritDoc}
612          * 
613          * @see org.splat.service.StepService#getStepComments(org.splat.som.Step)
614          */
615         @Override
616         @Transactional(readOnly = true)
617         public List<StepCommentDTO> getStepComments(final Step step)
618                         throws InvalidParameterException {
619                 ProjectElement owner = _projectElementDAO.get(step.getOwner().getRid());
620                 if (owner == null) {
621                         throw new InvalidParameterException("step owner id", Long.valueOf(
622                                         step.getOwner().getRid()).toString());
623                 }
624                 List<StepCommentAttribute> comments = _stepCommentAttributeDAO
625                                 .getFilteredList(Restrictions.and(Restrictions.eq("step",
626                                                 Integer.valueOf(step.getNumber())), Restrictions.eq(
627                                                 "owner", owner)));
628                 List<StepCommentDTO> commentDTOs = new ArrayList<StepCommentDTO>();
629                 for (StepCommentAttribute comment : comments) {
630                         StepCommentDTO stepCommentDTO = BeanHelper.copyBean(comment,
631                                         StepCommentDTO.class);
632                         stepCommentDTO.setText(comment.getValue());
633                         stepCommentDTO.setId(Long.valueOf(comment.getRid()));
634                         commentDTOs.add(stepCommentDTO);
635                 }
636                 return commentDTOs;
637         }
638
639         /**
640          * {@inheritDoc}
641          * 
642          * @see org.splat.service.StepService#removeStepComment(long)
643          */
644         @Override
645         @Transactional
646         public void removeStepComment(final long commentId)
647                         throws InvalidParameterException {
648                 StepCommentAttribute stepComment = _stepCommentAttributeDAO.get(Long
649                                 .valueOf(commentId));
650                 if (stepComment == null) {
651                         throw new InvalidParameterException("commentId", String
652                                         .valueOf(commentId));
653                 }
654                 _stepCommentAttributeDAO.delete(stepComment);
655         }
656
657         /**
658          * {@inheritDoc}
659          * 
660          * @see org.splat.service.StepService#editStepComment(long, java.lang.String, java.lang.String)
661          */
662         @Override
663         @Transactional
664         public void editStepComment(final long commentId, final String newValue,
665                         final String newTitle) throws InvalidParameterException {
666                 StepCommentAttribute comment = _stepCommentAttributeDAO.get(Long
667                                 .valueOf(commentId));
668                 if (comment == null) {
669                         throw new InvalidParameterException("commentId", String
670                                         .valueOf(commentId));
671                 }
672                 if (newTitle != null) {
673                         comment.setTitle(newTitle);
674                 }
675                 if (newValue != null) {
676                         comment.setValue(newValue);
677                 }
678                 _stepCommentAttributeDAO.update(comment);
679         }
680
681         /**
682          * {@inheritDoc}
683          * 
684          * @see org.splat.service.StepService#isCommentMadeByUser(long, long)
685          */
686         @Override
687         @Transactional(readOnly = true)
688         public boolean isCommentMadeByUser(final long commentId, final long userId)
689                         throws InvalidParameterException {
690                 StepCommentAttribute comment = _stepCommentAttributeDAO.get(Long
691                                 .valueOf(commentId));
692                 if (comment == null) {
693                         throw new InvalidParameterException("commentId", String
694                                         .valueOf(commentId));
695                 }
696                 return comment.getUser().getIndex() == userId;
697         }
698
699         /**
700          * Get the documentService.
701          * 
702          * @return the documentService
703          */
704         public DocumentService getDocumentService() {
705                 return _documentService;
706         }
707
708         /**
709          * Set the documentService.
710          * 
711          * @param documentService
712          *            the documentService to set
713          */
714         public void setDocumentService(final DocumentService documentService) {
715                 _documentService = documentService;
716         }
717
718         /**
719          * Get the simulationContextService.
720          * 
721          * @return the simulationContextService
722          */
723         public SimulationContextService getSimulationContextService() {
724                 return _simulationContextService;
725         }
726
727         /**
728          * Set the simulationContextService.
729          * 
730          * @param simulationContextService
731          *            the simulationContextService to set
732          */
733         public void setSimulationContextService(
734                         final SimulationContextService simulationContextService) {
735                 _simulationContextService = simulationContextService;
736         }
737
738         /**
739          * Get the documentDAO.
740          * 
741          * @return the documentDAO
742          */
743         public DocumentDAO getDocumentDAO() {
744                 return _documentDAO;
745         }
746
747         /**
748          * Set the documentDAO.
749          * 
750          * @param documentDAO
751          *            the documentDAO to set
752          */
753         public void setDocumentDAO(final DocumentDAO documentDAO) {
754                 _documentDAO = documentDAO;
755         }
756
757         /**
758          * Get the simulationContextDAO.
759          * 
760          * @return the simulationContextDAO
761          */
762         public SimulationContextDAO getSimulationContextDAO() {
763                 return _simulationContextDAO;
764         }
765
766         /**
767          * Set the simulationContextDAO.
768          * 
769          * @param simulationContextDAO
770          *            the simulationContextDAO to set
771          */
772         public void setSimulationContextDAO(
773                         final SimulationContextDAO simulationContextDAO) {
774                 _simulationContextDAO = simulationContextDAO;
775         }
776
777         /**
778          * Get the projectElementDAO.
779          * 
780          * @return the projectElementDAO
781          */
782         public ProjectElementDAO getProjectElementDAO() {
783                 return _projectElementDAO;
784         }
785
786         /**
787          * Set the projectElementDAO.
788          * 
789          * @param projectElementDAO
790          *            the projectElementDAO to set
791          */
792         public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
793                 _projectElementDAO = projectElementDAO;
794         }
795
796         /**
797          * Get the indexService.
798          * 
799          * @return the indexService
800          */
801         public IndexService getIndexService() {
802                 return _indexService;
803         }
804
805         /**
806          * Set the indexService.
807          * 
808          * @param indexService
809          *            the indexService to set
810          */
811         public void setIndexService(final IndexService indexService) {
812                 _indexService = indexService;
813         }
814
815         /**
816          * Get the fileDAO.
817          * 
818          * @return the fileDAO
819          */
820         public FileDAO getFileDAO() {
821                 return _fileDAO;
822         }
823
824         /**
825          * Set the fileDAO.
826          * 
827          * @param fileDAO
828          *            the fileDAO to set
829          */
830         public void setFileDAO(final FileDAO fileDAO) {
831                 _fileDAO = fileDAO;
832         }
833
834         /**
835          * Get the documentTypeService.
836          * 
837          * @return the documentTypeService
838          */
839         public DocumentTypeService getDocumentTypeService() {
840                 return _documentTypeService;
841         }
842
843         /**
844          * Set the documentTypeService.
845          * 
846          * @param documentTypeService
847          *            the documentTypeService to set
848          */
849         public void setDocumentTypeService(
850                         final DocumentTypeService documentTypeService) {
851                 _documentTypeService = documentTypeService;
852         }
853
854         /**
855          * Get the versionsRelationDAO.
856          * 
857          * @return the versionsRelationDAO
858          */
859         public VersionsRelationDAO getVersionsRelationDAO() {
860                 return _versionsRelationDAO;
861         }
862
863         /**
864          * Set the versionsRelationDAO.
865          * 
866          * @param versionsRelationDAO
867          *            the versionsRelationDAO to set
868          */
869         public void setVersionsRelationDAO(
870                         final VersionsRelationDAO versionsRelationDAO) {
871                 _versionsRelationDAO = versionsRelationDAO;
872         }
873
874         /**
875          * Get project settings.
876          * 
877          * @return Project settings service
878          */
879         private ProjectSettingsService getProjectSettings() {
880                 return _projectSettings;
881         }
882
883         /**
884          * Set project settings service.
885          * 
886          * @param projectSettingsService
887          *            project settings service
888          */
889         public void setProjectSettings(
890                         final ProjectSettingsService projectSettingsService) {
891                 _projectSettings = projectSettingsService;
892         }
893
894         /**
895          * Get the stepCommentAttributeDAO.
896          * 
897          * @return the stepCommentAttributeDAO
898          */
899         public StepCommentAttributeDAO getStepCommentAttributeDAO() {
900                 return _stepCommentAttributeDAO;
901         }
902
903         /**
904          * Set the stepCommentAttributeDAO.
905          * 
906          * @param commentAttributeDAO
907          *            the stepCommentAttributeDAO to set
908          */
909         public void setStepCommentAttributeDAO(
910                         final StepCommentAttributeDAO commentAttributeDAO) {
911                 _stepCommentAttributeDAO = commentAttributeDAO;
912         }
913
914         /**
915          * Get the userDAO.
916          * 
917          * @return the userDAO
918          */
919         public UserDAO getUserDAO() {
920                 return _userDAO;
921         }
922
923         /**
924          * Set the userDAO.
925          * 
926          * @param userDAO
927          *            the userDAO to set
928          */
929         public void setUserDAO(final UserDAO userDAO) {
930                 _userDAO = userDAO;
931         }
932
933         /**
934          * Get the publicationDAO.
935          * 
936          * @return the publicationDAO
937          */
938         public PublicationDAO getPublicationDAO() {
939                 return _publicationDAO;
940         }
941
942         /**
943          * Set the publicationDAO.
944          * 
945          * @param publicationDAO
946          *            the publicationDAO to set
947          */
948         public void setPublicationDAO(final PublicationDAO publicationDAO) {
949                 this._publicationDAO = publicationDAO;
950         }
951
952         /**
953          * Get the relationDAO.
954          * 
955          * @return the relationDAO
956          */
957         public RelationDAO getRelationDAO() {
958                 return _relationDAO;
959         }
960
961         /**
962          * Set the relationDAO.
963          * 
964          * @param relationDAO
965          *            the relationDAO to set
966          */
967         public void setRelationDAO(final RelationDAO relationDAO) {
968                 _relationDAO = relationDAO;
969         }
970 }