QpidProperty.java
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 valuethrows 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 valuethrows 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 valuethrows 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 valuethrows 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 = (IValidatorvalidatorConstructor.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-: _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 }