-package org.simantics.modeling.requests;\r
-\r
-import java.util.ArrayDeque;\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.Comparator;\r
-import java.util.Deque;\r
-import java.util.List;\r
-\r
-import org.eclipse.jface.viewers.IFilter;\r
-import org.simantics.scl.runtime.function.Function1;\r
-\r
-/**\r
- * @author Tuukka Lehtonen\r
- */\r
-public class Nodes {\r
-\r
- public static Collection<Node> breadthFirstFlatten(IFilter filter, Collection<Node> roots) {\r
- Collection<Node> result = new ArrayList<Node>();\r
- List<Node> sortedRoots = new ArrayList<Node>(roots);\r
- Collections.sort(sortedRoots);\r
- Deque<Node> todo = new ArrayDeque<Node>(sortedRoots);\r
- while (!todo.isEmpty()) {\r
- Node n = todo.removeFirst();\r
- List<Node> sorted = new ArrayList<Node>(n.getChildren());\r
- Collections.sort(sorted);\r
- todo.addAll(sorted);\r
- if (filter == null || filter.select(n))\r
- result.add(n);\r
- }\r
- return result;\r
- }\r
-\r
- public static Collection<Node> depthFirstFlatten(IFilter filter, Collection<Node> roots, Comparator<? super Node> comparator) {\r
- Collection<Node> result = new ArrayList<Node>();\r
- List<Node> sortedRoots = new ArrayList<Node>(roots);\r
- Collections.sort(sortedRoots, comparator);\r
- for (Node n : sortedRoots) {\r
- depthFirstFlattenRec(filter, comparator, n, result);\r
- }\r
- return result;\r
- }\r
-\r
- private static Collection<Node> depthFirstFlattenRec(IFilter filter, Comparator<? super Node> comparator, Node n, Collection<Node> result) {\r
- if (filter == null || filter.select(n))\r
- result.add(n);\r
-\r
- Collection<Node> children = n.getChildren();\r
- if (children.isEmpty())\r
- return result;\r
-\r
- List<Node> sorted = new ArrayList<Node>(children);\r
- Collections.sort(sorted, comparator);\r
- for (Node child : sorted)\r
- depthFirstFlattenRec(filter, comparator, child, result);\r
-\r
- return result;\r
- }\r
-\r
- /**\r
- * @param f\r
- * function that takes the walked Node as argument and returns a\r
- * boolean to describe whether to continue the walk or cancel the\r
- * walk. The returned value cannot be <code>null</code>.\r
- * @return <code>true</code> if the walk was completed or <code>false</code>\r
- * if the walk was cancelled\r
- */\r
- public static boolean walkTree(Function1<Node, Boolean> filter, Collection<Node> roots) {\r
- List<Node> sortedRoots = new ArrayList<Node>(roots);\r
- Collections.sort(sortedRoots);\r
- for (Node n : sortedRoots)\r
- if (!walkTreeRec(filter, n))\r
- return false;\r
- return true;\r
- }\r
-\r
- private static boolean walkTreeRec(Function1<Node, Boolean> filter, Node n) {\r
- if (!filter.apply(n))\r
- return false;\r
-\r
- Collection<Node> children = n.getChildren();\r
- if (!children.isEmpty()) {\r
- List<Node> sorted = new ArrayList<Node>(children);\r
- Collections.sort(sorted);\r
- for (Node child : sorted)\r
- if (!walkTreeRec(filter, child))\r
- return false;\r
- }\r
- return true;\r
- }\r
-\r
-}\r
+package org.simantics.modeling.requests;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Deque;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.function.Predicate;
+
+import org.eclipse.jface.viewers.IFilter;
+import org.simantics.scl.runtime.function.Function1;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class Nodes {
+
+ public static final Predicate<Node> DIAGRAM_RESOURCE_PREDICATE = n -> n.getDiagramResource() != null;
+ public static final Predicate<Node> DIAGRAM_RESOURCE_AND_RVI_PREDICATE = n -> n.getDiagramResource() != null && n.getRVI() != null;
+
+ public static Collection<Node> breadthFirstFlatten(IFilter filter, Collection<Node> roots) {
+ Collection<Node> result = new ArrayList<>();
+ List<Node> sortedRoots = new ArrayList<>(roots);
+ Collections.sort(sortedRoots);
+ Deque<Node> todo = new ArrayDeque<>(sortedRoots);
+ while (!todo.isEmpty()) {
+ Node n = todo.removeFirst();
+ List<Node> sorted = new ArrayList<>(n.getChildren());
+ Collections.sort(sorted);
+ todo.addAll(sorted);
+ if (filter == null || filter.select(n))
+ result.add(n);
+ }
+ return result;
+ }
+
+ public static Collection<Node> depthFirstFlatten(IFilter filter, Collection<Node> roots, Comparator<? super Node> comparator) {
+ Collection<Node> result = new ArrayList<>();
+ List<Node> sortedRoots = new ArrayList<>(roots);
+ Collections.sort(sortedRoots, comparator);
+ for (Node n : sortedRoots) {
+ depthFirstFlattenRec(filter, comparator, n, result);
+ }
+ return result;
+ }
+
+ private static Collection<Node> depthFirstFlattenRec(IFilter filter, Comparator<? super Node> comparator, Node n, Collection<Node> result) {
+ if (filter == null || filter.select(n))
+ result.add(n);
+
+ Collection<Node> children = n.getChildren();
+ if (children.isEmpty())
+ return result;
+
+ List<Node> sorted = new ArrayList<>(children);
+ Collections.sort(sorted, comparator);
+ for (Node child : sorted)
+ depthFirstFlattenRec(filter, comparator, child, result);
+
+ return result;
+ }
+
+ /**
+ * @param f
+ * function that takes the walked Node as argument and returns a
+ * boolean to describe whether to continue the walk or cancel the
+ * walk. The returned value cannot be <code>null</code>.
+ * @return <code>true</code> if the walk was completed or <code>false</code>
+ * if the walk was cancelled
+ */
+ public static boolean walkTree(Function1<Node, Boolean> filter, Collection<Node> roots) {
+ List<Node> sortedRoots = new ArrayList<>(roots);
+ Collections.sort(sortedRoots);
+ for (Node n : sortedRoots)
+ if (!walkTreeRec(filter, n))
+ return false;
+ return true;
+ }
+
+ private static boolean walkTreeRec(Function1<Node, Boolean> filter, Node n) {
+ if (!filter.apply(n))
+ return false;
+
+ Collection<Node> children = n.getChildren();
+ if (!children.isEmpty()) {
+ List<Node> sorted = new ArrayList<>(children);
+ Collections.sort(sorted);
+ for (Node child : sorted)
+ if (!walkTreeRec(filter, child))
+ return false;
+ }
+ return true;
+ }
+
+ public static boolean parentIsInSet(Set<Node> set, Node node) {
+ for (Node n = node.getParent(); n != null; n = n.getParent())
+ if (set.contains(n))
+ return true;
+ return false;
+ }
+
+ public static Set<Node> depthFirstFilter(Predicate<Node> filter, Collection<Node> nodes) {
+ Set<Node> result = new TreeSet<>(Node.CASE_INSENSITIVE_COMPARATOR);
+ for (Node n : nodes) {
+ Node newNode = depthFirstFilterRec(filter, n, null);
+ if (newNode != null)
+ result.add(newNode);
+ }
+ return result;
+ }
+
+ public static Node depthFirstFilter(Predicate<Node> filter, Node n) {
+ return depthFirstFilterRec(filter, n, null);
+ }
+
+ private static Node depthFirstFilterRec(Predicate<Node> filter, Node n, Node newParent) {
+ Collection<Node> children = n.getChildren();
+ if (children.isEmpty())
+ return filter.test(n) ? n.cloneWithoutChildren(newParent) : null;
+
+ Node newNode = n.cloneWithoutChildren(newParent);
+ int childCount = 0;
+ for (Node child : children) {
+ Node newChild = depthFirstFilterRec(filter, child, newNode);
+ if (newChild != null)
+ ++childCount;
+ }
+
+ return childCount > 0 ? newNode : null;
+ }
+
+}