Coverage Report - com.lexicalscope.fluentreflection.FluentFieldImpl
 
Classes in this File Line Coverage Branch Coverage Complexity
FluentFieldImpl
79%
49/62
70%
17/24
2.278
FluentFieldImpl$1
0%
0/3
N/A
2.278
 
 1  0
 package com.lexicalscope.fluentreflection;
 2  
 
 3  
 /*
 4  
  * Copyright 2011 Tim Wood
 5  
  *
 6  
  * Licensed under the Apache License, Version 2.0 (the "License");
 7  
  * you may not use this file except in compliance with the License.
 8  
  * You may obtain a copy of the License at
 9  
  *
 10  
  * http://www.apache.org/licenses/LICENSE-2.0
 11  
  *
 12  
  * Unless required by applicable law or agreed to in writing, software
 13  
  * distributed under the License is distributed on an "AS IS" BASIS,
 14  
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15  
  * See the License for the specific language governing permissions and
 16  
  * limitations under the License.
 17  
  */
 18  
 
 19  
 import static com.lexicalscope.fluentreflection.Visibility.visibilityFromModifiers;
 20  
 import static java.lang.String.format;
 21  
 
 22  
 import java.lang.reflect.Field;
 23  
 import java.lang.reflect.Modifier;
 24  
 import java.util.ArrayList;
 25  
 import java.util.List;
 26  
 
 27  
 import org.apache.commons.lang3.builder.EqualsBuilder;
 28  
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 29  
 
 30  
 import com.google.inject.TypeLiteral;
 31  
 
 32  
 final class FluentFieldImpl extends AbstractFluentAnnotated implements FluentField {
 33  
     private final ReflectedTypeFactory reflectedTypeFactory;
 34  
     private final FluentClass<?> reflectedClass;
 35  
     private final TypeLiteral<?> typeLiteral;
 36  
     private final Field field;
 37  
 
 38  
     public FluentFieldImpl(
 39  
             final ReflectedTypeFactory reflectedTypeFactory,
 40  
             final FluentClass<?> reflectedClass,
 41  
             final TypeLiteral<?> typeLiteral,
 42  
             final Field field) {
 43  1736
         super(reflectedTypeFactory, field);
 44  1736
         this.reflectedTypeFactory = reflectedTypeFactory;
 45  1736
         this.reflectedClass = reflectedClass;
 46  1736
         this.typeLiteral = typeLiteral;
 47  1736
         this.field = field;
 48  
 
 49  1736
         try { field.setAccessible(true); } catch(final SecurityException e)
 50  
         { /* ignore, if we can set the field as accessible we get much improved performance */ }
 51  1736
     }
 52  
 
 53  
     @Override public String name() {
 54  1296
         return field.getName();
 55  
     }
 56  
 
 57  
     @Override public FluentClass<?> declarer() {
 58  8
         return reflectedTypeFactory.reflect(typeLiteral);
 59  
     }
 60  
 
 61  
     @Override public boolean isStatic() {
 62  2088
         return Modifier.isStatic(field.getModifiers());
 63  
     }
 64  
 
 65  
     @Override public boolean isFinal() {
 66  48
         return Modifier.isFinal(field.getModifiers());
 67  
     }
 68  
 
 69  
     @Override public String property() {
 70  8
         return field.getName();
 71  
     }
 72  
 
 73  
     @Override public Field member() {
 74  8
         return field;
 75  
     }
 76  
 
 77  
     @Override public Visibility visibility() {
 78  112
         return visibilityFromModifiers(field.getModifiers());
 79  
     }
 80  
 
 81  
     @Override public String toString() {
 82  
         final String visibility;
 83  40
         if (visibility().toString().isEmpty())
 84  
         {
 85  8
             visibility = visibility().toString();
 86  
         }
 87  
         else
 88  
         {
 89  32
             visibility = visibility().toString() + " ";
 90  
         }
 91  
 
 92  
         final String staticModifier;
 93  40
         if (isStatic())
 94  
         {
 95  16
             staticModifier = "static ";
 96  
         }
 97  
         else
 98  
         {
 99  24
             staticModifier = "";
 100  
         }
 101  
 
 102  
         final String finalModifier;
 103  40
         if (isFinal())
 104  
         {
 105  8
             finalModifier = "final ";
 106  
         }
 107  
         else
 108  
         {
 109  32
             finalModifier = "";
 110  
         }
 111  
 
 112  40
         return format(
 113  40
                 "%s%s%s%s %s",
 114  40
                 visibility,
 115  40
                 staticModifier,
 116  40
                 finalModifier,
 117  40
                 type(),
 118  40
                 field.getName());
 119  
     }
 120  
 
 121  
     @Override public boolean equals(final Object obj) {
 122  8
         if (obj != null && this.getClass().equals(obj.getClass())) {
 123  8
             final FluentFieldImpl that = (FluentFieldImpl) obj;
 124  16
             return new EqualsBuilder()
 125  8
                     .append(this.field, that.field)
 126  8
                     .append(this.typeLiteral, that.typeLiteral)
 127  8
                     .isEquals();
 128  
         }
 129  0
         return false;
 130  
     }
 131  
 
 132  
     @Override public int hashCode() {
 133  16
         return new HashCodeBuilder().append(field).append(typeLiteral).toHashCode();
 134  
     }
 135  
 
 136  
     @Override public int argCount() {
 137  8
         return 1;
 138  
     }
 139  
 
 140  
     @Override public List<FluentClass<?>> args() {
 141  0
         return new ArrayList<FluentClass<?>>();
 142  
     }
 143  
 
 144  
     @Override public FluentClass<?> type() {
 145  40
         final TypeLiteral<?> returnType = typeLiteral.getFieldType(field);
 146  40
         if (returnType == null) {
 147  0
             return null;
 148  
         }
 149  40
         return reflectedTypeFactory.reflect(returnType);
 150  
     }
 151  
 
 152  
     @Override public Object callRaw(final Object... args) {
 153  96
         if(args == null || args.length == 0 || args[0] == null) {
 154  8
             throw new ReflectionRuntimeException("reading a field requires an instance argument");
 155  88
         } else if (args.length > 2) {
 156  8
             throw new ReflectionRuntimeException("reading a field requires one argument, writing a field requires two arguments. Got " + args.length + " arguments");
 157  
         }
 158  
 
 159  
         try {
 160  80
             final Object fieldValue = field.get(args[0]);
 161  80
             if(args.length == 2)
 162  
             {
 163  40
                 field.set(args[0], args[1]);
 164  
             }
 165  80
             return fieldValue;
 166  0
         } catch (final IllegalArgumentException e) {
 167  0
             throw new IllegalArgumentRuntimeException(e, field, args[0]);
 168  0
         } catch (final IllegalAccessException e) {
 169  0
             throw new IllegalAccessRuntimeException(e, field);
 170  
         }
 171  
     }
 172  
 
 173  
     @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public FluentObject<?> call(final Object... args) {
 174  0
         final Object object = callRaw(args);
 175  0
         if(object == null) {
 176  0
             return null;
 177  
         }
 178  0
         return reflectedTypeFactory.reflect((Class) object.getClass(), object);
 179  
     }
 180  
 
 181  
     @Override public <T> FluentCall<T> as(final Class<T> returnType) {
 182  0
         return new AbstractCall<T>(reflectedTypeFactory) {
 183  
             @Override public T callRaw(final Object... args) {
 184  0
                 return returnType.cast(FluentFieldImpl.this.callRaw(args));
 185  
             }
 186  
         };
 187  
     }
 188  
 }