001/* 002 * Copyright 2012 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.runtime.parameter; 017 018import java.util.HashMap; 019import java.util.Map; 020import java.util.regex.Pattern; 021 022import org.apache.avalon.framework.configuration.Configurable; 023import org.apache.avalon.framework.configuration.Configuration; 024import org.apache.avalon.framework.configuration.ConfigurationException; 025import org.apache.avalon.framework.logger.AbstractLogEnabled; 026import org.apache.avalon.framework.service.ServiceException; 027import org.apache.avalon.framework.service.ServiceManager; 028import org.apache.avalon.framework.service.Serviceable; 029import org.apache.cocoon.util.log.SLF4JLoggerAdapter; 030import org.slf4j.LoggerFactory; 031 032import org.ametys.runtime.i18n.I18nizableText; 033import org.ametys.runtime.plugin.component.PluginAware; 034 035 036/** 037 * This default implementation validates the following configurable stuff: 038 * <ul> 039 * <li>mandatory: check the parameter is set</li> 040 * <li>regexp: check the string parameter matches a regexp</li> 041 * </ul> 042 */ 043public class DefaultValidator extends AbstractLogEnabled implements Validator, Configurable, PluginAware, Serviceable 044{ 045 /** Is the value mandatory ? */ 046 protected boolean _isMandatory; 047 /** Does the value need to match a regexp */ 048 protected Pattern _regexp; 049 /** The error text to display if regexp fails */ 050 protected I18nizableText _invalidText; 051 /** The plugin name */ 052 protected String _pluginName; 053 054 /** The service manager */ 055 protected ServiceManager _smanager; 056 057 /** 058 * Default constructor for avalon 059 */ 060 public DefaultValidator() 061 { 062 // empty 063 } 064 065 /** 066 * Manual constructor 067 * @param regexp The regexp to check or null 068 * @param mandatory Is the value mandatory 069 */ 070 public DefaultValidator(String regexp, boolean mandatory) 071 { 072 _isMandatory = mandatory; 073 if (regexp != null) 074 { 075 _regexp = Pattern.compile(regexp); 076 } 077 enableLogging(new SLF4JLoggerAdapter(LoggerFactory.getLogger(this.getClass()))); 078 } 079 080 /** 081 * Manual constructor 082 * @param regexp The regexp to check or null 083 * @param invalidText The error text to display 084 * @param mandatory Is the value mandatory 085 */ 086 public DefaultValidator(String regexp, I18nizableText invalidText, boolean mandatory) 087 { 088 _isMandatory = mandatory; 089 if (regexp != null) 090 { 091 _regexp = Pattern.compile(regexp); 092 } 093 _invalidText = invalidText; 094 095 enableLogging(new SLF4JLoggerAdapter(LoggerFactory.getLogger(this.getClass()))); 096 } 097 098 @Override 099 public void service(ServiceManager smanager) throws ServiceException 100 { 101 _smanager = smanager; 102 } 103 104 @Override 105 public void setPluginInfo(String pluginName, String featureName, String id) 106 { 107 _pluginName = pluginName; 108 } 109 110 @Override 111 public void configure(Configuration configuration) throws ConfigurationException 112 { 113 Configuration validatorConfig = configuration.getChild("validation"); 114 115 _isMandatory = validatorConfig.getChild("mandatory", false) != null; 116 117 String regexp = validatorConfig.getChild("regexp").getValue(null); 118 if (regexp != null) 119 { 120 _regexp = Pattern.compile(regexp); 121 } 122 123 Configuration textConfig = validatorConfig.getChild("invalidText", false); 124 if (textConfig != null) 125 { 126 _invalidText = I18nizableText.parseI18nizableText(textConfig, "plugin." + _pluginName); 127 } 128 } 129 130 @Override 131 public Map<String, Object> getConfiguration() 132 { 133 Map<String, Object> configuration = new HashMap<>(); 134 135 configuration.put("mandatory", Boolean.valueOf(_isMandatory)); 136 137 if (_regexp != null) 138 { 139 configuration.put("regexp", _regexp); 140 } 141 142 if (_invalidText != null) 143 { 144 configuration.put("invalidText", _invalidText); 145 } 146 147 return configuration; 148 } 149 150 @Override 151 public void validate(Object value, Errors errors) 152 { 153 boolean isArray = value != null && value.getClass().isArray(); 154 if (isArray) 155 { 156 validateArrayValues((Object[]) value, errors); 157 } 158 else 159 { 160 validateSingleValue (value, errors); 161 } 162 } 163 164 /** 165 * Validates a single value. 166 * @param value the value to validate (can be <code>null</code>). 167 * @param errors the structure to populate if the validation failed. 168 */ 169 protected void validateSingleValue (Object value, Errors errors) 170 { 171 if (_isMandatory && (value == null || value.toString().length() == 0)) 172 { 173 if (getLogger().isDebugEnabled()) 174 { 175 getLogger().debug("The validator refused a missing or empty value for a mandatory parameter"); 176 } 177 178 errors.addError(new I18nizableText("plugin.core-ui", "PLUGINS_CORE_UI_DEFAULT_VALIDATOR_MANDATORY")); 179 } 180 181 if (_regexp != null && value != null && value.toString().length() != 0 && !_regexp.matcher(value.toString()).matches()) 182 { 183 if (getLogger().isDebugEnabled()) 184 { 185 getLogger().debug("The validator refused a value for a parameter that should respect a regexep"); 186 } 187 188 errors.addError(new I18nizableText("plugin.core-ui", "PLUGINS_CORE_UI_DEFAULT_VALIDATOR_PATTERN_FAILED")); 189 } 190 } 191 192 /** 193 * Validates a array of values. 194 * @param values the values to validate 195 * @param errors the structure to populate if the validation failed. 196 */ 197 protected void validateArrayValues (Object[] values, Errors errors) 198 { 199 if (_isMandatory && (values == null || values.length == 0)) 200 { 201 if (getLogger().isDebugEnabled()) 202 { 203 getLogger().debug("The validator refused a missing or empty value for a mandatory parameter"); 204 } 205 206 errors.addError(new I18nizableText("plugin.core-ui", "PLUGINS_CORE_UI_DEFAULT_VALIDATOR_MANDATORY")); 207 } 208 209 if (_regexp != null && values != null && !_matchRegexp(values)) 210 { 211 if (getLogger().isDebugEnabled()) 212 { 213 getLogger().debug("The validator refused a value for a parameter that should respect a regexep"); 214 } 215 216 errors.addError(new I18nizableText("plugin.core-ui", "PLUGINS_CORE_UI_DEFAULT_VALIDATOR_PATTERN_FAILED")); 217 } 218 } 219 220 private boolean _matchRegexp (Object[] values) 221 { 222 for (Object value : values) 223 { 224 if (!_regexp.matcher(value.toString()).matches()) 225 { 226 return false; 227 } 228 } 229 return true; 230 } 231 232 @Override 233 public int hashCode() 234 { 235 final int prime = 31; 236 int result = 1; 237 result = prime * result + ((_invalidText == null) ? 0 : _invalidText.hashCode()); 238 result = prime * result + (_isMandatory ? 1231 : 1237); 239 result = prime * result + ((_pluginName == null) ? 0 : _pluginName.hashCode()); 240 result = prime * result + ((_regexp == null) ? 0 : _regexp.hashCode()); 241 result = prime * result + ((_smanager == null) ? 0 : _smanager.hashCode()); 242 return result; 243 } 244 245 @Override 246 public boolean equals(Object obj) 247 { 248 // Generated method but modified to correctly compare patterns 249 if (this == obj) 250 { 251 return true; 252 } 253 if (obj == null) 254 { 255 return false; 256 } 257 if (getClass() != obj.getClass()) 258 { 259 return false; 260 } 261 DefaultValidator other = (DefaultValidator) obj; 262 if (_invalidText == null) 263 { 264 if (other._invalidText != null) 265 { 266 return false; 267 } 268 } 269 else if (!_invalidText.equals(other._invalidText)) 270 { 271 return false; 272 } 273 if (_isMandatory != other._isMandatory) 274 { 275 return false; 276 } 277 if (_regexp == null) 278 { 279 if (other._regexp != null) 280 { 281 return false; 282 } 283 } 284 // Beginning of the modification 285 else if (other._regexp == null) 286 { 287 return false; 288 } 289 else if (!_regexp.pattern().equals(other._regexp.pattern())) 290 { 291 return false; 292 } 293 // End of the modification 294 return true; 295 } 296}