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 */ 021package com.unboundid.util.args; 022 023 024 025import java.util.ArrayList; 026import java.util.Arrays; 027import java.util.Collections; 028import java.util.Iterator; 029import java.util.List; 030 031import com.unboundid.ldap.sdk.Filter; 032import com.unboundid.ldap.sdk.LDAPException; 033import com.unboundid.util.Mutable; 034import com.unboundid.util.ThreadSafety; 035import com.unboundid.util.ThreadSafetyLevel; 036 037import static com.unboundid.util.Debug.*; 038import 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) 049public 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}