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