View Javadoc

1   /*
2    * Grapht, an open source dependency injector.
3    * Copyright 2014-2015 various contributors (see CONTRIBUTORS.txt)
4    * Copyright 2010-2014 Regents of the University of Minnesota
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU Lesser General Public License as
8    * published by the Free Software Foundation; either version 2.1 of the
9    * License, or (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13   * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14   * details.
15   *
16   * You should have received a copy of the GNU General Public License along with
17   * this program; if not, write to the Free Software Foundation, Inc., 51
18   * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19   */
20  package org.grouplens.grapht.reflect.internal;
21  
22  import org.grouplens.grapht.reflect.InjectionPoint;
23  import org.grouplens.grapht.util.FieldProxy;
24  import org.grouplens.grapht.util.Preconditions;
25  import org.grouplens.grapht.util.Types;
26  
27  import javax.annotation.Nonnull;
28  import javax.annotation.Nullable;
29  import java.io.InvalidObjectException;
30  import java.io.ObjectInputStream;
31  import java.io.Serializable;
32  import java.lang.annotation.Annotation;
33  import java.lang.reflect.Field;
34  import java.lang.reflect.Type;
35  import java.util.Collection;
36  
37  /**
38   * FieldInjectionPoint is an injection point wrapping a field.
39   *
40   * @author <a href="http://grouplens.org">GroupLens Research</a>
41   */
42  public final class FieldInjectionPoint implements InjectionPoint, Serializable {
43      private static final long serialVersionUID = -1L;
44      // transient because we use a serialization proxy
45      private final transient Field field;
46      private final transient AnnotationHelper annotations;
47  
48      /**
49       * Create an injection point wrapping the given field
50       *
51       * @param field The field to inject
52       * @throws NullPointerException if field is null
53       */
54      public FieldInjectionPoint(@Nonnull Field field) {
55          Preconditions.notNull("field", field);
56          this.field = field;
57          annotations = new AnnotationHelper(field.getAnnotations());
58      }
59  
60      @Override
61      public Type getType() {
62          return Types.box(field.getGenericType());
63      }
64  
65      @Override
66      public Class<?> getErasedType() {
67          return Types.box(field.getType());
68      }
69  
70      @Nullable
71      @Override
72      public Annotation getQualifier() {
73          return annotations.getQualifier();
74      }
75  
76      @Nullable
77      @Override
78      public <A extends Annotation> A getAttribute(Class<A> atype) {
79          return annotations.getAttribute(atype);
80      }
81  
82      @Nonnull
83      @Override
84      public Collection<Annotation> getAttributes() {
85          return annotations.getAttributes();
86      }
87  
88      @Override @Nonnull
89      public Field getMember() {
90          return field;
91      }
92  
93      @Override
94      public boolean isNullable() {
95          return Types.hasNullableAnnotation(field.getAnnotations());
96      }
97  
98      @Override
99      public boolean equals(Object o) {
100         if (!(o instanceof FieldInjectionPoint)) {
101             return false;
102         }
103         return ((FieldInjectionPoint) o).field.equals(field);
104     }
105 
106     @Override
107     public int hashCode() {
108         return field.hashCode();
109     }
110 
111     @Override
112     public String toString() {
113         StringBuilder sb = new StringBuilder();
114         sb.append("field ");
115         if (getQualifier() != null) {
116             sb.append(getQualifier())
117               .append(" ");
118         }
119         sb.append(field.getType().toString())
120           .append(" ")
121           .append(field.getName());
122         return sb.toString();
123     }
124 
125     private Object writeReplace() {
126         return new SerialProxy(field);
127     }
128 
129     private void readObject(ObjectInputStream stream) throws InvalidObjectException {
130         throw new InvalidObjectException("Serialization proxy required");
131     }
132 
133     private static class SerialProxy implements Serializable {
134         private static final long serialVersionUID = 1L;
135 
136         private final FieldProxy field;
137 
138         public SerialProxy(Field f) {
139             field = FieldProxy.of(f);
140         }
141 
142         private Object readResolve() throws InvalidObjectException {
143             try {
144                 return new FieldInjectionPoint(field.resolve());
145             } catch (ClassNotFoundException e) {
146                 InvalidObjectException ex =
147                         new InvalidObjectException("no class for " + field.toString());
148                 ex.initCause(e);
149                 throw ex;
150             } catch (NoSuchFieldException e) {
151                 InvalidObjectException ex =
152                         new InvalidObjectException("cannot resolve " + field.toString());
153                 ex.initCause(e);
154                 throw ex;
155             }
156         }
157     }
158 }