@@ -30,8 +30,7 @@ public abstract class AbstractBavetNodeNetwork {
3030
3131 protected static AbstractNode [][] buildLayeredNodes (List <AbstractNode > nodeList ) {
3232 var layerMap = new TreeMap <Long , List <AbstractNode >>();
33- nodeList .forEach (node -> layerMap .computeIfAbsent (node .getLayerIndex (), unused -> new ArrayList <>())
34- .add (node ));
33+ nodeList .forEach (node -> layerMap .computeIfAbsent (node .getLayerIndex (), unused -> new ArrayList <>()).add (node ));
3534 var layerCount = layerMap .size ();
3635 var layeredNodes = new AbstractNode [layerCount ][];
3736 for (var i = 0 ; i < layerCount ; i ++) {
@@ -73,13 +72,21 @@ public int forEachNodeCount() {
7372 return declaredClassToNodeMap .size ();
7473 }
7574
75+ /**
76+ *
77+ * @param factClass
78+ * @return if {@link #isActivationCheckComplete()} is true, only returns active root nodes;
79+ * otherwise returns all root nodes.
80+ * This means that if this information was ever read before activation checks were complete,
81+ * it should be re-read after to make sure no inactive nodes are included.
82+ */
7683 public Stream <AbstractRootNode <?>> getRootNodesAcceptingType (Class <?> factClass ) {
7784 // The node needs to match the fact, or the node needs to be applicable to the entire solution.
7885 // The latter is for FromSolution nodes.
79- return declaredClassToNodeMap .entrySet ()
80- .stream ()
86+ return declaredClassToNodeMap .entrySet ().stream ()
8187 .flatMap (entry -> entry .getValue ().stream ())
82- .filter (tupleSourceRoot -> factClass == PlanningSolution .class || tupleSourceRoot .allowsInstancesOf (factClass ));
88+ .filter (tupleSourceRoot -> factClass == PlanningSolution .class || tupleSourceRoot .allowsInstancesOf (factClass ))
89+ .filter (node -> !isActivationCheckComplete () || activeNodeSet .contains (node ));
8390 }
8491
8592 public void settle () {
@@ -102,11 +109,8 @@ public void settle() {
102109 case AbstractTwoInputNode <?, ?> twoInputNode -> twoInputNode .isActive ();
103110 })
104111 .peek (activeNodes ::add )
105- .map (propagatorFunction )
106- .toArray (Propagator []::new ))
107- .filter (layer -> layer .length > 0 )
108- .peek (AbstractBavetNodeNetwork ::settleLayer )
109- .toArray (Propagator [][]::new );
112+ .map (propagatorFunction ).toArray (Propagator []::new ))
113+ .filter (layer -> layer .length > 0 ).peek (AbstractBavetNodeNetwork ::settleLayer ).toArray (Propagator [][]::new );
110114 this .activeNodeSet = activeNodes ;
111115 return ;
112116 }
@@ -116,15 +120,10 @@ public void settle() {
116120 }
117121 }
118122
119- protected boolean isActivationCheckComplete () {
123+ public boolean isActivationCheckComplete () {
120124 return layeredActivePropagators != null ;
121125 }
122126
123- /**
124- * For testing only. The nodes that remained active after {@link #settle()}.
125- *
126- * @throws IllegalStateException if called before {@link #settle()}.
127- */
128127 Set <AbstractNode > getActiveNodes () {
129128 if (activeNodeSet == null ) {
130129 throw new IllegalStateException ("Impossible state: getActiveNodes() called before settle()." );
@@ -136,9 +135,7 @@ Set<AbstractNode> getActiveNodes() {
136135 * For testing only. All nodes in the network, regardless of activity.
137136 */
138137 List <AbstractNode > getNodes () {
139- return Arrays .stream (layeredNodes )
140- .flatMap (Arrays ::stream )
141- .toList ();
138+ return Arrays .stream (layeredNodes ).flatMap (Arrays ::stream ).toList ();
142139 }
143140
144141 private static void settleLayer (Propagator [] nodesInLayer ) {
@@ -174,8 +171,7 @@ public int hashCode() {
174171
175172 @ Override
176173 public String toString () {
177- return "%s with %d forEach nodes."
178- .formatted (getClass ().getSimpleName (), forEachNodeCount ());
174+ return "%s with %d forEach nodes." .formatted (getClass ().getSimpleName (), forEachNodeCount ());
179175 }
180176
181177}
0 commit comments