| /******************************************************************************* |
| * 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; |
| } |
| |
| } |