001 /*
002 * Copyright 2008-2014 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2014 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.util.args;
022
023
024
025 import java.util.ArrayList;
026 import java.util.Arrays;
027 import java.util.Collections;
028 import java.util.Iterator;
029 import java.util.List;
030
031 import com.unboundid.ldap.sdk.Filter;
032 import com.unboundid.ldap.sdk.LDAPException;
033 import com.unboundid.util.Mutable;
034 import com.unboundid.util.ThreadSafety;
035 import com.unboundid.util.ThreadSafetyLevel;
036
037 import static com.unboundid.util.Debug.*;
038 import static com.unboundid.util.args.ArgsMessages.*;
039
040
041
042 /**
043 * This class defines an argument that is intended to hold one or more
044 * search filter values. Filter arguments must take values, and those values
045 * must be able to be parsed as LDAP search filters.
046 */
047 @Mutable()
048 @ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE)
049 public final class FilterArgument
050 extends Argument
051 {
052 /**
053 * The serial version UID for this serializable class.
054 */
055 private static final long serialVersionUID = -1889200072476038957L;
056
057
058
059 // The set of values assigned to this argument.
060 private final ArrayList<Filter> values;
061
062 // The list of default values for this argument.
063 private final List<Filter> defaultValues;
064
065
066
067 /**
068 * Creates a new filter argument with the provided information. It will not
069 * have a default value.
070 *
071 * @param shortIdentifier The short identifier for this argument. It may
072 * not be {@code null} if the long identifier is
073 * {@code null}.
074 * @param longIdentifier The long identifier for this argument. It may
075 * not be {@code null} if the short identifier is
076 * {@code null}.
077 * @param isRequired Indicates whether this argument is required to
078 * be provided.
079 * @param maxOccurrences The maximum number of times this argument may be
080 * provided on the command line. A value less than
081 * or equal to zero indicates that it may be present
082 * any number of times.
083 * @param valuePlaceholder A placeholder to display in usage information to
084 * indicate that a value must be provided. It must
085 * not be {@code null}.
086 * @param description A human-readable description for this argument.
087 * It must not be {@code null}.
088 *
089 * @throws ArgumentException If there is a problem with the definition of
090 * this argument.
091 */
092 public FilterArgument(final Character shortIdentifier,
093 final String longIdentifier, final boolean isRequired,
094 final int maxOccurrences, final String valuePlaceholder,
095 final String description)
096 throws ArgumentException
097 {
098 this(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
099 valuePlaceholder, description, (List<Filter>) null);
100 }
101
102
103
104
105
106
107 /**
108 * Creates a new filter argument with the provided information.
109 *
110 * @param shortIdentifier The short identifier for this argument. It may
111 * not be {@code null} if the long identifier is
112 * {@code null}.
113 * @param longIdentifier The long identifier for this argument. It may
114 * not be {@code null} if the short identifier is
115 * {@code null}.
116 * @param isRequired Indicates whether this argument is required to
117 * be provided.
118 * @param maxOccurrences The maximum number of times this argument may be
119 * provided on the command line. A value less than
120 * or equal to zero indicates that it may be present
121 * any number of times.
122 * @param valuePlaceholder A placeholder to display in usage information to
123 * indicate that a value must be provided. It must
124 * not be {@code null}.
125 * @param description A human-readable description for this argument.
126 * It must not be {@code null}.
127 * @param defaultValue The default value to use for this argument if no
128 * values were provided. It may be {@code null} if
129 * there should be no default values.
130 *
131 * @throws ArgumentException If there is a problem with the definition of
132 * this argument.
133 */
134 public FilterArgument(final Character shortIdentifier,
135 final String longIdentifier, final boolean isRequired,
136 final int maxOccurrences, final String valuePlaceholder,
137 final String description,
138 final Filter defaultValue)
139 throws ArgumentException
140 {
141 this(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
142 valuePlaceholder, description,
143 ((defaultValue == null) ? null : Arrays.asList(defaultValue)));
144 }
145
146
147
148 /**
149 * Creates a new filter argument with the provided information.
150 *
151 * @param shortIdentifier The short identifier for this argument. It may
152 * not be {@code null} if the long identifier is
153 * {@code null}.
154 * @param longIdentifier The long identifier for this argument. It may
155 * not be {@code null} if the short identifier is
156 * {@code null}.
157 * @param isRequired Indicates whether this argument is required to
158 * be provided.
159 * @param maxOccurrences The maximum number of times this argument may be
160 * provided on the command line. A value less than
161 * or equal to zero indicates that it may be present
162 * any number of times.
163 * @param valuePlaceholder A placeholder to display in usage information to
164 * indicate that a value must be provided. It must
165 * not be {@code null}.
166 * @param description A human-readable description for this argument.
167 * It must not be {@code null}.
168 * @param defaultValues The set of default values to use for this
169 * argument if no values were provided.
170 *
171 * @throws ArgumentException If there is a problem with the definition of
172 * this argument.
173 */
174 public FilterArgument(final Character shortIdentifier,
175 final String longIdentifier, final boolean isRequired,
176 final int maxOccurrences, final String valuePlaceholder,
177 final String description,
178 final List<Filter> defaultValues)
179 throws ArgumentException
180 {
181 super(shortIdentifier, longIdentifier, isRequired, maxOccurrences,
182 valuePlaceholder, description);
183
184 if (valuePlaceholder == null)
185 {
186 throw new ArgumentException(ERR_ARG_MUST_TAKE_VALUE.get(
187 getIdentifierString()));
188 }
189
190 if ((defaultValues == null) || defaultValues.isEmpty())
191 {
192 this.defaultValues = null;
193 }
194 else
195 {
196 this.defaultValues = Collections.unmodifiableList(defaultValues);
197 }
198
199 values = new ArrayList<Filter>();
200 }
201
202
203
204 /**
205 * Creates a new filter argument that is a "clean" copy of the provided source
206 * argument.
207 *
208 * @param source The source argument to use for this argument.
209 */
210 private FilterArgument(final FilterArgument source)
211 {
212 super(source);
213
214 defaultValues = source.defaultValues;
215 values = new ArrayList<Filter>();
216 }
217
218
219
220 /**
221 * Retrieves the list of default values for this argument, which will be used
222 * if no values were provided.
223 *
224 * @return The list of default values for this argument, or {@code null} if
225 * there are no default values.
226 */
227 public List<Filter> getDefaultValues()
228 {
229 return defaultValues;
230 }
231
232
233
234 /**
235 * {@inheritDoc}
236 */
237 @Override()
238 protected void addValue(final String valueString)
239 throws ArgumentException
240 {
241 final Filter filter;
242 try
243 {
244 filter = Filter.create(valueString);
245 }
246 catch (LDAPException le)
247 {
248 debugException(le);
249 throw new ArgumentException(ERR_FILTER_VALUE_NOT_FILTER.get(valueString,
250 getIdentifierString(), le.getMessage()),
251 le);
252 }
253
254 if (values.size() >= getMaxOccurrences())
255 {
256 throw new ArgumentException(ERR_ARG_MAX_OCCURRENCES_EXCEEDED.get(
257 getIdentifierString()));
258 }
259
260 values.add(filter);
261 }
262
263
264
265 /**
266 * Retrieves the value for this argument, or the default value if none was
267 * provided. If there are multiple values, then the first will be returned.
268 *
269 * @return The value for this argument, or the default value if none was
270 * provided, or {@code null} if there is no value and no default
271 * value.
272 */
273 public Filter getValue()
274 {
275 if (values.isEmpty())
276 {
277 if ((defaultValues == null) || defaultValues.isEmpty())
278 {
279 return null;
280 }
281 else
282 {
283 return defaultValues.get(0);
284 }
285 }
286 else
287 {
288 return values.get(0);
289 }
290 }
291
292
293
294 /**
295 * Retrieves the set of values for this argument, or the default values if
296 * none were provided.
297 *
298 * @return The set of values for this argument, or the default values if none
299 * were provided.
300 */
301 public List<Filter> getValues()
302 {
303 if (values.isEmpty() && (defaultValues != null))
304 {
305 return defaultValues;
306 }
307
308 return Collections.unmodifiableList(values);
309 }
310
311
312
313 /**
314 * {@inheritDoc}
315 */
316 @Override()
317 protected boolean hasDefaultValue()
318 {
319 return ((defaultValues != null) && (! defaultValues.isEmpty()));
320 }
321
322
323
324 /**
325 * {@inheritDoc}
326 */
327 @Override()
328 public String getDataTypeName()
329 {
330 return INFO_FILTER_TYPE_NAME.get();
331 }
332
333
334
335 /**
336 * {@inheritDoc}
337 */
338 @Override()
339 public String getValueConstraints()
340 {
341 return INFO_FILTER_CONSTRAINTS.get();
342 }
343
344
345
346 /**
347 * {@inheritDoc}
348 */
349 @Override()
350 public FilterArgument getCleanCopy()
351 {
352 return new FilterArgument(this);
353 }
354
355
356
357 /**
358 * {@inheritDoc}
359 */
360 @Override()
361 public void toString(final StringBuilder buffer)
362 {
363 buffer.append("FilterArgument(");
364 appendBasicToStringInfo(buffer);
365
366 if ((defaultValues != null) && (! defaultValues.isEmpty()))
367 {
368 if (defaultValues.size() == 1)
369 {
370 buffer.append(", defaultValue='");
371 buffer.append(defaultValues.get(0).toString());
372 }
373 else
374 {
375 buffer.append(", defaultValues={");
376
377 final Iterator<Filter> iterator = defaultValues.iterator();
378 while (iterator.hasNext())
379 {
380 buffer.append('\'');
381 buffer.append(iterator.next().toString());
382 buffer.append('\'');
383
384 if (iterator.hasNext())
385 {
386 buffer.append(", ");
387 }
388 }
389
390 buffer.append('}');
391 }
392 }
393
394 buffer.append(')');
395 }
396 }