1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.grouplens.grapht.reflect.internal;
21
22 import org.grouplens.grapht.CachePolicy;
23 import org.grouplens.grapht.Instantiator;
24 import org.grouplens.grapht.LifecycleManager;
25 import org.grouplens.grapht.reflect.Desire;
26 import org.grouplens.grapht.reflect.Satisfaction;
27 import org.grouplens.grapht.reflect.SatisfactionVisitor;
28 import org.grouplens.grapht.util.ClassProxy;
29 import org.grouplens.grapht.util.Preconditions;
30 import org.grouplens.grapht.util.Types;
31
32 import javax.inject.Singleton;
33 import java.io.InvalidObjectException;
34 import java.io.ObjectInputStream;
35 import java.io.ObjectStreamException;
36 import java.io.Serializable;
37 import java.lang.reflect.Modifier;
38 import java.lang.reflect.Type;
39 import java.util.List;
40 import java.util.Map;
41
42
43
44
45
46
47
48
49 public class ClassSatisfaction implements Satisfaction, Serializable {
50 private static final long serialVersionUID = -1L;
51 private final transient Class<?> type;
52
53
54
55
56
57
58
59
60 public ClassSatisfaction(Class<?> type) {
61 Preconditions.notNull("type", type);
62 int mods = type.getModifiers();
63 if (Modifier.isAbstract(mods) || Modifier.isInterface(mods)) {
64 throw new IllegalArgumentException("Satisfaction " + type + " is abstract");
65 }
66 if (!Types.isInstantiable(type)) {
67 throw new IllegalArgumentException("Satisfaction " + type + " is not instantiable");
68 }
69
70 this.type = Types.box(type);
71 }
72
73 @Override
74 public CachePolicy getDefaultCachePolicy() {
75 return (getErasedType().getAnnotation(Singleton.class) != null ? CachePolicy.MEMOIZE : CachePolicy.NO_PREFERENCE);
76 }
77
78 @Override
79 public List<Desire> getDependencies() {
80 return ReflectionDesire.getDesires(type);
81 }
82
83 @Override
84 public Type getType() {
85 return type;
86 }
87
88 @Override
89 public Class<?> getErasedType() {
90 return type;
91 }
92
93 @Override
94 public boolean hasInstance() {
95 return false;
96 }
97
98 @Override
99 public <T> T visit(SatisfactionVisitor<T> visitor) {
100 return visitor.visitClass(type);
101 }
102
103 @Override
104 @SuppressWarnings({ "rawtypes", "unchecked" })
105 public Instantiator makeInstantiator(Map<Desire,Instantiator> dependencies, LifecycleManager lm) {
106 return new ClassInstantiator(type, getDependencies(), dependencies, lm);
107 }
108
109 @Override
110 public boolean equals(Object o) {
111 if (!(o instanceof ClassSatisfaction)) {
112 return false;
113 }
114 return ((ClassSatisfaction) o).type.equals(type);
115 }
116
117 @Override
118 public int hashCode() {
119 return type.hashCode();
120 }
121
122 @Override
123 public String toString() {
124 return "Class(" + type.getName() + ")";
125 }
126
127 private Object writeReplace() {
128 return new SerialProxy(type);
129 }
130
131 private void readObject(ObjectInputStream stream) throws ObjectStreamException {
132 throw new InvalidObjectException("must use serialization proxy");
133 }
134
135 private static class SerialProxy implements Serializable {
136 private static final long serialVersionUID = 1L;
137
138 private final ClassProxy type;
139
140 public SerialProxy(Class<?> cls) {
141 type = ClassProxy.of(cls);
142 }
143
144 private Object readResolve() throws ObjectStreamException {
145 try {
146 return new ClassSatisfaction(type.resolve());
147 } catch (ClassNotFoundException e) {
148 InvalidObjectException ex = new InvalidObjectException("cannot resolve " + type);
149 ex.initCause(e);
150 throw ex;
151 }
152 }
153 }
154 }