001    package org.mesopotamia.lang.java.ref;
002    
003    import java.lang.ref.SoftReference;
004    import java.util.ArrayList;
005    import java.util.List;
006    import java.util.Map;
007    import java.util.concurrent.ConcurrentHashMap;
008    
009    /**
010     * Scope which caches resolved types, variables and methods
011     * using soft references.
012     * @author Pavel
013     */
014    public abstract class SoftCachingScope implements Scope {
015            
016            private static final MethodInfo NO_METHOD_INFO = new MethodInfo() {
017    
018                    public List<TypeInfo> getExceptionTypes() {
019                            throw new UnsupportedOperationException();
020                    }
021    
022                    public List<TypeSpecInfo> getParameterTypes() {
023                            throw new UnsupportedOperationException();
024                    }
025    
026                    public TypeSpecInfo getReturnType() {
027                            throw new UnsupportedOperationException();
028                    }
029    
030                    public TypeInfo getDeclaringType() {
031                            throw new UnsupportedOperationException();
032                    }
033    
034                    public String getFcn() {
035                            throw new UnsupportedOperationException();
036                    }
037    
038                    public List<String> getModifiers() {
039                            throw new UnsupportedOperationException();
040                    }
041    
042                    public String getName() {
043                            throw new UnsupportedOperationException();
044                    }
045                    
046            };
047    
048            private Map<List<String>, SoftReference<MethodInfo>> methodInfoCache = new ConcurrentHashMap<List<String>, SoftReference<MethodInfo>>();
049            
050            public MethodInfo findMethod(String name, String[] parameterTypes) {
051                    List<String> key = new ArrayList<String>();
052                    key.add(name);
053                    if (parameterTypes!=null) {
054                            for (String pt: parameterTypes) {
055                                    key.add(pt);
056                            }
057                    }
058                    
059                    SoftReference<MethodInfo> ref = methodInfoCache.get(key);
060                    MethodInfo ret = ref==null ? null : ref.get();
061                    if (ret == null) {
062                            ret = findMethodInternal(name, parameterTypes);
063                            if (ret == null) {
064                                    ret = NO_METHOD_INFO;
065                            }
066                            methodInfoCache.put(key, new SoftReference<MethodInfo>(ret));
067                    }
068                    return ret==NO_METHOD_INFO ? null : ret;
069            }
070            
071            protected abstract MethodInfo findMethodInternal(String name, String[] parameterTypes);
072    
073            private static final TypeInfo NO_TYPE_INFO = new TypeInfo() {
074    
075                    public MethodInfo findConstructor(String[] argumentTypes) {
076                            throw new UnsupportedOperationException();
077                    }
078    
079                    public TypeInfo findNestedType(String name) {
080                            throw new UnsupportedOperationException();
081                    }
082    
083                    public MethodInfo findTypeMethod(String name, String[] argumentTypes) {
084                            throw new UnsupportedOperationException();
085                    }
086    
087                    public VariableInfo findTypeVariable(String name) {
088                            throw new UnsupportedOperationException();
089                    }
090    
091                    public boolean isKindOf(String superFcn) {
092                            throw new UnsupportedOperationException();
093                    }
094    
095                    public TypeInfo getDeclaringType() {
096                            throw new UnsupportedOperationException();
097                    }
098    
099                    public String getFcn() {
100                            throw new UnsupportedOperationException();
101                    }
102    
103                    public List<String> getModifiers() {
104                            throw new UnsupportedOperationException();
105                    }
106    
107                    public String getName() {
108                            throw new UnsupportedOperationException();
109                    }
110                    
111            };
112            
113            private Map<String, SoftReference<TypeInfo>> typeInfoCache = new ConcurrentHashMap<String, SoftReference<TypeInfo>>();
114            
115            public TypeInfo findType(String name) {
116                    SoftReference<TypeInfo> ref = typeInfoCache.get(name);
117                    TypeInfo ret = ref==null ? null : ref.get();
118                    if (ret == null) {
119                            ret = findTypeInternal(name);
120                            if (ret == null) {
121                                    ret = NO_TYPE_INFO;
122                            }
123                            typeInfoCache.put(name, new SoftReference<TypeInfo>(ret));
124                    }
125                    return ret==NO_TYPE_INFO ? null : ret;
126            }       
127    
128            protected abstract TypeInfo findTypeInternal(String name);
129    
130            private static final VariableInfo NO_VARIABLE_INFO = new VariableInfo() {
131    
132                    public TypeSpecInfo getTypeSpecification() {
133                            throw new UnsupportedOperationException();
134                    }
135    
136                    public TypeInfo getDeclaringType() {
137                            throw new UnsupportedOperationException();
138                    }
139    
140                    public String getFcn() {
141                            throw new UnsupportedOperationException();
142                    }
143    
144                    public List<String> getModifiers() {
145                            throw new UnsupportedOperationException();
146                    }
147    
148                    public String getName() {
149                            throw new UnsupportedOperationException();
150                    }
151                    
152            };
153            
154            private Map<String, SoftReference<VariableInfo>> variableInfoCache = new ConcurrentHashMap<String, SoftReference<VariableInfo>>();
155            
156            public VariableInfo findVariable(String name) {
157                    SoftReference<VariableInfo> ref = variableInfoCache.get(name);
158                    VariableInfo ret = ref==null ? null : ref.get();
159                    if (ret == null) {
160                            ret = findVariableInternal(name);
161                            if (ret == null) {
162                                    ret = NO_VARIABLE_INFO;
163                            }
164                            variableInfoCache.put(name, new SoftReference<VariableInfo>(ret));
165                    }
166                    return ret==NO_VARIABLE_INFO ? null : ret;
167            }
168    
169            protected abstract VariableInfo findVariableInternal(String name);
170            
171    }