Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 29b1518532a0c34361abe3475a7c94b99201c5d0 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*******************************************************************************
 * Copyright (c) 2001, 2007 Oracle Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors:
 *     Oracle Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.jsf.core.internal.contentassist.el;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jst.jsf.common.internal.types.CompositeType;
import org.eclipse.jst.jsf.common.internal.types.IAssignable;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IDOMContextResolver;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IStructuredDocumentContextResolverFactory;
import org.eclipse.jst.jsf.context.resolver.structureddocument.ITaglibContextResolver;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext;
import org.eclipse.jst.jsf.context.symbol.IInstanceSymbol;
import org.eclipse.jst.jsf.context.symbol.IObjectSymbol;
import org.eclipse.jst.jsf.context.symbol.ISymbol;
import org.eclipse.jst.jsf.designtime.resolver.ISymbolContextResolver;
import org.eclipse.jst.jsf.designtime.resolver.StructuredDocumentSymbolResolverFactory;
import org.eclipse.jst.jsf.metadataprocessors.MetaDataEnabledProcessingFactory;
import org.eclipse.jst.jsf.metadataprocessors.features.ELIsNotValidException;
import org.eclipse.jst.jsf.metadataprocessors.features.IValidELValues;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Utility class for resolving symbols for a IStructuredDocumentContext.
 */
public class SymbolResolveUtil {

	private SymbolResolveUtil() {
		// utility class; not instantiable
	}

	/**
	 * Get symbol for a variable (managed bean name, bundle name)
	 * 
	 * @param context
	 * @param name
	 * @return ISymbol
	 */
	public static ISymbol getSymbolForVariable(
			final IStructuredDocumentContext context, final String name) {
		final ISymbolContextResolver symbolResolver = StructuredDocumentSymbolResolverFactory
				.getInstance().getSymbolContextResolver(context);

		return symbolResolver.getVariable(name);
	}

	/**
	 * Get symbol for a variable suffix (e. g. bean property/method, bundle
	 * property). Takes into account whether method bindings are expected for
	 * the given context.
	 * 
	 * @param context -
	 *            the IStructuredDocumentContext
	 * @param fullName -
	 *            full name of the suffix (e. g. bean.property1.property2)
	 * @param isLastSuffix -
	 *            set true if there follows no other suffix. Method names will
	 *            only be considered if true
	 * @return ISymbol. May be null.
	 */
	public static ISymbol getSymbolForVariableSuffixExpr(
			final IStructuredDocumentContext context, final String fullName,
			final boolean isLastSuffix) {
		String[] ids = fullName.split("\\."); //$NON-NLS-1$

		// if no suffixes, only one id
		if (ids.length < 1) {
			ids = new String[] { fullName };
		}

		final ISymbolContextResolver symbolResolver = StructuredDocumentSymbolResolverFactory
				.getInstance().getSymbolContextResolver(context);
		if (symbolResolver != null) {
			ISymbol symbol = symbolResolver.getVariable(ids[0]);
			if (symbol instanceof IInstanceSymbol
					&& ((IInstanceSymbol) symbol).isTypeResolved()) {
				for (int curSuffixIdx = 1; curSuffixIdx < ids.length; curSuffixIdx++) {
					if (isLastSuffix && curSuffixIdx == ids.length - 1
							&& isMethodBindingExpected(context)) {
						/*
						 * TODO Take into acount required method signature,
						 * since there may be different methods with the same
						 * name
						 */
						return symbolResolver.getMethod((IObjectSymbol) symbol,
								ids[curSuffixIdx]);
					}

					final ISymbol property = symbolResolver.getProperty(symbol,
							ids[curSuffixIdx]);

					if (property == null) {
						return null;
					}
					symbol = property;
				}
				return symbol;
			}
		}
		return null;
	}

	/**
	 * Tells whether method bindings are expected for the given context.
	 * 
	 * @param context -
	 *            the IStructuredDocumentContext
	 * @return true, if method bindings expected
	 */
	public static boolean isMethodBindingExpected(
			final IStructuredDocumentContext context) {
		return isMethodBindingExpected(context, null);
	}

	/**
	 * Tells whether method bindings are expected for the given context. Will
	 * add signatures of expected method bindings to a given list.
	 * 
	 * @param context -
	 *            the IStructuredDocumentContext
	 * @param expectedBindings -
	 *            a list. If not null, signatures of expected method bindings
	 *            will be appended to this list.
	 * @return true, if method bindings expected
	 */
	public static boolean isMethodBindingExpected(
			final IStructuredDocumentContext context,
			final List expectedBindings) {
		final IDOMContextResolver domResolver = IStructuredDocumentContextResolverFactory.INSTANCE
				.getDOMContextResolver(context);

		final Node curNode = domResolver.getNode();

		if (curNode instanceof Attr) {
			final Attr attr = (Attr) curNode;
			final Element element = attr.getOwnerElement();

			final ITaglibContextResolver taglibResolver = IStructuredDocumentContextResolverFactory.INSTANCE
					.getTaglibContextResolver(context);

			final String uri = taglibResolver.getTagURIForNodeName(element);

			final List elVals = MetaDataEnabledProcessingFactory.getInstance()
					.getAttributeValueRuntimeTypeFeatureProcessors(
							IValidELValues.class, context, uri,
							element.getLocalName(), attr.getLocalName());

			boolean methodBindingExpected = false;
			for (final Iterator it = elVals.iterator(); it.hasNext();) {
				final IValidELValues validValues = (IValidELValues) it.next();

				try {
					final CompositeType type = validValues
							.getExpectedRuntimeType();
					if (type != null
							&& type.getAssignmentTypeMask() == IAssignable.ASSIGNMENT_TYPE_NONE) {
						methodBindingExpected = true;
						if (expectedBindings != null) {
							expectedBindings.addAll(Arrays.asList(validValues
									.getExpectedRuntimeType().getSignatures()));
						} else {
							// if we don't need the method signatures, *one*
							// expected method binding is sufficient.
							return true;
						}
					}
				} catch (final ELIsNotValidException e) {
					// do nothing
				}
			}
			return methodBindingExpected;
		}
		// default condition is no method binding
		return false;
	}

}

Back to the top