Coverage Report - be.objectify.led.PropertySetter
 
Classes in this File Line Coverage Branch Coverage Complexity
PropertySetter
94%
48/51
83%
20/24
2.444
 
 1  
 /*
 2  
  * Copyright 2009-2010 Steve Chaloner
 3  
  *
 4  
  * Licensed under the Apache License, Version 2.0 (the "License");
 5  
  * you may not use this file except in compliance with the License.
 6  
  * You may obtain a copy of the License at
 7  
  *
 8  
  *     http://www.apache.org/licenses/LICENSE-2.0
 9  
  *
 10  
  * Unless required by applicable law or agreed to in writing, software
 11  
  * distributed under the License is distributed on an "AS IS" BASIS,
 12  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  
  * See the License for the specific language governing permissions and
 14  
  * limitations under the License.
 15  
  */
 16  
 package be.objectify.led;
 17  
 
 18  
 import be.objectify.led.util.ContractUtils;
 19  
 import be.objectify.led.util.StringUtils;
 20  
 import be.objectify.led.validation.ValidationFunction;
 21  
 import org.slf4j.Logger;
 22  
 import org.slf4j.LoggerFactory;
 23  
 
 24  
 import java.lang.reflect.AccessibleObject;
 25  
 import java.lang.reflect.Field;
 26  
 import java.lang.reflect.Modifier;
 27  
 
 28  
 /**
 29  
  * @author Steve Chaloner
 30  
  */
 31  
 public class PropertySetter
 32  
 {
 33  1
     private static final Logger LOGGER = LoggerFactory.getLogger(PropertySetter.class);
 34  
 
 35  
     private final FactoryResolver factoryResolver;
 36  
 
 37  
     private final PropertyContext propertyContext;
 38  
 
 39  
     private final PropertySetterConfiguration configuration;
 40  
 
 41  
     /**
 42  
      * Initialises a new instance with a default {@link PropertyContext} and {@link FactoryResolver}.
 43  
      */
 44  
     public PropertySetter()
 45  
     {
 46  24
         this(new DefaultFactoryResolver(),
 47  
              new DefaultPropertyContext());
 48  24
     }
 49  
 
 50  
     /**
 51  
      * Initialses a new instance with the given {@link PropertyContext} and default {@link FactoryResolver}.
 52  
      *
 53  
      * @param propertyContext the property context.  Must not be null
 54  
      */
 55  
     public PropertySetter(PropertyContext propertyContext)
 56  
     {
 57  4
         this(new DefaultFactoryResolver(),
 58  
              propertyContext);
 59  4
     }
 60  
 
 61  
     /**
 62  
      * Initialises a new instance with the given property context and a object factory registry, and a default type factory registry.
 63  
      *
 64  
      * @param factoryResolver the object factory resolver.  Must not be null
 65  
      * @param propertyContext the property context.  Must not be null
 66  
      */
 67  
     public PropertySetter(FactoryResolver factoryResolver,
 68  
                           PropertyContext propertyContext)
 69  57
     {
 70  57
         ContractUtils.notNull(factoryResolver, "factoryResolver");
 71  57
         ContractUtils.notNull(propertyContext, "propertyContext");
 72  
 
 73  57
         this.factoryResolver = factoryResolver;
 74  57
         this.propertyContext = propertyContext;
 75  57
         this.configuration = new PropertySetterConfiguration();
 76  57
     }
 77  
 
 78  
     /**
 79  
      * Processes any {@link Property} annotations in the given class.  This
 80  
      * will not affect any instance members.
 81  
      *
 82  
      * @param target the class to check
 83  
      * @param validationFunctions validation checks
 84  
      */
 85  
     public void process(Class target,
 86  
                         ValidationFunction... validationFunctions)
 87  
     {
 88  3
         Field[] fields = target.getDeclaredFields();
 89  7
         for (Field field : fields)
 90  
         {
 91  4
             if (field.isAnnotationPresent(Property.class) &&
 92  
                 Modifier.isStatic(field.getModifiers()))
 93  
             {
 94  3
                 setProperty(target,
 95  
                             field,
 96  
                             validationFunctions);
 97  
             }
 98  
         }
 99  3
     }
 100  
 
 101  
     /**
 102  
      * Processes any {@link Property} annotations in the given object, including
 103  
      * static members.
 104  
      *
 105  
      * @param target the object to check
 106  
      * @param validationFunctions validation checks
 107  
      */
 108  
     public void process(Object target,
 109  
                         ValidationFunction... validationFunctions)
 110  
     {
 111  54
         Field[] fields = target.getClass().getDeclaredFields();
 112  179
         for (Field field : fields)
 113  
         {
 114  127
             if (field.isAnnotationPresent(Property.class))
 115  
             {
 116  77
                 setProperty(target,
 117  
                             field,
 118  
                             validationFunctions);
 119  
             }
 120  
         }
 121  52
     }
 122  
 
 123  
     /**
 124  
      * Sets any system property defined for the field.
 125  
      *
 126  
      * @param target the instance to work on
 127  
      * @param field  the field to use to set the property
 128  
      * @param validationFunctions validation checks
 129  
      */
 130  
     private void setProperty(Object target,
 131  
                              Field field,
 132  
                              ValidationFunction... validationFunctions)
 133  
     {
 134  80
         String propertyValue = getProperty(field);
 135  80
         boolean finalField = Modifier.isFinal(field.getModifiers());
 136  80
         if (!StringUtils.isEmpty(propertyValue) &&
 137  
             (!finalField || configuration.isAllowFinalSetting()))
 138  
         {
 139  59
             Class<?> type = field.getType();
 140  59
             ObjectFactory objectFactory = factoryResolver.resolveFactory(type,
 141  
                                                                          field);
 142  59
             if (objectFactory != null)
 143  
             {
 144  59
                 String fieldName = field.getAnnotation(Property.class).value();
 145  59
                 objectFactory.validate(fieldName,
 146  
                                        propertyValue,
 147  
                                        validationFunctions);
 148  57
                 setValue(target,
 149  
                          field,
 150  
                          objectFactory.createObject(fieldName,
 151  
                                                     propertyValue));
 152  57
             }
 153  
             else
 154  
             {
 155  0
                 LOGGER.info("No factory available for type [{}]",
 156  
                             type);
 157  
             }
 158  
         }
 159  78
     }
 160  
 
 161  
     /**
 162  
      * Sets the value on the target.
 163  
      *
 164  
      * @param target the target object/class
 165  
      * @param field  the field to set
 166  
      * @param value  the value to set
 167  
      */
 168  
     private void setValue(Object target,
 169  
                           Field field,
 170  
                           Object value)
 171  
     {
 172  57
         if (value != null)
 173  
         {
 174  
             try
 175  
             {
 176  57
                 boolean accessibleState = field.isAccessible();
 177  57
                 if (!accessibleState)
 178  
                 {
 179  57
                     field.setAccessible(true);
 180  
                 }
 181  57
                 field.set(target,
 182  
                           value);
 183  57
                 field.setAccessible(accessibleState);
 184  
             }
 185  0
             catch (IllegalAccessException e)
 186  
             {
 187  0
                 LOGGER.error("Unable to set property",
 188  
                              e);
 189  57
             }
 190  
         }
 191  57
     }
 192  
 
 193  
     private String getProperty(AccessibleObject accessibleObject)
 194  
     {
 195  80
         Property annotation = accessibleObject.getAnnotation(Property.class);
 196  80
         String propertyName = annotation.value();
 197  80
         String propertyValue = propertyContext.getValue(propertyName);
 198  
 
 199  80
         if (!StringUtils.isEmpty(propertyValue))
 200  
         {
 201  63
             LOGGER.debug("Found value [{}] for system property [{}] on [{}]",
 202  
                          new Object[] {
 203  
                                  propertyValue,
 204  
                                  propertyName,
 205  
                                  accessibleObject.toString()
 206  
                          });
 207  
         }
 208  
 
 209  80
         return propertyValue;
 210  
     }
 211  
 
 212  
     public PropertySetterConfiguration getConfiguration()
 213  
     {
 214  2
         return configuration;
 215  
     }
 216  
 }