001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.refactoring.java.plugins;
043:
044: import javax.lang.model.util.Types;
045: import org.netbeans.modules.refactoring.java.spi.RefactoringVisitor;
046: import com.sun.source.tree.*;
047: import com.sun.source.util.TreePath;
048: import java.util.HashSet;
049: import java.util.Set;
050: import javax.lang.model.element.*;
051: import javax.lang.model.type.TypeMirror;
052: import org.netbeans.api.java.source.ElementHandle;
053: import org.netbeans.api.java.source.GeneratorUtilities;
054: import org.netbeans.modules.refactoring.api.Problem;
055: import org.netbeans.modules.refactoring.java.RetoucheUtils;
056: import org.netbeans.modules.refactoring.java.api.MemberInfo;
057:
058: /**
059: *
060: * @author Jan Becicka
061: */
062: public class PushDownTransformer extends RefactoringVisitor {
063:
064: private MemberInfo<ElementHandle<? extends Element>>[] members;
065: private Problem problem;
066:
067: public Problem getProblem() {
068: return problem;
069: }
070:
071: public PushDownTransformer(
072: MemberInfo<ElementHandle<? extends Element>> members[]) {
073: this .members = members;
074: }
075:
076: @Override
077: public Tree visitClass(ClassTree tree, Element p) {
078: Element el = workingCopy.getTrees()
079: .getElement(getCurrentPath());
080: GeneratorUtilities genUtils = GeneratorUtilities
081: .get(workingCopy);
082: ClassTree njuClass = tree;
083: if (el.equals(p)) {
084: //source type
085: boolean classIsAbstract = el.getKind().isInterface();
086:
087: for (Tree t : njuClass.getImplementsClause()) {
088: Element currentInterface = workingCopy.getTrees()
089: .getElement(
090: TreePath.getPath(getCurrentPath(), t));
091: for (int i = 0; i < members.length; i++) {
092: if (members[i].getGroup() == MemberInfo.Group.IMPLEMENTS
093: && currentInterface.equals(members[i]
094: .getElementHandle().resolve(
095: workingCopy))) {
096: njuClass = make.removeClassImplementsClause(
097: njuClass, t);
098: rewrite(tree, njuClass);
099: }
100: }
101: }
102:
103: for (Tree t : njuClass.getMembers()) {
104: for (int i = 0; i < members.length; i++) {
105: Element current = workingCopy.getTrees()
106: .getElement(
107: TreePath.getPath(workingCopy
108: .getCompilationUnit(), t));
109: if (members[i].getGroup() != MemberInfo.Group.IMPLEMENTS
110: && current != null
111: && current.equals(members[i]
112: .getElementHandle().resolve(
113: workingCopy))) {
114: if (members[i].isMakeAbstract()) {
115: if (el.getKind().isClass()) {
116: if (!classIsAbstract) {
117: classIsAbstract = true;
118: Set<Modifier> mod = new HashSet<Modifier>(
119: njuClass.getModifiers()
120: .getFlags());
121: mod.add(Modifier.ABSTRACT);
122: ModifiersTree modifiers = make
123: .Modifiers(mod);
124: rewrite(njuClass.getModifiers(),
125: modifiers);
126: }
127:
128: MethodTree method = (MethodTree) t;
129: Set<Modifier> mod = new HashSet<Modifier>(
130: method.getModifiers()
131: .getFlags());
132: mod.add(Modifier.ABSTRACT);
133: MethodTree nju = make.Method(make
134: .Modifiers(mod), method
135: .getName(), method
136: .getReturnType(), method
137: .getTypeParameters(), method
138: .getParameters(), method
139: .getThrows(), (BlockTree) null,
140: (ExpressionTree) method
141: .getDefaultValue());
142: rewrite(method, nju);
143: }
144: } else {
145: njuClass = make.removeClassMember(njuClass,
146: t);
147: rewrite(tree, njuClass);
148: }
149: }
150: }
151:
152: }
153: } else {
154: //target type
155: TypeMirror tm = el.asType();
156: Types types = workingCopy.getTypes();
157: if (types.isSubtype(types.erasure(tm), types.erasure(p
158: .asType()))) {
159: for (int i = 0; i < members.length; i++) {
160: Element member = members[i].getElementHandle()
161: .resolve(workingCopy);
162: if (members[i].getGroup() == MemberInfo.Group.IMPLEMENTS) {
163: if (((TypeElement) el).getInterfaces()
164: .contains(member.asType())) {
165: problem = MoveTransformer
166: .createProblem(
167: problem,
168: false,
169: org.openide.util.NbBundle
170: .getMessage(
171: PushDownTransformer.class,
172: "ERR_PushDown_AlreadyExists",
173: member
174: .getSimpleName(),
175: el
176: .getSimpleName()));
177: }
178: njuClass = make.addClassImplementsClause(
179: njuClass, make.Identifier(member));
180: } else {
181: if (RetoucheUtils.elementExistsIn(
182: (TypeElement) el, member, workingCopy)) {
183: problem = MoveTransformer
184: .createProblem(
185: problem,
186: false,
187: org.openide.util.NbBundle
188: .getMessage(
189: PushDownTransformer.class,
190: "ERR_PushDown_AlreadyExists",
191: member
192: .getSimpleName(),
193: el
194: .getSimpleName()));
195: }
196: TreePath path = workingCopy.getTrees().getPath(
197: member);
198: Tree memberTree = genUtils.importComments(path
199: .getLeaf(), path.getCompilationUnit());
200: memberTree = genUtils
201: .importFQNs(path.getLeaf());
202: if (member != null)
203: RetoucheUtils.copyJavadoc(member,
204: memberTree, workingCopy);
205: njuClass = genUtils.insertClassMember(njuClass,
206: memberTree);
207: }
208: }
209: rewrite(tree, njuClass);
210: }
211: }
212: return super.visitClass(tree, p);
213: }
214:
215: }
|