]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/requests/Nodes.java
Merge "(refs #7307) Added features field to SCL module header"
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / requests / Nodes.java
1 package org.simantics.modeling.requests;
2
3 import java.util.ArrayDeque;
4 import java.util.ArrayList;
5 import java.util.Collection;
6 import java.util.Collections;
7 import java.util.Comparator;
8 import java.util.Deque;
9 import java.util.List;
10 import java.util.Set;
11 import java.util.TreeSet;
12 import java.util.function.Predicate;
13
14 import org.eclipse.jface.viewers.IFilter;
15 import org.simantics.scl.runtime.function.Function1;
16
17 /**
18  * @author Tuukka Lehtonen
19  */
20 public class Nodes {
21
22     public static final Predicate<Node> DIAGRAM_RESOURCE_PREDICATE = n -> n.getDiagramResource() != null;
23     public static final Predicate<Node> DIAGRAM_RESOURCE_AND_RVI_PREDICATE = n -> n.getDiagramResource() != null && n.getRVI() != null;
24
25     public static Collection<Node> breadthFirstFlatten(IFilter filter, Collection<Node> roots) {
26         Collection<Node> result = new ArrayList<>();
27         List<Node> sortedRoots = new ArrayList<>(roots);
28         Collections.sort(sortedRoots);
29         Deque<Node> todo = new ArrayDeque<>(sortedRoots);
30         while (!todo.isEmpty()) {
31             Node n = todo.removeFirst();
32             List<Node> sorted = new ArrayList<>(n.getChildren());
33             Collections.sort(sorted);
34             todo.addAll(sorted);
35             if (filter == null || filter.select(n))
36                 result.add(n);
37         }
38         return result;
39     }
40
41     public static Collection<Node> depthFirstFlatten(IFilter filter, Collection<Node> roots, Comparator<? super Node> comparator) {
42         Collection<Node> result = new ArrayList<>();
43         List<Node> sortedRoots = new ArrayList<>(roots);
44         Collections.sort(sortedRoots, comparator);
45         for (Node n : sortedRoots) {
46             depthFirstFlattenRec(filter, comparator, n, result);
47         }
48         return result;
49     }
50
51     private static Collection<Node> depthFirstFlattenRec(IFilter filter, Comparator<? super Node> comparator, Node n, Collection<Node> result) {
52         if (filter == null || filter.select(n))
53             result.add(n);
54
55         Collection<Node> children = n.getChildren();
56         if (children.isEmpty())
57             return result;
58
59         List<Node> sorted = new ArrayList<>(children);
60         Collections.sort(sorted, comparator);
61         for (Node child : sorted)
62             depthFirstFlattenRec(filter, comparator, child, result);
63
64         return result;
65     }
66
67     /**
68      * @param f
69      *            function that takes the walked Node as argument and returns a
70      *            boolean to describe whether to continue the walk or cancel the
71      *            walk. The returned value cannot be <code>null</code>.
72      * @return <code>true</code> if the walk was completed or <code>false</code>
73      *         if the walk was cancelled
74      */
75     public static boolean walkTree(Function1<Node, Boolean> filter, Collection<Node> roots) {
76         List<Node> sortedRoots = new ArrayList<>(roots);
77         Collections.sort(sortedRoots);
78         for (Node n : sortedRoots)
79             if (!walkTreeRec(filter, n))
80                return false;
81         return true;
82    }
83
84     private static boolean walkTreeRec(Function1<Node, Boolean> filter, Node n) {
85         if (!filter.apply(n))
86             return false;
87
88         Collection<Node> children = n.getChildren();
89         if (!children.isEmpty()) {
90             List<Node> sorted = new ArrayList<>(children);
91             Collections.sort(sorted);
92             for (Node child : sorted)
93                 if (!walkTreeRec(filter, child))
94                     return false;
95         }
96         return true;
97     }
98
99     public static boolean parentIsInSet(Set<Node> set, Node node) {
100         for (Node n = node.getParent(); n != null; n = n.getParent())
101             if (set.contains(n))
102                 return true;
103         return false;
104     }
105
106     public static Set<Node> depthFirstFilter(Predicate<Node> filter, Collection<Node> nodes) {
107         Set<Node> result = new TreeSet<>(Node.CASE_INSENSITIVE_COMPARATOR);
108         for (Node n : nodes) {
109             Node newNode = depthFirstFilterRec(filter, n, null);
110             if (newNode != null)
111                 result.add(newNode);
112         }
113         return result;
114     }
115
116     public static Node depthFirstFilter(Predicate<Node> filter, Node n) {
117         return depthFirstFilterRec(filter, n, null);
118     }
119
120     private static Node depthFirstFilterRec(Predicate<Node> filter, Node n, Node newParent) {
121         Collection<Node> children = n.getChildren();
122         if (children.isEmpty())
123             return filter.test(n) ? n.cloneWithoutChildren(newParent) : null;
124
125         Node newNode = n.cloneWithoutChildren(newParent);
126         int childCount = 0;
127         for (Node child : children) {
128             Node newChild = depthFirstFilterRec(filter, child, newNode);
129             if (newChild != null)
130                 ++childCount;
131         }
132
133         return childCount > 0 ? newNode : null;
134     }
135
136 }