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-2007 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 dwarfvsmodel;
043:
044: import java.util.*;
045:
046: /**
047: * Represents a set of
048: * - model or dwarf declarations and
049: * - nested nodes
050: *
051: * @author vk155633
052: */
053: public class Node<T> {
054:
055: private Node<T> parent;
056: private List<T> declarations = new ArrayList<T>();
057: private List<Node<T>> subnodes = new ArrayList<Node<T>>();
058:
059: public Iterable<T> getDeclarations() {
060: return declarations;
061: }
062:
063: public Iterable<Node<T>> getSubnodes() {
064: return subnodes;
065: }
066:
067: public void addDeclaration(T declaration) {
068: declarations.add(declaration);
069: }
070:
071: public void addSubnode(Node<T> node) {
072: // subnodes.add(node);
073: if (node.getDeclarations().iterator().hasNext()) {
074: subnodes.add(node);
075: node.setParent(this );
076: } else {
077: for (Node<T> subnode : node.getSubnodes()) {
078: addSubnode(subnode);
079: }
080: }
081: }
082:
083: private void setParent(Node<T> parent) {
084: this .parent = parent;
085: }
086:
087: public boolean isEmpty() {
088: return declarations.isEmpty() && subnodes.isEmpty();
089: }
090:
091: public void flatten() {
092: flatten3();
093: }
094:
095: private void flatten1() {
096: List<Node<T>> newSubnodes = new ArrayList<Node<T>>();
097: for (Node<T> child : subnodes) {
098: child.flatten();
099: if (!child.isEmpty()) {
100: newSubnodes.add(child);
101: newSubnodes.addAll(child.subnodes);
102: child.subnodes.clear();
103: }
104: }
105: subnodes = newSubnodes;
106: }
107:
108: private void flatten2() {
109: List<T> newDeclarations = new ArrayList<T>();
110: getDeclarationsRecursively(newDeclarations, subnodes);
111: Node<T> subnode = new Node<T>();
112: subnode.declarations = newDeclarations;
113: subnodes.clear();
114: addSubnode(subnode);
115: }
116:
117: private void flatten3() {
118: getDeclarationsRecursively(declarations, subnodes);
119: subnodes.clear();
120: }
121:
122: /**
123: * Adds all declarations from nodes into the given list, recursively
124: * @param declarations list to add declarations to
125: * @param nodes nodes from which to extract declarations
126: */
127: private void getDeclarationsRecursively(List<T> declarations,
128: Iterable<Node<T>> nodes) {
129: if (nodes != null) {
130: for (Node<T> node : nodes) {
131: DMUtils.addAll(declarations, node.getDeclarations());
132: getDeclarationsRecursively(declarations, node.subnodes);
133: }
134: }
135: }
136:
137: public int getDeclarationsCount() {
138: int sum = declarations.size();
139: for (Node<T> child : subnodes) {
140: sum += child.getDeclarationsCount();
141: }
142: return sum;
143: }
144:
145: private class NodeComparator implements Comparator<Node<T>> {
146:
147: private Comparator<T> comparator;
148:
149: public NodeComparator(Comparator<T> comparator) {
150: this .comparator = comparator;
151: }
152:
153: public int compare(Node<T> node1, Node<T> node2) {
154: // NB: we assume that both nodes are already sorted
155: if (node1.declarations.isEmpty()) {
156: return 0;
157: } else if (node2.declarations.isEmpty()) {
158: return 0;
159: } else {
160: return comparator.compare(node1.declarations.get(0),
161: node2.declarations.get(0));
162: }
163: }
164: }
165:
166: public void sort(final Comparator<T> comparator) {
167: Collections.sort(declarations, comparator);
168: for (Node<T> child : subnodes) {
169: child.sort(comparator);
170: }
171: // NB: first call sort for each child, then sort children
172: Collections.sort(subnodes, new NodeComparator(comparator));
173: }
174: }
|