1 /*****************************************************************************
5 * Creation date 06.10.2012
8 *****************************************************************************/
10 package org.splat.service;
13 import java.io.FileNotFoundException;
14 import java.io.IOException;
15 import java.text.ParseException;
16 import java.util.ArrayList;
17 import java.util.Date;
18 import java.util.HashSet;
19 import java.util.Iterator;
20 import java.util.List;
22 import org.apache.log4j.Logger;
23 import org.splat.dal.bo.kernel.User;
24 import org.splat.dal.bo.som.ConvertsRelation;
25 import org.splat.dal.bo.som.Document;
26 import org.splat.dal.bo.som.DocumentType;
27 import org.splat.dal.bo.som.ProgressState;
28 import org.splat.dal.bo.som.ProjectElement;
29 import org.splat.dal.bo.som.Publication;
30 import org.splat.dal.bo.som.SimulationContext;
31 import org.splat.dal.bo.som.SimulationContextType;
32 import org.splat.dal.bo.som.Study;
33 import org.splat.dal.bo.som.Timestamp;
34 import org.splat.dal.bo.som.UsedByRelation;
35 import org.splat.dal.bo.som.ValidationCycle;
36 import org.splat.dal.bo.som.ValidationStep;
37 import org.splat.dal.dao.som.ProjectElementDAO;
38 import org.splat.dal.dao.som.PublicationDAO;
39 import org.splat.dal.dao.som.TimestampDAO;
40 import org.splat.kernel.InvalidPropertyException;
41 import org.splat.kernel.MismatchException;
42 import org.splat.kernel.MissedPropertyException;
43 import org.splat.kernel.MultiplyDefinedException;
44 import org.splat.kernel.NotApplicableException;
45 import org.splat.manox.Reader;
46 import org.splat.manox.Toolbox;
47 import org.splat.service.technical.RepositoryService;
48 import org.splat.som.DocumentRights;
49 import org.splat.som.Revision;
50 import org.splat.som.Step;
51 import org.springframework.transaction.annotation.Transactional;
54 * Publication service implementation.
56 * @author <a href="mailto:roman.kozlov@opencascade.com">Roman Kozlov (RKV)</a>
58 public class PublicationServiceImpl implements PublicationService {
61 * Logger for this class.
63 protected final static Logger LOG = Logger
64 .getLogger(PublicationServiceImpl.class);
67 * Injected study service.
69 private StudyService _studyService;
71 * Injected step service.
73 private StepService _stepService;
75 * Injected document service.
77 private DocumentService _documentService;
79 * Injected document type service.
81 private DocumentTypeService _documentTypeService;
83 * Injected user service.
85 private UserService _userService;
87 * Injected project element service.
89 private ProjectElementService _projectElementService;
91 * Injected simulation context service.
93 private SimulationContextService _simulationContextService;
95 * Injected publication DAO.
97 private PublicationDAO _publicationDAO;
99 * Injected timestamp DAO.
101 private TimestampDAO _timestampDAO;
103 * Injected project element DAO.
105 private ProjectElementDAO _projectElementDAO;
107 * Injected repository service.
109 private RepositoryService _repositoryService;
114 * @see org.splat.service.PublicationService#copy(org.splat.dal.bo.som.Publication, org.splat.dal.bo.som.ProjectElement)
116 public Publication copy(final Publication aPublication,
117 final ProjectElement publisher) {
118 Publication copy = new Publication();
119 copy.setValue(aPublication.value());
120 copy.setStep(aPublication.getStep()); // May not be initialized yet
121 copy.setOwner(publisher);
122 copy.setIsnew(aPublication.getIsnew());
123 if (!copy.getOwnerStudy().equals(aPublication.getOwnerStudy())) {
124 copy.setIsnew('N'); // The referenced document is not new for the given study
132 * @see org.splat.service.PublicationService#createDoc(long, org.splat.som.Step, long, long, java.lang.String, java.lang.String,
133 * org.splat.dal.bo.som.ProgressState, java.lang.String, java.lang.String, java.util.Date, java.util.List)
136 public Publication createDoc(final long ownerId, final Step step,
137 final long documentTypeId, final long userId, final String fname,
138 final String doctitle, final ProgressState docstate,
139 final String reference, final String version, final Date docDate,
140 final List<Long> docuses) throws MissedPropertyException,
141 InvalidPropertyException, MultiplyDefinedException, IOException,
142 NotApplicableException, InterruptedException, ParseException {
143 DocumentType type = getDocumentTypeService().selectType(
144 (int) documentTypeId);
145 User user = getUserService().selectUser(userId);
146 File updir = getRepositoryService().getDownloadDirectory(user);
147 File upfile = new File(updir.getPath() + "/" + fname);
148 String[] table = fname.split("\\x2E");
150 // Creation of the document
151 Document.Properties dprop = new Document.Properties();
152 dprop.setLocalPath(upfile.getPath());
155 if (reference.length() == 0) { // Importation of a foreign document
156 // TODO: Extract property of supported documents (DOCX, ODT...)
157 addoc = getStepService().createDocument(
159 dprop.setName(doctitle).setType(type).setFormat(
160 table[table.length - 1]).setAuthor(user));
161 updir = addoc.getSourceFile().asFile();
162 if (LOG.isInfoEnabled()) {
163 LOG.info("Moving \"" + upfile.getAbsolutePath() + "\" to \""
164 + updir.getPath() + "\".");
166 upfile.renameTo(updir);
168 saveAs(addoc, docstate); // May throw FileNotFound if rename was not done
169 } catch (FileNotFoundException saverror) {
171 LOG.info("Waiting for the file.");
172 upfile.renameTo(updir);
173 saveAs(addoc, docstate); // Forget it if throw again FileNotFound
175 } else { // Importation of a previously created template-based document
176 if (docDate != null) {
177 dprop.setDate(docDate);
179 addoc = getStepService().assignDocument(step,
180 dprop.setReference(reference).setName(doctitle));
181 updir = addoc.getSourceFile().asFile();
182 if (LOG.isInfoEnabled()) {
183 LOG.info("Moving \"" + upfile.getName() + "\" to \""
184 + updir.getPath() + "\".");
186 upfile.renameTo(updir);
188 if (version.length() > 0) {
189 saveAs(addoc, new Revision(version));
191 saveAs(addoc, docstate);
193 } catch (FileNotFoundException saverror) {
195 LOG.info("Waiting for the file.");
196 upfile.renameTo(updir);
197 if (version.length() > 0) {
198 saveAs(addoc, new Revision(version));
200 saveAs(addoc, docstate);
204 // Creation of uses relations
205 if (docuses != null) {
206 for (Long index : docuses) {
207 Document used = getDocumentService().selectDocument(index);
208 addoc.addDependency(used);
217 * @see org.splat.service.PublicationService#versionDocument(org.splat.som.Step, org.splat.dal.bo.kernel.User, java.lang.String, long,
218 * java.lang.String, java.lang.String, org.splat.dal.bo.som.ProgressState, java.util.Date, java.lang.String[], long[])
221 public void versionDocument(final Step step, final User user,
222 final String filename, final long docIndex, final String docver,
223 final String summary, final ProgressState state, final Date date,
224 final String[] docuses, final long[] docusedby)
225 throws MissedPropertyException, InvalidPropertyException,
226 MultiplyDefinedException, IOException, MismatchException,
227 NotApplicableException, InterruptedException {
228 File updir = getRepositoryService().getDownloadDirectory(user);
229 File upfile = new File(updir.getPath() + "/" + filename);
231 // Versioning of the document
232 Document.Properties dprop = new Document.Properties();
233 dprop.setLocalPath(upfile.getPath());
234 Publication current = step.getDocument(docIndex);
237 if ((docver.length() != 0) && // Importation of a not foreign document
241 if ((summary != null) && (summary.length() > 0)) {
242 dprop.setDescription(summary);
244 next = getStepService().versionDocument(step, current,
245 dprop.setAuthor(user));
246 updir = next.getSourceFile().asFile();
247 if (LOG.isInfoEnabled()) {
248 LOG.info("Moving \"" + upfile.getName() + "\" to \""
249 + updir.getPath() + "\".");
251 upfile.renameTo(updir);
254 if (docver.length() == 0) { // Importation of a foreign document
255 saveAs(next, state); // May throw FileNotFound if rename was not done
257 saveAs(next, new Revision(docver));
259 } catch (FileNotFoundException saverror) {
261 LOG.info("Waiting for the file.");
262 upfile.renameTo(updir);
265 // TODO: Remove current document details from the contents of open study
267 // Creation of uses relations
268 updateRelations(current, next, docuses, docusedby);
272 * Update relations after creation of a new document version.
275 * the current version
279 * ids of used documents
281 * ids of documents used by the versioned one.
283 private void updateRelations(final Publication current,
284 final Publication next, final String[] docuses,
285 final long[] docusedby) {
286 if (docuses != null) {
287 for (int i = 0; i < docuses.length; i++) {
288 Long index = Long.valueOf(docuses[i].trim());
289 Document used = getDocumentService().selectDocument(index);// RKV: getPublication(index, steps);
290 next.addDependency(used);
293 // Outdating impacted document
294 HashSet<Long> compatible = new HashSet<Long>();
295 if (docusedby != null) {
296 for (int i = 0; i < docusedby.length; i++) {
297 compatible.add(docusedby[i]);
300 List<Publication> relist = current.getRelations(UsedByRelation.class);
301 for (Iterator<Publication> i = relist.iterator(); i.hasNext();) {
302 Publication using = i.next();
303 if (!compatible.contains(using.getIndex())) {
310 * protected Publication getPublication(int index, List<Step> steps) { for (Iterator<Step> i = steps.iterator(); i.hasNext();) { List<Publication>
311 * published = i.next().getAllDocuments(); for (Iterator<Publication> j = published.iterator(); j.hasNext();) { Publication found =
312 * j.next(); // In a given study step, if (found.value().getIndex() == index) return found; // there is only one publication of a given
313 * document } } return null; }
318 * @see org.splat.service.PublicationService#approve(org.splat.dal.bo.som.Publication, java.util.Date)
321 public Timestamp approve(final Publication aPublication, final Date adate) {
322 Timestamp res = null;
323 if (!(aPublication.isOutdated() || (aPublication.value()
324 .getProgressState() != ProgressState.inCHECK))) {
325 DocumentType type = aPublication.value().getType();
326 Study owner = aPublication.getOwnerStudy();
327 ValidationCycle cycle = getStudyService().getValidationCycleOf(
329 User approver = cycle.getActor(ValidationStep.APPROVAL);
330 Timestamp stamp = new Timestamp(ValidationStep.APPROVAL,
331 aPublication.value(), approver, adate);
332 getTimestampDAO().create(stamp);
334 if (getDocumentService().promote(aPublication.value(), stamp)) {
336 if (getDocumentService().isStudyResult(type)
337 && owner.getProgressState() == ProgressState.inCHECK) {
338 getStudyService().promote(owner);
342 return res; // Hoping that promotion of the study succeeded
348 * @see org.splat.service.PublicationService#demote(org.splat.dal.bo.som.Publication)
351 public boolean demote(final Publication aPublication) {
353 DocumentType type = aPublication.value().getType();
354 Study owner = aPublication.getOwnerStudy();
356 if (aPublication.value().getProgressState() == ProgressState.inCHECK) {
357 ValidationCycle cycle = getStudyService().getValidationCycleOf(
359 if (cycle.enables(ValidationStep.REVIEW)) {
360 res = getDocumentService().demote(aPublication.value());
362 res = getDocumentService().demote(aPublication.value());
364 getDocumentService().demote(aPublication.value());
367 } else if (aPublication.value().getProgressState() == ProgressState.inDRAFT) {
368 res = getDocumentService().demote(aPublication.value());
370 if (res && getDocumentService().isStudyResult(type)
371 && owner.getProgressState() != ProgressState.inWORK) {
372 getStudyService().demote(owner);
380 * @see org.splat.service.PublicationService#invalidate(org.splat.dal.bo.som.Publication)
383 public boolean invalidate(final Publication aPublication) {
385 if ((aPublication.value().getProgressState() == ProgressState.inCHECK)
386 && getDocumentService().demote(aPublication.value())) {
387 DocumentType type = aPublication.value().getType();
388 Study owner = aPublication.getOwnerStudy();
389 if (getDocumentService().isStudyResult(type)
390 && owner.getProgressState() == ProgressState.inCHECK) {
391 getStudyService().demote(owner);
401 * @see org.splat.service.PublicationService#promote(org.splat.dal.bo.som.Publication, java.util.Date)
404 public Timestamp promote(final Publication aPublication, final Date pdate) {
405 Timestamp res = null;
406 if ((!aPublication.isOutdated())
407 && (aPublication.value().getProgressState() == ProgressState.inWORK)) {
408 DocumentType type = aPublication.value().getType();
409 Study owner = aPublication.getOwnerStudy();
410 ValidationCycle cycle = getStudyService().getValidationCycleOf(
412 User promoter = cycle.getActor(ValidationStep.PROMOTION);
413 if (promoter == null) {
414 promoter = getInvolvedStep(aPublication).getActor();
416 if (promoter == null) {
417 promoter = owner.getAuthor();
419 Timestamp stamp = new Timestamp(ValidationStep.PROMOTION,
420 aPublication.value(), promoter, pdate);
421 getTimestampDAO().create(stamp);
423 if (getDocumentService().promote(aPublication.value(), stamp)) {
425 if (!cycle.enables(ValidationStep.REVIEW)) {
426 getDocumentService().promote(aPublication.value(), null);
428 if (getDocumentService().isStudyResult(type)
429 && owner.getProgressState() == ProgressState.inWORK) {
430 getStudyService().promote(owner);
434 return res; // Hoping that promotion of the study succeeded
440 * @see org.splat.service.PublicationService#review(org.splat.dal.bo.som.Publication, java.util.Date)
443 public Timestamp review(final Publication aPublication, final Date rdate) {
444 Timestamp res = null;
445 if (!aPublication.isOutdated()
446 && !(aPublication.value().getProgressState() != ProgressState.inDRAFT)) {
448 DocumentType type = aPublication.value().getType();
449 Study owner = aPublication.getOwnerStudy();
450 ValidationCycle cycle = getStudyService().getValidationCycleOf(
452 User reviewer = cycle.getActor(ValidationStep.REVIEW);
453 Timestamp stamp = new Timestamp(ValidationStep.REVIEW, aPublication
454 .value(), reviewer, rdate);
455 getTimestampDAO().create(stamp);
457 if (getDocumentService().promote(aPublication.value(), stamp)) {
459 if (getDocumentService().isStudyResult(type)
460 && owner.getProgressState() == ProgressState.inDRAFT) {
461 getStudyService().promote(owner);
465 return res; // Hoping that promotion of the study succeeded
471 * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.som.Revision)
476 public void saveAs(final Publication aPublication, final Revision newvers)
477 throws FileNotFoundException, NotApplicableException {
478 if (aPublication.value().isUndefined()) {
479 throw new NotApplicableException(
480 "Cannot save a Publication object refering an undefined Document");
482 if (!aPublication.value().getSourceFile().exists()) {
483 throw new FileNotFoundException();
486 getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
487 getDocumentService().updateAs(aPublication.value(), newvers); // May change the branch name of given revision
488 updateOwner(aPublication);
494 * @see org.splat.service.PublicationService#saveAs(org.splat.dal.bo.som.Publication, org.splat.dal.bo.som.ProgressState)
497 public void saveAs(final Publication aPublication, final ProgressState state)
498 throws FileNotFoundException, NotApplicableException {
499 if (aPublication.value().isUndefined()) {
500 throw new NotApplicableException(
501 "Cannot save a Publication object refering an undefined Document");
503 if (!aPublication.value().getSourceFile().exists()) {
504 throw new FileNotFoundException(aPublication.value().getSourceFile().asFile().getAbsolutePath());
507 if (state == ProgressState.inWORK || state == ProgressState.EXTERN) {
508 getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
510 getDocumentService().updateAs(aPublication.value(), state);
512 DocumentType mytype = aPublication.value().getType();
513 Study owner = aPublication.getOwnerStudy();
514 ValidationCycle cycle = getStudyService().getValidationCycleOf(
516 boolean review = cycle.enables(ValidationStep.REVIEW);
517 if (!(state == ProgressState.inDRAFT && review)
518 && !(state == ProgressState.inCHECK && !review)) {
519 throw new NotApplicableException(
520 "Cannot save a result document in " + state.toString()
523 getPublicationDAO().create(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
525 getDocumentService().updateAs(aPublication.value(),
526 ProgressState.inWORK);
528 promote(aPublication, aPublication.value()
529 .getLastModificationDate()); // Promotes to the appropriate state in accordance to the validation cycle
531 updateOwner(aPublication);
535 * Update an owner of the publication.
537 * @param aPublication
538 * the document publication
541 private void updateOwner(final Publication aPublication) {
542 Step step = getInvolvedStep(aPublication);
544 // Update of involved step
545 Document previous = aPublication.value().getPreviousVersion();
546 if (previous != null) {
547 Publication oldoc = step.getDocument(previous.getIndex());
548 getStepService().remove(step, oldoc); // Decrements the configuration tag count of document
550 getStepService().add(step, aPublication); // Increments the configuration tag count of document
552 // Import the document properties and update of the study
553 forwardProperties(aPublication, aPublication.value().getSourceFile()
555 getProjectElementDAO().merge(aPublication.getOwner());
559 * Propagate simulation contexts from the given config file to the publication's owner (study or step).
561 * @param aPublication
562 * the document publication
568 private void forwardProperties(final Publication aPublication,
569 final java.io.File from, final Step to) {
570 Reader tool = Toolbox.getReader(from);
571 if (tool != null) { // Properties extractor available for this type of document
572 SimulationContextType.Properties sprop = new SimulationContextType.Properties()
573 .setStep(to.getStep()).setProgressState(
574 ProgressState.APPROVED);
575 List<SimulationContextType> contype = getSimulationContextService()
576 .selectTypesWhere(sprop);
577 if (!contype.isEmpty()) { // There is an approved property type configured at this step
579 SimulationContext.Properties cprop = new SimulationContext.Properties();
580 List<SimulationContext> context = to.getAllSimulationContexts();
582 context = new ArrayList<SimulationContext>(context.size());
583 context.addAll(to.getAllSimulationContexts());
584 cprop.disableCheck();
585 for (Iterator<SimulationContextType> i = contype.iterator(); i
587 SimulationContextType property = i.next();
588 boolean isFound = false;
589 for (Iterator<SimulationContext> j = context.iterator(); j
591 SimulationContext existing = j.next();
592 isFound = existing.getType().equals(property);
594 // Forget this property as it is already set
600 String value = tool.extractProperty(property
603 continue; // Property not defined into the document
606 cprop.setType(property).setValue(value);
607 if (aPublication.getOwner() instanceof Study) {
608 getStudyService().addProjectContext(
609 (Study) aPublication.getOwner(), cprop); // Re-indexes knowledges and the study
612 .addSimulationContext(to, cprop); // Re-indexes knowledges only
614 } catch (Exception e) {
624 * Returns the study Step into which the document version referenced by this publication has been published.
626 * @param aPublication
627 * the document publication
628 * @return the study step where the document is published
630 public Step getInvolvedStep(final Publication aPublication) {
631 if (aPublication.getStep() == null) {
632 Step[] step = getProjectElementService().getSteps(
633 aPublication.getOwner());
634 for (int i = 0; i < step.length; i++) {
635 aPublication.setStep(step[i]); // The involved step necessarily exists
636 if (aPublication.value().isInto(aPublication.getStep())) {
641 return aPublication.getStep();
645 * Undo the out-date operation.
647 * @param aPublication
649 * @return true if the acceptance succeeds
651 * @see DocumentRights#canAccept()
654 public boolean actualize(final Publication aPublication) {
655 boolean res = aPublication.isOutdated();
657 aPublication.setIsnew('Y');
658 getPublicationDAO().update(aPublication);
664 * Out-dates this publication and recursively all publications using this one. Typically, a publication is out-dated when modifying a
665 * document to which it depends.
667 * @param aPublication
670 * @see #getProgressState()
673 public void outdate(final Publication aPublication) {
674 if (aPublication.isOutdated()) {
678 List<Publication> relist = aPublication
679 .getRelations(UsedByRelation.class);
680 for (Iterator<Publication> i = relist.iterator(); i.hasNext();) {
683 aPublication.setIsnew('O');
684 getPublicationDAO().update(aPublication);
688 * Create "Converts" relation for the given document publication and format.
690 * @param aPublication
691 * the document publication
694 * @return the created "Converts" relation
697 public ConvertsRelation attach(final Publication aPublication,
698 final String format) {
699 return getDocumentService().attach(aPublication.value(), format);
703 * Create "Converts" relation for the given document publication, format and description.
705 * @param aPublication
706 * the document publication
710 * the description of the relation
711 * @return the created "Converts" relation
714 public ConvertsRelation attach(final Publication aPublication,
715 final String format, final String description) {
716 return getDocumentService().attach(aPublication.value(), format,
721 * Rename the published document.
723 * @param aPublication
724 * the publication of the document
726 * the new document title
727 * @throws InvalidPropertyException
728 * if the new title is empty
730 public void rename(final Publication aPublication, final String title)
731 throws InvalidPropertyException {
732 getDocumentService().rename(aPublication.value(), title);
736 * Get the projectElementService.
738 * @return the projectElementService
740 public ProjectElementService getProjectElementService() {
741 return _projectElementService;
745 * Set the projectElementService.
747 * @param projectElementService
748 * the projectElementService to set
750 public void setProjectElementService(
751 final ProjectElementService projectElementService) {
752 _projectElementService = projectElementService;
756 * Get the simulationContextService.
758 * @return the simulationContextService
760 public SimulationContextService getSimulationContextService() {
761 return _simulationContextService;
765 * Set the simulationContextService.
767 * @param simulationContextService
768 * the simulationContextService to set
770 public void setSimulationContextService(
771 final SimulationContextService simulationContextService) {
772 _simulationContextService = simulationContextService;
776 * Get the studyService.
778 * @return the studyService
780 public StudyService getStudyService() {
781 return _studyService;
785 * Set the studyService.
787 * @param studyService
788 * the studyService to set
790 public void setStudyService(final StudyService studyService) {
791 _studyService = studyService;
795 * Get the stepService.
797 * @return the stepService
799 public StepService getStepService() {
804 * Set the stepService.
807 * the stepService to set
809 public void setStepService(final StepService stepService) {
810 _stepService = stepService;
814 * Get the documentService.
816 * @return the documentService
818 public DocumentService getDocumentService() {
819 return _documentService;
823 * Set the documentService.
825 * @param documentService
826 * the documentService to set
828 public void setDocumentService(final DocumentService documentService) {
829 _documentService = documentService;
833 * Get the publicationDAO.
835 * @return the publicationDAO
837 public PublicationDAO getPublicationDAO() {
838 return _publicationDAO;
842 * Set the publicationDAO.
844 * @param publicationDAO
845 * the publicationDAO to set
847 public void setPublicationDAO(final PublicationDAO publicationDAO) {
848 _publicationDAO = publicationDAO;
852 * Get the projectElementDAO.
854 * @return the projectElementDAO
856 public ProjectElementDAO getProjectElementDAO() {
857 return _projectElementDAO;
861 * Set the projectElementDAO.
863 * @param projectElementDAO
864 * the projectElementDAO to set
866 public void setProjectElementDAO(final ProjectElementDAO projectElementDAO) {
867 _projectElementDAO = projectElementDAO;
871 * Get the repositoryService.
873 * @return the repositoryService
875 public RepositoryService getRepositoryService() {
876 return _repositoryService;
880 * Set the repositoryService.
882 * @param repositoryService
883 * the repositoryService to set
885 public void setRepositoryService(final RepositoryService repositoryService) {
886 _repositoryService = repositoryService;
890 * Get the timestampDAO.
892 * @return the timestampDAO
894 public TimestampDAO getTimestampDAO() {
895 return _timestampDAO;
899 * Set the timestampDAO.
901 * @param timestampDAO
902 * the timestampDAO to set
904 public void setTimestampDAO(final TimestampDAO timestampDAO) {
905 _timestampDAO = timestampDAO;
909 * Get the documentTypeService.
911 * @return the documentTypeService
913 public DocumentTypeService getDocumentTypeService() {
914 return _documentTypeService;
918 * Set the documentTypeService.
920 * @param documentTypeService
921 * the documentTypeService to set
923 public void setDocumentTypeService(
924 final DocumentTypeService documentTypeService) {
925 _documentTypeService = documentTypeService;
929 * Get the userService.
931 * @return the userService
933 public UserService getUserService() {
938 * Set the userService.
941 * the userService to set
943 public void setUserService(final UserService userService) {
944 _userService = userService;