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