1 /*****************************************************************************
5 * Creation date 06.10.2012
8 *****************************************************************************/
10 package org.splat.service;
12 import java.io.FileNotFoundException;
13 import java.util.ArrayList;
14 import java.util.Date;
15 import java.util.Iterator;
16 import java.util.List;
18 import org.hibernate.Session;
19 import org.splat.dal.bo.kernel.User;
20 import org.splat.dal.bo.som.Document;
21 import org.splat.dal.bo.som.DocumentType;
22 import org.splat.dal.bo.som.ProgressState;
23 import org.splat.dal.bo.som.ProjectElement;
24 import org.splat.dal.bo.som.Publication;
25 import org.splat.dal.bo.som.SimulationContext;
26 import org.splat.dal.bo.som.SimulationContextType;
27 import org.splat.dal.bo.som.Study;
28 import org.splat.dal.bo.som.Timestamp;
29 import org.splat.dal.bo.som.ValidationCycle;
30 import org.splat.dal.bo.som.ValidationStep;
31 import org.splat.dal.dao.som.Database;
32 import org.splat.kernel.NotApplicableException;
33 import org.splat.manox.Reader;
34 import org.splat.manox.Toolbox;
35 import org.splat.som.DocumentRights;
36 import org.splat.som.Revision;
37 import org.splat.som.Step;
43 public class PublicationServiceImpl implements PublicationService {
45 private StudyService _studyService;
46 private StepService _stepService;
47 private DocumentTypeService _documentTypeService;
48 private ProjectElementService _projectElementService;
50 public Publication copy(Publication aPublication, ProjectElement publisher) {
51 // -----------------------------------------------------
52 Publication copy = new Publication();
53 copy.setValue(aPublication.value());
54 copy.setStep(aPublication.getStep()); // May not be initialized yet
55 copy.setOwner(publisher);
56 copy.setIsnew(aPublication.getIsnew());
57 if (!copy.getOwnerStudy().equals(aPublication.getOwnerStudy())) {
58 copy.setIsnew('N'); // The referenced document is not new for the given study
64 * Promotes the document referenced by this publication from In-Check to Approved state, if not out-dated, and attaches the
65 * corresponding time-stamp to the document.</br> If the promoted document is the final result of the owner study, the study is itself
66 * is promoted as well.</br> </br> Limitation: the way this promotion is propagated to the study supposes that the study has only ONE
67 * final result document.
70 * the date of approval
71 * @return true if the approval succeeded
72 * @see #getProgressState()
73 * @see DocumentRights#canApprove()
74 * @see DocumentType#isStudyResult()
75 * @see Study#getApproverOf(Publication)
77 public Timestamp approve(Publication aPublication, Date adate) {
78 // -------------------------------------
79 if (aPublication.isOutdated())
81 else if (aPublication.value().getProgressState() != ProgressState.inCHECK)
82 return null; // This statement must conform to the corresponding right
84 DocumentType type = aPublication.value().getType();
85 Study owner = aPublication.getOwnerStudy();
86 ValidationCycle cycle = owner.getValidationCycleOf(type);
87 User approver = cycle.getActor(ValidationStep.APPROVAL);
88 Timestamp stamp = new Timestamp(ValidationStep.APPROVAL,
89 aPublication.value(), approver, adate);
90 if (!aPublication.value().promote(stamp))
92 if (getDocumentTypeService().isStudyResult(type)
93 && owner.getProgressState() == ProgressState.inCHECK)
94 getStudyService().promote(owner);
95 return stamp; // Hoping that promotion of the study succeeded
99 * Demotes the document referenced by this publication to In-Work state, and removes the Promoter of the document, if exist.</br> The
100 * In-Draft state is skipped (direct demotion to In-Work) if the validation cycle of the document does not include the review step.</br>
101 * If the demoted document is the final result of the owner study, the study is itself is demoted as well.</br> </br> Limitation: the
102 * way this demotion is propagated to the study supposes that the study has only ONE final result document.
104 * @return true if the demotion succeeded
105 * @see #getProgressState()
106 * @see DocumentRights#canDemote()
107 * @see DocumentType#isStudyResult()
109 public boolean demote(Publication aPublication) {
110 // ------------------------
111 DocumentType type = aPublication.value().getType();
112 Study owner = aPublication.getOwnerStudy();
114 if (aPublication.value().getProgressState() == ProgressState.inCHECK) {
115 ValidationCycle cycle = owner.getValidationCycleOf(type);
116 if (cycle.enables(ValidationStep.REVIEW)) {
117 if (!aPublication.value().demote())
120 if (!aPublication.value().demote())
122 aPublication.value().demote();
124 } else if (aPublication.value().getProgressState() == ProgressState.inDRAFT) {
125 if (!aPublication.value().demote())
130 if (getDocumentTypeService().isStudyResult(type)
131 && owner.getProgressState() != ProgressState.inWORK)
132 getStudyService().demote(owner);
137 * Undo the review operation by demoting the document referenced by this publication from In-Check to In-Draft state and removing the
138 * Reviewer.</br> If the demoted document is the final result of the owner study, the study is itself is demoted as well.</br> </br>
139 * Limitation: the way this demotion is propagated to the study supposes that the study has only ONE final result document.
141 * @return true if the demotion succeeded
142 * @see #getProgressState()
144 * @see DocumentRights#canInvalidate()
145 * @see DocumentType#isStudyResult()
147 public boolean invalidate(Publication aPublication) {
148 // ----------------------------
149 if (aPublication.value().getProgressState() != ProgressState.inCHECK)
151 if (!aPublication.value().demote()) // Removes the reviewer if this document is In-Check
153 DocumentType type = aPublication.value().getType();
154 Study owner = aPublication.getOwnerStudy();
155 if (getDocumentTypeService().isStudyResult(type)
156 && owner.getProgressState() == ProgressState.inCHECK)
157 getStudyService().demote(owner);
162 * Promotes the document referenced by this publication from In-Work to In-Draft or In-Check state, if not out-dated, and attaches the
163 * corresponding time-stamp to the document.</br> The In-Draft state is skipped (direct promotion to In-Check) if the validation cycle
164 * of the document does not include the review step.</br> Also, if the promoted document is the final result of the owner study, the
165 * study is itself promoted as well.</br> This operation can be undo-ed by demote().</br> </br> Limitation: the way this promotion is
166 * propagated to the study supposes that the study has only ONE final result document.
168 * @return true if the promotion succeeded
169 * @see #getProgressState()
171 * @see DocumentRights#canPromote()
172 * @see DocumentType#isStudyResult()
174 public Timestamp promote(Publication aPublication, Date pdate) {
175 if (aPublication.isOutdated())
177 else if (aPublication.value().getProgressState() != ProgressState.inWORK)
178 return null; // This statement must conform to the corresponding right
180 DocumentType type = aPublication.value().getType();
181 Study owner = aPublication.getOwnerStudy();
182 ValidationCycle cycle = owner.getValidationCycleOf(type);
183 User promoter = cycle.getActor(ValidationStep.PROMOTION);
184 if (promoter == null)
185 promoter = getInvolvedStep(aPublication).getActor();
186 if (promoter == null)
187 promoter = owner.getAuthor();
188 Timestamp stamp = new Timestamp(ValidationStep.PROMOTION,
189 aPublication.value(), promoter, pdate);
191 if (!aPublication.value().promote(stamp)) // Promotion to being reviewed
193 if (!cycle.enables(ValidationStep.REVIEW)) {
194 aPublication.value().promote(null);
196 if (getDocumentTypeService().isStudyResult(type)
197 && owner.getProgressState() == ProgressState.inWORK)
198 getStudyService().promote(owner);
199 return stamp; // Hoping that promotion of the study succeeded
204 * Promotes the document referenced by this publication from In-Draft to In-Check state, if not out-dated, and attaches the
205 * corresponding time-stamp to the document.</br> If the promoted document is the final result of the owner study, the study is itself
206 * is promoted as well.</br> This operation can be undo-ed by invalidate().</br> </br> Limitation: the way this promotion is propagated
207 * to the study supposes that the study has only ONE final result document.
211 * @return true if the review succeeded
212 * @see #getProgressState()
214 * @see DocumentRights#canReview()
215 * @see DocumentType#isStudyResult()
216 * @see Study#getReviewerOf(Publication)
218 public Timestamp review(Publication aPublication, Date rdate) {
219 if (aPublication.isOutdated())
221 else if (aPublication.value().getProgressState() != ProgressState.inDRAFT)
222 return null; // This statement must conform to the corresponding right
224 DocumentType type = aPublication.value().getType();
225 Study owner = aPublication.getOwnerStudy();
226 ValidationCycle cycle = owner.getValidationCycleOf(type);
227 User reviewer = cycle.getActor(ValidationStep.REVIEW);
228 Timestamp stamp = new Timestamp(ValidationStep.REVIEW,
229 aPublication.value(), reviewer, rdate);
230 if (!aPublication.value().promote(stamp))
232 if (getDocumentTypeService().isStudyResult(type)
233 && owner.getProgressState() == ProgressState.inDRAFT)
234 getStudyService().promote(owner);
235 return stamp; // Hoping that promotion of the study succeeded
239 * Publishes the document referenced by this publication into the owner Project Element under the given revision number.<br/>
240 * The state of the referenced document is supposed being automatically set according to the given revision number, but, due to the
241 * versioning scheme, as it is not possible to differentiate In-Work and In-Draft states, this function has been deprecated (it is
242 * currently used only for the need of integration of Microsoft Office which anyway has to be redesigned). <br/>
243 * Note: in the context of branch versioning, the given revision may be modified by an update of the branch name.
246 * the required revision number
247 * @throws FileNotFoundException
248 * If the referenced document is empty
249 * @throws NotApplicableException
250 * If the referenced document is undefined
253 public void saveAs(Publication aPublication, Revision newvers)
254 throws FileNotFoundException, NotApplicableException {
255 // -------------------------------------
256 if (aPublication.value().isUndefined())
257 throw new NotApplicableException(
258 "Cannot save a Publication object refering an undefined Document");
259 if (!aPublication.value().getSourceFile().exists())
260 throw new FileNotFoundException();
262 Database.getSession().save(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
263 aPublication.value().updateAs(newvers); // May change the branch name of given revision
264 updateOwner(aPublication);
268 * Publishes the document referenced by this publication into the owner Project Element under the given state, the revision number of
269 * the document being automatically set accordingly. If the given state is In-Draft and the document is final result of the owner study,
270 * this automatically promotes the study to In-Draft.
273 * the required progress state
274 * @throws FileNotFoundException
275 * If the referenced document is empty
276 * @throws NotApplicableException
277 * If the referenced document is undefined
279 public void saveAs(Publication aPublication, ProgressState state)
280 throws FileNotFoundException, NotApplicableException {
281 // ----------------------------------------
282 if (aPublication.value().isUndefined())
283 throw new NotApplicableException(
284 "Cannot save a Publication object refering an undefined Document");
285 if (!aPublication.value().getSourceFile().exists())
286 throw new FileNotFoundException();
288 if (state == ProgressState.inWORK || state == ProgressState.EXTERN) {
289 Database.getSession().save(aPublication); // Must be done before updating the study in order to fix this final (rid-based) hascode
290 aPublication.value().updateAs(state);
292 DocumentType mytype = aPublication.value().getType();
293 Study owner = aPublication.getOwnerStudy();
294 ValidationCycle cycle = owner.getValidationCycleOf(mytype);
295 boolean review = cycle.enables(ValidationStep.REVIEW);
296 if (!(state == ProgressState.inDRAFT && review)
297 && !(state == ProgressState.inCHECK && !review)) {
298 throw new NotApplicableException(
299 "Cannot save a result document in " + state.toString()
302 Database.getSession().save(aPublication); // Must be done before updating the study in order to fix this final (rid-based)
304 aPublication.value().updateAs(ProgressState.inWORK);
306 promote(aPublication, aPublication.value()
307 .getLastModificationDate()); // Promotes to the appropriate state in accordance to the validation cycle
309 updateOwner(aPublication);
312 public void updateOwner(Publication aPublication) {
313 // ---------------------------
314 Session session = Database.getSession();
315 Step step = getInvolvedStep(aPublication);
317 // Update of involved step
318 Document previous = aPublication.value().getPreviousVersion();
319 if (previous != null) {
320 Publication oldoc = step.getDocument(previous.getIndex());
321 boolean done = step.remove(oldoc); // Decrements the configuration tag count of document
323 session.delete(oldoc); // WARNING: Potential problem because it's not automatically done as orphan object
325 step.add(aPublication); // Increments the configuration tag count of document
327 // Import the document properties and update of the study
328 forwardProperties(aPublication, aPublication.value().getSourceFile()
330 session.update(aPublication.getOwner());
333 private void forwardProperties(Publication aPublication, java.io.File from,
335 // -----------------------------------------------------------
336 Reader tool = Toolbox.getReader(from);
338 return; // No properties extractor available for this type of document
340 SimulationContextType.Properties sprop = new SimulationContextType.Properties()
341 .setStep(to.getStep()).setState(ProgressState.APPROVED);
342 List<SimulationContextType> contype = SimulationContext
343 .selectTypesWhere(sprop);
344 if (contype.isEmpty())
345 return; // No approved property type configured at this step
347 SimulationContext.Properties cprop = new SimulationContext.Properties();
348 List<SimulationContext> context = to.getAllSimulationContexts();
350 context = new ArrayList<SimulationContext>(context.size());
351 context.addAll(to.getAllSimulationContexts());
352 cprop.disableCheck();
353 for (Iterator<SimulationContextType> i = contype.iterator(); i
355 SimulationContextType property = i.next();
356 for (Iterator<SimulationContext> j = context.iterator(); j
358 SimulationContext existing = j.next();
359 if (!existing.getType().equals(property))
361 property = null; // Forget this property as it is already set
364 if (property != null)
366 String value = tool.extractProperty(property.getName());
368 continue; // Property not defined into the document
370 cprop.setType(property).setValue(value);
371 if (aPublication.getOwner() instanceof Study)
372 getStudyService().addProjectContext(
373 (Study) aPublication.getOwner(), cprop); // Re-indexes knowledges and the study
375 getStepService().addSimulationContext(to, cprop); // Re-indexes knowledges only
376 } catch (Exception e) {
383 * Returns the study Step into which the document version referenced by this publication has been published.
385 public Step getInvolvedStep(Publication aPublication) {
386 if (aPublication.getStep() == null) {
387 Step[] step = getProjectElementService().getSteps(aPublication.getOwner());
388 for (int i = 0; i < step.length; i++) {
389 aPublication.setStep(step[i]); // The involved step necessarily exists
390 if (aPublication.value().isInto(aPublication.getStep()))
394 return aPublication.getStep();
400 private StepService getStepService() {
404 public void setStepService(StepService stepService) {
405 _stepService = stepService;
411 public StudyService getStudyService() {
412 return _studyService;
415 public void setStudyService(StudyService studyService) {
416 _studyService = studyService;
422 public DocumentTypeService getDocumentTypeService() {
423 return _documentTypeService;
426 public void setDocumentTypeService(DocumentTypeService documentTypeService) {
427 _documentTypeService = documentTypeService;
431 * Get the projectElementService.
432 * @return the projectElementService
434 public ProjectElementService getProjectElementService() {
435 return _projectElementService;
439 * Set the projectElementService.
440 * @param projectElementService the projectElementService to set
442 public void setProjectElementService(ProjectElementService projectElementService) {
443 _projectElementService = projectElementService;