org.eclipse.jst.jsp.ui.internal.hyperlink.JSPJavaHyperlinkDetector.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.jst.jsp.ui.internal.hyperlink.JSPJavaHyperlinkDetector.java

Source

/*******************************************************************************
 * Copyright (c) 2006, 2013 IBM 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.jsp.ui.internal.hyperlink;

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

import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
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.jst.jsp.core.internal.java.IJSPTranslation;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslation;
import org.eclipse.jst.jsp.core.internal.java.JSPTranslationAdapter;
import org.eclipse.jst.jsp.ui.internal.Logger;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;

/**
 * Detects hyperlinks in JSP Java content
 */
public class JSPJavaHyperlinkDetector extends AbstractHyperlinkDetector {

    private IHyperlink createHyperlink(IJavaElement element, IRegion region, IDocument document) {
        IHyperlink link = null;
        if (region != null) {
            // open local variable in the JSP file...
            boolean isInTranslationCU = false;
            if (element instanceof ISourceReference) {
                IFile file = null;
                int jspOffset = 0;

                // try to locate the file in the workspace
                ITextFileBuffer textFileBuffer = FileBuffers.getTextFileBufferManager().getTextFileBuffer(document);
                if (textFileBuffer != null && textFileBuffer.getLocation() != null) {
                    file = getFile(textFileBuffer.getLocation().toString());
                }

                // get Java range and translate to JSP range
                try {
                    ISourceRange range = null;
                    IJSPTranslation jspTranslation = getJSPTranslation(document);
                    if (jspTranslation != null) {
                        // link to local variable definitions
                        if (element instanceof ILocalVariable) {
                            range = ((ILocalVariable) element).getNameRange();
                            Object cu = ((ILocalVariable) element).getAncestor(IJavaElement.COMPILATION_UNIT);
                            if (cu != null && cu.equals(jspTranslation.getCompilationUnit()))
                                isInTranslationCU = true;
                        }
                        // linking to fields of the same compilation unit
                        else if (element.getElementType() == IJavaElement.FIELD) {
                            Object cu = ((IField) element).getCompilationUnit();
                            if (cu != null && cu.equals(jspTranslation.getCompilationUnit())) {
                                range = ((ISourceReference) element).getSourceRange();
                                isInTranslationCU = true;
                            }
                        }
                        // linking to methods of the same compilation unit
                        else if (element.getElementType() == IJavaElement.METHOD) {
                            Object cu = ((IMethod) element).getCompilationUnit();
                            if (cu != null && cu.equals(jspTranslation.getCompilationUnit())) {
                                range = ((ISourceReference) element).getSourceRange();
                                isInTranslationCU = true;
                            }
                        }
                    }

                    if (jspTranslation != null && range != null && file != null) {
                        jspOffset = jspTranslation.getJspOffset(range.getOffset());
                        if (jspOffset >= 0) {
                            link = new WorkspaceFileHyperlink(region, file,
                                    new Region(jspOffset, range.getLength()));
                        }
                    }
                } catch (JavaModelException jme) {
                    Logger.log(Logger.WARNING_DEBUG, jme.getMessage(), jme);
                }
            }
            if (link == null && !isInTranslationCU) { // Don't try to open the translation CU
                link = new JSPJavaHyperlink(region, element);
            }
        }
        return link;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.text.hyperlink.IHyperlinkDetector#detectHyperlinks(org.eclipse.jface.text.ITextViewer,
     *      org.eclipse.jface.text.IRegion, boolean)
     */
    public IHyperlink[] detectHyperlinks(ITextViewer textViewer, IRegion region,
            boolean canShowMultipleHyperlinks) {
        List hyperlinks = new ArrayList(0);

        if (region != null && textViewer != null) {
            IDocument document = textViewer.getDocument();
            JSPTranslation jspTranslation = getJSPTranslation(document);
            if (jspTranslation != null) {
                // check if we are in JSP Java content
                int javaOffset = jspTranslation.getJavaOffset(region.getOffset());
                if (javaOffset > -1) {
                    // check that we are not in indirect Java content (like
                    // included files)
                    if (!jspTranslation.isIndirect(javaOffset)) {
                        // get Java elements
                        IJavaElement[] elements = jspTranslation.getElementsFromJspRange(region.getOffset(),
                                region.getOffset() + region.getLength());
                        if (elements != null && elements.length > 0) {
                            // create a JSPJavaHyperlink for each Java element
                            for (int i = 0; i < elements.length; ++i) {
                                IJavaElement element = elements[i];

                                // find hyperlink range for Java element
                                IRegion hyperlinkRegion = selectWord(document, region.getOffset());
                                IHyperlink link = createHyperlink(element, hyperlinkRegion, document);
                                if (link != null) {
                                    hyperlinks.add(link);
                                }
                            }
                        }
                    }
                }
            }
        }

        if (hyperlinks.isEmpty())
            return null;
        return (IHyperlink[]) hyperlinks.toArray(new IHyperlink[0]);
    }

    /**
     * Returns an IFile from the given uri if possible, null if cannot find
     * file from uri.
     * 
     * @param fileString
     *            file system path
     * @return returns IFile if fileString exists in the workspace
     */
    private IFile getFile(String fileString) {
        IFile file = null;

        if (fileString != null) {
            Path filePath = new Path(fileString);
            if (filePath.segmentCount() > 1
                    && ResourcesPlugin.getWorkspace().getRoot().getFile(filePath).exists()) {
                return ResourcesPlugin.getWorkspace().getRoot().getFile(filePath);
            }
            IFile[] files = ResourcesPlugin.getWorkspace().getRoot().findFilesForLocation(filePath);
            for (int i = 0; i < files.length && file == null; i++)
                if (files[i].exists())
                    file = files[i];
        }

        return file;
    }

    /**
     * Get JSP translation object
     * 
     * @return JSPTranslation if one exists, null otherwise
     */
    private JSPTranslation getJSPTranslation(IDocument document) {
        JSPTranslation translation = null;

        IDOMModel xmlModel = null;
        try {
            xmlModel = (IDOMModel) StructuredModelManager.getModelManager().getExistingModelForRead(document);
            if (xmlModel != null) {
                IDOMDocument xmlDoc = xmlModel.getDocument();
                JSPTranslationAdapter adapter = (JSPTranslationAdapter) xmlDoc.getAdapterFor(IJSPTranslation.class);
                if (adapter != null) {
                    translation = adapter.getJSPTranslation();
                }
            }
        } finally {
            if (xmlModel != null)
                xmlModel.releaseFromRead();
        }
        return translation;
    }

    /**
     * Java always selects word when defining region
     * 
     * @param document
     * @param anchor
     * @return IRegion
     */
    private IRegion selectWord(IDocument document, int anchor) {

        try {
            int offset = anchor;
            char c;

            while (offset >= 0) {
                c = document.getChar(offset);
                if (!Character.isJavaIdentifierPart(c))
                    break;
                --offset;
            }

            int start = offset;

            offset = anchor;
            int length = document.getLength();

            while (offset < length) {
                c = document.getChar(offset);
                if (!Character.isJavaIdentifierPart(c))
                    break;
                ++offset;
            }

            int end = offset;

            if (start == end)
                return new Region(start, 0);

            return new Region(start + 1, end - start - 1);

        } catch (BadLocationException x) {
            return null;
        }
    }
}