Java tutorial
/* * 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(); } }