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 legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2008 Sun Microsystems, Inc. 025 * Portions Copyright 2014-2015 ForgeRock AS 026 */ 027 028package org.opends.server.admin; 029import org.forgerock.i18n.LocalizableMessage; 030 031 032 033import static org.forgerock.util.Reject.ifNull; 034 035import java.util.EnumSet; 036import java.util.Locale; 037import java.util.MissingResourceException; 038 039 040 041/** 042 * Integer property definition. 043 * <p> 044 * All values must be zero or positive and within the lower/upper limit 045 * constraints. Support is provided for "unlimited" values. These are 046 * represented using a negative value or using the string "unlimited". 047 */ 048public final class IntegerPropertyDefinition extends 049 PropertyDefinition<Integer> { 050 051 /** String used to represent unlimited. */ 052 private static final String UNLIMITED = "unlimited"; 053 054 /** The lower limit of the property value. */ 055 private final int lowerLimit; 056 057 /** The optional upper limit of the property value. */ 058 private final Integer upperLimit; 059 060 /** 061 * Indicates whether this property allows the use of the "unlimited" value 062 * (represented using a -1 or the string "unlimited"). 063 */ 064 private final boolean allowUnlimited; 065 066 067 068 /** 069 * An interface for incrementally constructing integer property definitions. 070 */ 071 public static class Builder extends 072 AbstractBuilder<Integer, IntegerPropertyDefinition> { 073 074 /** The lower limit of the property value. */ 075 private int lowerLimit; 076 077 /** The optional upper limit of the property value. */ 078 private Integer upperLimit; 079 080 /** 081 * Indicates whether this property allows the use of the "unlimited" value 082 * (represented using a -1 or the string "unlimited"). 083 */ 084 private boolean allowUnlimited; 085 086 087 088 /** Private constructor. */ 089 private Builder( 090 AbstractManagedObjectDefinition<?, ?> d, String propertyName) { 091 super(d, propertyName); 092 } 093 094 095 096 /** 097 * Set the lower limit. 098 * 099 * @param lowerLimit 100 * The new lower limit (must be >= 0). 101 * @throws IllegalArgumentException 102 * If a negative lower limit was specified or the lower limit is 103 * greater than the upper limit. 104 */ 105 public final void setLowerLimit(int lowerLimit) 106 throws IllegalArgumentException { 107 if (lowerLimit < 0) { 108 throw new IllegalArgumentException("Negative lower limit"); 109 } 110 if (upperLimit != null && lowerLimit > upperLimit) { 111 throw new IllegalArgumentException( 112 "Lower limit greater than upper limit"); 113 } 114 this.lowerLimit = lowerLimit; 115 } 116 117 118 119 /** 120 * Set the upper limit. 121 * 122 * @param upperLimit 123 * The new upper limit or <code>null</code> if there is no upper 124 * limit. 125 */ 126 public final void setUpperLimit(Integer upperLimit) { 127 if (upperLimit != null) { 128 if (upperLimit < 0) { 129 throw new IllegalArgumentException("Negative lower limit"); 130 } 131 if (lowerLimit > upperLimit) { 132 throw new IllegalArgumentException( 133 "Lower limit greater than upper limit"); 134 } 135 } 136 this.upperLimit = upperLimit; 137 } 138 139 140 141 /** 142 * Specify whether or not this property definition will allow unlimited 143 * values (default is false). 144 * 145 * @param allowUnlimited 146 * <code>true</code> if the property will allow unlimited values, 147 * or <code>false</code> otherwise. 148 */ 149 public final void setAllowUnlimited(boolean allowUnlimited) { 150 this.allowUnlimited = allowUnlimited; 151 } 152 153 154 155 /** {@inheritDoc} */ 156 @Override 157 protected IntegerPropertyDefinition buildInstance( 158 AbstractManagedObjectDefinition<?, ?> d, String propertyName, 159 EnumSet<PropertyOption> options, 160 AdministratorAction adminAction, 161 DefaultBehaviorProvider<Integer> defaultBehavior) { 162 return new IntegerPropertyDefinition(d, propertyName, options, 163 adminAction, defaultBehavior, lowerLimit, upperLimit, allowUnlimited); 164 } 165 166 } 167 168 169 170 /** 171 * Create an integer property definition builder. 172 * 173 * @param d 174 * The managed object definition associated with this 175 * property definition. 176 * @param propertyName 177 * The property name. 178 * @return Returns the new integer property definition builder. 179 */ 180 public static Builder createBuilder( 181 AbstractManagedObjectDefinition<?, ?> d, String propertyName) { 182 return new Builder(d, propertyName); 183 } 184 185 186 187 /** Private constructor. */ 188 private IntegerPropertyDefinition( 189 AbstractManagedObjectDefinition<?, ?> d, String propertyName, 190 EnumSet<PropertyOption> options, 191 AdministratorAction adminAction, 192 DefaultBehaviorProvider<Integer> defaultBehavior, int lowerLimit, 193 Integer upperLimit, boolean allowUnlimited) { 194 super(d, Integer.class, propertyName, options, adminAction, 195 defaultBehavior); 196 this.lowerLimit = lowerLimit; 197 this.upperLimit = upperLimit; 198 this.allowUnlimited = allowUnlimited; 199 } 200 201 202 203 /** 204 * Get the lower limit. 205 * 206 * @return Returns the lower limit. 207 */ 208 public int getLowerLimit() { 209 return lowerLimit; 210 } 211 212 213 214 /** 215 * Get the upper limit. 216 * 217 * @return Returns the upper limit or <code>null</code> if there is no upper 218 * limit. 219 */ 220 public Integer getUpperLimit() { 221 return upperLimit; 222 } 223 224 225 226 /** 227 * Gets the optional unit synopsis of this integer property 228 * definition in the default locale. 229 * 230 * @return Returns the unit synopsis of this integer property 231 * definition in the default locale, or <code>null</code> 232 * if there is no unit synopsis. 233 */ 234 public LocalizableMessage getUnitSynopsis() { 235 return getUnitSynopsis(Locale.getDefault()); 236 } 237 238 239 240 /** 241 * Gets the optional unit synopsis of this integer property 242 * definition in the specified locale. 243 * 244 * @param locale 245 * The locale. 246 * @return Returns the unit synopsis of this integer property 247 * definition in the specified locale, or <code>null</code> 248 * if there is no unit synopsis. 249 */ 250 public LocalizableMessage getUnitSynopsis(Locale locale) { 251 ManagedObjectDefinitionI18NResource resource = 252 ManagedObjectDefinitionI18NResource.getInstance(); 253 String property = "property." + getName() + ".syntax.integer.unit-synopsis"; 254 try { 255 return resource.getMessage(getManagedObjectDefinition(), 256 property, locale); 257 } catch (MissingResourceException e) { 258 return null; 259 } 260 } 261 262 263 264 /** 265 * Determine whether this property allows unlimited values. 266 * 267 * @return Returns <code>true</code> if this this property allows unlimited 268 * values. 269 */ 270 public boolean isAllowUnlimited() { 271 return allowUnlimited; 272 } 273 274 275 276 /** {@inheritDoc} */ 277 @Override 278 public void validateValue(Integer value) 279 throws PropertyException { 280 ifNull(value); 281 282 if (!allowUnlimited && value < lowerLimit) { 283 throw PropertyException.illegalPropertyValueException(this, value); 284 285 // unlimited allowed 286 } else if (value >= 0 && value < lowerLimit) { 287 throw PropertyException.illegalPropertyValueException(this, value); 288 } 289 290 if (upperLimit != null && value > upperLimit) { 291 throw PropertyException.illegalPropertyValueException(this, value); 292 } 293 } 294 295 /** {@inheritDoc} */ 296 @Override 297 public String encodeValue(Integer value) 298 throws PropertyException { 299 ifNull(value); 300 301 // Make sure that we correctly encode negative values as "unlimited". 302 if (allowUnlimited && value < 0) { 303 return UNLIMITED; 304 } 305 306 return value.toString(); 307 } 308 309 /** {@inheritDoc} */ 310 @Override 311 public Integer decodeValue(String value) throws PropertyException { 312 ifNull(value); 313 314 if (allowUnlimited && value.trim().equalsIgnoreCase(UNLIMITED)) { 315 return -1; 316 } 317 318 Integer i; 319 try { 320 i = Integer.valueOf(value); 321 } catch (NumberFormatException e) { 322 throw PropertyException.illegalPropertyValueException(this, value); 323 } 324 325 try { 326 validateValue(i); 327 } catch (PropertyException e) { 328 throw PropertyException.illegalPropertyValueException(this, value); 329 } 330 331 return i; 332 } 333 334 335 336 /** {@inheritDoc} */ 337 @Override 338 public <R, P> R accept(PropertyDefinitionVisitor<R, P> v, P p) { 339 return v.visitInteger(this, p); 340 } 341 342 343 344 /** {@inheritDoc} */ 345 @Override 346 public <R, P> R accept(PropertyValueVisitor<R, P> v, Integer value, P p) { 347 return v.visitInteger(this, value, p); 348 } 349 350 351 352 /** {@inheritDoc} */ 353 @Override 354 public void toString(StringBuilder builder) { 355 super.toString(builder); 356 357 builder.append(" lowerLimit="); 358 builder.append(lowerLimit); 359 360 if (upperLimit != null) { 361 builder.append(" upperLimit="); 362 builder.append(upperLimit); 363 } 364 365 builder.append(" allowUnlimited="); 366 builder.append(allowUnlimited); 367 } 368 369 370 371 /** {@inheritDoc} */ 372 @Override 373 public int compare(Integer o1, Integer o2) { 374 return o1.compareTo(o2); 375 } 376 377}