001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 028 package org.opends.server.admin; 029 import org.opends.messages.Message; 030 031 032 033 import static org.opends.server.util.Validator.ensureNotNull; 034 035 import java.util.EnumSet; 036 import java.util.Locale; 037 import java.util.MissingResourceException; 038 import java.util.regex.Matcher; 039 import java.util.regex.Pattern; 040 import java.util.regex.PatternSyntaxException; 041 042 043 044 /** 045 * String property definition. 046 */ 047 public final class StringPropertyDefinition extends PropertyDefinition<String> { 048 049 /** 050 * An interface for incrementally constructing string property 051 * definitions. 052 */ 053 public static class Builder extends 054 AbstractBuilder<String, StringPropertyDefinition> { 055 056 // Flag indicating whether values of this property are 057 // case-insensitive. 058 private boolean isCaseInsensitive = true; 059 060 // Optional pattern which values of this property must match. 061 private Pattern pattern = null; 062 063 // Pattern usage which provides a user-friendly summary of the 064 // pattern if present. 065 private String patternUsage = null; 066 067 068 069 // Private constructor 070 private Builder(AbstractManagedObjectDefinition<?, ?> d, 071 String propertyName) { 072 super(d, propertyName); 073 } 074 075 076 077 /** 078 * Set a flag indicating whether values of this property are 079 * case-insensitive. 080 * 081 * @param value 082 * <code>true</code> if values are case-insensitive, or 083 * <code>false</code> otherwise. 084 */ 085 public final void setCaseInsensitive(boolean value) { 086 isCaseInsensitive = value; 087 } 088 089 090 091 /** 092 * Set the regular expression pattern which values of this 093 * property must match. By default there is no pattern defined. 094 * 095 * @param pattern 096 * The regular expression pattern string, or 097 * <code>null</code> if there is no pattern. 098 * @param patternUsage 099 * A user-friendly usage string representing the pattern 100 * which can be used in error messages and help (e.g. for 101 * patterns which match a host/port combination, the 102 * usage string "HOST:PORT" would be appropriate). 103 * @throws PatternSyntaxException 104 * If the provided regular expression pattern has an 105 * invalid syntax. 106 */ 107 public final void setPattern(String pattern, String patternUsage) 108 throws PatternSyntaxException { 109 if (pattern == null) { 110 this.pattern = null; 111 this.patternUsage = null; 112 } else { 113 this.pattern = Pattern.compile(pattern); 114 this.patternUsage = patternUsage; 115 } 116 } 117 118 119 120 /** 121 * {@inheritDoc} 122 */ 123 @Override 124 protected StringPropertyDefinition buildInstance( 125 AbstractManagedObjectDefinition<?, ?> d, String propertyName, 126 EnumSet<PropertyOption> options, 127 AdministratorAction adminAction, 128 DefaultBehaviorProvider<String> defaultBehavior) { 129 return new StringPropertyDefinition(d, propertyName, options, 130 adminAction, defaultBehavior, isCaseInsensitive, pattern, 131 patternUsage); 132 } 133 134 } 135 136 137 138 /** 139 * Create a string property definition builder. 140 * 141 * @param d 142 * The managed object definition associated with this 143 * property definition. 144 * @param propertyName 145 * The property name. 146 * @return Returns the new string property definition builder. 147 */ 148 public static Builder createBuilder(AbstractManagedObjectDefinition<?, ?> d, 149 String propertyName) { 150 return new Builder(d, propertyName); 151 } 152 153 // Flag indicating whether values of this property are 154 // case-insensitive. 155 private final boolean isCaseInsensitive; 156 157 // Optional pattern which values of this property must match. 158 private final Pattern pattern; 159 160 // Pattern usage which provides a user-friendly summary of the 161 // pattern if present. 162 private final String patternUsage; 163 164 165 166 // Private constructor. 167 private StringPropertyDefinition(AbstractManagedObjectDefinition<?, ?> d, 168 String propertyName, EnumSet<PropertyOption> options, 169 AdministratorAction adminAction, 170 DefaultBehaviorProvider<String> defaultBehavior, 171 boolean isCaseInsensitive, Pattern pattern, String patternUsage) { 172 super(d, String.class, propertyName, options, adminAction, 173 defaultBehavior); 174 this.isCaseInsensitive = isCaseInsensitive; 175 this.pattern = pattern; 176 this.patternUsage = patternUsage; 177 } 178 179 180 181 /** 182 * {@inheritDoc} 183 */ 184 @Override 185 public <R, P> R accept(PropertyDefinitionVisitor<R, P> v, P p) { 186 return v.visitString(this, p); 187 } 188 189 190 191 /** 192 * {@inheritDoc} 193 */ 194 @Override 195 public <R, P> R accept(PropertyValueVisitor<R, P> v, String value, P p) { 196 return v.visitString(this, value, p); 197 } 198 199 200 201 /** 202 * {@inheritDoc} 203 */ 204 @Override 205 public String decodeValue(String value) 206 throws IllegalPropertyValueStringException { 207 ensureNotNull(value); 208 209 try { 210 validateValue(value); 211 } catch (IllegalPropertyValueException e) { 212 throw new IllegalPropertyValueStringException(this, value); 213 } 214 215 return value; 216 } 217 218 219 220 /** 221 * Gets the optional regular expression pattern which values of this 222 * property must match. 223 * 224 * @return Returns the optional regular expression pattern which 225 * values of this property must match, or <code>null</code> 226 * if there is no pattern. 227 */ 228 public Pattern getPattern() { 229 return pattern; 230 } 231 232 233 234 /** 235 * Gets the pattern synopsis of this string property definition in 236 * the default locale. 237 * 238 * @return Returns the pattern synopsis of this string property 239 * definition in the default locale, or <code>null</code> 240 * if there is no pattern synopsis (which is the case when 241 * there is no pattern matching defined for this string 242 * property definition). 243 */ 244 public Message getPatternSynopsis() { 245 return getPatternSynopsis(Locale.getDefault()); 246 } 247 248 249 250 /** 251 * Gets the optional pattern synopsis of this string property 252 * definition in the specified locale. 253 * 254 * @param locale 255 * The locale. 256 * @return Returns the pattern synopsis of this string property 257 * definition in the specified locale, or <code>null</code> 258 * if there is no pattern synopsis (which is the case when 259 * there is no pattern matching defined for this string 260 * property definition). 261 */ 262 public Message getPatternSynopsis(Locale locale) { 263 ManagedObjectDefinitionI18NResource resource = 264 ManagedObjectDefinitionI18NResource.getInstance(); 265 String property = "property." + getName() 266 + ".syntax.string.pattern.synopsis"; 267 try { 268 return resource 269 .getMessage(getManagedObjectDefinition(), property, locale); 270 } catch (MissingResourceException e) { 271 return null; 272 } 273 } 274 275 276 277 /** 278 * Gets a user-friendly usage string representing the pattern which 279 * can be used in error messages and help (e.g. for patterns which 280 * match a host/port combination, the usage string "HOST:PORT" would 281 * be appropriate). 282 * 283 * @return Returns the user-friendly pattern usage string, or 284 * <code>null</code> if there is no pattern. 285 */ 286 public String getPatternUsage() { 287 return patternUsage; 288 } 289 290 291 292 /** 293 * Query whether values of this property are case-insensitive. 294 * 295 * @return Returns <code>true</code> if values are 296 * case-insensitive, or <code>false</code> otherwise. 297 */ 298 public boolean isCaseInsensitive() { 299 return isCaseInsensitive; 300 } 301 302 303 304 /** 305 * {@inheritDoc} 306 */ 307 @Override 308 public String normalizeValue(String value) 309 throws IllegalPropertyValueException { 310 ensureNotNull(value); 311 312 if (isCaseInsensitive()) { 313 return value.trim().toLowerCase(); 314 } else { 315 return value.trim(); 316 } 317 } 318 319 320 321 /** 322 * {@inheritDoc} 323 */ 324 @Override 325 public void validateValue(String value) throws IllegalPropertyValueException { 326 ensureNotNull(value); 327 328 if (pattern != null) { 329 Matcher matcher = pattern.matcher(value); 330 if (!matcher.matches()) { 331 throw new IllegalPropertyValueException(this, value); 332 } 333 } 334 } 335 }