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 */ 026 027package org.forgerock.opendj.config; 028 029import org.forgerock.util.Reject; 030 031import java.util.EnumSet; 032import java.util.Locale; 033import java.util.MissingResourceException; 034 035import org.forgerock.i18n.LocalizableMessage; 036 037/** 038 * Integer property definition. 039 * <p> 040 * All values must be zero or positive and within the lower/upper limit 041 * constraints. Support is provided for "unlimited" values. These are 042 * represented using a negative value or using the string "unlimited". 043 */ 044public final class IntegerPropertyDefinition extends PropertyDefinition<Integer> { 045 046 /** String used to represent unlimited. */ 047 private static final String UNLIMITED = "unlimited"; 048 049 /** The lower limit of the property value. */ 050 private final int lowerLimit; 051 052 /** The optional upper limit of the property value. */ 053 private final Integer upperLimit; 054 055 /** 056 * Indicates whether this property allows the use of the "unlimited" value 057 * (represented using a -1 or the string "unlimited"). 058 */ 059 private final boolean allowUnlimited; 060 061 /** 062 * An interface for incrementally constructing integer property definitions. 063 */ 064 public static final class Builder extends AbstractBuilder<Integer, IntegerPropertyDefinition> { 065 066 /** The lower limit of the property value. */ 067 private int lowerLimit; 068 069 /** The optional upper limit of the property value. */ 070 private Integer upperLimit; 071 072 /** 073 * Indicates whether this property allows the use of the "unlimited" value 074 * (represented using a -1 or the string "unlimited"). 075 */ 076 private boolean allowUnlimited; 077 078 /** Private constructor. */ 079 private Builder(AbstractManagedObjectDefinition<?, ?> d, String propertyName) { 080 super(d, propertyName); 081 } 082 083 /** 084 * Set the lower limit. 085 * 086 * @param lowerLimit 087 * The new lower limit (must be >= 0). 088 * @throws IllegalArgumentException 089 * If a negative lower limit was specified or the lower 090 * limit is greater than the upper limit. 091 */ 092 public final void setLowerLimit(int lowerLimit) { 093 if (lowerLimit < 0) { 094 throw new IllegalArgumentException("Negative lower limit"); 095 } 096 if (upperLimit != null && lowerLimit > upperLimit) { 097 throw new IllegalArgumentException("Lower limit greater than upper limit"); 098 } 099 this.lowerLimit = lowerLimit; 100 } 101 102 /** 103 * Set the upper limit. 104 * 105 * @param upperLimit 106 * The new upper limit or <code>null</code> if there is no 107 * upper limit. 108 */ 109 public final void setUpperLimit(Integer upperLimit) { 110 if (upperLimit != null) { 111 if (upperLimit < 0) { 112 throw new IllegalArgumentException("Negative lower limit"); 113 } 114 if (lowerLimit > upperLimit) { 115 throw new IllegalArgumentException("Lower limit greater than upper limit"); 116 } 117 } 118 this.upperLimit = upperLimit; 119 } 120 121 /** 122 * Specify whether or not this property definition will allow unlimited 123 * values (default is false). 124 * 125 * @param allowUnlimited 126 * <code>true</code> if the property will allow unlimited 127 * values, or <code>false</code> otherwise. 128 */ 129 public final void setAllowUnlimited(boolean allowUnlimited) { 130 this.allowUnlimited = allowUnlimited; 131 } 132 133 /** {@inheritDoc} */ 134 @Override 135 protected IntegerPropertyDefinition buildInstance(AbstractManagedObjectDefinition<?, ?> d, 136 String propertyName, EnumSet<PropertyOption> options, AdministratorAction adminAction, 137 DefaultBehaviorProvider<Integer> defaultBehavior) { 138 return new IntegerPropertyDefinition(d, propertyName, options, adminAction, defaultBehavior, lowerLimit, 139 upperLimit, allowUnlimited); 140 } 141 142 } 143 144 /** 145 * Create an integer property definition builder. 146 * 147 * @param d 148 * The managed object definition associated with this property 149 * definition. 150 * @param propertyName 151 * The property name. 152 * @return Returns the new integer property definition builder. 153 */ 154 public static Builder createBuilder(AbstractManagedObjectDefinition<?, ?> d, String propertyName) { 155 return new Builder(d, propertyName); 156 } 157 158 /** Private constructor. */ 159 private IntegerPropertyDefinition(AbstractManagedObjectDefinition<?, ?> d, String propertyName, 160 EnumSet<PropertyOption> options, AdministratorAction adminAction, 161 DefaultBehaviorProvider<Integer> defaultBehavior, int lowerLimit, Integer upperLimit, boolean allowUnlimited) { 162 super(d, Integer.class, propertyName, options, adminAction, defaultBehavior); 163 this.lowerLimit = lowerLimit; 164 this.upperLimit = upperLimit; 165 this.allowUnlimited = allowUnlimited; 166 } 167 168 /** 169 * Get the lower limit. 170 * 171 * @return Returns the lower limit. 172 */ 173 public int getLowerLimit() { 174 return lowerLimit; 175 } 176 177 /** 178 * Get the upper limit. 179 * 180 * @return Returns the upper limit or <code>null</code> if there is no upper 181 * limit. 182 */ 183 public Integer getUpperLimit() { 184 return upperLimit; 185 } 186 187 /** 188 * Gets the optional unit synopsis of this integer property definition in 189 * the default locale. 190 * 191 * @return Returns the unit synopsis of this integer property definition in 192 * the default locale, or <code>null</code> if there is no unit 193 * synopsis. 194 */ 195 public LocalizableMessage getUnitSynopsis() { 196 return getUnitSynopsis(Locale.getDefault()); 197 } 198 199 /** 200 * Gets the optional unit synopsis of this integer property definition in 201 * the specified locale. 202 * 203 * @param locale 204 * The locale. 205 * @return Returns the unit synopsis of this integer property definition in 206 * the specified locale, or <code>null</code> if there is no unit 207 * synopsis. 208 */ 209 public LocalizableMessage getUnitSynopsis(Locale locale) { 210 ManagedObjectDefinitionI18NResource resource = ManagedObjectDefinitionI18NResource.getInstance(); 211 String property = "property." + getName() + ".syntax.integer.unit-synopsis"; 212 try { 213 return resource.getMessage(getManagedObjectDefinition(), property, locale); 214 } catch (MissingResourceException e) { 215 return null; 216 } 217 } 218 219 /** 220 * Determine whether this property allows unlimited values. 221 * 222 * @return Returns <code>true</code> if this this property allows unlimited 223 * values. 224 */ 225 public boolean isAllowUnlimited() { 226 return allowUnlimited; 227 } 228 229 /** {@inheritDoc} */ 230 @Override 231 public void validateValue(Integer value) { 232 Reject.ifNull(value); 233 234 if (!allowUnlimited && value < lowerLimit) { 235 throw PropertyException.illegalPropertyValueException(this, value); 236 237 // unlimited allowed 238 } else if (value >= 0 && value < lowerLimit) { 239 throw PropertyException.illegalPropertyValueException(this, value); 240 } 241 242 if (upperLimit != null && value > upperLimit) { 243 throw PropertyException.illegalPropertyValueException(this, value); 244 } 245 } 246 247 /** {@inheritDoc} */ 248 @Override 249 public String encodeValue(Integer value) { 250 Reject.ifNull(value); 251 252 // Make sure that we correctly encode negative values as "unlimited". 253 if (allowUnlimited && value < 0) { 254 return UNLIMITED; 255 } 256 257 return value.toString(); 258 } 259 260 /** {@inheritDoc} */ 261 @Override 262 public Integer decodeValue(String value) { 263 Reject.ifNull(value); 264 265 if (allowUnlimited && UNLIMITED.equalsIgnoreCase(value.trim())) { 266 return -1; 267 } 268 269 Integer i; 270 try { 271 i = Integer.valueOf(value); 272 } catch (NumberFormatException e) { 273 throw PropertyException.illegalPropertyValueException(this, value); 274 } 275 276 try { 277 validateValue(i); 278 } catch (PropertyException e) { 279 throw PropertyException.illegalPropertyValueException(this, value); 280 } 281 282 return i; 283 } 284 285 /** {@inheritDoc} */ 286 @Override 287 public <R, P> R accept(PropertyDefinitionVisitor<R, P> v, P p) { 288 return v.visitInteger(this, p); 289 } 290 291 /** {@inheritDoc} */ 292 @Override 293 public <R, P> R accept(PropertyValueVisitor<R, P> v, Integer value, P p) { 294 return v.visitInteger(this, value, p); 295 } 296 297 /** {@inheritDoc} */ 298 @Override 299 public void toString(StringBuilder builder) { 300 super.toString(builder); 301 302 builder.append(" lowerLimit="); 303 builder.append(lowerLimit); 304 305 if (upperLimit != null) { 306 builder.append(" upperLimit="); 307 builder.append(upperLimit); 308 } 309 310 builder.append(" allowUnlimited="); 311 builder.append(allowUnlimited); 312 } 313 314 /** {@inheritDoc} */ 315 @Override 316 public int compare(Integer o1, Integer o2) { 317 return o1.compareTo(o2); 318 } 319 320}