001    package org.mesopotamia.lang.java.ref;
002    
003    import java.lang.ref.SoftReference;
004    import java.util.ArrayList;
005    import java.util.HashMap;
006    import java.util.List;
007    import java.util.Map;
008    import java.util.concurrent.ConcurrentHashMap;
009    
010    /**
011     * Type info which caches resolved types, methods, and variables
012     * in soft references and other values in hard references.
013     * @author Pavel
014     *
015     */
016    public abstract class SoftCachingTypeInfo implements TypeInfo {
017                    
018            private static final MethodInfo NO_METHOD_INFO = new MethodInfo() {
019    
020                    public List<TypeInfo> getExceptionTypes() {
021                            throw new UnsupportedOperationException();
022                    }
023    
024                    public List<TypeSpecInfo> getParameterTypes() {
025                            throw new UnsupportedOperationException();
026                    }
027    
028                    public TypeSpecInfo getReturnType() {
029                            throw new UnsupportedOperationException();
030                    }
031    
032                    public TypeInfo getDeclaringType() {
033                            throw new UnsupportedOperationException();
034                    }
035    
036                    public String getFcn() {
037                            throw new UnsupportedOperationException();
038                    }
039    
040                    public List<String> getModifiers() {
041                            throw new UnsupportedOperationException();
042                    }
043    
044                    public String getName() {
045                            throw new UnsupportedOperationException();
046                    }
047                    
048            };
049    
050            private Map<List<String>, SoftReference<MethodInfo>> methodInfoCache = new ConcurrentHashMap<List<String>, SoftReference<MethodInfo>>();
051            
052            public MethodInfo findTypeMethod(String name, String[] parameterTypes) {
053                    List<String> key = new ArrayList<String>();
054                    key.add(name);
055                    if (parameterTypes!=null) {
056                            for (String pt: parameterTypes) {
057                                    key.add(pt);
058                            }
059                    }
060                    
061                    SoftReference<MethodInfo> ref = methodInfoCache.get(key);
062                    MethodInfo ret = ref==null ? null : ref.get();
063                    if (ret == null) {
064                            ret = findMethodInternal(name, parameterTypes);
065                            if (ret == null) {
066                                    ret = NO_METHOD_INFO;
067                            }
068                            methodInfoCache.put(key, new SoftReference<MethodInfo>(ret));
069                    }
070                    return ret==NO_METHOD_INFO ? null : ret;
071            }
072            
073            private Map<List<String>, SoftReference<MethodInfo>> constructorInfoCache = new ConcurrentHashMap<List<String>, SoftReference<MethodInfo>>();
074            
075            public MethodInfo findConstructor(String[] parameterTypes) {
076                    List<String> key = new ArrayList<String>();
077                    if (parameterTypes!=null) {
078                            for (String pt: parameterTypes) {
079                                    key.add(pt);
080                            }
081                    }
082                    
083                    SoftReference<MethodInfo> ref = constructorInfoCache.get(key);
084                    MethodInfo ret = ref==null ? null : ref.get();
085                    if (ret == null) {
086                            ret = findConstructorInternal(parameterTypes);
087                            if (ret == null) {
088                                    ret = NO_METHOD_INFO;
089                            }
090                            constructorInfoCache.put(key, new SoftReference<MethodInfo>(ret));
091                    }
092                    return ret==NO_METHOD_INFO ? null : ret;
093            }
094            
095            protected abstract MethodInfo findConstructorInternal(String[] parameterTypes);
096            protected abstract MethodInfo findMethodInternal(String name, String[] parameterTypes);
097    
098            private static final TypeInfo NO_TYPE_INFO = new TypeInfo() {
099    
100                    public MethodInfo findConstructor(String[] argumentTypes) {
101                            throw new UnsupportedOperationException();
102                    }
103    
104                    public TypeInfo findNestedType(String name) {
105                            throw new UnsupportedOperationException();
106                    }
107    
108                    public MethodInfo findTypeMethod(String name, String[] argumentTypes) {
109                            throw new UnsupportedOperationException();
110                    }
111    
112                    public VariableInfo findTypeVariable(String name) {
113                            throw new UnsupportedOperationException();
114                    }
115    
116                    public boolean isKindOf(String superFcn) {
117                            throw new UnsupportedOperationException();
118                    }
119    
120                    public TypeInfo getDeclaringType() {
121                            throw new UnsupportedOperationException();
122                    }
123    
124                    public String getFcn() {
125                            throw new UnsupportedOperationException();
126                    }
127    
128                    public List<String> getModifiers() {
129                            throw new UnsupportedOperationException();
130                    }
131    
132                    public String getName() {
133                            throw new UnsupportedOperationException();
134                    }
135                    
136            };
137            
138            private Map<String, SoftReference<TypeInfo>> typeInfoCache = new ConcurrentHashMap<String, SoftReference<TypeInfo>>();
139            
140            public TypeInfo findNestedType(String name) {
141                    SoftReference<TypeInfo> ref = typeInfoCache.get(name);
142                    TypeInfo ret = ref==null ? null : ref.get();
143                    if (ret == null) {
144                            ret = findNestedTypeInternal(name);
145                            if (ret == null) {
146                                    ret = NO_TYPE_INFO;
147                            }
148                            typeInfoCache.put(name, new SoftReference<TypeInfo>(ret));
149                    }
150                    return ret==NO_TYPE_INFO ? null : ret;
151            }       
152    
153            protected abstract TypeInfo findNestedTypeInternal(String name);
154    
155            private static final VariableInfo NO_VARIABLE_INFO = new VariableInfo() {
156    
157                    public TypeSpecInfo getTypeSpecification() {
158                            throw new UnsupportedOperationException();
159                    }
160    
161                    public TypeInfo getDeclaringType() {
162                            throw new UnsupportedOperationException();
163                    }
164    
165                    public String getFcn() {
166                            throw new UnsupportedOperationException();
167                    }
168    
169                    public List<String> getModifiers() {
170                            throw new UnsupportedOperationException();
171                    }
172    
173                    public String getName() {
174                            throw new UnsupportedOperationException();
175                    }
176                    
177            };
178            
179            private Map<String, SoftReference<VariableInfo>> variableInfoCache = new ConcurrentHashMap<String, SoftReference<VariableInfo>>();
180            
181            public VariableInfo findTypeVariable(String name) {
182                    SoftReference<VariableInfo> ref = variableInfoCache.get(name);
183                    VariableInfo ret = ref==null ? null : ref.get();
184                    if (ret == null) {
185                            ret = findTypeVariableInternal(name);
186                            if (ret == null) {
187                                    ret = NO_VARIABLE_INFO;
188                            }
189                            variableInfoCache.put(name, new SoftReference<VariableInfo>(ret));
190                    }
191                    return ret==NO_VARIABLE_INFO ? null : ret;
192            }
193    
194            protected abstract VariableInfo findTypeVariableInternal(String name);
195            
196            private Map<String, Boolean> isKindOfMap = new HashMap<String, Boolean>();
197    
198            public boolean isKindOf(String superFcn) {
199                    Boolean ret = isKindOfMap.get(superFcn);
200                    if (ret==null) {
201                            ret = isKindOfInternal(superFcn) ? Boolean.TRUE : Boolean.FALSE;
202                            isKindOfMap.put(superFcn, ret);
203                    }
204                    return ret.booleanValue();
205            }
206    
207            protected abstract boolean isKindOfInternal(String superFcn);
208    
209            private TypeInfo declaringType;
210            private boolean isDeclaringTypeRetrieved;
211            protected abstract TypeInfo getDeclaringTypeInternal(); 
212            
213            public TypeInfo getDeclaringType() {
214                    if (!isDeclaringTypeRetrieved) {
215                            declaringType = getDeclaringTypeInternal();
216                            isDeclaringTypeRetrieved = true;
217                    }
218                    return declaringType;
219            }
220            
221            private String fcn;
222            private boolean isFcnRetrieved;
223            protected abstract String getFcnInternal();
224    
225            public String getFcn() {
226                    if (!isFcnRetrieved) {
227                            fcn = getFcnInternal();
228                            isFcnRetrieved = true;
229                    }
230                    return fcn;
231            }
232    
233            private List<String> modifiers;
234            private boolean areModifiersRetrieved;
235            protected abstract List<String> getModifiersInternal();
236            
237            public List<String> getModifiers() {
238                    if (!areModifiersRetrieved) {
239                            modifiers = getModifiersInternal();
240                            areModifiersRetrieved = true;
241                    }
242                    return modifiers;
243            }
244    
245    }