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.ui.tree;
043:
044: import com.sun.source.tree.Tree;
045: import com.sun.source.util.TreePath;
046: import java.util.HashSet;
047: import java.util.Set;
048: import java.util.WeakHashMap;
049: import javax.lang.model.element.Element;
050: import org.netbeans.api.java.source.CompilationInfo;
051: import org.openide.filesystems.FileObject;
052:
053: /**
054: *
055: * @author Jan Becicka
056: */
057: public class ElementGripFactory {
058:
059: private static ElementGripFactory instance;
060: private WeakHashMap<FileObject, Interval> map = new WeakHashMap();
061:
062: /**
063: * Creates a new instance of ElementGripFactory
064: */
065: private ElementGripFactory() {
066: }
067:
068: public static ElementGripFactory getDefault() {
069: if (instance == null) {
070: instance = new ElementGripFactory();
071: }
072: return instance;
073: }
074:
075: public void cleanUp() {
076: map.clear();
077: }
078:
079: public ElementGrip get(FileObject fileObject, int position) {
080: Interval start = map.get(fileObject);
081: if (start == null)
082: return null;
083: try {
084: return (ElementGrip) start.get(position).item;
085: } catch (RuntimeException e) {
086: return start.item;
087: }
088: }
089:
090: public ElementGrip getParent(ElementGrip el) {
091: Interval start = map.get(el.getFileObject());
092: return (ElementGrip) start.getParent(el);
093: }
094:
095: public void put(FileObject parentFile, TreePath tp,
096: CompilationInfo info) {
097: Interval root = map.get(parentFile);
098: Interval i = Interval.createInterval(tp, info, root, null,
099: parentFile);
100: if (i != null) {
101: map.put(parentFile, i);
102: }
103: }
104:
105: private static class Interval {
106: long from = -1, to = -1;
107: Set<Interval> subintervals = new HashSet();
108: ElementGrip item = null;
109:
110: Interval get(long position) {
111: if (from <= position && to >= position) {
112: for (Interval o : subintervals) {
113: Interval ob = o.get(position);
114: if (ob != null)
115: return ob;
116: }
117: return this ;
118: }
119: return null;
120: }
121:
122: ElementGrip getParent(ElementGrip eh) {
123: for (Interval i : subintervals) {
124: if (i.item.equals(eh)) {
125: return this .item;
126: } else {
127: ElementGrip e = i.getParent(eh);
128: if (e != null) {
129: return e;
130: }
131: }
132: }
133: return null;
134: }
135:
136: public static Interval createInterval(TreePath tp,
137: CompilationInfo info, Interval root, Interval p,
138: FileObject parentFile) {
139: Tree t = tp.getLeaf();
140: long start = info.getTrees().getSourcePositions()
141: .getStartPosition(info.getCompilationUnit(), t);
142: long end = info.getTrees().getSourcePositions()
143: .getEndPosition(info.getCompilationUnit(), t);
144: Element current = info.getTrees().getElement(tp);
145: Tree.Kind kind = tp.getLeaf().getKind();
146: if (kind != Tree.Kind.CLASS && kind != Tree.Kind.METHOD) {
147: if (tp.getParentPath() == null
148: || tp.getParentPath().getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
149: //xxx: rather workaround. should be fixed better.
150: return null;
151: } else {
152: return createInterval(tp.getParentPath(), info,
153: root, p, parentFile);
154: }
155: }
156: Interval i = null;
157: if (root != null) {
158: Interval o = root.get(start);
159: if (o != null && current != null
160: && current.equals(o.item.resolveElement(info))) {
161: if (p != null)
162: o.subintervals.add(p);
163: return null;
164: }
165: }
166: if (i == null)
167: i = new Interval();
168: if (i.from != start) {
169: i.from = start;
170: i.to = end;
171: ElementGrip currentHandle2 = new ElementGrip(tp, info);
172: i.item = currentHandle2;
173: }
174: if (p != null) {
175: i.subintervals.add(p);
176: }
177: if (tp.getParentPath().getLeaf().getKind() == Tree.Kind.COMPILATION_UNIT) {
178: return i;
179: }
180: return createInterval(tp.getParentPath(), info, root, i,
181: parentFile);
182: }
183: }
184: }
|