blob: 158d3cb9fac61d8e7c99272195ad65ba76bdf9b3 [file] [log] [blame]
rsrinivasancf824322008-05-02 19:51:19 +00001/*******************************************************************************
2 * Copyright (c) 2001, 2008 Oracle Corporation and others.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Oracle Corporation - initial API and implementation
10 *******************************************************************************/
cbatemana90783d2008-02-12 07:58:15 +000011package org.eclipse.jst.jsf.designtime.resolver;
12
13import java.util.HashMap;
14import java.util.Map;
15
16import org.eclipse.jst.jsf.context.IModelContext;
17import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext;
18import org.eclipse.jst.jsf.context.symbol.IMethodSymbol;
19import org.eclipse.jst.jsf.context.symbol.IObjectSymbol;
20import org.eclipse.jst.jsf.context.symbol.ISymbol;
21import org.eclipse.jst.jsf.context.symbol.SymbolFactory;
22
23/**
24 * A symbol resolver that delegates to the default SymbolContextResolver, but
25 * caches the results and returns those on subsequent calls.
26 *
27 * WARNING: this resolver is suitable *only* in situations where the state
28 * of dependent symbol sources won't change between calls. This resolver makes
29 * no attempt to ensure that cached data is in sync with changes to symbols
30 * such addition, modification or removal of Java class underlying beans.
31 *
32 * NOTE: this resolver is experimental and should NOT be considered API
33 *
34 * Clients should not use this resolver directly. Access it through the factory instead
35 * @author cbateman
36 *
37 */
38public final class CachingSymbolContextResolver extends AbstractSymbolContextResolver
39{
40 private final static ISymbol SYMBOL_NOT_FOUND = SymbolFactory.eINSTANCE.createIComponentSymbol();
cbateman7d3f5182009-08-19 19:22:30 +000041 private final static ISymbol PROPERTY_NOT_FOUND = SymbolFactory.eINSTANCE.createIPropertySymbol();
cbatemana90783d2008-02-12 07:58:15 +000042 private final static IMethodSymbol METHOD_SYMBOL_NOT_FOUND =
43 SymbolFactory.eINSTANCE.createIMethodSymbol();
44
cbateman5a4ac102009-08-19 18:23:55 +000045 private final ISymbolContextResolver _delegate;
cbatemana90783d2008-02-12 07:58:15 +000046
47 private final Map<String, ISymbol> _variablesByName = new HashMap<String, ISymbol>();
48 private ISymbol[] _allVariables;
49
50 private final Map<ISymbol, Map<Object, ISymbol>> _propertiesByOwner =
51 new HashMap<ISymbol, Map<Object,ISymbol>>();
52 private ISymbol[] _allProperties;
53
54 private final Map<IObjectSymbol, Map<Object, IMethodSymbol>> _methodsByOwner =
55 new HashMap<IObjectSymbol, Map<Object,IMethodSymbol>>();
56 private ISymbol[] _allMethods;
57
58 /**
59 * @param context
60 */
61 public CachingSymbolContextResolver(final IStructuredDocumentContext context)
62 {
63 _delegate = new SymbolContextResolver(context);
64 }
65
cbateman5a4ac102009-08-19 18:23:55 +000066 /**
67 * @param delegate
68 */
69 public CachingSymbolContextResolver(final ISymbolContextResolver delegate)
70 {
71 _delegate = delegate;
72 }
73
cbatemana90783d2008-02-12 07:58:15 +000074 @Override
75 public boolean canResolveContext(final IModelContext modelContext)
76 {
77 return _delegate.canResolveContext(modelContext);
78 }
79
80 @Override
81 public ISymbol[] getAllVariables()
82 {
83 if (_allVariables == null)
84 {
85 _allVariables = _delegate.getAllVariables();
86 }
87 return _allVariables;
88 }
89
90 @Override
91 public IMethodSymbol getMethod(final IObjectSymbol base, final Object methodName)
92 {
93 Map<Object, IMethodSymbol> methods = _methodsByOwner.get(base);
94
95 if (methods == null)
96 {
97 methods = new HashMap<Object, IMethodSymbol>();
98 _methodsByOwner.put(base, methods);
99 }
100
101 IMethodSymbol method = methods.get(methodName);
102
cbateman7d3f5182009-08-19 19:22:30 +0000103 if (method == METHOD_SYMBOL_NOT_FOUND)
cbatemana90783d2008-02-12 07:58:15 +0000104 {
105 method = null;
106 }
107 else
108 {
109 if (method == null)
110 {
111 method = _delegate.getMethod(base, methodName);
112
113 if (method == null)
114 {
115 // if the delegate couldn't find the property,
116 // then mark this in case it is requested again
117 methods.put(methodName, METHOD_SYMBOL_NOT_FOUND);
118 }
119 else
120 {
121 methods.put(methodName, method);
122 }
123 }
124 }
125 return method;
126 }
127
128 @Override
129 public ISymbol[] getMethods(final IObjectSymbol base)
130 {
131 if (_allMethods == null)
132 {
133 _allMethods = _delegate.getMethods(base);
134 }
135 return _allMethods;
136 }
137
138 @Override
139 public ISymbol[] getProperties(final ISymbol symbol)
140 {
141 if (_allProperties == null)
142 {
143 _allProperties = _delegate.getProperties(symbol);
144 }
145 return _allProperties;
146 }
147
148 @Override
149 public ISymbol getProperty(final ISymbol symbol, final Object propertyName)
150 {
151 Map<Object, ISymbol> properties = _propertiesByOwner.get(symbol);
152
153 if (properties == null)
154 {
155 properties = new HashMap<Object, ISymbol>();
156 _propertiesByOwner.put(symbol, properties);
157 }
158
159 ISymbol property = properties.get(propertyName);
160
cbateman7d3f5182009-08-19 19:22:30 +0000161 if (property == PROPERTY_NOT_FOUND)
cbatemana90783d2008-02-12 07:58:15 +0000162 {
163 property = null;
164 }
165 else
166 {
167 if (property == null)
168 {
169 property = _delegate.getProperty(symbol, propertyName);
170
171 if (property == null)
172 {
173 // if the delegate couldn't find the property,
174 // then mark this in case it is requested again
cbateman7d3f5182009-08-19 19:22:30 +0000175 properties.put(propertyName, PROPERTY_NOT_FOUND);
cbatemana90783d2008-02-12 07:58:15 +0000176 }
177 else
178 {
179 properties.put(propertyName, property);
180 }
181 }
182 }
183 return property;
184 }
185
186 @Override
187 public ISymbol getVariable(final String name)
188 {
189 ISymbol variable = _variablesByName.get(name);
190
191 // if the symbol was not found, return null but avoid calling the
192 // delegate again
193 if (variable == SYMBOL_NOT_FOUND)
194 {
195 variable = null;
196 }
197 else
198 {
199 if (variable == null)
200 {
201 variable = _delegate.getVariable(name);
202
203 if (variable == null)
204 {
205 // if the delegate couldn't find the variable,
206 // then mark this in case it is requested again
207 _variablesByName.put(name, SYMBOL_NOT_FOUND);
208 }
209 else
210 {
211 _variablesByName.put(name, variable);
212 }
213 }
214 }
215 return variable;
216 }
217
218 @Override
219 public boolean hasSameResolution(IModelContext modelContext)
220 {
221 return _delegate.hasSameResolution(modelContext);
222 }
223}