com.liferay.ide.portlet.ui.editor.PortletURLHyperlinkDetector.java Source code

Java tutorial

Introduction

Here is the source code for com.liferay.ide.portlet.ui.editor.PortletURLHyperlinkDetector.java

Source

/*******************************************************************************
 * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
 *
 * This library is free software; you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation; either version 2.1 of the License, or (at your option)
 * any later version.
 *
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
 * details.
 *
 *******************************************************************************/
package com.liferay.ide.portlet.ui.editor;

import com.liferay.ide.core.util.CoreUtil;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.IJavaSearchScope;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.core.search.SearchMatch;
import org.eclipse.jdt.core.search.SearchParticipant;
import org.eclipse.jdt.core.search.SearchPattern;
import org.eclipse.jdt.core.search.SearchRequestor;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension4;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.hyperlink.AbstractHyperlinkDetector;
import org.eclipse.jface.text.hyperlink.IHyperlink;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.search.core.util.DOMUtils;
import org.w3c.dom.Node;

/**
 * @author Gregory Amerson
 */
@SuppressWarnings("restriction")
public class PortletURLHyperlinkDetector extends AbstractHyperlinkDetector {
    private IFile lastFile;
    private long lastModStamp;
    private IRegion lastNodeRegion;
    private IMethod[] lastActionUrlMethods;

    private static class ActionMethodCollector extends SearchRequestor {
        private final List<IMethod> results;

        public ActionMethodCollector(List<IMethod> results) {
            super();
            this.results = results;
        }

        @Override
        public void acceptSearchMatch(SearchMatch match) throws CoreException {
            final Object element = match.getElement();

            if (element instanceof IMethod && isActionMethod((IMethod) element)) {
                this.results.add((IMethod) element);
            }
        }
    }

    private static boolean isActionMethod(IMethod method) {
        final String[] paramTypes = method.getParameterTypes();

        return paramTypes.length == 2 && paramTypes[0].toLowerCase().contains("request")
                && paramTypes[1].toLowerCase().contains("response");
    }

    public PortletURLHyperlinkDetector() {
        super();
    }

    public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region,
            boolean canShowMultipleHyperlinks) {
        IHyperlink[] retval = null;

        if (shouldDetectHyperlinks(textViewer, region)) {
            final IDocument document = textViewer.getDocument();
            final int offset = region.getOffset();
            final IDOMNode currentNode = DOMUtils.getNodeByOffset(document, offset);
            final IRegion nodeRegion = new Region(currentNode.getStartOffset(),
                    currentNode.getEndOffset() - currentNode.getStartOffset());

            if (isActionURL(currentNode)) {
                final Node name = currentNode.getAttributes().getNamedItem("name");

                if (name != null) {
                    final long modStamp = ((IDocumentExtension4) document).getModificationStamp();
                    final IFile file = DOMUtils.getFile(document);

                    IMethod[] actionUrlMethods = null;

                    if (file.equals(this.lastFile) && modStamp == this.lastModStamp
                            && nodeRegion.equals(this.lastNodeRegion)) {
                        actionUrlMethods = this.lastActionUrlMethods;
                    } else {
                        final String nameValue = name.getNodeValue();

                        // search for this method in any portlet classes
                        actionUrlMethods = findPortletMethods(document, nameValue);

                        this.lastModStamp = modStamp;
                        this.lastFile = file;
                        this.lastNodeRegion = nodeRegion;
                        this.lastActionUrlMethods = actionUrlMethods;
                    }

                    if (!CoreUtil.isNullOrEmpty(actionUrlMethods)) {
                        final List<IHyperlink> links = new ArrayList<IHyperlink>();

                        for (IMethod method : actionUrlMethods) {
                            if (method.exists()) {
                                links.add(new BasicJavaElementHyperlink(nodeRegion, method));
                            }
                        }

                        if (links.size() != 0) {
                            if (canShowMultipleHyperlinks) {
                                retval = links.toArray(new IHyperlink[0]);
                            } else {
                                retval = new IHyperlink[] { links.get(0) };
                            }
                        }
                    }
                }
            }
        }

        return retval;
    }

    private IMethod[] findPortletMethods(IDocument document, String nameValue) {
        IMethod[] retval = null;

        final IFile file = DOMUtils.getFile(document);

        if (file != null && file.exists()) {
            final IJavaProject project = JavaCore.create(file.getProject());

            if (project != null && project.exists()) {
                try {
                    final IType portlet = project.findType("javax.portlet.Portlet");

                    if (portlet != null) {
                        final List<IMethod> methods = new ArrayList<IMethod>();
                        final SearchRequestor requestor = new ActionMethodCollector(methods);

                        final IJavaSearchScope scope = SearchEngine.createStrictHierarchyScope(project, portlet,
                                true, false, null);

                        final SearchPattern search = SearchPattern.createPattern(nameValue,
                                IJavaSearchConstants.METHOD, IJavaSearchConstants.DECLARATIONS,
                                SearchPattern.R_EXACT_MATCH | SearchPattern.R_CASE_SENSITIVE);

                        new SearchEngine().search(search,
                                new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() }, scope,
                                requestor, new NullProgressMonitor());

                        retval = methods.toArray(new IMethod[0]);
                    }
                } catch (JavaModelException e) {
                } catch (CoreException e) {
                }
            }
        }

        return retval;
    }

    private boolean isActionURL(Node currentNode) {
        return currentNode != null && currentNode.getNodeName() != null
                && currentNode.getNodeType() == Node.ELEMENT_NODE
                && currentNode.getNodeName().endsWith("actionURL");
    }

    private boolean shouldDetectHyperlinks(final ITextViewer textViewer, final IRegion region) {
        return region != null && textViewer != null;
    }

}