001: /*******************************************************************************
002: * Copyright (c) 2000, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.jdt.internal.corext.refactoring;
011:
012: import java.util.ArrayList;
013: import java.util.Arrays;
014: import java.util.Comparator;
015: import java.util.Iterator;
016: import java.util.List;
017: import java.util.Map;
018:
019: import org.eclipse.core.runtime.Assert;
020: import org.eclipse.core.runtime.CoreException;
021:
022: import org.eclipse.jdt.core.Flags;
023: import org.eclipse.jdt.core.IBuffer;
024: import org.eclipse.jdt.core.ICompilationUnit;
025: import org.eclipse.jdt.core.IField;
026: import org.eclipse.jdt.core.IImportContainer;
027: import org.eclipse.jdt.core.IJavaElement;
028: import org.eclipse.jdt.core.ISourceReference;
029: import org.eclipse.jdt.core.JavaModelException;
030: import org.eclipse.jdt.core.dom.AST;
031: import org.eclipse.jdt.core.dom.ASTNode;
032: import org.eclipse.jdt.core.dom.ASTParser;
033: import org.eclipse.jdt.core.dom.CompilationUnit;
034: import org.eclipse.jdt.core.dom.FieldDeclaration;
035: import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
036:
037: import org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils;
038: import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
039: import org.eclipse.jdt.internal.corext.util.Strings;
040:
041: /**
042: * A tuple used to keep source of an element and its type.
043: * @see IJavaElement
044: * @see org.eclipse.jdt.core.ISourceReference
045: */
046: public class TypedSource {
047:
048: private static class SourceTuple {
049:
050: private SourceTuple(ICompilationUnit unit) {
051: this .unit = unit;
052: }
053:
054: private ICompilationUnit unit;
055: private CompilationUnit node;
056: }
057:
058: private final String fSource;
059: private final int fType;
060:
061: private TypedSource(String source, int type) {
062: Assert.isNotNull(source);
063: Assert.isTrue(canCreateForType(type));
064: fSource = source;
065: fType = type;
066: }
067:
068: public static TypedSource create(String source, int type) {
069: if (source == null || !canCreateForType(type))
070: return null;
071: return new TypedSource(source, type);
072: }
073:
074: public String getSource() {
075: return fSource;
076: }
077:
078: public int getType() {
079: return fType;
080: }
081:
082: /* (non-Javadoc)
083: * @see java.lang.Object#equals(java.lang.Object)
084: */
085: public boolean equals(Object other) {
086: if (!(other instanceof TypedSource))
087: return false;
088:
089: TypedSource ts = (TypedSource) other;
090: return ts.getSource().equals(getSource())
091: && ts.getType() == getType();
092: }
093:
094: /* (non-Javadoc)
095: * @see java.lang.Object#hashCode()
096: */
097: public int hashCode() {
098: return getSource().hashCode() ^ (97 * getType());
099: }
100:
101: private static boolean canCreateForType(int type) {
102: return type == IJavaElement.FIELD || type == IJavaElement.TYPE
103: || type == IJavaElement.IMPORT_CONTAINER
104: || type == IJavaElement.IMPORT_DECLARATION
105: || type == IJavaElement.INITIALIZER
106: || type == IJavaElement.METHOD
107: || type == IJavaElement.PACKAGE_DECLARATION;
108: }
109:
110: public static void sortByType(TypedSource[] typedSources) {
111: Arrays.sort(typedSources, createTypeComparator());
112: }
113:
114: public static Comparator createTypeComparator() {
115: return new Comparator() {
116: public int compare(Object arg0, Object arg1) {
117: return ((TypedSource) arg0).getType()
118: - ((TypedSource) arg1).getType();
119: }
120: };
121: }
122:
123: public static TypedSource[] createTypedSources(
124: IJavaElement[] javaElements) throws CoreException {
125: //Map<ICompilationUnit, List<IJavaElement>>
126: Map grouped = ReorgUtils.groupByCompilationUnit(Arrays
127: .asList(javaElements));
128: List result = new ArrayList(javaElements.length);
129: for (Iterator iter = grouped.keySet().iterator(); iter
130: .hasNext();) {
131: ICompilationUnit cu = (ICompilationUnit) iter.next();
132: for (Iterator iterator = ((List) grouped.get(cu))
133: .iterator(); iterator.hasNext();) {
134: SourceTuple tuple = new SourceTuple(cu);
135: TypedSource[] ts = createTypedSources(
136: (IJavaElement) iterator.next(), tuple);
137: if (ts != null)
138: result.addAll(Arrays.asList(ts));
139: }
140: }
141: return (TypedSource[]) result.toArray(new TypedSource[result
142: .size()]);
143: }
144:
145: private static TypedSource[] createTypedSources(IJavaElement elem,
146: SourceTuple tuple) throws CoreException {
147: if (!ReorgUtils.isInsideCompilationUnit(elem))
148: return null;
149: if (elem.getElementType() == IJavaElement.IMPORT_CONTAINER)
150: return createTypedSourcesForImportContainer(tuple,
151: (IImportContainer) elem);
152: else if (elem.getElementType() == IJavaElement.FIELD)
153: return new TypedSource[] { create(getFieldSource(
154: (IField) elem, tuple), elem.getElementType()) };
155: return new TypedSource[] { create(getSourceOfDeclararationNode(
156: elem, tuple.unit), elem.getElementType()) };
157: }
158:
159: private static TypedSource[] createTypedSourcesForImportContainer(
160: SourceTuple tuple, IImportContainer container)
161: throws JavaModelException, CoreException {
162: IJavaElement[] imports = container.getChildren();
163: List result = new ArrayList(imports.length);
164: for (int i = 0; i < imports.length; i++) {
165: result.addAll(Arrays.asList(createTypedSources(imports[i],
166: tuple)));
167: }
168: return (TypedSource[]) result.toArray(new TypedSource[result
169: .size()]);
170: }
171:
172: private static String getFieldSource(IField field, SourceTuple tuple)
173: throws CoreException {
174: if (Flags.isEnum(field.getFlags())) {
175: String source = field.getSource();
176: if (source != null)
177: return source;
178: } else {
179: if (tuple.node == null) {
180: ASTParser parser = ASTParser.newParser(AST.JLS3);
181: parser.setSource(tuple.unit);
182: tuple.node = (CompilationUnit) parser.createAST(null);
183: }
184: FieldDeclaration declaration = ASTNodeSearchUtil
185: .getFieldDeclarationNode(field, tuple.node);
186: if (declaration.fragments().size() == 1)
187: return getSourceOfDeclararationNode(field, tuple.unit);
188: VariableDeclarationFragment declarationFragment = ASTNodeSearchUtil
189: .getFieldDeclarationFragmentNode(field, tuple.node);
190: IBuffer buffer = tuple.unit.getBuffer();
191: StringBuffer buff = new StringBuffer();
192: buff.append(buffer.getText(declaration.getStartPosition(),
193: ((ASTNode) declaration.fragments().get(0))
194: .getStartPosition()
195: - declaration.getStartPosition()));
196: buff.append(buffer.getText(declarationFragment
197: .getStartPosition(), declarationFragment
198: .getLength()));
199: buff.append(";"); //$NON-NLS-1$
200: return buff.toString();
201: }
202: return ""; //$NON-NLS-1$
203: }
204:
205: private static String getSourceOfDeclararationNode(
206: IJavaElement elem, ICompilationUnit cu)
207: throws JavaModelException, CoreException {
208: Assert
209: .isTrue(elem.getElementType() != IJavaElement.IMPORT_CONTAINER);
210: if (elem instanceof ISourceReference) {
211: ISourceReference reference = (ISourceReference) elem;
212: String source = reference.getSource();
213: if (source != null)
214: return Strings.trimIndentation(source, cu
215: .getJavaProject(), false);
216: }
217: return ""; //$NON-NLS-1$
218: }
219: }
|