qwickie.util.DocumentHelper.java Source code

Java tutorial

Introduction

Here is the source code for qwickie.util.DocumentHelper.java

Source

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package qwickie.util;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.ICodeAssist;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
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.jdt.internal.core.NamedMember;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.ITextEditor;

import qwickie.QWickieActivator;

/**
 * @author count.negative
 *
 */
@SuppressWarnings("restriction")
public final class DocumentHelper {
    public static final String WICKET = "wicket";
    public static final String WICKET_MESSAGE = "wicket:message";
    public static final String KEY = "key";
    public static final String GET_STRING = "getString";
    public static final String RESOURCE_MODEL = "ResourceModel";
    public static final String STRING_RESOURCE_MODEL = "StringResourceModel";

    private DocumentHelper() {
    }

    /**
     * finds an argument between "" <br>
     * eg. new String("lalal");
     */
    public static IRegion findStringArgumentInJava(final IDocument document, final int offset) {
        try {
            final IRegion li = document.getLineInformationOfOffset(offset);
            for (int i = offset - 1; i >= li.getOffset(); i--) {
                if (document.getChar(i) == '"') {
                    for (int j = offset; j <= li.getOffset() + li.getLength(); j++) {
                        if (document.getChar(j) == '"') {
                            return new Region(i + 1, j - i - 1);
                        }
                    }
                }
            }
        } catch (final BadLocationException e) {
        }
        return null;
    }

    public static IRegion findWord(final IDocument document, final int offset) {
        int start = -2;
        int end = -1;
        try {
            int pos = offset;

            while (pos >= 0) {
                char c = document.getChar(pos);
                if ((!(Character.isJavaIdentifierPart(c))) && (!(((55296 <= c) && (c <= 57343))))) {
                    break;
                }

                --pos;
            }
            start = pos;

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

            while (pos < length) {
                char c = document.getChar(pos);
                if ((!(Character.isJavaIdentifierPart(c))) && (!(((55296 <= c) && (c <= 57343))))) {
                    break;
                }

                ++pos;
            }
            end = pos;
        } catch (BadLocationException localBadLocationException) {
        }
        if ((start >= -1) && (end > -1)) {
            if ((start == offset) && (end == offset)) {
                return new Region(offset, 0);
            }
            if (start == offset) {
                return new Region(start, end - start);
            }
            return new Region(start + 1, end - start - 1);
        }

        return null;
    }

    public static String getNamespacePrefix(final IDocument document) {
        Assert.isNotNull(document);
        FindReplaceDocumentAdapter frda = new FindReplaceDocumentAdapter(document);
        try {
            final IRegion dtd = frda.find(0, QWickieActivator.WICKET_DTD, true, false, false, false);
            if (dtd != null) {
                final IRegion li = document.getLineInformationOfOffset(dtd.getOffset());
                final String line = document.get(li.getOffset(), li.getLength());
                return getWicketNamespace(line);
            }
        } catch (BadLocationException e) {
        }
        return WICKET;
    }

    public static String getWicketNamespace(final String line) {
        int start = line.indexOf("xmlns:");
        if (start != -1) {
            return line.substring(start + 6, line.indexOf("=", start));
        }
        return WICKET;
    }

    public static IRegion findStringArgumentInMarkup(final IDocument document, final int offset,
            final String argument) {
        try {
            final IRegion lineInfo = document.getLineInformationOfOffset(offset);
            final String line = document.get(lineInfo.getOffset(), lineInfo.getLength());
            final int lineRelativeOffset = offset - lineInfo.getOffset();
            final int firstG = line.lastIndexOf('"', lineRelativeOffset - 1);
            final int lastG = line.indexOf('"', lineRelativeOffset);
            if (firstG == -1 || firstG == lastG) {
                return null;
            }
            final int start = line.lastIndexOf(" ", firstG) + 1;
            final int end = firstG - 1;
            if (start >= end) {
                return null;
            }
            final CharSequence attribute = line.subSequence(start, end);
            if (!attribute.equals(argument) && !KEY.equals(attribute)) {
                return null;
            }
            // could be a <wicket:message key="linkText"/>
            if (KEY.equals(attribute) && line.lastIndexOf(argument, firstG - KEY.length()) == -1) {
                return null;
            }
            return new Region(offset - (lineRelativeOffset - firstG - 1), lastG - firstG - 1);
        } catch (final BadLocationException e) {
            return null;
        }
    }

    /** Finds every wicket:id element in a java editor */
    public static IRegion[] findWicketRegions(final IEditorPart editor, final IDocument document,
            final int offset) {
        Assert.isNotNull(editor);
        Assert.isNotNull(document);

        final IRegion[] regions = new IRegion[3];

        try {
            IRegion wicketIdRegion = findStringArgumentInJava(document, offset);
            if (wicketIdRegion == null) {
                return null;
            }
            final IRegion wicketComponentRegion = DocumentHelper.findWicketComponentRegion(document,
                    wicketIdRegion.getOffset());
            if (wicketComponentRegion == null) {
                return null;
            }
            final IRegion javaRegion = findWord(document, wicketComponentRegion.getOffset());
            if (javaRegion.getLength() == 0) {
                return null;
            }
            final IJavaElement input = EditorUtility.getEditorInputJavaElement(editor, false);
            final IJavaElement[] javaElements = ((ICodeAssist) input).codeSelect(javaRegion.getOffset(),
                    javaRegion.getLength());
            if (javaElements == null || javaElements.length == 0) {
                return null;
            }
            for (final IJavaElement javaElement : javaElements) {
                final boolean isWicketComponent = TypeHelper.isWicketComponent(javaElement);
                // search for a string in a properties file
                if (STRING_RESOURCE_MODEL.equals(javaElement.getElementName())
                        || RESOURCE_MODEL.equals(javaElement.getElementName())
                        || (GET_STRING.equals(javaElement.getElementName()) && isWicketComponent)) {
                    regions[2] = findStringArgumentInJava(document, offset);
                    regions[1] = regions[2];
                } else {
                    regions[1] = DocumentHelper.getRegionOfWicketComponent(document, offset, javaElement);
                }
            }
            regions[0] = wicketIdRegion;
            return regions;
        } catch (final JavaModelException e) {
            return null;
        }
    }

    /** Finds the IRegion where a wicket Component (one that extends Component) is found */
    public static IRegion getRegionOfWicketComponent(final IDocument document, final int offset,
            final IJavaElement javaElement) throws JavaModelException {
        if (javaElement != null && javaElement instanceof NamedMember) {
            final NamedMember method = (NamedMember) javaElement;
            final IType type = method.getDeclaringType();
            if (type != null) {
                final ITypeHierarchy hierarchy = type.newSupertypeHierarchy(null);
                if (hierarchy != null) {
                    final IType[] supertypes = hierarchy.getAllSupertypes(type);
                    for (final IType iType : supertypes) {
                        if (iType.getFullyQualifiedName().equals(TypeHelper.COMPONENT)) {
                            try {
                                final IRegion lineInfo = document.getLineInformationOfOffset(offset);
                                final String line = document.get(lineInfo.getOffset(), lineInfo.getLength());
                                final int lineRelativeOffset = offset - lineInfo.getOffset();
                                final int index = line.indexOf(javaElement.getElementName());
                                return new Region(offset - lineRelativeOffset + index,
                                        javaElement.getElementName().length());
                            } catch (final Exception ex) {
                                return null;
                            }
                        }
                    }
                }
            }
        }
        return null;
    }

    /**
     * finds the Region where a wicket component is created
     *
     * @param document
     *            the java document
     * @param offset
     *            where the search should begin
     * @return A region where the java component part begins (e.g. the 'F' in "new Form<Customer>("customerForm");" length is always 1
     */
    public static IRegion findWicketComponentRegion(final IDocument document, final int offset) {
        try {
            final IRegion lineInfo = document.getLineInformationOfOffset(offset);
            final String line = document.get(lineInfo.getOffset(), lineInfo.getLength());
            final int lineRelativeOffset = offset - lineInfo.getOffset();
            int start = lineRelativeOffset;
            boolean qFound = false;
            for (int i = line.length() == lineRelativeOffset ? lineRelativeOffset - 1
                    : lineRelativeOffset; i > 0; i--) {
                final char c = line.charAt(i);
                if (c == '(' || c == ',') {
                    start = i;
                    break;
                }
                if (!qFound && c == '"') {
                    qFound = true;
                } else if (qFound && c == '"') {
                    return null;
                }
            }
            int funcStart = line.lastIndexOf(GET_STRING, start) + 1;
            if (funcStart == 0) {
                for (int i = start - 1; i > 0; i--) {
                    final char c = line.charAt(i);
                    if (c == '(' || c == ' ') {
                        funcStart = i + 1;
                        break;
                    }
                }
            }
            return new Region(offset - lineRelativeOffset + funcStart, 1);
        } catch (final BadLocationException e) {
            return null;
        }
    }

    /**
     * marks all occurrences of the given string
     */
    public static void markOccurrence(final ITextEditor textEditor, final String string) {
        if (string == null) {
            return;
        }
        SearchPattern pattern = SearchPattern.createPattern(string, IJavaSearchConstants.FIELD,
                IJavaSearchConstants.ALL_OCCURRENCES, SearchPattern.R_EXACT_MATCH);

        SearchRequestor requestor = new SearchRequestor() {
            @Override
            public void acceptSearchMatch(final SearchMatch match) {
                IAnnotationModel model = textEditor.getDocumentProvider()
                        .getAnnotationModel(textEditor.getEditorInput());
                Annotation annotation = new Annotation("org.eclipse.jdt.ui.occurrences", false,
                        "wicket id constant");
                model.addAnnotation(annotation, new Position(match.getOffset(), match.getLength()));
            }
        };

        SearchEngine searchEngine = new SearchEngine();
        try {
            searchEngine.search(pattern, new SearchParticipant[] { SearchEngine.getDefaultSearchParticipant() },
                    SearchEngine.createWorkspaceScope(), requestor, new NullProgressMonitor());
        } catch (CoreException e) {
        }
    }

    /**
     * returns the String constant name in a line of java code e.g. <code>protected String PETE = "pete";</code> returns <code>PETE</code>
     */
    public static String getStringConstantName(final String line) {
        Assert.isNotNull(line);
        final int ios = line.indexOf("String ");
        if (ios == -1) {
            return null;
        }
        return line.substring(ios + 6, line.indexOf('=')).trim();
    }
}