001/* 002 * Copyright 2010 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.cms.workflow; 017 018import java.time.ZonedDateTime; 019import java.util.HashMap; 020import java.util.Map; 021import java.util.Optional; 022 023import javax.jcr.RepositoryException; 024 025import org.ametys.cms.CmsConstants; 026import org.ametys.cms.ObservationConstants; 027import org.ametys.cms.repository.Content; 028import org.ametys.cms.repository.ModifiableWorkflowAwareContent; 029import org.ametys.cms.repository.WorkflowAwareContent; 030import org.ametys.core.observation.Event; 031import org.ametys.core.user.UserIdentity; 032import org.ametys.plugins.repository.AmetysRepositoryException; 033import org.ametys.runtime.i18n.I18nizableText; 034 035import com.opensymphony.module.propertyset.PropertySet; 036import com.opensymphony.workflow.WorkflowException; 037 038/** 039 * OSWorkflow function for validating a content. 040 */ 041public class ValidateContentFunction extends AbstractContentFunction 042{ 043 /** Context parameter for major validation */ 044 public static final String IS_MAJOR = "validation.major"; 045 046 @Override 047 public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException 048 { 049 _logger.info("Performing content validation"); 050 051 WorkflowAwareContent content = getContent(transientVars); 052 053 if (!(content instanceof ModifiableWorkflowAwareContent)) 054 { 055 throw new IllegalArgumentException("The provided content " + content.getId() + " is not a ModifiableWorkflowAwareContent."); 056 } 057 058 ModifiableWorkflowAwareContent modifiableContent = (ModifiableWorkflowAwareContent) content; 059 060 try 061 { 062 // Set the validation metadata. 063 _validateContent(modifiableContent, transientVars, args); 064 // Set the current step ID. 065 _setCurrentStepIdAndNotify(modifiableContent, transientVars); 066 // Create a new version. 067 _createVersion(modifiableContent); 068 // Add the live label on the newly created version. 069 _addLabel(modifiableContent, CmsConstants.LIVE_LABEL); 070 } 071 catch (RepositoryException e) 072 { 073 throw new WorkflowException("Unable to link the workflow to the content", e); 074 } 075 catch (AmetysRepositoryException e) 076 { 077 throw new WorkflowException("Unable to validate the content", e); 078 } 079 080 _notifyObservers(transientVars, modifiableContent); 081 } 082 083 /** 084 * Notify observers of content validation 085 * @param transientVars The transient variables 086 * @param content The created content 087 * @throws AmetysRepositoryException If an error occurred with the repository 088 * @throws WorkflowException If an error occurred with the workflow 089 */ 090 protected void _notifyObservers (Map transientVars, Content content) throws AmetysRepositoryException, WorkflowException 091 { 092 Map<String, Object> eventParams = new HashMap<>(); 093 eventParams.put(ObservationConstants.ARGS_CONTENT, content); 094 eventParams.put(ObservationConstants.ARGS_CONTENT_ID, content.getId()); 095 _observationManager.notify(new Event(ObservationConstants.EVENT_CONTENT_VALIDATED, getUser(transientVars), eventParams)); 096 } 097 098 /** 099 * Validates the content: set the validation metadata. 100 * @param content the content. 101 * @param transientVars the transient vars 102 * @param args the arguments 103 * @throws WorkflowException if an error occurs. 104 * @throws RepositoryException if an error occurs. 105 */ 106 protected void _validateContent(ModifiableWorkflowAwareContent content, Map transientVars, Map args) throws WorkflowException, RepositoryException 107 { 108 UserIdentity user = getUser(transientVars); 109 110 ZonedDateTime validationDate = ZonedDateTime.now(); 111 112 // Last major validation 113 boolean isMajor = _isMajorValidation(getContextParameters(transientVars), args); 114 if (isMajor) 115 { 116 if (user != null) 117 { 118 content.setLastMajorValidator(user); 119 } 120 content.setLastMajorValidationDate(validationDate); 121 } 122 123 // Last validation 124 if (user != null) 125 { 126 content.setLastValidator(user); 127 } 128 content.setLastValidationDate(validationDate); 129 130 // First validation 131 if (content.getFirstValidationDate() == null) 132 { 133 if (user != null) 134 { 135 content.setFirstValidator(user); 136 } 137 content.setFirstValidationDate(validationDate); 138 } 139 140 // Remove the proposal date. 141 content.setProposalDate(null); 142 143 content.saveChanges(); 144 } 145 146 /** 147 * Search into context parameters and arguments if major information is filled, if not default value is <code>true</code>. 148 * @param contextParameters the context parameters 149 * @param args the arguments 150 * @return <code>true</code> if the current validation is a major validation. 151 */ 152 protected boolean _isMajorValidation(Map<String, Object> contextParameters, Map args) 153 { 154 return Optional.of(contextParameters) 155 .map(params -> contextParameters.get(IS_MAJOR)) 156 .map(Boolean.class::cast) 157 .orElseGet(() -> !"false".equals(args.get("major"))); 158 } 159 160 @Override 161 public FunctionType getFunctionExecType() 162 { 163 return FunctionType.POST; 164 } 165 166 @Override 167 public I18nizableText getLabel() 168 { 169 return new I18nizableText("plugin.cms", "PLUGINS_CMS_VALIDATE_CONTENT_FUNCTION_LABEL"); 170 } 171}