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.*;
23  import org.grouplens.grapht.reflect.Desire;
24  import org.grouplens.grapht.reflect.Satisfaction;
25  import org.grouplens.grapht.reflect.SatisfactionVisitor;
26  import org.grouplens.grapht.util.ClassProxy;
27  import org.grouplens.grapht.util.Preconditions;
28  import org.grouplens.grapht.util.Types;
29  
30  import javax.inject.Singleton;
31  import java.io.InvalidObjectException;
32  import java.io.ObjectInputStream;
33  import java.io.ObjectStreamException;
34  import java.io.Serializable;
35  import java.lang.reflect.Type;
36  import java.util.Collections;
37  import java.util.List;
38  import java.util.Map;
39  
40  /**
41   * NullSatisfaction is a satisfaction that explicitly satisfies desires with the
42   * <code>null</code> value.
43   * 
44   * @author <a href="http://grouplens.org">GroupLens Research</a>
45   */
46  public class
47          NullSatisfaction implements Satisfaction, Serializable {
48      private static final long serialVersionUID = -1L;
49      private final transient Class<?> type;
50      
51      /**
52       * Create a NullSatisfaction that uses <code>null</code> to satisfy the
53       * given class type.
54       * 
55       * @param type The type to satisfy
56       * @throws NullPointerException if type is null
57       */
58      public NullSatisfaction(Class<?> type) {
59          Preconditions.notNull("type", type);
60          this.type = Types.box(type);
61      }
62      
63      @Override
64      public CachePolicy getDefaultCachePolicy() {
65          return (getErasedType().getAnnotation(Singleton.class) != null ? CachePolicy.MEMOIZE : CachePolicy.NO_PREFERENCE);
66      }
67      
68      @Override
69      public List<Desire> getDependencies() {
70          return Collections.emptyList();
71      }
72  
73      @Override
74      public Type getType() {
75          return type;
76      }
77  
78      @Override
79      public Class<?> getErasedType() {
80          return type;
81      }
82  
83      @Override
84      public boolean hasInstance() {
85          // Null satisfactions have instances, just null ones.
86          return true;
87      }
88  
89      @Override
90      public <T> T visit(SatisfactionVisitor<T> visitor) {
91          return visitor.visitNull();
92      }
93  
94      @Override
95      @SuppressWarnings({ "unchecked", "rawtypes" })
96      public Instantiator makeInstantiator(Map<Desire,Instantiator> dependencies,
97                                           LifecycleManager lm) {
98          return Instantiators.ofNull(type);
99      }
100     
101     @Override
102     public boolean equals(Object o) {
103         if (!(o instanceof NullSatisfaction)) {
104             return false;
105         }
106         return ((NullSatisfaction) o).type.equals(type);
107     }
108     
109     @Override
110     public int hashCode() {
111         return type.hashCode();
112     }
113     
114     @Override
115     public String toString() {
116         return "Null(" + type.getSimpleName() + ")";
117     }
118 
119     private Object writeReplace() {
120         return new SerialProxy(type);
121     }
122 
123     private void readObject(ObjectInputStream stream) throws ObjectStreamException {
124         throw new InvalidObjectException("must use serialization proxy");
125     }
126 
127     private static class SerialProxy implements Serializable {
128         private static final long serialVersionUID = 1L;
129 
130         private final ClassProxy type;
131 
132         public SerialProxy(Class<?> cls) {
133             type = ClassProxy.of(cls);
134         }
135 
136         private Object readResolve() throws ObjectStreamException {
137             try {
138                 return new NullSatisfaction(type.resolve());
139             } catch (ClassNotFoundException e) {
140                 InvalidObjectException ex = new InvalidObjectException("cannot resolve " + type);
141                 ex.initCause(e);
142                 throw ex;
143             }
144         }
145     }
146 }