001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.management.domain.model;
022
023 import java.lang.reflect.Constructor;
024
025 import org.apache.qpid.management.Messages;
026 import org.apache.qpid.management.configuration.Configuration;
027 import org.apache.qpid.management.domain.model.type.Type;
028 import org.apache.qpid.transport.util.Logger;
029
030 /**
031 * Qpid property definition.
032 *
033 * @author Andrea Gazzarini
034 */
035 class QpidProperty extends QpidAttribute
036 {
037 private final static Logger LOGGER = Logger.get(QpidProperty.class);
038
039 private final static int [] MASKS = {1,2,4,8,16,32,64,128};
040
041 /**
042 * Decoder interface used for decoding incomng values for this property.
043 *
044 * @author Andrea Gazzarini
045 */
046 interface Decoder
047 {
048 Object decodeValue(org.apache.qpid.transport.codec.Decoder decoder,byte [] presenceBitMasks);
049 }
050
051 /**
052 * Decoder used for decoding incoming values for this optional property.
053 */
054 final Decoder _optionalPropertyDecoder = new Decoder() {
055
056 public Object decodeValue (org.apache.qpid.transport.codec.Decoder decoder, byte[] presenceBitMasks)
057 {
058 return ((presenceBitMasks[_optionalIndex/8] & MASKS[_maskIndex]) != 0)
059 ? QpidProperty.this.decodeValue(decoder)
060 : null;
061 }
062 };
063
064 /**
065 * Decoder used for decoding incoming values for this mandatory property.
066 */
067 final Decoder _mandatoryPropertyDecoder = new Decoder() {
068
069 public Object decodeValue (org.apache.qpid.transport.codec.Decoder decoder, byte[] presenceBitMasks)
070 {
071 return QpidProperty.this.decodeValue(decoder);
072 }
073 };
074
075
076 /**
077 * Null object used to perform a dummy validation.
078 * This is the default validator installed at creation time.
079 */
080 final static IValidator EMPTY_VALIDATOR = new IValidator()
081 {
082 public void validate (Object value) throws ValidationException
083 {
084 // Nothing to do here.
085 }
086 };
087
088 /**
089 * Validator responsible for validating strings.
090 * At the moment the only constraint that should be applied to a string feature is the "max length"
091 */
092 class StringValidator implements IValidator
093 {
094 public void validate (Object value) throws ValidationException
095 {
096 if ((_maxLength != Integer.MIN_VALUE) && (value != null)){
097 int length = value.toString().length();
098 if (length > _maxLength) {
099 throw new ValidationException(
100 ValidationException.MAX_LENGTH,
101 _maxLength,
102 _name,
103 length);
104 }
105 }
106 }
107 };
108
109 /**
110 * Validator responsible for validating numbers.
111 */
112 class NumberValidator implements IValidator
113 {
114 public void validate (Object value) throws ValidationException
115 {
116 if (value != null) {
117 double numericValue = ((Number)value).doubleValue();
118 if (_minValue != Integer.MIN_VALUE && numericValue < _minValue) {
119 throw new ValidationException(
120 ValidationException.MIN_VALUE,
121 _minValue,
122 _name,
123 numericValue);
124 }
125
126 if (_maxValue != Integer.MIN_VALUE && numericValue > _maxValue) {
127 throw new ValidationException(
128 ValidationException.MAX_VALUE,
129 _maxValue,
130 _name,
131 numericValue);
132 }
133 }
134 }
135 };
136
137 private AccessMode _accessMode;
138 private int _minValue = Integer.MIN_VALUE;
139 private int _maxValue = Integer.MIN_VALUE;
140 private int _maxLength = Integer.MIN_VALUE;
141
142 private int _optionalIndex;
143 private int _maskIndex;
144
145 Decoder _decoder = _mandatoryPropertyDecoder;
146
147 private IValidator _validator = EMPTY_VALIDATOR;
148
149 /**
150 * Validates the given value according to the current validator.
151 * It delegates the validation to the current installed validator.
152 *
153 * @param value the value of this qpid property.
154 * @throws ValidationException when the given value is violating the current validator constraints.
155 */
156 void validate(Object value) throws ValidationException {
157 _validator.validate(value);
158 }
159
160 /**
161 * Sets the type of this property.
162 * In addition this method tries to detect if a validator has been associated with the type.
163 * If no validator is found then the default validator will be used; that is : no validator will be performed on this
164 * property.
165 *
166 * @param type the type of this property.
167 */
168 void setType (Type type)
169 {
170 super.setType(type);
171 try {
172 Class<?> validatorClass = Class.forName(Configuration.getInstance().getValidatorClassName(type));
173 Constructor<?> validatorConstructor = validatorClass.getDeclaredConstructor(QpidProperty.class);
174 _validator = (IValidator) validatorConstructor.newInstance(this);
175 LOGGER.debug(Messages.QMAN_200022_VALIDATOR_INSTALLED ,validatorClass.getName(), type);
176 } catch(Exception exception) {
177 _validator = EMPTY_VALIDATOR;
178 LOGGER.debug(Messages.QMAN_200023_VALIDATOR_NOT_FOUND , type);
179 }
180 }
181
182 /**
183 * Gets the value of this property according to its type definition.
184 *
185 * @param decoder the decoder used to extract the value.
186 * @return the value of this feature according to its type definition
187 */
188 Object decodeValue(org.apache.qpid.transport.codec.Decoder decoder,byte [] presenceBitMasks)
189 {
190 return _decoder.decodeValue(decoder, presenceBitMasks);
191 }
192
193 /**
194 * Sets access mode for this property.
195 *
196 * @param accessMode the access mode for this property.
197 */
198 void setAccessMode (AccessMode accessMode)
199 {
200 this._accessMode = accessMode;
201 }
202
203 /**
204 * Gets the minimum allowed value for this property.
205 *
206 * @return the minimum allowed value for this property.
207 */
208 int getMinValue ()
209 {
210 return _minValue;
211 }
212
213 /**
214 * Sets the minimum allowed value for this property.
215 *
216 * @param minValue the minimum allowed value for this property.
217 */
218 void setMinValue (int minValue)
219 {
220 this._minValue = minValue;
221 }
222
223 /**
224 * Gets the maximum allowed value for this property.
225 *
226 * @return the maximum allowed value for this property.
227 */
228 int getMaxValue ()
229 {
230 return _maxValue;
231 }
232
233 /**
234 * Sets the masimum allowed value for this property.
235 *
236 * @param maxValue the maximum allowed value for this property.
237 */
238 void setMaxValue (int maxValue)
239 {
240 this._maxValue = maxValue;
241 }
242
243 /**
244 * Gets the max length value for this property.
245 *
246 * @return the max length value for this property.
247 */
248 int getMaxLength ()
249 {
250 return _maxLength;
251 }
252
253 /**
254 * Sets the max length value for this property.
255 *
256 * @param maxLength the max length value for this property.
257 */
258 void setMaxLength (int maxLength)
259 {
260 this._maxLength = maxLength;
261 }
262
263 /**
264 * Gets the description of this property.
265 *
266 * @return the description of this property.
267 */
268 AccessMode getAccessMode ()
269 {
270 return _accessMode;
271 }
272
273 /**
274 * Marks this property as optional.
275 *
276 * @param optional the optional attribute value for this property.
277 * @param index the index of this optional property
278 */
279 void markAsOptional (int index)
280 {
281 this._optionalIndex = index;
282 this._maskIndex = (_optionalIndex >= 8) ? _optionalIndex-8 : _optionalIndex;
283 _decoder = _optionalPropertyDecoder;
284 }
285
286 /**
287 * Returns true if this property is marked as optional.
288 *
289 * @return true if this property is marked as optional, false otherwise.
290 */
291 boolean isOptional ()
292 {
293 return _decoder == _optionalPropertyDecoder;
294 }
295 }
|