/******************************************************************************* * Copyright (c) 2011 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is 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 * * Contributor: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.jboss.tools.jsf.model; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeSet; import org.eclipse.core.resources.IFile; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.IDocument; import org.jboss.tools.common.el.core.ca.AbstractELCompletionEngine; import org.jboss.tools.common.el.core.ca.MessagesELTextProposal; import org.jboss.tools.common.el.core.model.ELArgumentInvocation; import org.jboss.tools.common.el.core.model.ELExpression; import org.jboss.tools.common.el.core.model.ELInstance; import org.jboss.tools.common.el.core.model.ELInvocationExpression; import org.jboss.tools.common.el.core.model.ELModel; import org.jboss.tools.common.el.core.model.ELObjectType; import org.jboss.tools.common.el.core.model.ELPropertyInvocation; import org.jboss.tools.common.el.core.parser.ELParser; import org.jboss.tools.common.el.core.parser.ELParserFactory; import org.jboss.tools.common.el.core.parser.ELParserUtil; import org.jboss.tools.common.el.core.resolver.ELContext; import org.jboss.tools.common.el.core.resolver.ELResolution; import org.jboss.tools.common.el.core.resolver.ELResolutionImpl; import org.jboss.tools.common.el.core.resolver.ELSegmentImpl; import org.jboss.tools.common.el.core.resolver.IRelevanceCheck; import org.jboss.tools.common.el.core.resolver.IVariable; import org.jboss.tools.common.el.core.resolver.TypeInfoCollector.MemberInfo; import org.jboss.tools.common.model.XModel; import org.jboss.tools.common.model.XModelObject; import org.jboss.tools.common.model.project.IModelNature; import org.jboss.tools.common.model.util.EclipseResourceUtil; import org.jboss.tools.common.model.util.PositionHolder; import org.jboss.tools.common.text.TextProposal; import org.jboss.tools.common.text.ext.util.StructuredModelWrapper; import org.jboss.tools.common.text.ext.util.Utils; import org.jboss.tools.common.util.StringUtil; import org.jboss.tools.jsf.JSFModelPlugin; import org.jboss.tools.jsf.model.helpers.converter.OpenKeyHelper; import org.jboss.tools.jst.web.kb.IPageContext; import org.jboss.tools.jst.web.kb.IResourceBundle; import org.jboss.tools.jst.web.kb.PageContextFactory; import org.jboss.tools.jst.web.kb.el.MessagePropertyELSegmentImpl; import org.jboss.tools.jst.web.project.list.WebPromptingProvider; import org.w3c.dom.Attr; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; public class JSFMessageELCompletionEngine extends AbstractELCompletionEngine<IVariable> { private static final ImageDescriptor JSF_EL_MESSAGES_PROPOSAL_IMAGE = JSFModelPlugin.getDefault().getImageDescriptorFromRegistry(JSFModelPlugin.CA_JSF_MESSAGES_IMAGE_PATH); private static final List<Variable> EMPTY_VARIABLES = Collections.unmodifiableList(new ArrayList<Variable>()); /* * (non-Javadoc) * @see org.jboss.tools.common.el.core.ca.AbstractELCompletionEngine#getELProposalImageForMember(org.jboss.tools.common.el.core.resolver.TypeInfoCollector.MemberInfo) */ @Override public ImageDescriptor getELProposalImageForMember(MemberInfo memberInfo) { return JSF_EL_MESSAGES_PROPOSAL_IMAGE; } private static ELParserFactory factory = ELParserUtil.getDefaultFactory(); public JSFMessageELCompletionEngine() {} /* * (non-Javadoc) * @see org.jboss.tools.common.el.core.resolver.ELResolver#getParserFactory() */ public ELParserFactory getParserFactory() { return factory; } /* * (non-Javadoc) * @see org.jboss.tools.common.el.core.ca.AbstractELCompletionEngine#log(java.lang.Exception) */ protected void log(Exception e) { JSFModelPlugin.getPluginLog().logError(e); } /* * (non-Javadoc) * @see org.jboss.tools.common.el.core.resolver.ELResolver2#getProposals(org.jboss.tools.common.el.core.resolver.ELContext, java.lang.String) */ public List<TextProposal> getProposals(ELContext context, String el, int offset) { currentOffset = offset; return getCompletions(el, false, 0, context); } public List<TextProposal> getCompletions(String elString, boolean returnEqualedVariablesOnly, int position, ELContext context) { IDocument document = null; IResourceBundle[] bundles = new IResourceBundle[0]; if(context instanceof IPageContext) { IPageContext pageContext = (IPageContext)context; document = pageContext.getDocument(); bundles = pageContext.getResourceBundles(); } List<TextProposal> proposals = null; try { proposals = getCompletions(context.getResource(), document, elString.subSequence(0, elString.length()), position, returnEqualedVariablesOnly, bundles); } catch (StringIndexOutOfBoundsException e) { log(e); } catch (BadLocationException e) { log(e); } return proposals; } int currentOffset = 0; /* * (non-Javadoc) * @see org.jboss.tools.common.el.core.resolver.ELResolver2#resolve(org.jboss.tools.common.el.core.resolver.ELContext, org.jboss.tools.common.el.core.model.ELExpression) */ public ELResolution resolve(ELContext context, ELExpression operand, int offset) { currentOffset = offset; ELResolutionImpl resolution = resolveELOperand(operand, context, true); if(resolution != null) resolution.setContext(context); return resolution; } public ELResolutionImpl resolveELOperand(ELExpression operand, ELContext context, boolean returnEqualedVariablesOnly) { IResourceBundle[] bundles = new IResourceBundle[0]; if(context instanceof IPageContext) { IPageContext pageContext = (IPageContext)context; bundles = pageContext.getResourceBundles(); } try { return resolveELOperand(context.getResource(), operand, returnEqualedVariablesOnly, bundles); } catch (StringIndexOutOfBoundsException e) { log(e); } catch (BadLocationException e) { log(e); } return null; } public List<TextProposal> getCompletions(IFile file, IDocument document, CharSequence prefix, int position, boolean returnEqualedVariablesOnly, IResourceBundle[] bundles) throws BadLocationException, StringIndexOutOfBoundsException { List<TextProposal> completions = new ArrayList<TextProposal>(); ELResolutionImpl status = resolveELOperand(file, parseOperand("" + prefix), returnEqualedVariablesOnly, bundles); //$NON-NLS-1$ if(status!=null) { completions.addAll(status.getProposals()); } return completions; } public ELExpression parseOperand(String operand) { if(operand == null) return null; String el = (operand.indexOf("#{") < 0 && operand.indexOf("${") < 0) ? "#{" + operand + "}" : operand; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ ELParser p = getParserFactory().createParser(); ELModel model = p.parse(el); List<ELInstance> is = model.getInstances(); if(is.isEmpty()) return null; return is.get(0).getExpression(); } public ELResolutionImpl resolveELOperand(IFile file, ELExpression operand, boolean returnEqualedVariablesOnly, IResourceBundle[] bundles) throws BadLocationException, StringIndexOutOfBoundsException { if(!(operand instanceof ELInvocationExpression) || file == null) { return null; } ELInvocationExpression expr = (ELInvocationExpression)operand; boolean isIncomplete = expr.getType() == ELObjectType.EL_PROPERTY_INVOCATION && ((ELPropertyInvocation)expr).getName() == null; boolean isArgument = expr.getType() == ELObjectType.EL_ARGUMENT_INVOCATION; ELResolutionImpl resolution = new ELResolutionImpl(expr); ELInvocationExpression left = expr; List<Variable> resolvedVariables = EMPTY_VARIABLES; if (expr.getLeft() != null && isArgument) { left = expr.getLeft(); resolvedVariables = resolveVariables(file, left, bundles, false, true); // is Final and equal names are because of // we have no more to resolve the parts of expression, // but we have to resolve arguments of probably a message component if (resolvedVariables != null && !resolvedVariables.isEmpty()) { resolution.setLastResolvedToken(left); ELSegmentImpl segment = new MessagePropertyELSegmentImpl(left.getFirstToken()); processMessageBundleSegment(expr, (MessagePropertyELSegmentImpl)segment, resolvedVariables); segment.setResolved(true); for (Variable variable : resolvedVariables) { segment.getVariables().add(variable); } resolution.addSegment(segment); } } else if (expr.getLeft() == null && isIncomplete) { resolvedVariables = resolveVariables(file, expr, bundles, true, returnEqualedVariablesOnly); } else { while(left != null) { List<Variable>resolvedVars = resolveVariables(file, left, bundles, left == expr, returnEqualedVariablesOnly); if (resolvedVars != null && !resolvedVars.isEmpty()) { resolvedVariables = resolvedVars; resolution.setLastResolvedToken(left); ELSegmentImpl segment = new MessagePropertyELSegmentImpl(left.getFirstToken()); processMessageBundleSegment(expr, (MessagePropertyELSegmentImpl)segment, resolvedVariables); segment.setResolved(true); for (Variable variable : resolvedVars) { segment.getVariables().add(variable); } resolution.addSegment(segment); break; } left = (ELInvocationExpression)left.getLeft(); } } if (resolution.getLastResolvedToken() == null && !returnEqualedVariablesOnly && expr != null && isIncomplete) { // no vars are resolved // the tokens are the part of var name ended with a separator (.) resolvedVariables = resolveVariables(file, expr, bundles, true, returnEqualedVariablesOnly); Set<TextProposal> proposals = new TreeSet<TextProposal>(TextProposal.KB_PROPOSAL_ORDER); if (left != null) { ELSegmentImpl segment = new MessagePropertyELSegmentImpl(left.getFirstToken()); processMessageBundleSegment(expr, (MessagePropertyELSegmentImpl)segment, resolvedVariables); segment.setResolved(false); resolution.addSegment(segment); for (Variable var : resolvedVariables) { String varName = var.getName(); if(varName.startsWith(operand.getText())) { MessagesELTextProposal proposal = new MessagesELTextProposal(); proposal.setReplacementString(varName.substring(operand.getLength())); proposal.setImageDescriptor(getELProposalImageForMember(null)); List<XModelObject> objects = new ArrayList<XModelObject>(); IModelNature n = EclipseResourceUtil.getModelNature(var.f.getProject()); XModel model = n != null ? n.getModel() : null; if(model != null) { OpenKeyHelper keyHelper = new OpenKeyHelper(); XModelObject[] properties = keyHelper.findBundles(model, var.basename, null); if(properties == null) continue; for (XModelObject p : properties) { objects.add(p); // IFile propFile = (IFile)p.getAdapter(IFile.class); // if(propFile == null) // continue; } } proposal.setBaseName(var.basename); proposal.setObjects(objects); // if (!lastSegment.isBundle()) { // proposal.setPropertyName(lastSegment.getToken().getText()); // } proposals.add(proposal); } } resolution.setProposals(proposals); segment.setResolved(!proposals.isEmpty()); } return resolution; } // Here we have a list of vars for some part of expression // OK. we'll proceed with members of these vars if (resolution.getLastResolvedToken() == operand) { // First segment is the last one Set<TextProposal> proposals = new TreeSet<TextProposal>(TextProposal.KB_PROPOSAL_ORDER); for (Variable var : resolvedVariables) { String varName = var.getName(); if(operand.getLength()<=varName.length()) { MessagesELTextProposal proposal = new MessagesELTextProposal(); proposal.setReplacementString(varName.substring(operand.getLength())); proposal.setLabel(varName); proposal.setImageDescriptor(getELProposalImageForMember(null)); List<XModelObject> objects = new ArrayList<XModelObject>(); IModelNature n = EclipseResourceUtil.getModelNature(var.f.getProject()); XModel model = n != null ? n.getModel() : null; if(model != null) { OpenKeyHelper keyHelper = new OpenKeyHelper(); XModelObject[] properties = keyHelper.findBundles(model, var.basename, null); if(properties == null) continue; for (XModelObject p : properties) { objects.add(p); // IFile propFile = (IFile)p.getAdapter(IFile.class); // if(propFile == null) // continue; } } proposal.setBaseName(var.basename); proposal.setObjects(objects); // if (!lastSegment.isBundle()) { // proposal.setPropertyName(lastSegment.getToken().getText()); // } proposals.add(proposal); } else if(returnEqualedVariablesOnly) { TextProposal proposal = new TextProposal(); proposal.setReplacementString(varName); proposal.setLabel(varName); proposal.setImageDescriptor(getELProposalImageForMember(null)); proposals.add(proposal); } resolution.getLastSegment().getVariables().add(var); } resolution.setLastResolvedToken(expr); resolution.setProposals(proposals); return resolution; } //process segments one by one if(left != null) { while(left != expr) { left = (ELInvocationExpression)left.getParent(); if (left != expr) { // inside expression ELSegmentImpl segment = new ELSegmentImpl(left.getLastToken()); segment.setResolved(true); resolution.addSegment(segment); resolution.setLastResolvedToken(left); return resolution; } else { // Last segment resolveLastSegment((ELInvocationExpression)operand, resolvedVariables, resolution, returnEqualedVariablesOnly); break; } } } else { ELSegmentImpl segment = new ELSegmentImpl(expr.getFirstToken()); resolution.addSegment(segment); } return resolution; } public List<Variable> resolveVariables(IFile file, ELInvocationExpression expr, IResourceBundle[] bundles, boolean isFinal, boolean onlyEqualNames) { List<Variable> result = EMPTY_VARIABLES; if(expr.getLeft() != null) return result; IModelNature n = EclipseResourceUtil.getModelNature(file.getProject()); if(n == null) return result; XModel model = n.getModel(); String varName = expr.toString(); for (IResourceBundle b: bundles) { String name = b.getVar(); if(!isFinal || onlyEqualNames) { if(!name.equals(varName)) continue; } if(!name.startsWith(varName)) continue; Variable v = new Variable(name, b.getBasename(), file); result = addVariable(result, v); } List<?> l = WebPromptingProvider.getInstance().getList(model, WebPromptingProvider.JSF_REGISTERED_BUNDLES, null, null); if(l != null && l.size() > 0 && (l.get(0) instanceof Map)) { Map<?,?> map = (Map<?,?>)l.get(0); Iterator<?> it = map.keySet().iterator(); while(it.hasNext()) { String name = it.next().toString(); String basename = map.get(name).toString(); if(!isFinal || onlyEqualNames) { if(!name.equals(varName)) continue; } if(!name.startsWith(varName)) continue; Variable v = new Variable(name, basename, file); result = addVariable(result, v); } } return result; } private List<Variable> addVariable(List<Variable> result, Variable v) { if(result == null || result == EMPTY_VARIABLES) { result = new ArrayList<Variable>(); } result.add(v); return result; } protected void resolveLastSegment(ELInvocationExpression expr, List<Variable> members, ELResolutionImpl resolution, boolean returnEqualedVariablesOnly) { Set<TextProposal> kbProposals = new TreeSet<TextProposal>(TextProposal.KB_PROPOSAL_ORDER); ELSegmentImpl segment = new ELSegmentImpl(expr.getFirstToken()); resolution.setProposals(kbProposals); if(expr instanceof ELPropertyInvocation) { segment = new MessagePropertyELSegmentImpl(((ELPropertyInvocation)expr).getName()); processMessagePropertySegment(expr, (MessagePropertyELSegmentImpl)segment, members); } else if (expr instanceof ELArgumentInvocation) { segment = new MessagePropertyELSegmentImpl(((ELArgumentInvocation)expr).getArgument().getOpenArgumentToken().getNextToken()); processMessagePropertySegment(expr, (MessagePropertyELSegmentImpl)segment, members); } if(segment.getToken()!=null) { resolution.addSegment(segment); } if (expr.getType() == ELObjectType.EL_PROPERTY_INVOCATION && ((ELPropertyInvocation)expr).getName() == null) { // return all the methods + properties for (Variable mbr : members) { processSingularMember(mbr, kbProposals); } } else if(expr.getType() != ELObjectType.EL_ARGUMENT_INVOCATION) { String filter = (expr.getMemberName() == null ? "" : expr.getMemberName()); for (Variable mbr : members) { Collection<String> keys = mbr.getKeys(); for (String key : keys) { // We do expect nothing but name for method tokens (No round brackets) if(returnEqualedVariablesOnly) { // This is used for validation. if (key.equals(filter)) { MessagesELTextProposal kbProposal = createProposal(mbr, key); kbProposals.add(kbProposal); break; } } else if (key.startsWith(filter)) { // This is used for CA. MessagesELTextProposal kbProposal = createProposal(mbr, key); if (key.indexOf('.') == -1) kbProposal.setReplacementString(key.substring(filter.length())); else kbProposal.setReplacementString('[' + kbProposal.getReplacementString()); kbProposals.add(kbProposal); } } } } else if(expr.getType() == ELObjectType.EL_ARGUMENT_INVOCATION) { String filter = expr.getMemberName() == null ? "" : expr.getMemberName(); boolean b = filter.startsWith("'") || filter.startsWith("\""); //$NON-NLS-1$ //$NON-NLS-2$ boolean e = filter.length() > 1 && filter.endsWith("'") || filter.endsWith("\"");//$NON-NLS-1$ //$NON-NLS-2$ filter = StringUtil.trimQuotes(filter); for (Variable mbr : members) { if ((!b && filter.length() > 0) || (b && e && filter.length() == 0)) { //Value is set as expression itself, we cannot compute it resolution.setMapOrCollectionOrBundleAmoungTheTokens(true); return; } Collection<String> keys = mbr.getKeys(); for (String key : keys) { if(returnEqualedVariablesOnly) { // This is used for validation. if (key.equals(filter)) { MessagesELTextProposal kbProposal = createProposal(mbr, key); kbProposals.add(kbProposal); break; } } else if (key.startsWith(filter)) { // This is used for CA. MessagesELTextProposal kbProposal = createProposal(mbr, key); String existingString = expr.getMemberName() == null ? "" : expr.getMemberName(); // Because we're in argument invocation we should fix the proposal by surrounding it with quotes as needed String replacement = kbProposal.getReplacementString(); String label = kbProposal.getLabel(); if (!replacement.startsWith("'")) { replacement = '\'' + key + '\''; label = "['" + key + "']"; } replacement = replacement.substring(existingString.length()); kbProposal.setReplacementString(replacement); kbProposal.setLabel(label); kbProposals.add(kbProposal); } } } } segment.setResolved(!kbProposals.isEmpty()); if (resolution.isResolved()){ resolution.setLastResolvedToken(expr); } } private void processMessageBundleSegment(ELInvocationExpression expr, MessagePropertyELSegmentImpl segment, List<Variable> variables) { if(segment.getToken() == null) return; for(Variable variable : variables){ if(expr.getFirstToken().getText().equals(variable.name)){ IModelNature n = EclipseResourceUtil.getModelNature(variable.f.getProject()); if(n == null) return; XModel model = n.getModel(); if(model == null) return; OpenKeyHelper keyHelper = new OpenKeyHelper(); XModelObject[] properties = keyHelper.findBundles(model, variable.basename, null); if(properties == null) return; for (XModelObject p : properties) { segment.addObject(p); IFile propFile = (IFile)p.getAdapter(IFile.class); if(propFile == null) continue; segment.setMessageBundleResource(propFile); } segment.setBaseName(variable.basename); segment.setBundleOnlySegment(true); } } } private void processMessagePropertySegment(ELInvocationExpression expr, MessagePropertyELSegmentImpl segment, List<Variable> variables){ if(segment.getToken() == null) return; for(Variable variable : variables){ if(expr.getFirstToken().getText().equals(variable.name)){ int offset = currentOffset; String locale = getPageLocale(variable.f, offset); IModelNature n = EclipseResourceUtil.getModelNature(variable.f.getProject()); if(n == null) return; XModel model = n.getModel(); if(model == null) return; OpenKeyHelper keyHelper = new OpenKeyHelper(); XModelObject[] properties = keyHelper.findBundles(model, variable.basename, locale); if(properties == null) return; for (XModelObject p : properties) { String name = segment.getToken().getText(); XModelObject property = p.getChildByPath(StringUtil.trimQuotes(name)); if(property == null) continue; segment.addObject(property); PositionHolder h = PositionHolder.getPosition(property, null); h.update(); segment.setMessagePropertySourceReference(h.getStart(), name.length()); IFile propFile = (IFile)p.getAdapter(IFile.class); if(propFile != null) segment.setMessageBundleResource(propFile); } segment.setBaseName(variable.basename); segment.setBundleOnlySegment(false); } } } private static final String VIEW_TAGNAME = "view"; //$NON-NLS-1$ private static final String LOCALE_ATTRNAME = "locale"; //$NON-NLS-1$ private static final String PREFIX_SEPARATOR = ":"; //$NON-NLS-1$ private String getPageLocale(IFile file, int offset) { ELContext c = PageContextFactory.createPageContext(file); if(!(c instanceof IPageContext)) return ""; IPageContext context = (IPageContext)c; IDocument document = context.getDocument(); if(document == null) return ""; StructuredModelWrapper smw = new StructuredModelWrapper(); try { smw.init(document); Document xmlDocument = smw.getDocument(); if (xmlDocument == null) return null; Node n = Utils.findNodeForOffset(xmlDocument, offset); if (!(n instanceof Attr) ) return null; Element el = ((Attr)n).getOwnerElement(); Element jsfCoreViewTag = null; String nodeToFind = PREFIX_SEPARATOR + VIEW_TAGNAME; while (el != null) { if (el.getNodeName() != null && el.getNodeName().endsWith(nodeToFind)) { jsfCoreViewTag = el; break; } Node parent = el.getParentNode(); el = (parent instanceof Element ? (Element)parent : null); } if (jsfCoreViewTag == null || !jsfCoreViewTag.hasAttribute(LOCALE_ATTRNAME)) return null; String locale = Utils.trimQuotes((jsfCoreViewTag.getAttributeNode(LOCALE_ATTRNAME)).getValue()); if (locale == null || locale.length() == 0) return null; return locale; } finally { smw.dispose(); } } public boolean findPropertyLocation(XModelObject property, String content, MessagePropertyELSegmentImpl segment) { String name = property.getAttributeValue("name"); //$NON-NLS-1$ String nvs = property.getAttributeValue("name-value-separator"); //$NON-NLS-1$ int i = content.indexOf(name + nvs); if(i < 0) return false; segment.setMessagePropertySourceReference(i, name.length()); return true; } private MessagesELTextProposal createProposal(Variable mbr, String proposal) { MessagesELTextProposal kbProposal = new MessagesELTextProposal(); if (proposal.indexOf('.') != -1) { kbProposal.setReplacementString('\'' + proposal + '\''); kbProposal.setLabel("['" + proposal + "']"); } else { kbProposal.setReplacementString(proposal); kbProposal.setLabel(proposal); } kbProposal.setAlternateMatch(proposal); kbProposal.setImageDescriptor(getELProposalImageForMember(null)); List<XModelObject> objects = new ArrayList<XModelObject>(); String locale = getPageLocale(mbr.f, currentOffset); IModelNature n = EclipseResourceUtil.getModelNature(mbr.f.getProject()); XModel model = n != null ? n.getModel() : null; if(model != null) { OpenKeyHelper keyHelper = new OpenKeyHelper(); XModelObject[] properties = keyHelper.findBundles(model, mbr.basename, locale); if(properties != null) { for (XModelObject p : properties) { XModelObject property = p.getChildByPath(proposal); if(property != null) objects.add(property); } } } kbProposal.setBaseName(mbr.basename); kbProposal.setPropertyName(proposal); kbProposal.setObjects(objects); return kbProposal; } protected void processSingularMember(Variable mbr, Set<TextProposal> kbProposals) { // Surround the "long" keys containing the dots with [' '] TreeSet<String> keys = new TreeSet<String>(String.CASE_INSENSITIVE_ORDER); keys.addAll(mbr.getKeys()); Iterator<String> sortedKeys = keys.iterator(); while(sortedKeys.hasNext()) { String key = sortedKeys.next(); if (key == null || key.length() == 0) continue; MessagesELTextProposal proposal = createProposal(mbr, key); if (key.indexOf('.') != -1) { proposal.setReplacementString("['" + key + "']"); //$NON-NLS-1$ //$NON-NLS-2$ proposal.setLabel("['" + key + "']"); } else { proposal.setReplacementString(key); proposal.setLabel(key); } kbProposals.add(proposal); } } static class Variable implements IVariable { IFile f; String name; String basename; public Variable(String name, String basename, IFile f) { this.name = name; this.basename = basename; this.f = f; } public String getName() { return name; } public String getBasename() { return basename; } public Collection<String> getKeys() { TreeSet<String> result = new TreeSet<String>(); IModelNature n = EclipseResourceUtil.getModelNature(f.getProject()); if(n == null) return result; XModel model = n.getModel(); List l = WebPromptingProvider.getInstance().getList(model, WebPromptingProvider.JSF_BUNDLE_PROPERTIES, basename, null); for (int i = 0; i < l.size(); i++) { result.add(l.get(i).toString()); } return result; } } /* * (non-Javadoc) * @see org.jboss.tools.common.el.core.ca.AbstractELCompletionEngine#getMemberInfoByVariable(org.jboss.tools.common.el.core.resolver.IVariable, boolean) */ @Override protected MemberInfo getMemberInfoByVariable(IVariable var, ELContext context, boolean onlyEqualNames, int offset) { return null; } /* * (non-Javadoc) * @see org.jboss.tools.common.el.core.ca.AbstractELCompletionEngine#resolveVariables(org.eclipse.core.resources.IFile, org.jboss.tools.common.el.core.model.ELInvocationExpression, boolean, boolean) */ @Override public List<IVariable> resolveVariables(IFile file, ELContext context, ELInvocationExpression expr, boolean isFinal, boolean onlyEqualNames, int offset) { return null; } @Override protected boolean isStaticMethodsCollectingEnabled() { return false; } public IRelevanceCheck createRelevanceCheck(IJavaElement element) { return IRRELEVANT; } }