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 }