| /******************************************************************************* |
| * Copyright (c) 2000, 2011 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.jdt.internal.corext.refactoring; |
| |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Comparator; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import org.eclipse.core.runtime.Assert; |
| import org.eclipse.core.runtime.CoreException; |
| |
| import org.eclipse.jdt.core.Flags; |
| import org.eclipse.jdt.core.IBuffer; |
| import org.eclipse.jdt.core.ICompilationUnit; |
| import org.eclipse.jdt.core.IField; |
| import org.eclipse.jdt.core.IImportContainer; |
| import org.eclipse.jdt.core.IJavaElement; |
| import org.eclipse.jdt.core.ISourceReference; |
| import org.eclipse.jdt.core.JavaModelException; |
| import org.eclipse.jdt.core.dom.ASTNode; |
| import org.eclipse.jdt.core.dom.ASTParser; |
| import org.eclipse.jdt.core.dom.CompilationUnit; |
| import org.eclipse.jdt.core.dom.FieldDeclaration; |
| import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
| |
| import org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils; |
| import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; |
| import org.eclipse.jdt.internal.corext.util.Strings; |
| |
| import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; |
| |
| /** |
| * A tuple used to keep source of an element and its type. |
| * @see IJavaElement |
| * @see org.eclipse.jdt.core.ISourceReference |
| */ |
| public class TypedSource { |
| |
| private static class SourceTuple { |
| |
| private SourceTuple(ICompilationUnit unit) { |
| this.unit= unit; |
| } |
| private ICompilationUnit unit; |
| private CompilationUnit node; |
| } |
| |
| private final String fSource; |
| private final int fType; |
| |
| private TypedSource(String source, int type){ |
| Assert.isNotNull(source); |
| Assert.isTrue(canCreateForType(type)); |
| fSource= source; |
| fType= type; |
| } |
| |
| public static TypedSource create(String source, int type) { |
| if (source == null || ! canCreateForType(type)) |
| return null; |
| return new TypedSource(source, type); |
| } |
| |
| public String getSource() { |
| return fSource; |
| } |
| |
| public int getType() { |
| return fType; |
| } |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#equals(java.lang.Object) |
| */ |
| @Override |
| public boolean equals(Object other) { |
| if (! (other instanceof TypedSource)) |
| return false; |
| |
| TypedSource ts= (TypedSource)other; |
| return ts.getSource().equals(getSource()) && ts.getType() == getType(); |
| } |
| |
| /* (non-Javadoc) |
| * @see java.lang.Object#hashCode() |
| */ |
| @Override |
| public int hashCode() { |
| return getSource().hashCode() ^ (97 * getType()); |
| } |
| |
| private static boolean canCreateForType(int type){ |
| return type == IJavaElement.FIELD |
| || type == IJavaElement.TYPE |
| || type == IJavaElement.IMPORT_CONTAINER |
| || type == IJavaElement.IMPORT_DECLARATION |
| || type == IJavaElement.INITIALIZER |
| || type == IJavaElement.METHOD |
| || type == IJavaElement.PACKAGE_DECLARATION; |
| } |
| |
| |
| public static void sortByType(TypedSource[] typedSources){ |
| Arrays.sort(typedSources, createTypeComparator()); |
| } |
| |
| public static Comparator<TypedSource> createTypeComparator() { |
| return new Comparator<TypedSource>(){ |
| public int compare(TypedSource arg0, TypedSource arg1) { |
| return arg0.getType() - arg1.getType(); |
| } |
| }; |
| } |
| public static TypedSource[] createTypedSources(IJavaElement[] javaElements) throws CoreException { |
| //Map<ICompilationUnit, List<IJavaElement>> |
| Map<ICompilationUnit, List<IJavaElement>> grouped= ReorgUtils.groupByCompilationUnit(Arrays.asList(javaElements)); |
| List<TypedSource> result= new ArrayList<TypedSource>(javaElements.length); |
| for (Iterator<ICompilationUnit> iter= grouped.keySet().iterator(); iter.hasNext();) { |
| ICompilationUnit cu= iter.next(); |
| for (Iterator<IJavaElement> iterator= grouped.get(cu).iterator(); iterator.hasNext();) { |
| SourceTuple tuple= new SourceTuple(cu); |
| TypedSource[] ts= createTypedSources(iterator.next(), tuple); |
| if (ts != null) |
| result.addAll(Arrays.asList(ts)); |
| } |
| } |
| return result.toArray(new TypedSource[result.size()]); |
| } |
| |
| private static TypedSource[] createTypedSources(IJavaElement elem, SourceTuple tuple) throws CoreException { |
| if (! ReorgUtils.isInsideCompilationUnit(elem)) |
| return null; |
| if (elem.getElementType() == IJavaElement.IMPORT_CONTAINER) |
| return createTypedSourcesForImportContainer(tuple, (IImportContainer)elem); |
| else if (elem.getElementType() == IJavaElement.FIELD) |
| return new TypedSource[] {create(getFieldSource((IField)elem, tuple), elem.getElementType())}; |
| return new TypedSource[] {create(getSourceOfDeclararationNode(elem, tuple.unit), elem.getElementType())}; |
| } |
| |
| private static TypedSource[] createTypedSourcesForImportContainer(SourceTuple tuple, IImportContainer container) throws JavaModelException, CoreException { |
| IJavaElement[] imports= container.getChildren(); |
| List<TypedSource> result= new ArrayList<TypedSource>(imports.length); |
| for (int i= 0; i < imports.length; i++) { |
| result.addAll(Arrays.asList(createTypedSources(imports[i], tuple))); |
| } |
| return result.toArray(new TypedSource[result.size()]); |
| } |
| |
| private static String getFieldSource(IField field, SourceTuple tuple) throws CoreException { |
| if (Flags.isEnum(field.getFlags())) { |
| String source= field.getSource(); |
| if (source != null) |
| return source; |
| } else { |
| if (tuple.node == null) { |
| ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); |
| parser.setSource(tuple.unit); |
| tuple.node= (CompilationUnit) parser.createAST(null); |
| } |
| FieldDeclaration declaration= ASTNodeSearchUtil.getFieldDeclarationNode(field, tuple.node); |
| if (declaration.fragments().size() == 1) |
| return getSourceOfDeclararationNode(field, tuple.unit); |
| VariableDeclarationFragment declarationFragment= ASTNodeSearchUtil.getFieldDeclarationFragmentNode(field, tuple.node); |
| IBuffer buffer= tuple.unit.getBuffer(); |
| StringBuffer buff= new StringBuffer(); |
| buff.append(buffer.getText(declaration.getStartPosition(), ((ASTNode) declaration.fragments().get(0)).getStartPosition() - declaration.getStartPosition())); |
| buff.append(buffer.getText(declarationFragment.getStartPosition(), declarationFragment.getLength())); |
| buff.append(";"); //$NON-NLS-1$ |
| return buff.toString(); |
| } |
| return ""; //$NON-NLS-1$ |
| } |
| |
| private static String getSourceOfDeclararationNode(IJavaElement elem, ICompilationUnit cu) throws JavaModelException, CoreException { |
| Assert.isTrue(elem.getElementType() != IJavaElement.IMPORT_CONTAINER); |
| if (elem instanceof ISourceReference) { |
| ISourceReference reference= (ISourceReference) elem; |
| String source= reference.getSource(); |
| if (source != null) |
| return Strings.trimIndentation(source, cu.getJavaProject(), false); |
| } |
| return ""; //$NON-NLS-1$ |
| } |
| } |