/* * Copyright 2003-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jetbrains.mps.ide.ui.tree.module; import jetbrains.mps.ide.ui.tree.MPSTreeNode; import jetbrains.mps.util.ToStringComparator; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Enumeration; import java.util.List; public abstract class NamespaceTreeBuilder<N extends MPSTreeNode, T extends MPSTreeNode> { private T myRootNamespace; private NamespaceNodeBuilder<T> myBuilder; protected NamespaceTreeBuilder(NamespaceNodeBuilder<T> builder) { myBuilder = builder; myRootNamespace = myBuilder.createNamespaceNode(""); } /** * @return never <code>null</code>, empty string for root namespace */ protected abstract String getNamespace(N node); public void addNode(N node) { String namespace = getNamespace(node); List<String> pathElements = new ArrayList<String>(Arrays.asList(namespace.split("\\."))); if (pathElements.size() == 1 && pathElements.get(0).equals("")) { pathElements.remove(0); } addNode(node, getSubnamespace(myRootNamespace, pathElements)); } protected void addNode(N node, T namespace) { namespace.add(node); } public void fillNode(MPSTreeNode root) { sortTree(myRootNamespace); compactNodes(myRootNamespace); Enumeration children = myRootNamespace.children(); List<MPSTreeNode> oldChildren = new ArrayList<MPSTreeNode>(); while (children.hasMoreElements()) { oldChildren.add((MPSTreeNode) children.nextElement()); } for (MPSTreeNode node : oldChildren) { myRootNamespace.remove(node); root.add(node); } } private void sortTree(T node) { List<MPSTreeNode> nodes = new ArrayList<MPSTreeNode>(); List<T> namespaces = new ArrayList<T>(); for (int i = 0; i < node.getChildCount(); i++) { MPSTreeNode child = (MPSTreeNode) node.getChildAt(i); if (myBuilder.isNamespaceNode(child)) { @SuppressWarnings("unchecked") T nsNode = (T) child; sortTree(nsNode); namespaces.add(nsNode); } else { nodes.add(child); } } Collections.sort(namespaces, new ToStringComparator()); Collections.sort(nodes, new ModuleTreeNodeComparator()); node.removeAllChildren(); for (T ns : namespaces) { node.add(ns); } for (MPSTreeNode n : nodes) { node.add(n); } } private void compactNodes(T node) { for (int i = 0; i < node.getChildCount(); i++) { MPSTreeNode child = (MPSTreeNode) node.getChildAt(i); if (myBuilder.isNamespaceNode(child)) { @SuppressWarnings("unchecked") T nsNode = (T) child; compactNodes(nsNode); } } if (node.getParent() != null && //skip root node.getChildCount() == 1 && myBuilder.isNamespaceNode((MPSTreeNode) node.getChildAt(0))) { @SuppressWarnings("unchecked") T child = (T) node.getChildAt(0); myBuilder.setName(node, myBuilder.getName(node) + "." + myBuilder.getName(child)); Enumeration children = child.children(); List<MPSTreeNode> oldChildren = new ArrayList<MPSTreeNode>(); while (children.hasMoreElements()) { oldChildren.add((MPSTreeNode) children.nextElement()); } for (MPSTreeNode c : oldChildren) { child.remove(c); node.add(c); } node.remove(child); } } private T getSubnamespace(T sourceNode, List<String> pathElements) { if (pathElements.size() == 0) return sourceNode; String first = pathElements.get(0); List<String> otherElements = pathElements.subList(1, pathElements.size()); for (int i = 0; i < sourceNode.getChildCount(); i++) { if (myBuilder.isNamespaceNode((MPSTreeNode) sourceNode.getChildAt(i))) { @SuppressWarnings("unchecked") T child = (T) sourceNode.getChildAt(i); if (first.equals(myBuilder.getName(child))) { return getSubnamespace(child, otherElements); } } } T newChild = myBuilder.createNamespaceNode(first); sourceNode.add(newChild); return getSubnamespace(newChild, otherElements); } public interface NamespaceNodeBuilder<N extends MPSTreeNode> { N createNamespaceNode(String text); String getName(N node); void setName(N node, String name); boolean isNamespaceNode(MPSTreeNode n); } }