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