Coverage Report - org.openpermis.editor.policy.beans.PropertyAccess
 
Classes in this File Line Coverage Branch Coverage Complexity
PropertyAccess
67%
36/53
59%
13/22
4.375
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.editor.policy.beans;
 11  
 
 12  
 import java.lang.reflect.InvocationTargetException;
 13  
 import java.lang.reflect.Method;
 14  
 
 15  
 import org.slf4j.Logger;
 16  
 import org.slf4j.LoggerFactory;
 17  
 
 18  
 /**
 19  
  * Helper class that provides access to Java Bean properties.
 20  
  * @since 0.1.0
 21  
  */
 22  
 public class PropertyAccess {
 23  
 
 24  
         //---- Static
 25  
         
 26  
         /**
 27  
          * The logger object of this class.
 28  
          * @since 0.1.0
 29  
          */
 30  1
         private static final Logger LOGGER = 
 31  
                 LoggerFactory.getLogger(PropertyAccess.class);
 32  
 
 33  
         //---- State
 34  
         
 35  
         /**
 36  
          * The bean this support class operates on.
 37  
          * @since 0.1.0
 38  
          */
 39  
         private final Object bean;
 40  
 
 41  
         //---- Constructors
 42  
         
 43  
         /**
 44  
          * Creates a bean property access object for the specified Java Bean.
 45  
          * @param bean the Java Bean to operate on, must not be {@code null}.
 46  
          * @since 0.1.0
 47  
          */
 48  22
         public PropertyAccess (Object bean) {
 49  22
                 if (bean == null) {
 50  1
                         throw new IllegalArgumentException("Illegal bean [null].");
 51  
                 }
 52  21
                 if (!BeanUtilities.isJavaBean(bean)) {
 53  1
                         throw new IllegalArgumentException(
 54  
                                 "Illegal bean object of class [" + bean.getClass() + "], this is not a bean."
 55  
                         );
 56  
                 }
 57  20
                 this.bean = bean;
 58  20
         }
 59  
 
 60  
         /**
 61  
          * Logs a warning with the specified message and cause.
 62  
          * @param message the message to log.
 63  
          * @param cause the cause.
 64  
          * @since 0.1.0
 65  
          */
 66  
         protected void warn (String message, Throwable cause) {
 67  0
                 LOGGER.warn(message, cause);
 68  0
         }
 69  
         
 70  
         //---- Methods
 71  
 
 72  
         /**
 73  
          * Checks if the property is valid.
 74  
          * @param property the property to check.
 75  
          * @throws IllegalArgumentException if the property is invalid.
 76  
          * @since 0.1.0
 77  
          */
 78  
         private void checkProperty (String property) {
 79  21
                 if (property == null) {
 80  2
                         throw new IllegalArgumentException("Illegal property [null].");
 81  19
                 } else if (property.length() == 0) {
 82  1
                         throw new IllegalArgumentException("Illegal empty property.");
 83  
                 }
 84  18
         }
 85  
         
 86  
         /**
 87  
          * Check if the bean has a property that can be read.
 88  
          * @param property the property to check.
 89  
          * @return {@code true} if the bean has the property and it can be read.
 90  
          * @since 0.1.0
 91  
          */
 92  
         public boolean canGetProperty (String property) {
 93  0
                 checkProperty(property);
 94  0
                 return BeanUtilities.getter(this.bean.getClass(), property) != null;
 95  
         }
 96  
         
 97  
         /**
 98  
          * Check if the bean has a property that can be written.
 99  
          * @param property the property to check.
 100  
          * @return {@code true} if the bean has the property and it can be written.
 101  
          * @since 0.1.0
 102  
          */
 103  
         public boolean canSetProperty (String property) {
 104  0
                 checkProperty(property);
 105  0
                 return BeanUtilities.setter(this.bean.getClass(), property) != null;
 106  
         }
 107  
         
 108  
         /**
 109  
          * Check if the bean has a property that can be read and written.
 110  
          * @param property the property to check.
 111  
          * @return {@code true} if the bean has the property and it can be read and written.
 112  
          * @since 0.1.0
 113  
          */
 114  
         public boolean canGetSetProperty (String property) {
 115  0
                 checkProperty(property);
 116  0
                 return
 117  
                         BeanUtilities.getter(this.bean.getClass(), property) != null &&
 118  
                         BeanUtilities.setter(this.bean.getClass(), property) != null;
 119  
         }
 120  
         
 121  
         /**
 122  
          * Calls the setter of the property of the bean bound to this access object.
 123  
          * @param property the property to set, must not be {@code null} or empty.
 124  
          * @param value the value to set at the bean, may (of course) be {@code null}.
 125  
          * @throws IllegalArgumentException if the bean does not have the property or the
 126  
          * value specified is of an incompatible type.
 127  
          * @throws IllegalStateException if the bean reports an error.
 128  
          * @since 0.1.0
 129  
          */
 130  
         public void set (String property, Object value) {
 131  12
                 checkProperty(property);
 132  11
                 final Method method = BeanUtilities.setter(this.bean.getClass(), property);
 133  11
                 if (method == null) {
 134  2
                         throw new IllegalArgumentException(
 135  
                                 "No getter for [" + property + 
 136  
                                 "] in bean class [" + this.bean.getClass() + "]."
 137  
                         );
 138  
                 }
 139  
                 try {
 140  9
                         method.invoke(this.bean, new Object[] { value });
 141  1
                 } catch (IllegalArgumentException e) {
 142  1
                         final String v = value == null ? "[null]" : " of type [" + value.getClass() + "]";
 143  1
                         final String message = 
 144  
                                 "Incompatible value " + v + " for property [" + property + 
 145  
                                 "] while calling [" + method + "] in bean class [" + this.bean.getClass() + "].";
 146  1
                         warn(message, e);
 147  1
                         throw new IllegalArgumentException(message, e);
 148  0
                 } catch (IllegalAccessException e) {
 149  0
                         warn("Cannot access bean method [" + method + "].", e);
 150  0
                         throw new IllegalStateException(
 151  
                                 "Cannot access bean method [" + method + "].", e
 152  
                         );
 153  1
                 } catch (InvocationTargetException e) {
 154  1
                         warn("Error while executing bean method [" + method + "].", e.getCause());
 155  1
                         throw new IllegalStateException(
 156  
                                 "Error while executing bean method [" + method + "].",
 157  
                                 e.getCause()
 158  
                         );
 159  7
                 }
 160  7
         }
 161  
         
 162  
         /**
 163  
          * Calls the getter of the property of the bean bound to this access object.
 164  
          * @param property the property to request the value for, must not be {@code null} or empty.
 165  
          * @return the property value requested.
 166  
          * @throws IllegalArgumentException if the bean does not have the property.
 167  
          * @throws IllegalStateException if the bean reports an error.
 168  
          * @since 0.1.0
 169  
          */
 170  
         public Object get (String property) {
 171  9
                 checkProperty(property);
 172  7
                 final Method method = BeanUtilities.getter(this.bean.getClass(), property);
 173  7
                 if (method == null) {
 174  2
                         throw new IllegalArgumentException(
 175  
                                 "No getter for [" + property + 
 176  
                                 "] in bean class [" + this.bean.getClass() + "]."
 177  
                         );
 178  
                 }
 179  
                 try {
 180  5
                         return method.invoke(this.bean);
 181  0
                 } catch (IllegalArgumentException e) {
 182  0
                         warn("Unexpected exception while invoking method [" + method + "].", e);
 183  0
                         throw new IllegalArgumentException("Internal error.", e);
 184  0
                 } catch (IllegalAccessException e) {
 185  0
                         warn("Cannot access bean method [" + method + "].", e);
 186  0
                         throw new IllegalStateException(
 187  
                                 "Cannot access bean method [" + method + "].", e
 188  
                         );
 189  1
                 } catch (InvocationTargetException e) {
 190  1
                         warn("Error while executing bean method [" + method + "].", e.getCause());
 191  1
                         throw new IllegalStateException(
 192  
                                 "Error while executing bean method [" + method + "].",
 193  
                                 e.getCause()
 194  
                         );
 195  
                 }
 196  
         }
 197  
         
 198  
 }