001/* 002 * Copyright 2018 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.odfpilotage.helper; 017 018import java.time.LocalDate; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Set; 024import java.util.stream.Collectors; 025 026import org.apache.avalon.framework.component.Component; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.avalon.framework.service.Serviceable; 030import org.apache.commons.lang3.ArrayUtils; 031 032import org.ametys.cms.ObservationConstants; 033import org.ametys.cms.repository.Content; 034import org.ametys.cms.repository.ModifiableDefaultContent; 035import org.ametys.core.observation.Event; 036import org.ametys.core.observation.ObservationManager; 037import org.ametys.core.right.RightManager; 038import org.ametys.core.right.RightManager.RightResult; 039import org.ametys.core.user.CurrentUserProvider; 040import org.ametys.core.user.UserIdentity; 041import org.ametys.odf.ODFHelper; 042import org.ametys.odf.ProgramItem; 043import org.ametys.odf.program.Program; 044import org.ametys.odf.workflow.ValidateODFContentFunction; 045import org.ametys.plugins.repository.AmetysObjectResolver; 046import org.ametys.plugins.repository.data.holder.group.impl.ModifiableModelAwareComposite; 047import org.ametys.runtime.model.ModelItem; 048import org.ametys.runtime.plugin.component.AbstractLogEnabled; 049 050/** 051 * Helper for ODF pilotage status 052 */ 053public class PilotageStatusHelper extends AbstractLogEnabled implements Component, Serviceable 054{ 055 /** The component role. */ 056 public static final String ROLE = PilotageStatusHelper.class.getName(); 057 058 /** The super right for mention validation state */ 059 public static final String MENTION_VALIDATION_SUPER_RIGHT_ID = "ODF_Pilotage_Mention_Validated_Super_Rights"; 060 061 /** The super right for orgunit validation state */ 062 public static final String ORGUNIT_VALIDATION_SUPER_RIGHT_ID = "ODF_Pilotage_OrgUnit_Validated_Super_Rights"; 063 064 /** The attribute name for the pilotage composite */ 065 private static final String __PILOTAGE_COMPOSITE = "pilotage"; 066 067 /** The attribute name for the pilotage status */ 068 private static final String __PILOTAGE_STATUS = "pilotage_status"; 069 070 /** The attribute name for the date of the mention validation */ 071 private static final String __MENTION_VALIDATION_DATE = "mention_validation_date"; 072 073 /** The attribute name for the author of the mention validation */ 074 private static final String __MENTION_VALIDATION_AUTHOR = "mention_validation_author"; 075 076 /** The attribute name for the comment of the mention validation */ 077 private static final String __MENTION_VALIDATION_COMMENT = "mention_validation_comment"; 078 079 /** The attribute name for the date of the orgUnit validation */ 080 private static final String __ORGUNIT_VALIDATION_DATE = "orgunit_validation_date"; 081 082 /** The attribute name for the author of the orgUnit validation */ 083 private static final String __ORGUNIT_VALIDATION_AUTHOR = "orgunit_validation_author"; 084 085 /** The attribute name for the comment of the orgUnit validation */ 086 private static final String __ORGUNIT_VALIDATION_COMMENT = "orgunit_validation_comment"; 087 088 /** The attribute name for the date of the CFVU validation */ 089 private static final String __CFVU_VALIDATION_DATE = "cfvu_validation_date"; 090 091 /** The attribute name for the author of the CFVU validation */ 092 private static final String __CFVU_VALIDATION_AUTHOR = "cfvu_validation_author"; 093 094 /** The attribute name for the comment of the CFVU validation */ 095 private static final String __CFVU_VALIDATION_COMMENT = "cfvu_validation_comment"; 096 097 /** The attribute name for the date of the CFVU MCC validation */ 098 private static final String __CFVU_MCC_VALIDATION_DATE = "cfvu_mcc_validation_date"; 099 100 /** The attribute name for the author of the CFVU MCC validation */ 101 private static final String __CFVU_MCC_VALIDATION_AUTHOR = "cfvu_mcc_validation_author"; 102 103 /** The attribute name for the comment of the CFVU MCC validation */ 104 private static final String __CFVU_MCC_VALIDATION_COMMENT = "cfvu_mcc_validation_comment"; 105 106 /** The odf helper */ 107 protected ODFHelper _odfHelper; 108 109 /** The Ametys object resolver */ 110 protected AmetysObjectResolver _resolver; 111 112 /** The right manager */ 113 protected RightManager _rightManager; 114 115 /** The current user provider */ 116 protected CurrentUserProvider _currentUserProvider; 117 118 /** The observation manager */ 119 protected ObservationManager _observationManager; 120 121 /** 122 * Enumeration for the pilotage status 123 */ 124 public enum PilotageStatus 125 { 126 /** State 0 : No status */ 127 NONE, 128 /** State 1 : Mention validated */ 129 MENTION_VALIDATED, 130 /** State 2 : OrgUnit validated */ 131 ORGUNIT_VALIDATED, 132 /** State 3 : CFVU validated */ 133 CFVU_VALIDATED, 134 /** State 4 : CFVU MCC validated */ 135 CFVU_MCC_VALIDATED 136 } 137 138 @Override 139 public void service(ServiceManager manager) throws ServiceException 140 { 141 _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE); 142 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 143 _rightManager = (RightManager) manager.lookup(RightManager.ROLE); 144 _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE); 145 _observationManager = (ObservationManager) manager.lookup(ObservationManager.ROLE); 146 } 147 148 /** 149 * Get all program parent from the program item 150 * @param programItem the program item 151 * @return the set of program parent 152 */ 153 public Set<Program> getParentPrograms(ProgramItem programItem) 154 { 155 Set<Program> parentPrograms = new HashSet<>(); 156 if (programItem instanceof Program) 157 { 158 parentPrograms.add((Program) programItem); 159 return parentPrograms; 160 } 161 162 List<ProgramItem> parents = _odfHelper.getParentProgramItems(programItem); 163 for (ProgramItem parent : parents) 164 { 165 if (parent instanceof Program) 166 { 167 parentPrograms.add((Program) parent); 168 } 169 else 170 { 171 parentPrograms.addAll(getParentPrograms(parent)); 172 } 173 } 174 175 return parentPrograms; 176 } 177 178 /** 179 * Get all program parent with a pilotage status from the program item 180 * @param programItem the program item 181 * @return the set of program parent 182 */ 183 public Set<Program> getParentProgramsWithPilotageStatus(ProgramItem programItem) 184 { 185 Set<Program> parentPrograms = new HashSet<>(); 186 for (Program parent : getParentPrograms(programItem)) 187 { 188 PilotageStatus pilotageStatus = getPilotageStatus(parent); 189 if (!pilotageStatus.equals(PilotageStatus.NONE)) 190 { 191 parentPrograms.add(parent); 192 } 193 } 194 195 return parentPrograms; 196 } 197 198 /** 199 * Return true if the current user has the edit super right depend on the pilotage status of the program 200 * @param program the program 201 * @return true if the user has the super right 202 */ 203 public boolean hasEditSuperRight(Program program) 204 { 205 PilotageStatus pilotageStatus = getPilotageStatus(program); 206 207 UserIdentity user = _currentUserProvider.getUser(); 208 switch (pilotageStatus) 209 { 210 case NONE: 211 return true; 212 case MENTION_VALIDATED: 213 return _rightManager.hasRight(user, MENTION_VALIDATION_SUPER_RIGHT_ID, program).equals(RightResult.RIGHT_ALLOW); 214 case ORGUNIT_VALIDATED: 215 return _rightManager.hasRight(user, ORGUNIT_VALIDATION_SUPER_RIGHT_ID, program).equals(RightResult.RIGHT_ALLOW); 216 case CFVU_MCC_VALIDATED: 217 case CFVU_VALIDATED: 218 default: 219 return false; 220 } 221 } 222 223 /** 224 * Compare two programs depends on their pilotage status 225 * Pilotage status order : NONE lower than MENTION_VALIDATED lower than ORGUNIT_VALIDATED lower than CFVU_VALIDATED lower than CFVU_VALIDATED lower than CFVU_MCC_VALIDATED 226 * -1 if pilotage status of program 1 is lower than pilotage status of program 2 227 * 0 if they have the same pilotage status 228 * 1 if pilotage status of program 1 is higher than pilotage status of program 2 229 * -2 if we don't know 230 * @param program1 program 1 231 * @param program2 progam 2 232 * @return the int compare number 233 */ 234 public int comparePilotageStatus(Program program1, Program program2) 235 { 236 PilotageStatus pilotageStatus1 = getPilotageStatus(program1); 237 PilotageStatus pilotageStatus2 = getPilotageStatus(program2); 238 239 switch (pilotageStatus1) 240 { 241 case NONE: 242 return PilotageStatus.NONE.equals(pilotageStatus2) ? 0 : 1; 243 case MENTION_VALIDATED: 244 if (PilotageStatus.NONE.equals(pilotageStatus2)) 245 { 246 return -1; 247 } 248 else 249 { 250 return PilotageStatus.MENTION_VALIDATED.equals(pilotageStatus2) ? 0 : 1; 251 } 252 case ORGUNIT_VALIDATED: 253 if (PilotageStatus.NONE.equals(pilotageStatus2) || PilotageStatus.MENTION_VALIDATED.equals(pilotageStatus2)) 254 { 255 return -1; 256 } 257 else 258 { 259 return PilotageStatus.ORGUNIT_VALIDATED.equals(pilotageStatus2) ? 0 : 1; 260 } 261 case CFVU_VALIDATED: 262 if (PilotageStatus.CFVU_MCC_VALIDATED.equals(pilotageStatus2)) 263 { 264 return 1; 265 } 266 else 267 { 268 return PilotageStatus.CFVU_VALIDATED.equals(pilotageStatus2) ? 0 : -1; 269 } 270 case CFVU_MCC_VALIDATED: 271 return PilotageStatus.CFVU_MCC_VALIDATED.equals(pilotageStatus2) ? 0 : -1; 272 default: 273 break; 274 } 275 276 return -2; 277 } 278 279 /** 280 * Get parent program or it self from program item with the higher pilotage status. 281 * Program with pilotage status NONE are ignored, so can be null if there are no program with active pilotage status. 282 * @param programItem the program item 283 * @return the program parent 284 */ 285 public Program getParentProgramWithHigherPilotageStatus(ProgramItem programItem) 286 { 287 Set<Program> parentProgramsWithPilotageStatus = getParentProgramsWithPilotageStatus(programItem); 288 Program parentProgram = null; 289 for (Program program : parentProgramsWithPilotageStatus) 290 { 291 if (parentProgram == null || comparePilotageStatus(parentProgram, program) == 1) 292 { 293 parentProgram = program; 294 } 295 } 296 297 return parentProgram; 298 } 299 300 /** 301 * Get the pilotage information status for a client side element. 302 * The button is enabled if the pilotage status of root programs is NONE or if the current user has super edit right on root program of higher status 303 * @param contentId the content id 304 * @return the pilotage information 305 */ 306 public Map<String, Object> getPilotageButtonInfo(String contentId) 307 { 308 Map<String, Object> contentParams = new HashMap<>(); 309 Content content = _resolver.resolveById(contentId); 310 if (content instanceof ProgramItem) 311 { 312 ProgramItem programItem = (ProgramItem) content; 313 314 // Get parent program (or itself) with the higher pilotage status (program with no pilotage status are ignored) 315 Program parentProgramWithHigherPilotageStatus = getParentProgramWithHigherPilotageStatus(programItem); 316 boolean noParentProgramWithActivePilotageStatus = parentProgramWithHigherPilotageStatus == null; 317 318 contentParams.put("isEnabled", noParentProgramWithActivePilotageStatus || hasEditSuperRight(parentProgramWithHigherPilotageStatus)); 319 320 if (!noParentProgramWithActivePilotageStatus) 321 { 322 // Get parent programs (or itself) which have an active pilotage status (!= NONE) 323 Set<Program> parentPrograms = getParentProgramsWithPilotageStatus(programItem); 324 List<String> programTitles = parentPrograms.stream() 325 .map(p -> p.getTitle()) 326 .collect(Collectors.toList()); 327 328 contentParams.put("programTitles", programTitles); 329 } 330 } 331 else 332 { 333 contentParams.put("isEnabled", true); 334 } 335 336 return contentParams; 337 } 338 339 /** 340 * Get the pilotage status of the content 341 * @param content the content 342 * @return the pilotage status 343 */ 344 public PilotageStatus getPilotageStatus(Content content) 345 { 346 String pilotageStatusDataPath = __PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __PILOTAGE_STATUS; 347 String status = content.getValue(pilotageStatusDataPath, false, PilotageStatus.NONE.name()); 348 return PilotageStatus.valueOf(status); 349 } 350 351 /** 352 * Send a notification with the content modified event. 353 * @param content The content to notify on 354 */ 355 protected void _notifyPilotageWorkflowModification(Content content) 356 { 357 Map<String, Object> eventParams = new HashMap<>(); 358 eventParams.put(ObservationConstants.ARGS_CONTENT, content); 359 eventParams.put(ObservationConstants.ARGS_CONTENT_ID, content.getId()); 360 _observationManager.notify(new Event(ObservationConstants.EVENT_CONTENT_MODIFIED, _currentUserProvider.getUser(), eventParams)); 361 } 362 363 /** 364 * Set the validation attribute (date, login, comment) to the content 365 * @param content the content 366 * @param validationDate the validation date 367 * @param user the user 368 * @param comment the comment 369 * @param status the pilotage status 370 */ 371 public void setValidationAttribute(ModifiableDefaultContent content, LocalDate validationDate, UserIdentity user, String comment, PilotageStatus status) 372 { 373 boolean hasChanges = false; 374 switch (status) 375 { 376 case NONE : 377 // Do nothing 378 break; 379 case MENTION_VALIDATED : 380 hasChanges = setMentionValidationAttribute(content, validationDate, user, comment); 381 break; 382 case ORGUNIT_VALIDATED : 383 hasChanges = setOrgUnitValidationAttribute(content, validationDate, user, comment); 384 break; 385 case CFVU_VALIDATED : 386 hasChanges = setCFVUValidationAttribute(content, validationDate, user, comment); 387 break; 388 case CFVU_MCC_VALIDATED : 389 hasChanges = setCFVUMCCValidationAttribute(content, validationDate, user, comment); 390 break; 391 default : 392 getLogger().error("{} is an unknown pilotage status", status); 393 } 394 395 if (hasChanges) 396 { 397 _notifyPilotageWorkflowModification(content); 398 } 399 } 400 401 /** 402 * Remove the validation attribute from the content 403 * @param content the content 404 * @param status the pilotage status 405 */ 406 public void removePilotageStatus(ModifiableDefaultContent content, PilotageStatus status) 407 { 408 boolean hasChanges = false; 409 switch (status) 410 { 411 case NONE : 412 // Do nothing 413 break; 414 case MENTION_VALIDATED : 415 hasChanges = removeMentionValidationAttribute(content); 416 break; 417 case ORGUNIT_VALIDATED : 418 hasChanges = removeOrgUnitValidationAttribute(content); 419 break; 420 case CFVU_VALIDATED : 421 hasChanges = removeCFVUValidationAttribute(content); 422 break; 423 case CFVU_MCC_VALIDATED : 424 hasChanges = removeCFVUMCCValidationAttribute(content); 425 break; 426 default : 427 getLogger().error("{} is an unknown pilotage status", status); 428 } 429 430 if (hasChanges) 431 { 432 _notifyPilotageWorkflowModification(content); 433 } 434 } 435 436 /** 437 * Set the validation attribute for 'mention validated' state 438 * @param content the content 439 * @param validationDate the validation date 440 * @param user the user 441 * @param comment the comment 442 * @return <code>true</code> if the content has changed. 443 */ 444 public boolean setMentionValidationAttribute(ModifiableDefaultContent content, LocalDate validationDate, UserIdentity user, String comment) 445 { 446 ModifiableModelAwareComposite composite = content.getComposite(__PILOTAGE_COMPOSITE, true); 447 composite.setValue(__MENTION_VALIDATION_DATE, validationDate); 448 composite.setValue(__MENTION_VALIDATION_AUTHOR, user); 449 composite.setValue(__MENTION_VALIDATION_COMMENT, comment); 450 451 composite.setValue(__PILOTAGE_STATUS, PilotageStatus.MENTION_VALIDATED.name()); 452 453 return saveContent(content); 454 } 455 456 457 /** 458 * Remove validation attribute for 'mention validated' state 459 * @param content the content 460 * @return <code>true</code> if the content has changed. 461 */ 462 public boolean removeMentionValidationAttribute(ModifiableDefaultContent content) 463 { 464 // Remove the first step 465 return removePilotageWorkflow(content); 466 } 467 468 /** 469 * Set the validation attribute for 'orgunit validated' state 470 * @param content the content 471 * @param validationDate the validation date 472 * @param user the user 473 * @param comment the comment 474 * @return <code>true</code> if the content has changed. 475 */ 476 public boolean setOrgUnitValidationAttribute(ModifiableDefaultContent content, LocalDate validationDate, UserIdentity user, String comment) 477 { 478 ModifiableModelAwareComposite composite = content.getComposite(__PILOTAGE_COMPOSITE, true); 479 composite.setValue(__ORGUNIT_VALIDATION_DATE, validationDate); 480 composite.setValue(__ORGUNIT_VALIDATION_AUTHOR, user); 481 composite.setValue(__ORGUNIT_VALIDATION_COMMENT, comment); 482 483 composite.setValue(__PILOTAGE_STATUS, PilotageStatus.ORGUNIT_VALIDATED.name()); 484 485 return saveContent(content); 486 } 487 488 /** 489 * Remove validation attribute for 'orgunit validated' state 490 * @param content the content 491 * @return <code>true</code> if the content has changed. 492 */ 493 public boolean removeOrgUnitValidationAttribute(ModifiableDefaultContent content) 494 { 495 ModifiableModelAwareComposite compositeMetadata = content.getComposite(__PILOTAGE_COMPOSITE, true); 496 compositeMetadata.removeValue(__ORGUNIT_VALIDATION_DATE); 497 compositeMetadata.removeValue(__ORGUNIT_VALIDATION_AUTHOR); 498 compositeMetadata.removeValue(__ORGUNIT_VALIDATION_COMMENT); 499 500 compositeMetadata.setValue(__PILOTAGE_STATUS, PilotageStatus.MENTION_VALIDATED.name()); 501 502 return saveContent(content); 503 } 504 505 /** 506 * Set the validation attribute for 'CFVU validated' state 507 * @param content the content 508 * @param validationDate the validation date 509 * @param user the login 510 * @param comment the comment 511 * @return <code>true</code> if the content has changed. 512 */ 513 public boolean setCFVUValidationAttribute(ModifiableDefaultContent content, LocalDate validationDate, UserIdentity user, String comment) 514 { 515 ModifiableModelAwareComposite composite = content.getComposite(__PILOTAGE_COMPOSITE, true); 516 composite.setValue(__CFVU_VALIDATION_DATE, validationDate); 517 composite.setValue(__CFVU_VALIDATION_AUTHOR, user); 518 composite.setValue(__CFVU_VALIDATION_COMMENT, comment); 519 520 composite.setValue(__PILOTAGE_STATUS, PilotageStatus.CFVU_VALIDATED.name()); 521 522 return saveContent(content); 523 } 524 525 /** 526 * Remove validation attribute for 'CFVU validated' state 527 * @param content the content 528 * @return <code>true</code> if the content has changed. 529 */ 530 public boolean removeCFVUValidationAttribute(ModifiableDefaultContent content) 531 { 532 ModifiableModelAwareComposite composite = content.getComposite(__PILOTAGE_COMPOSITE, true); 533 composite.removeValue(__CFVU_VALIDATION_DATE); 534 composite.removeValue(__CFVU_VALIDATION_AUTHOR); 535 composite.removeValue(__CFVU_VALIDATION_COMMENT); 536 537 composite.setValue(__PILOTAGE_STATUS, PilotageStatus.ORGUNIT_VALIDATED.name()); 538 539 return saveContent(content); 540 } 541 542 /** 543 * Set the validation attribute for 'CFVU MCC validated' state 544 * @param content the content 545 * @param validationDate the validation date 546 * @param user the user 547 * @param comment the comment 548 * @return <code>true</code> if the content has changed. 549 */ 550 public boolean setCFVUMCCValidationAttribute(ModifiableDefaultContent content, LocalDate validationDate, UserIdentity user, String comment) 551 { 552 ModifiableModelAwareComposite composite = content.getComposite(__PILOTAGE_COMPOSITE, true); 553 composite.setValue(__CFVU_MCC_VALIDATION_DATE, validationDate); 554 composite.setValue(__CFVU_MCC_VALIDATION_AUTHOR, user); 555 composite.setValue(__CFVU_MCC_VALIDATION_COMMENT, comment); 556 557 composite.setValue(__PILOTAGE_STATUS, PilotageStatus.CFVU_MCC_VALIDATED.name()); 558 559 return saveContent(content); 560 } 561 562 /** 563 * Remove validation attribute for 'CFVU MCC validated' state 564 * @param content the content 565 * @return <code>true</code> if the content has changed. 566 */ 567 public boolean removeCFVUMCCValidationAttribute(ModifiableDefaultContent content) 568 { 569 ModifiableModelAwareComposite composite = content.getComposite(__PILOTAGE_COMPOSITE, true); 570 composite.removeValue(__CFVU_MCC_VALIDATION_DATE); 571 composite.removeValue(__CFVU_MCC_VALIDATION_AUTHOR); 572 composite.removeValue(__CFVU_MCC_VALIDATION_COMMENT); 573 574 composite.setValue(__PILOTAGE_STATUS, PilotageStatus.CFVU_VALIDATED.name()); 575 576 return saveContent(content); 577 } 578 579 /** 580 * Get mention validation date 581 * @param content the content 582 * @return the validation date 583 */ 584 public LocalDate getMentionValidationDate(Content content) 585 { 586 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __MENTION_VALIDATION_DATE); 587 } 588 589 /** 590 * Get mention validation comment 591 * @param content the content 592 * @return the validation comment 593 */ 594 public String getMentionValidationComment(Content content) 595 { 596 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __MENTION_VALIDATION_COMMENT); 597 } 598 599 /** 600 * Get mention validation author 601 * @param content the content 602 * @return the validation author 603 */ 604 public UserIdentity getMentionValidationAuthor(Content content) 605 { 606 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __MENTION_VALIDATION_AUTHOR); 607 } 608 609 /** 610 * Get orgUnit validation date 611 * @param content the content 612 * @return the validation date 613 */ 614 public LocalDate getOrgUnitValidationDate(Content content) 615 { 616 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __ORGUNIT_VALIDATION_DATE); 617 } 618 619 /** 620 * Get orgUnit validation comment 621 * @param content the content 622 * @return the validation comment 623 */ 624 public String getOrgUnitValidationComment(Content content) 625 { 626 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __ORGUNIT_VALIDATION_COMMENT); 627 } 628 629 /** 630 * Get orgUnit validation author 631 * @param content the content 632 * @return the validation author 633 */ 634 public UserIdentity getOrgUnitValidationAuthor(Content content) 635 { 636 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __ORGUNIT_VALIDATION_AUTHOR); 637 } 638 639 /** 640 * Get CFVU validation date 641 * @param content the content 642 * @return the validation date 643 */ 644 public LocalDate getCFVUValidationDate(Content content) 645 { 646 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __CFVU_VALIDATION_DATE); 647 } 648 649 /** 650 * Get CFVU validation comment 651 * @param content the content 652 * @return the validation comment 653 */ 654 public String getCFVUValidationComment(Content content) 655 { 656 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __CFVU_VALIDATION_COMMENT); 657 } 658 659 /** 660 * Get CFVU validation author 661 * @param content the content 662 * @return the validation author 663 */ 664 public UserIdentity getCFVUValidationAuthor(Content content) 665 { 666 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __CFVU_VALIDATION_AUTHOR); 667 } 668 669 /** 670 * Get CFVU MMC validation date 671 * @param content the content 672 * @return the validation date 673 */ 674 public LocalDate getCFVUMCCValidationDate(Content content) 675 { 676 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __CFVU_MCC_VALIDATION_DATE); 677 } 678 679 /** 680 * Get CFVU MCC validation comment 681 * @param content the content 682 * @return the validation comment 683 */ 684 public String getCFVUMCCValidationComment(Content content) 685 { 686 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __CFVU_MCC_VALIDATION_COMMENT); 687 } 688 689 /** 690 * Get CFVU MCC validation author 691 * @param content the content 692 * @return the validation author 693 */ 694 public UserIdentity getCFVUMCCValidationAuthor(Content content) 695 { 696 return content.getValue(__PILOTAGE_COMPOSITE + ModelItem.ITEM_PATH_SEPARATOR + __CFVU_MCC_VALIDATION_AUTHOR); 697 } 698 699 /** 700 * Remove the pilotage workflow metadata. 701 * @param content The content to clean 702 * @return <code>true</code> if the content has changed 703 */ 704 public boolean removePilotageWorkflow(ModifiableDefaultContent content) 705 { 706 if (content.hasValue(__PILOTAGE_COMPOSITE)) 707 { 708 content.removeValue(__PILOTAGE_COMPOSITE); 709 return saveContent(content); 710 } 711 712 return false; 713 } 714 715 /** 716 * Save the content if needed, add a version (checkpoint) and move the Live label if the last version was validated. 717 * @param content The content to save 718 * @return <code>true</code> if the content has changed 719 */ 720 protected boolean saveContent(ModifiableDefaultContent content) 721 { 722 if (content.needsSave()) 723 { 724 boolean currentVersionIsLive = ArrayUtils.contains(content.getLabels(), ValidateODFContentFunction.VALID_LABEL); 725 726 content.saveChanges(); 727 content.checkpoint(); 728 729 // Move the Live label if the last version was validated. 730 if (currentVersionIsLive) 731 { 732 content.addLabel(ValidateODFContentFunction.VALID_LABEL, true); 733 } 734 735 return true; 736 } 737 738 return false; 739 } 740}