org.jboss.tools.cdi.seam.config.ui.contentassist.SeamConfigXmlCompletionProposalComputer.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.cdi.seam.config.ui.contentassist.SeamConfigXmlCompletionProposalComputer.java

Source

/*******************************************************************************
 * Copyright (c) 2012 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
 * 
 * Contributors:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.cdi.seam.config.ui.contentassist;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2;
import org.eclipse.jface.text.IDocument;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.ui.contentassist.CompletionProposalInvocationContext;
import org.eclipse.wst.sse.ui.internal.contentassist.ContentAssistUtils;
import org.eclipse.wst.sse.ui.internal.contentassist.CustomCompletionProposal;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.eclipse.wst.xml.ui.internal.contentassist.AbstractXMLModelQueryCompletionProposalComputer;
import org.eclipse.wst.xml.ui.internal.contentassist.ContentAssistRequest;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLContentModelGenerator;
import org.eclipse.wst.xml.ui.internal.contentassist.XMLRelevanceConstants;
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImageHelper;
import org.eclipse.wst.xml.ui.internal.editor.XMLEditorPluginImages;
import org.jboss.tools.cdi.core.CDICoreNature;
import org.jboss.tools.cdi.core.CDICorePlugin;
import org.jboss.tools.cdi.seam.config.core.CDISeamConfigConstants;
import org.jboss.tools.cdi.seam.config.core.CDISeamConfigExtension;
import org.jboss.tools.cdi.seam.config.core.util.Util;
import org.jboss.tools.cdi.seam.config.core.xml.SAXElement;
import org.jboss.tools.cdi.seam.config.ui.CDISeamConfigUIPlugin;
import org.jboss.tools.cdi.seam.config.ui.CDISeamConfigUiImages;
import org.jboss.tools.common.model.util.EclipseJavaUtil;
import org.jboss.tools.common.model.util.EclipseResourceUtil;
import org.jboss.tools.common.xml.XMLUtilities;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

/**
 * 
 * @author Viacheslav Kabanovich
 *
 */
public class SeamConfigXmlCompletionProposalComputer extends AbstractXMLModelQueryCompletionProposalComputer
        implements CDISeamConfigConstants {
    static int RELEVANCE_TAG = XMLRelevanceConstants.R_STRICTLY_VALID_TAG_NAME + 100;
    static int RELEVANCE_TAG_KEYWORD = RELEVANCE_TAG - 1;
    static int RELEVANCE_TAG_ANNOTATION = RELEVANCE_TAG_KEYWORD - 1;
    static int RELEVANCE_TAG_MEMBER = RELEVANCE_TAG_ANNOTATION - 1;
    static int RELEVANCE_TAG_TYPE = RELEVANCE_TAG_MEMBER - 1;

    CompletionProposalInvocationContext context;
    Node currentNode;
    Element parentElement;
    SAXElement sax;

    IFile resource;
    IProject project;
    IJavaProject javaProject;
    CDICoreNature cdi;
    CDISeamConfigExtension extension;

    Map<String, String> uriByPrefix = new HashMap<String, String>();
    Map<String, String> prefixByUri = new HashMap<String, String>();
    String eePrefix;
    Map<String, String> prefixByPackage = new HashMap<String, String>();

    public List<?> computeCompletionProposals(CompletionProposalInvocationContext context,
            IProgressMonitor monitor) {
        this.context = context;
        currentNode = findNode();
        if (currentNode instanceof IDOMElement
                && context.getInvocationOffset() == ((IDOMElement) currentNode).getStartOffset()) {
            currentNode = currentNode.getPreviousSibling() != null ? currentNode.getPreviousSibling()
                    : currentNode.getParentNode();
        }

        Node p = currentNode;
        while (p != null && !(p instanceof Element))
            p = p.getParentNode();
        if (!(p instanceof Element)) {
            // can do nothing without context of parent element.
            return new ArrayList<Object>();
        }
        parentElement = (Element) p;
        sax = buildSAXElement(currentNode);

        fillNameSpaces(currentNode);
        resource = findResource(getDocument());
        if (resource != null) {
            javaProject = EclipseResourceUtil.getJavaProject(resource.getProject());
            cdi = CDICorePlugin.getCDI(resource.getProject(), true);
            if (cdi != null)
                extension = CDISeamConfigExtension.getExtension(cdi);
        }
        if (!isActive()) {
            return new ArrayList<Object>();
        }
        //compute the completion proposals
        return super.computeCompletionProposals(context, monitor);
    }

    protected boolean isActive() {
        //Cannot work without resource.
        //Have nothing to suggest without packages.
        //can only add in context of an element.
        return (resource != null && !prefixByPackage.isEmpty() && sax != null);
    }

    protected IDocument getDocument() {
        return context.getDocument();
    }

    private Node findNode() {
        return (Node) ContentAssistUtils.getNodeAt(context.getViewer(), context.getInvocationOffset());
    }

    private IFile findResource(IDocument document) {
        IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(document);
        try {
            if (sModel != null) {
                String baseLocation = sModel.getBaseLocation();
                IPath location = new Path(baseLocation).makeAbsolute();
                return FileBuffers.getWorkspaceFileAtLocation(location);
            }
        } finally {
            if (sModel != null) {
                sModel.releaseFromRead();
            }
        }
        return null;
    }

    private SAXElement buildSAXElement(Node node) {
        while (node != null && !(node instanceof Element)) {
            node = node.getParentNode();
        }
        if (node != null) {
            SAXElement sax = new SAXElement(node);
            SAXElement parent = buildSAXElement(node.getParentNode());
            sax.setParent(parent);
            return sax;
        }

        return null;
    }

    @Override
    protected void addTagInsertionProposals(ContentAssistRequest contentAssistRequest, int childPosition,
            CompletionProposalInvocationContext context) {
        Set<TagData> tagData = collectTagData();

        for (TagData tag : tagData) {
            if (tag.isUnique() && childOtherThanCurrentNodeExists(tag.getName())) {
                continue;
            }
            String tagText = tag.getText();
            int positionAdjustment = (tagText.indexOf("><") > 0) ? tagText.indexOf("><") + 1 : tagText.length();
            String displayText = tag.getName();
            if (tag.getMember() instanceof IType) {
                displayText += " - " + ((IType) tag.getMember()).getPackageFragment().getElementName();
            }
            createProposal(contentAssistRequest, tagText, displayText, positionAdjustment, tag.getMember(),
                    tag.getRelevance());
        }
    }

    private boolean childOtherThanCurrentNodeExists(String tagName) {
        Element element = XMLUtilities.getUniqueChild((Element) parentElement, tagName);
        return element != null && element != currentNode;
    }

    private Set<TagData> collectTagData() {
        String parentElementName = sax.getLocalName();
        String parentElementPrefix = sax.getPrefix();

        Set<TagData> tagData = new HashSet<TagData>();

        if ("beans".equals(parentElementName)) {
            //suggest all classes in all packages.
            addTypeNames(tagData, false, false);
        } else if (parentElementPrefix != null && prefixByPackage.containsValue(parentElementPrefix)) {
            // If we are not in <beans>, then we have to be in context of some seam package.
            IType contextType = null;
            if (Util.isEntry(sax)) {
                //Inside entry - only <key> and <value>
                if (eePrefix != null) {
                    addTagData(tagData, eePrefix, KEYWORD_KEY, true, true, RELEVANCE_TAG_KEYWORD);
                    addTagData(tagData, eePrefix, KEYWORD_VALUE, true, true, RELEVANCE_TAG_KEYWORD);
                }
            } else if (Util.isValue(sax) || Util.isKey(sax)) {
                //Inside value or key we can define new bean.
                addTypeNames(tagData, false, true);
            } else if (Util.isParameters(sax)) {
                //TODO find parent method name and type, and suggest parameter types. 
            } else if ((contextType = Util.resolveType(sax, cdi)) != null) {
                //We are inside bean. Suggest members and annotations.
                addTypeNames(tagData, true, false); //only annotations allowed here.
                addTagData(tagData, getTagNamesForMembers(parentElementPrefix, contextType, false),
                        RELEVANCE_TAG_MEMBER);

                if (eePrefix != null) {
                    if (!childOtherThanCurrentNodeExists(eePrefix + ":" + KEYWORD_MODIFIES)
                            && !childOtherThanCurrentNodeExists(eePrefix + ":" + KEYWORD_REPLACES)) {
                        addTagData(tagData, eePrefix, KEYWORD_MODIFIES, false, true, RELEVANCE_TAG_KEYWORD);
                        addTagData(tagData, eePrefix, KEYWORD_REPLACES, false, true, RELEVANCE_TAG_KEYWORD);
                    }
                    addTagData(tagData, eePrefix, KEYWORD_PARAMETERS, true, true, RELEVANCE_TAG_KEYWORD);
                }
            } else if (sax.getParent() != null
                    && ((contextType = Util.resolveType(sax.getParent(), cdi)) != null)) {
                IMember member = null;
                try {
                    member = Util.resolveMember(contextType, sax);
                } catch (JavaModelException e) {
                    CDISeamConfigUIPlugin.getDefault().logError(e);
                }
                if (member != null) {
                    //We are inside bean member. Suggest annotations and <value>.
                    addTypeNames(tagData, true, false); //only annotations allowed here.
                    if (eePrefix != null) {
                        if (member instanceof IField) {
                            addTagData(tagData, eePrefix, KEYWORD_VALUE, true, RELEVANCE_TAG_KEYWORD);
                            //should we suggest entry only for maps...
                            addTagData(tagData, eePrefix, KEYWORD_ENTRY, true, true, RELEVANCE_TAG_KEYWORD);
                        } else if (member instanceof IMethod) {
                            addTagData(tagData, eePrefix, KEYWORD_PARAMETERS, true, true, RELEVANCE_TAG_KEYWORD);
                        }
                    }

                }
            }
        }
        return tagData;
    }

    private void addTypeNames(Set<TagData> tagData, boolean annotationsOnly, boolean classesOnly) {
        try {
            Map<String, IMember> tagNames = getAllTagNames(annotationsOnly, classesOnly);
            Set<TagData> append = new HashSet<TagData>();
            addTagData(append, tagNames, annotationsOnly ? RELEVANCE_TAG_ANNOTATION : RELEVANCE_TAG_TYPE);
            if (annotationsOnly) {
                for (TagData tag : append) {
                    tag.setHasClosingTag(false);
                }
            }
            tagData.addAll(append);
        } catch (JavaModelException e) {
            CDISeamConfigUIPlugin.getDefault().logError(e);
        }
    }

    private void addTagData(Set<TagData> tagData, String prefix, String name, boolean hasClosingTag,
            int relevance) {
        tagData.add(new TagData(prefix, name, hasClosingTag, false, relevance));
    }

    private void addTagData(Set<TagData> tagData, String prefix, String name, boolean hasClosingTag,
            boolean isUnique, int relevance) {
        tagData.add(new TagData(prefix, name, hasClosingTag, isUnique, relevance));
    }

    private void addTagData(Set<TagData> tagData, Map<String, IMember> tagNames, int relevance) {
        for (String tagName : tagNames.keySet()) {
            TagData d = new TagData(tagName, relevance);
            IMember m = tagNames.get(tagName);
            if (m instanceof IType) {
                String qn = ((IType) m).getFullyQualifiedName();
                //TODO improve list of annotations that never need children.  
                if (QUALIFIER_ANNOTATION_TYPE_NAME.equals(qn) || ANY_QUALIFIER_TYPE_NAME.equals(qn)
                        || DEFAULT_QUALIFIER_TYPE_NAME.equals(qn) || SPECIALIZES_ANNOTATION_TYPE_NAME.equals(qn)
                        || DECORATOR_STEREOTYPE_TYPE_NAME.equals(qn) || INJECT_ANNOTATION_TYPE_NAME.equals(qn)
                        || PRODUCES_ANNOTATION_TYPE_NAME.equals(qn)) {
                    d.setHasClosingTag(false);
                }
            }
            d.setMember(m);
            tagData.add(d);
        }
    }

    protected void addTagNameProposals(ContentAssistRequest contentAssistRequest, int childPosition,
            CompletionProposalInvocationContext context) {
        IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
        boolean isEnded = (node.getNodeType() != Node.TEXT_NODE)
                && node.getFirstStructuredDocumentRegion().isEnded();
        if (currentNode == parentElement) {
            if (parentElement.getParentNode() instanceof Element) {
                parentElement = (Element) parentElement.getParentNode();
                sax = sax.getParent();
            }
        }

        String match = contentAssistRequest.getMatchString();

        Set<TagData> tagData = collectTagData();
        if (match != null && match.length() > 0) {
            Iterator<TagData> i = tagData.iterator();
            while (i.hasNext()) {
                TagData d = i.next();
                if (!d.getName().startsWith(match) && d.getName().indexOf(":" + match) < 0) {
                    i.remove();
                }
            }
        }

        for (TagData tag : tagData) {
            if (tag.isUnique() && childOtherThanCurrentNodeExists(tag.getName())) {
                continue;
            }
            String tagText = isEnded ? tag.getName() : tag.getText();
            if (tagText.startsWith("<"))
                tagText = tagText.substring(1);
            int positionAdjustment = (tagText.indexOf("><") > 0) ? tagText.indexOf("><") + 1 : tagText.length();
            String displayText = tag.getName();
            if (tag.getMember() instanceof IType) {
                displayText += " - " + ((IType) tag.getMember()).getPackageFragment().getElementName();
            }
            createProposal(contentAssistRequest, tagText, displayText, positionAdjustment, tag.getMember(),
                    tag.getRelevance());
        }
    }

    private void createProposal(ContentAssistRequest contentAssistRequest, String tagText, String displayText,
            int positionAdjustment, final IMember member, int relevance) {
        int begin = contentAssistRequest.getReplacementBeginPosition();
        int length = contentAssistRequest.getReplacementLength();
        String imagePath = XMLEditorPluginImages.IMG_OBJ_TAG_GENERIC;
        if (tagText.endsWith("\"")) { //improve that dirty hack
            imagePath = XMLEditorPluginImages.IMG_OBJ_ATTRIBUTE;
        }
        CustomCompletionProposal textProposal = new CustomCompletionProposal(tagText, begin, length,
                positionAdjustment, XMLEditorPluginImageHelper.getInstance().getImage(imagePath), displayText, null,
                null, relevance) {
            String proposedInfo = null;

            public String getAdditionalProposalInfo() {
                if (member != null && proposedInfo == null) {
                    try {
                        proposedInfo = JavadocContentAccess2.getHTMLContent(member, true);
                        if (proposedInfo == null)
                            proposedInfo = "";
                    } catch (JavaModelException e) {
                        CDISeamConfigUIPlugin.getDefault().logError(e);
                    }
                }
                return proposedInfo;
            }

        };
        contentAssistRequest.addProposal(textProposal);
    }

    protected void addAttributeNameProposals(ContentAssistRequest contentAssistRequest,
            CompletionProposalInvocationContext context) {
        IType contextType = Util.resolveType(sax, cdi);
        if (contextType != null) {
            String match = contentAssistRequest.getMatchString();
            Set<TagData> tagData = new HashSet<TagData>();
            addTagData(tagData, getTagNamesForMembers(sax.getPrefix(), contextType, true), RELEVANCE_TAG_MEMBER);
            for (TagData tag : tagData) {
                String attrName = tag.getName().substring(tag.getName().indexOf(':') + 1);
                if (parentElement.hasAttribute(attrName))
                    continue;
                if (match != null && !attrName.startsWith(match))
                    continue;
                String tagText = attrName + "=\"\"";
                int positionAdjustment = tagText.length() - 1;
                createProposal(contentAssistRequest, tagText, attrName, positionAdjustment, tag.getMember(),
                        tag.getRelevance());
            }
        }

    }

    protected void addAttributeValueProposals(ContentAssistRequest contentAssistRequest,
            CompletionProposalInvocationContext context) {

        IDOMNode node = (IDOMNode) contentAssistRequest.getNode();
        // Find the attribute region and name for which this position should
        // have a value proposed
        IStructuredDocumentRegion open = node.getFirstStructuredDocumentRegion();
        ITextRegionList openRegions = open.getRegions();
        int i = openRegions.indexOf(contentAssistRequest.getRegion());
        if (i < 0) {
            return;
        }
        ITextRegion nameRegion = null;
        while (i >= 0) {
            nameRegion = openRegions.get(i--);
            if (nameRegion.getType() == DOMRegionContext.XML_TAG_ATTRIBUTE_NAME) {
                break;
            }
        }
        // the name region is REQUIRED to do anything useful
        if (nameRegion != null) {
            String attributeName = open.getText(nameRegion);
            if (attributeName.startsWith("xmlns:")) {
                String match = contentAssistRequest.getMatchString();
                if (match == null) {
                    match = "";
                } else if (match.startsWith("\"") || match.startsWith("'")) {
                    match = match.substring(1);
                }
                if (match.length() == 0 || match.startsWith(URI_PREFIX) || URI_PREFIX.startsWith(match)) {
                    Set<String> packages = new HashSet<String>();
                    try {
                        packages = getAllPackages(javaProject);
                    } catch (JavaModelException e) {
                        CDISeamConfigUIPlugin.getDefault().logError(e);
                    }
                    packages.add(PACKAGE_EE);
                    for (String pkg : packages) {
                        String proposal = "urn:java:" + pkg;
                        if (match.startsWith(URI_PREFIX)) {
                            int q = match.lastIndexOf(":");
                            String pMatch = match.substring(q + 1);
                            if (!pkg.startsWith(pMatch)) {
                                continue;
                            }
                            if (pkg.indexOf('.', pMatch.length() + 1) >= 0) {
                                continue;
                            }
                            proposal = match.substring(0, q + 1) + pkg;
                        } else {
                            if (pkg.indexOf('.') > 0)
                                continue;
                        }
                        int positionAdjustment = proposal.length();
                        String displayText = pkg;
                        createValueProposal(contentAssistRequest, proposal, displayText, positionAdjustment, null,
                                1000);
                    }
                }
            }
        }

    }

    private void createValueProposal(ContentAssistRequest contentAssistRequest, String tagText, String displayText,
            int positionAdjustment, IMember member, int relevance) {
        int begin = contentAssistRequest.getReplacementBeginPosition() + 1;
        String match = contentAssistRequest.getMatchString();
        int length = match == null || match.length() == 0 ? 0 : match.length() - 1;
        String proposedInfo = null;
        CustomCompletionProposal textProposal = new CustomCompletionProposal(tagText, begin, length,
                positionAdjustment, CDISeamConfigUiImages.PACKAGE_IMAGE, displayText, null, proposedInfo,
                relevance) {
            // we make it our own type to filter from WTP's proposals
        };
        contentAssistRequest.addProposal(textProposal);
    }

    @Override
    protected XMLContentModelGenerator getContentGenerator() {
        return new XMLContentModelGenerator();
    }

    @Override
    protected boolean validModelQueryNode(CMNode node) {
        return false;
    }

    static String XMLNS_PREFIX = "xmlns:";

    private void fillNameSpaces(Node node) {
        uriByPrefix.clear();
        prefixByUri.clear();
        prefixByPackage.clear();
        eePrefix = null;
        while (node != null) {
            if (node instanceof Element) {
                Element element = (Element) node;
                NamedNodeMap as = element.getAttributes();
                for (int i = 0; i < as.getLength(); i++) {
                    Node a = as.item(i);
                    String nm = a.getNodeName();
                    if (nm.startsWith(XMLNS_PREFIX)) {
                        String prefix = nm.substring(XMLNS_PREFIX.length());
                        String uri = a.getNodeValue();
                        if (uri != null) {
                            uriByPrefix.put(prefix, uri);
                            prefixByUri.put(uri, prefix);
                            String[] packages = Util.getPackages(uri);
                            for (String pkg : packages) {
                                prefixByPackage.put(pkg, prefix);
                            }
                        }
                    }
                }
            }
            eePrefix = prefixByPackage.get(PACKAGE_EE);
            node = node.getParentNode();
        }
    }

    Map<String, IMember> getAllTagNames(boolean annotationsOnly, boolean classesOnly) throws JavaModelException {
        Map<String, IMember> result = new HashMap<String, IMember>();
        for (String packageName : prefixByPackage.keySet()) {
            String prefix = prefixByPackage.get(packageName);
            Map<String, IMember> typeNames = findTypeNamesByPackage(javaProject, packageName, annotationsOnly,
                    classesOnly);
            for (String typeName : typeNames.keySet()) {
                result.put(prefix + ":" + typeName, typeNames.get(typeName));
            }
        }
        return result;
    }

    Map<String, IMember> getTypeNamesByPrefix(String prefix, boolean annotationsOnly, boolean classesOnly)
            throws JavaModelException {
        Map<String, IMember> result = new HashMap<String, IMember>();
        String uri = uriByPrefix.get(prefix);
        for (String packageName : Util.getPackages(uri)) {
            result.putAll(findTypeNamesByPackage(javaProject, packageName, annotationsOnly, classesOnly));
        }
        return result;
    }

    public static Map<String, IMember> findTypeNamesByPackage(IJavaProject javaProject, String packageName,
            boolean annotationsOnly, boolean classesOnly) throws JavaModelException {
        Map<String, IMember> result = new HashMap<String, IMember>();
        if (PACKAGE_EE.equals(packageName)) {
            for (String name : Util.EE_TYPES.keySet()) {
                String cls = Util.EE_TYPES.get(name);
                IType t = EclipseJavaUtil.findType(javaProject, cls);
                if (accept(t, annotationsOnly, classesOnly))
                    result.put(name, t);
            }
            for (String name : Util.EE_TYPES_30.keySet()) {
                String cls = Util.EE_TYPES_30.get(name);
                IType t = EclipseJavaUtil.findType(javaProject, cls);
                if (accept(t, annotationsOnly, classesOnly))
                    result.put(name, t);
            }
        } else if (javaProject != null) {
            IPackageFragmentRoot[] rs = javaProject.getAllPackageFragmentRoots();
            for (IPackageFragmentRoot r : rs) {
                IPackageFragment pkg = r.getPackageFragment(packageName);
                if (pkg != null && pkg.exists()) {
                    ICompilationUnit[] units = pkg.getCompilationUnits();
                    for (ICompilationUnit u : units) {
                        IType[] ts = u.getTypes();
                        for (IType t : ts)
                            if (accept(t, annotationsOnly, classesOnly))
                                result.put(t.getElementName(), t);
                    }
                    IClassFile[] cs = pkg.getClassFiles();
                    for (IClassFile cls : cs) {
                        if (accept(cls.getType(), annotationsOnly, classesOnly))
                            result.put(cls.getType().getElementName(), cls.getType());
                    }
                }
            }

        }
        return result;
    }

    public static Set<String> getAllPackages(IJavaProject javaProject) throws JavaModelException {
        Set<String> result = new HashSet<String>();
        IPackageFragmentRoot[] rs = javaProject.getAllPackageFragmentRoots();
        for (IPackageFragmentRoot r : rs) {
            IJavaElement[] cs = r.getChildren();
            for (IJavaElement c : cs) {
                if (c instanceof IPackageFragment) {
                    result.add(((IPackageFragment) c).getElementName());
                }
            }
        }
        return result;
    }

    private static boolean accept(IType type, boolean annotationOnly, boolean classesOnly)
            throws JavaModelException {
        return (type != null) && (!annotationOnly || type.isAnnotation() && (!classesOnly || !type.isInterface()));
    }

    private Map<String, IMember> getTagNamesForMembers(String prefix, IType type, boolean fieldsOnly) {
        Map<String, IMember> result = new HashMap<String, IMember>();
        try {
            IField[] fs = type.getFields();
            for (IField f : fs) {
                result.put(prefix + ":" + f.getElementName(), f);
            }
            if (!fieldsOnly || type.isAnnotation()) {
                IMethod[] ms = type.getMethods();
                for (IMethod m : ms) {
                    result.put(prefix + ":" + m.getElementName(), m);
                }
            }
        } catch (JavaModelException e) {
            CDISeamConfigUIPlugin.getDefault().logError(e);
        }
        return result;
    }

}