This is an automated email from the ASF dual-hosted git repository.

mariofusco pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/incubator-kie-drools.git


The following commit(s) were added to refs/heads/main by this push:
     new 09c45d09d6 #5651 Move tuple order correction from runtime to network 
build time (#5652)
09c45d09d6 is described below

commit 09c45d09d6ccde961a4bf0fefa482214ff6d5bae
Author: mdproctor <[email protected]>
AuthorDate: Wed Jan 24 10:56:19 2024 +0000

    #5651 Move tuple order correction from runtime to network build time (#5652)
---
 .../org/drools/core/common/DefaultFactHandle.java  | 153 +++++++++++++--------
 .../drools/core/common/DisconnectedFactHandle.java |   4 -
 .../org/drools/core/common/InternalFactHandle.java |  28 ++--
 .../drools/core/common/QueryElementFactHandle.java |   4 -
 .../java/org/drools/core/phreak/DetachedTuple.java |  40 ++++++
 .../org/drools/core/phreak/EagerPhreakBuilder.java |  26 +++-
 .../org/drools/core/phreak/LazyPhreakBuilder.java  |   9 +-
 .../main/java/org/drools/core/reteoo/BetaNode.java |  98 +++++++++++++
 .../drools/core/reteoo/LeftInputAdapterNode.java   |  33 +++--
 .../org/drools/core/reteoo/RuleTerminalNode.java   |   2 +-
 .../java/org/drools/core/reteoo/TupleImpl.java     |   2 +-
 11 files changed, 299 insertions(+), 100 deletions(-)

diff --git 
a/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java 
b/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java
index 002feeb0ed..51365d30d7 100644
--- a/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java
+++ b/drools-core/src/main/java/org/drools/core/common/DefaultFactHandle.java
@@ -28,6 +28,7 @@ import jakarta.xml.bind.annotation.XmlAccessorType;
 import jakarta.xml.bind.annotation.XmlAttribute;
 import jakarta.xml.bind.annotation.XmlRootElement;
 
+import org.drools.base.common.RuleBasePartitionId;
 import org.drools.base.factmodel.traits.TraitTypeEnum;
 import org.drools.base.rule.EntryPointId;
 import org.drools.core.WorkingMemoryEntryPoint;
@@ -369,10 +370,6 @@ public class DefaultFactHandle extends 
AbstractLinkedListNode<DefaultFactHandle>
         linkedTuples.addLastLeftTuple( leftTuple );
     }
 
-    public void addTupleInPosition( TupleImpl tuple ) {
-        linkedTuples.addTupleInPosition( tuple );
-    }
-
     public void removeLeftTuple( TupleImpl leftTuple ) {
         linkedTuples.removeLeftTuple( leftTuple );
     }
@@ -510,48 +507,6 @@ public class DefaultFactHandle extends 
AbstractLinkedListNode<DefaultFactHandle>
             lastLeftTuple = leftTuple;
         }
 
-        @Override
-        public void addTupleInPosition( TupleImpl tuple ) {
-            boolean          left  = tuple.isLeftTuple();
-            ObjectTypeNodeId otnId = tuple.getInputOtnId();
-            if (otnId == null) { // can happen only in tests // @FIXME fix this
-                addLastTuple( tuple, left );
-                return;
-            }
-
-            TupleImpl previous = left ? lastLeftTuple : lastRightTuple;
-            if ( previous == null ) {
-                // no other LeftTuples, just add.
-                tuple.setHandlePrevious( null );
-                tuple.setHandleNext( null );
-                setFirstTuple( tuple, left );
-                setLastTuple( tuple, left );
-                return;
-            } else if (previous.getSink() == null || 
!otnId.before(previous.getInputOtnId()) ) {
-                // the last LeftTuple comes before the new one so just add it 
at the end
-                tuple.setHandlePrevious( previous );
-                tuple.setHandleNext( null );
-                previous.setHandleNext( tuple );
-                setLastTuple( tuple, left );
-                return;
-            }
-
-            TupleImpl next = previous;
-            previous = previous.getHandlePrevious();
-            while (previous != null && otnId.before( previous.getInputOtnId()) 
) {
-                next = previous;
-                previous = previous.getHandlePrevious();
-            }
-            tuple.setHandleNext( next );
-            next.setHandlePrevious( tuple );
-            tuple.setHandlePrevious( previous );
-            if ( previous != null ) {
-                previous.setHandleNext( tuple );
-            } else {
-                setFirstTuple( tuple, left );
-            }
-        }
-
         private void addLastTuple(TupleImpl tuple, boolean left) {
             if (left) {
                 addLastLeftTuple(tuple);
@@ -715,6 +670,82 @@ public class DefaultFactHandle extends 
AbstractLinkedListNode<DefaultFactHandle>
         TupleImpl getFirstRightTuple() {
             return firstRightTuple;
         }
+
+        public TupleImpl detachLeftTupleAfter(RuleBasePartitionId partitionId, 
ObjectTypeNodeId otnId) {
+            TupleImpl tuple = lastLeftTuple;
+            TupleImpl detached = null;
+            // Find the first Tuple that comes after the current ID, so it can 
be detached.
+            while (tuple != null && otnId.before(tuple.getInputOtnId())) {
+                detached = tuple;
+                tuple = tuple.getHandlePrevious();
+            }
+
+            if (detached != null) {
+                if (firstLeftTuple == detached) {
+                    firstLeftTuple = null;
+                }
+
+                if (lastLeftTuple == detached) {
+                    lastLeftTuple = null;
+                }
+
+                if (detached.getHandlePrevious() != null) {
+                    lastLeftTuple = detached.getHandlePrevious();
+                    detached.setHandlePrevious(null);
+                    lastLeftTuple.setHandleNext(null);
+                }
+            }
+
+            return detached;
+        }
+
+        public TupleImpl detachRightTupleAfter(RuleBasePartitionId 
partitionId, ObjectTypeNodeId otnId) {
+            TupleImpl tuple = lastRightTuple;
+            TupleImpl detached = null;
+            // Find the first Tuple that comes after the current ID, so it can 
be detached.
+            while (tuple != null && otnId.before(tuple.getInputOtnId())) {
+                detached = tuple;
+                tuple = tuple.getHandlePrevious();
+            }
+
+            if (detached != null) {
+                if (firstRightTuple == detached) {
+                    firstRightTuple = null;
+                }
+
+                if (lastRightTuple == detached) {
+                    lastRightTuple = null;
+                }
+
+                if (detached.getHandlePrevious() != null) {
+                    lastRightTuple = detached.getHandlePrevious();
+                    detached.setHandlePrevious(null);
+                    lastRightTuple.setHandleNext(null);
+                }
+            }
+
+            return detached;
+        }
+
+        public void reattachToLeft(TupleImpl tuple) {
+            if (lastLeftTuple == null) {
+                lastLeftTuple = tuple;
+            } else {
+                lastLeftTuple.setHandleNext(tuple);
+                tuple.setHandlePrevious(lastLeftTuple);
+                lastLeftTuple = tuple;
+            }
+        }
+
+        public void reattachToRight(TupleImpl tuple) {
+            if (lastRightTuple == null) {
+                lastRightTuple = tuple;
+            } else {
+                lastRightTuple.setHandleNext(tuple);
+                tuple.setHandlePrevious(lastRightTuple);
+                lastRightTuple = tuple;
+            }
+        }
     }
 
     public static class CompositeLinkedTuples implements LinkedTuples {
@@ -780,11 +811,6 @@ public class DefaultFactHandle extends 
AbstractLinkedListNode<DefaultFactHandle>
             getOrCreatePartitionedTuple(leftTuple).addLastLeftTuple( leftTuple 
);
         }
 
-        @Override
-        public void addTupleInPosition( TupleImpl tuple ) {
-            getOrCreatePartitionedTuple(tuple).addTupleInPosition( tuple );
-        }
-
         @Override
         public void removeLeftTuple( TupleImpl leftTuple ) {
             getPartitionedTuple(leftTuple).removeLeftTuple( leftTuple );
@@ -807,6 +833,26 @@ public class DefaultFactHandle extends 
AbstractLinkedListNode<DefaultFactHandle>
             }
         }
 
+        @Override
+        public TupleImpl detachLeftTupleAfter(RuleBasePartitionId partitionId, 
ObjectTypeNodeId otnId) {
+            return 
getOrCreatePartitionedTuple(partitionId.getId()).detachLeftTupleAfter(partitionId,
 otnId);
+        }
+
+        @Override
+        public TupleImpl detachRightTupleAfter(RuleBasePartitionId 
partitionId, ObjectTypeNodeId otnId) {
+            return 
getOrCreatePartitionedTuple(partitionId.getId()).detachRightTupleAfter(partitionId,
 otnId);
+        }
+
+        @Override
+        public void reattachToLeft(TupleImpl tuple) {
+            getOrCreatePartitionedTuple(tuple).reattachToLeft(tuple);
+        }
+
+        @Override
+        public void reattachToRight(TupleImpl tuple) {
+            getOrCreatePartitionedTuple(tuple).reattachToRight(tuple);
+        }
+
         @Override
         public void clearLeftTuples() {
             for (int i = 0; i < partitionedTuples.length; i++) {
@@ -900,11 +946,6 @@ public class DefaultFactHandle extends 
AbstractLinkedListNode<DefaultFactHandle>
             throw new UnsupportedOperationException();
         }
 
-        @Override
-        public void addTupleInPosition(TupleImpl tuple) {
-            throw new UnsupportedOperationException();
-        }
-
         @Override
         public void removeLeftTuple(TupleImpl leftTuple) {
             throw new UnsupportedOperationException();
diff --git 
a/drools-core/src/main/java/org/drools/core/common/DisconnectedFactHandle.java 
b/drools-core/src/main/java/org/drools/core/common/DisconnectedFactHandle.java
index 46546638a0..e9a44b2735 100644
--- 
a/drools-core/src/main/java/org/drools/core/common/DisconnectedFactHandle.java
+++ 
b/drools-core/src/main/java/org/drools/core/common/DisconnectedFactHandle.java
@@ -363,10 +363,6 @@ public class DisconnectedFactHandle
         throw new 
UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR_MESSAGE);
     }
 
-    public void addTupleInPosition(TupleImpl rightTuple) {
-        throw new 
UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR_MESSAGE);
-    }
-
     public void removeRightTuple(TupleImpl rightTuple) {
         throw new 
UnsupportedOperationException(UNSUPPORTED_OPERATION_ERROR_MESSAGE);
     }
diff --git 
a/drools-core/src/main/java/org/drools/core/common/InternalFactHandle.java 
b/drools-core/src/main/java/org/drools/core/common/InternalFactHandle.java
index d83f0940c8..d8a4af38df 100644
--- a/drools-core/src/main/java/org/drools/core/common/InternalFactHandle.java
+++ b/drools-core/src/main/java/org/drools/core/common/InternalFactHandle.java
@@ -26,6 +26,7 @@ import org.drools.base.common.RuleBasePartitionId;
 import org.drools.base.factmodel.traits.TraitTypeEnum;
 import org.drools.base.rule.EntryPointId;
 import org.drools.core.WorkingMemoryEntryPoint;
+import org.drools.core.reteoo.ObjectTypeNodeId;
 import org.drools.core.reteoo.TupleImpl;
 import org.kie.api.runtime.rule.FactHandle;
 
@@ -112,8 +113,6 @@ public interface InternalFactHandle
 
     void removeRightTuple( TupleImpl rightTuple);
 
-    void addTupleInPosition( TupleImpl tuple);
-
     boolean isNegated();
     void setNegated(boolean negated);
 
@@ -142,9 +141,7 @@ public interface InternalFactHandle
 
         void addFirstLeftTuple( TupleImpl leftTuple);
         void addLastLeftTuple( TupleImpl leftTuple);
-
-        void addTupleInPosition( TupleImpl tuple);
-
+        
         void removeLeftTuple( TupleImpl leftTuple);
 
         void addFirstRightTuple( TupleImpl rightTuple);
@@ -171,6 +168,22 @@ public interface InternalFactHandle
         default TupleImpl getFirstRightTuple(RuleBasePartitionId partitionId) {
             return getFirstRightTuple( partitionId.getParallelEvaluationSlot() 
);
         }
+
+        default TupleImpl detachLeftTupleAfter(RuleBasePartitionId 
partitionId, ObjectTypeNodeId otnId) {
+            throw new UnsupportedOperationException();
+        }
+
+        default TupleImpl detachRightTupleAfter(RuleBasePartitionId 
partitionId, ObjectTypeNodeId otnId) {
+            throw new UnsupportedOperationException();
+        }
+
+        default void reattachToLeft(TupleImpl tuple) {
+            throw new UnsupportedOperationException();
+        }
+
+        default void reattachToRight(TupleImpl tuple) {
+            throw new UnsupportedOperationException();
+        }
     }
 
     static InternalFactHandle dummyFactHandleOf(Object object) {
@@ -345,11 +358,6 @@ public interface InternalFactHandle
             throw new UnsupportedOperationException();
         }
 
-        @Override
-        public void addTupleInPosition( TupleImpl tuple) {
-            throw new UnsupportedOperationException();
-        }
-
         @Override
         public boolean isNegated() {
             throw new UnsupportedOperationException();
diff --git 
a/drools-core/src/main/java/org/drools/core/common/QueryElementFactHandle.java 
b/drools-core/src/main/java/org/drools/core/common/QueryElementFactHandle.java
index 26227b0d46..cb98519126 100644
--- 
a/drools-core/src/main/java/org/drools/core/common/QueryElementFactHandle.java
+++ 
b/drools-core/src/main/java/org/drools/core/common/QueryElementFactHandle.java
@@ -250,10 +250,6 @@ public class QueryElementFactHandle
         throw new UnsupportedOperationException( "QueryElementFactHandle does 
not support this method" );
     }
 
-    public void addTupleInPosition( TupleImpl rightTuple ) {
-        throw new UnsupportedOperationException( "QueryElementFactHandle does 
not support this method" );
-    }
-
     public void removeRightTuple( TupleImpl rightTuple ) {
         throw new UnsupportedOperationException( "QueryElementFactHandle does 
not support this method" );
     }
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/DetachedTuple.java 
b/drools-core/src/main/java/org/drools/core/phreak/DetachedTuple.java
new file mode 100644
index 0000000000..f3ecf2cddf
--- /dev/null
+++ b/drools-core/src/main/java/org/drools/core/phreak/DetachedTuple.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 org.drools.core.phreak;
+
+import org.drools.core.common.DefaultFactHandle;
+import org.drools.core.reteoo.TupleImpl;
+
+public class DetachedTuple {
+    private DefaultFactHandle fh;
+    private TupleImpl tuple;
+
+    public DetachedTuple(DefaultFactHandle fh, TupleImpl tuple) {
+        this.fh    = fh;
+        this.tuple = tuple;
+    }
+
+    public void reattachToLeft() {
+        fh.getLinkedTuples().reattachToLeft(tuple);
+    }
+
+    public void reattachToRight() {
+        fh.getLinkedTuples().reattachToRight(tuple);
+    }
+}
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java 
b/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
index e53afd9935..a4d37f49d3 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/EagerPhreakBuilder.java
@@ -46,9 +46,10 @@ import 
org.drools.core.reteoo.AccumulateNode.AccumulateMemory;
 import org.drools.core.reteoo.AlphaTerminalNode;
 import org.drools.core.reteoo.BetaMemory;
 import org.drools.core.reteoo.BetaNode;
+import org.drools.core.reteoo.BetaNode.RightTupleSinkAdapter;
 import org.drools.core.reteoo.FromNode.FromMemory;
 import org.drools.core.reteoo.LeftInputAdapterNode;
-import org.drools.core.reteoo.LeftInputAdapterNode.RightTupleSinkAdapter;
+import org.drools.core.reteoo.LeftInputAdapterNode.LeftTupleSinkAdapter;
 import org.drools.core.reteoo.LeftTuple;
 import org.drools.core.reteoo.LeftTupleNode;
 import org.drools.core.reteoo.LeftTupleSinkNode;
@@ -268,11 +269,26 @@ public class EagerPhreakBuilder implements PhreakBuilder {
             final PropagationContext  pctx        = 
pctxFactory.createPropagationContext(wm.getNextPropagationIdCounter(), 
PropagationContext.Type.RULE_ADDITION, null, null, null);
             LeftInputAdapterNode      lian        = (LeftInputAdapterNode) 
startNode;
             if (allBranches && visited.add(lian.getId()) || 
lian.getAssociatedTerminalsSize() == 1 ) {
-                RightTupleSinkAdapter liaAdapter = new 
RightTupleSinkAdapter(lian);
-                lian.getObjectSource().updateSink(liaAdapter, pctx, wm);
+                attachAdapterAndPropagate(wm, lian, pctx);
             }
         }
 
+        public static void attachAdapterAndPropagate(InternalWorkingMemory wm, 
LeftInputAdapterNode lian, PropagationContext pctx) {
+            List<DetachedTuple>  detachedTuples = new ArrayList<>();
+            LeftTupleSinkAdapter liaAdapter     = new 
LeftTupleSinkAdapter(lian, detachedTuples);
+            lian.getObjectSource().updateSink(liaAdapter, pctx, wm);
+            detachedTuples.forEach(d -> d.reattachToLeft());
+        }
+
+        public static void attachAdapterAndPropagate(InternalWorkingMemory wm, 
BetaNode bn) {
+            PropagationContextFactory pctxFactory = 
RuntimeComponentFactory.get().getPropagationContextFactory();
+            final PropagationContext pctx = 
pctxFactory.createPropagationContext(wm.getNextPropagationIdCounter(), 
PropagationContext.Type.RULE_ADDITION, null, null, null);
+            List<DetachedTuple> detachedTuples = new ArrayList<>();
+            RightTupleSinkAdapter bnAdapter = new RightTupleSinkAdapter(bn, 
detachedTuples);
+            bn.getRightInput().updateSink(bnAdapter, pctx, wm);
+            detachedTuples.forEach(d -> d.reattachToRight());
+        }
+
         public static SegmentPrototype processSplit(LeftTupleNode splitNode, 
InternalRuleBase kbase, Collection<InternalWorkingMemory> wms, 
Set<SegmentMemoryPair> smemsToNotify) {
             LeftTupleNode segmentRoot = 
BuildtimeSegmentUtilities.findSegmentRoot(splitNode);
             SegmentPrototype proto1 = kbase.getSegmentPrototype(segmentRoot);
@@ -326,9 +342,7 @@ public class EagerPhreakBuilder implements PhreakBuilder {
                         BetaNode bn = (BetaNode) node;
 
                         if (!bn.isRightInputIsRiaNode()) {
-                            PropagationContextFactory pctxFactory = 
RuntimeComponentFactory.get().getPropagationContextFactory();
-                            final PropagationContext pctx = 
pctxFactory.createPropagationContext(wm.getNextPropagationIdCounter(), 
PropagationContext.Type.RULE_ADDITION, null, null, null);
-                            bn.getRightInput().updateSink(bn, pctx, wm);
+                            attachAdapterAndPropagate(wm, bn);
                         }
                     }
                 }
diff --git 
a/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java 
b/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
index bc527959b7..6402ba6eba 100644
--- a/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
+++ b/drools-core/src/main/java/org/drools/core/phreak/LazyPhreakBuilder.java
@@ -56,7 +56,6 @@ import org.drools.core.reteoo.EvalConditionNode;
 import org.drools.core.reteoo.FromNode;
 import org.drools.core.reteoo.FromNode.FromMemory;
 import org.drools.core.reteoo.LeftInputAdapterNode;
-import org.drools.core.reteoo.LeftInputAdapterNode.RightTupleSinkAdapter;
 import org.drools.core.reteoo.LeftTuple;
 import org.drools.core.reteoo.LeftTupleNode;
 import org.drools.core.reteoo.LeftTupleSink;
@@ -95,6 +94,7 @@ import static 
org.drools.core.phreak.BuildtimeSegmentUtilities.isRootNode;
 import static org.drools.core.phreak.BuildtimeSegmentUtilities.isSet;
 import static org.drools.core.phreak.BuildtimeSegmentUtilities.nextNodePosMask;
 import static 
org.drools.core.phreak.BuildtimeSegmentUtilities.updateNodeTypesMask;
+import static 
org.drools.core.phreak.EagerPhreakBuilder.Add.attachAdapterAndPropagate;
 import static org.drools.core.phreak.EagerPhreakBuilder.deleteLeftTuple;
 import static 
org.drools.core.phreak.RuntimeSegmentUtilities.createRiaSegmentMemory;
 import static 
org.drools.core.phreak.RuntimeSegmentUtilities.getOrCreateSegmentMemory;
@@ -711,8 +711,7 @@ class LazyPhreakBuilder implements PhreakBuilder {
         PropagationContextFactory pctxFactory = 
RuntimeComponentFactory.get().getPropagationContextFactory();
         final PropagationContext  pctx        = 
pctxFactory.createPropagationContext(wm.getNextPropagationIdCounter(), 
PropagationContext.Type.RULE_ADDITION, null, null, null);
         LeftInputAdapterNode      lian        = (LeftInputAdapterNode) 
startNode;
-        RightTupleSinkAdapter     liaAdapter  = new 
RightTupleSinkAdapter(lian);
-        lian.getObjectSource().updateSink(liaAdapter, pctx, wm);
+        attachAdapterAndPropagate(wm, lian, pctx);
     }
 
     private static void insertFacts(PathEndNodes endNodes, 
Collection<InternalWorkingMemory> wms) {
@@ -730,9 +729,7 @@ class LazyPhreakBuilder implements PhreakBuilder {
 
                     if (!bn.isRightInputIsRiaNode()) {
                         for ( InternalWorkingMemory wm : wms ) {
-                            PropagationContextFactory pctxFactory = 
RuntimeComponentFactory.get().getPropagationContextFactory();
-                            final PropagationContext pctx = 
pctxFactory.createPropagationContext(wm.getNextPropagationIdCounter(), 
PropagationContext.Type.RULE_ADDITION, null, null, null);
-                            bn.getRightInput().updateSink(bn, pctx, wm);
+                            attachAdapterAndPropagate(wm, bn);
                         }
                     }
                 }
diff --git a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java 
b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java
index ebffdcc114..357d720350 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/BetaNode.java
@@ -26,12 +26,14 @@ import java.util.Objects;
 import org.drools.base.base.ObjectType;
 import org.drools.base.common.NetworkNode;
 import org.drools.base.common.RuleBasePartitionId;
+import org.drools.base.reteoo.BaseTerminalNode;
 import org.drools.base.reteoo.NodeTypeEnums;
 import org.drools.base.rule.IndexableConstraint;
 import org.drools.base.rule.Pattern;
 import org.drools.base.util.index.IndexUtil;
 import org.drools.core.RuleBaseConfiguration;
 import org.drools.core.common.BetaConstraints;
+import org.drools.core.common.DefaultFactHandle;
 import org.drools.core.common.DoubleBetaConstraints;
 import org.drools.core.common.DoubleNonIndexSkipBetaConstraints;
 import org.drools.core.common.InternalFactHandle;
@@ -47,6 +49,7 @@ import org.drools.core.common.TripleBetaConstraints;
 import org.drools.core.common.TripleNonIndexSkipBetaConstraints;
 import org.drools.core.common.TupleSets;
 import org.drools.core.common.UpdateContext;
+import org.drools.core.phreak.DetachedTuple;
 import org.drools.core.reteoo.AccumulateNode.AccumulateMemory;
 import org.drools.core.reteoo.builder.BuildContext;
 import org.drools.base.rule.constraint.BetaConstraint;
@@ -54,6 +57,7 @@ import org.drools.core.util.FastIterator;
 import org.drools.util.bitmask.AllSetBitMask;
 import org.drools.util.bitmask.BitMask;
 import org.drools.util.bitmask.EmptyBitMask;
+import org.kie.api.definition.rule.Rule;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -680,4 +684,98 @@ public abstract class BetaNode extends LeftTupleSource
     public void setRightInputOtnId(ObjectTypeNodeId rightInputOtnId) {
         this.rightInputOtnId = rightInputOtnId;
     }
+
+    /**
+     * Used with the updateSink method, so that the parent ObjectSource
+     * can  update the  TupleSink
+     */
+    public static class RightTupleSinkAdapter
+            implements
+            ObjectSink {
+        private BetaNode bnNode;
+
+        private List<DetachedTuple> detachedTuples;
+
+        public RightTupleSinkAdapter(BetaNode bnNode, List<DetachedTuple> 
detachedTuples) {
+            this.bnNode = bnNode;
+            this.detachedTuples = detachedTuples;
+        }
+
+        /**
+         * Do not use this constructor. It should be used just by 
deserialization.
+         */
+        public RightTupleSinkAdapter() {
+        }
+
+        public void assertObject(final InternalFactHandle factHandle,
+                                 final PropagationContext context,
+                                 final ReteEvaluator reteEvaluator) {
+            ObjectTypeNodeId otnId = bnNode.getRightInputOtnId();
+            TupleImpl detached = 
factHandle.getLinkedTuples().detachRightTupleAfter(getPartitionId(), otnId);
+            if (detached != null) {
+                detachedTuples.add(new DetachedTuple((DefaultFactHandle) 
factHandle, detached));
+            }
+
+            bnNode.assertObject(factHandle, context, reteEvaluator);
+        }
+
+        public void modifyObject(InternalFactHandle factHandle,
+                                 ModifyPreviousTuples modifyPreviousTuples,
+                                 PropagationContext context,
+                                 ReteEvaluator reteEvaluator) {
+            throw new UnsupportedOperationException( "ObjectSinkAdapter onlys 
supports assertObject method calls" );
+        }
+
+        public int getId() {
+            return 0;
+        }
+
+        public RuleBasePartitionId getPartitionId() {
+            return bnNode.getPartitionId();
+        }
+
+        public void byPassModifyToBetaNode(InternalFactHandle factHandle,
+                                           ModifyPreviousTuples 
modifyPreviousTuples,
+                                           PropagationContext context,
+                                           ReteEvaluator reteEvaluator) {
+            throw new UnsupportedOperationException();
+        }
+
+        public int getType() {
+            return NodeTypeEnums.LeftInputAdapterNode;
+        }
+
+        @Override public Rule[] getAssociatedRules() {
+            return bnNode.getAssociatedRules();
+        }
+
+        public boolean isAssociatedWith(Rule rule) {
+            return bnNode.isAssociatedWith( rule );
+        }
+
+        @Override
+        public NetworkNode[] getSinks() {
+            return new NetworkNode[0];
+        }
+
+        @Override
+        public void addAssociatedTerminal(BaseTerminalNode terminalNode) {
+            bnNode.addAssociatedTerminal(terminalNode);
+        }
+
+        @Override
+        public void removeAssociatedTerminal(BaseTerminalNode terminalNode) {
+            bnNode.removeAssociatedTerminal(terminalNode);
+        }
+
+        @Override
+        public int getAssociatedTerminalsSize() {
+            return bnNode.getAssociatedTerminalsSize();
+        }
+
+        @Override
+        public boolean hasAssociatedTerminal(BaseTerminalNode terminalNode) {
+            return bnNode.hasAssociatedTerminal(terminalNode);
+        }
+    }
 }
diff --git 
a/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java 
b/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java
index e2f73f70cf..793d0ff330 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/LeftInputAdapterNode.java
@@ -31,7 +31,7 @@ import org.drools.base.reteoo.BaseTerminalNode;
 import org.drools.base.reteoo.NodeTypeEnums;
 import org.drools.base.rule.Pattern;
 import org.drools.core.RuleBaseConfiguration;
-import org.drools.core.common.BaseNode;
+import org.drools.core.common.DefaultFactHandle;
 import org.drools.core.common.InternalFactHandle;
 import org.drools.core.common.Memory;
 import org.drools.core.common.MemoryFactory;
@@ -40,6 +40,7 @@ import org.drools.core.common.ReteEvaluator;
 import org.drools.core.common.SuperCacheFixer;
 import org.drools.core.common.TupleSets;
 import org.drools.core.common.UpdateContext;
+import org.drools.core.phreak.DetachedTuple;
 import org.drools.core.phreak.RuntimeSegmentUtilities;
 import org.drools.core.reteoo.builder.BuildContext;
 import org.drools.core.rule.consequence.InternalMatch;
@@ -595,25 +596,33 @@ public class LeftInputAdapterNode extends LeftTupleSource
      * Used with the updateSink method, so that the parent ObjectSource
      * can  update the  TupleSink
      */
-    public static class RightTupleSinkAdapter
+    public static class LeftTupleSinkAdapter
             implements
             ObjectSink {
-        private LeftTupleSink sink;
         private LeftInputAdapterNode liaNode;
 
-        public RightTupleSinkAdapter(LeftInputAdapterNode liaNode) {
+        private List<DetachedTuple> detachedTuples;
+
+        public LeftTupleSinkAdapter(LeftInputAdapterNode liaNode, 
List<DetachedTuple> detachedTuples) {
             this.liaNode = liaNode;
+            this.detachedTuples = detachedTuples;
         }
 
         /**
          * Do not use this constructor. It should be used just by 
deserialization.
          */
-        public RightTupleSinkAdapter() {
+        public LeftTupleSinkAdapter() {
         }
 
         public void assertObject(final InternalFactHandle factHandle,
                                  final PropagationContext context,
                                  final ReteEvaluator reteEvaluator) {
+            ObjectTypeNodeId otnId = 
liaNode.getSinkPropagator().getFirstLeftTupleSink().getLeftInputOtnId();
+            TupleImpl detached = 
factHandle.getLinkedTuples().detachLeftTupleAfter(getPartitionId(), otnId);
+            if (detached != null) {
+                detachedTuples.add(new DetachedTuple((DefaultFactHandle) 
factHandle, detached));
+            }
+
             liaNode.assertObject(factHandle, context, reteEvaluator);
         }
 
@@ -629,7 +638,7 @@ public class LeftInputAdapterNode extends LeftTupleSource
         }
 
         public RuleBasePartitionId getPartitionId() {
-            return sink.getPartitionId();
+            return liaNode.getPartitionId();
         }
 
         public void byPassModifyToBetaNode(InternalFactHandle factHandle,
@@ -644,11 +653,11 @@ public class LeftInputAdapterNode extends LeftTupleSource
         }
 
         @Override public Rule[] getAssociatedRules() {
-            return sink.getAssociatedRules();
+            return liaNode.getAssociatedRules();
         }
 
         public boolean isAssociatedWith(Rule rule) {
-            return sink.isAssociatedWith( rule );
+            return liaNode.isAssociatedWith( rule );
         }
 
         @Override
@@ -658,22 +667,22 @@ public class LeftInputAdapterNode extends LeftTupleSource
 
         @Override
         public void addAssociatedTerminal(BaseTerminalNode terminalNode) {
-            sink.addAssociatedTerminal(terminalNode);
+            liaNode.addAssociatedTerminal(terminalNode);
         }
 
         @Override
         public void removeAssociatedTerminal(BaseTerminalNode terminalNode) {
-            sink.removeAssociatedTerminal(terminalNode);
+            liaNode.removeAssociatedTerminal(terminalNode);
         }
 
         @Override
         public int getAssociatedTerminalsSize() {
-            return sink.getAssociatedTerminalsSize();
+            return liaNode.getAssociatedTerminalsSize();
         }
 
         @Override
         public boolean hasAssociatedTerminal(BaseTerminalNode terminalNode) {
-            return sink.hasAssociatedTerminal(terminalNode);
+            return liaNode.hasAssociatedTerminal(terminalNode);
         }
     }
 
diff --git 
a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java 
b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
index 1e53bcd600..9bb2559d67 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/RuleTerminalNode.java
@@ -48,7 +48,7 @@ public class RuleTerminalNode extends AbstractTerminalNode {
 
     protected boolean                       fireDirect;
 
-    protected transient ObjectTypeNodeId leftInputOtnId;
+    protected transient ObjectTypeNodeId leftInputOtnId = 
ObjectTypeNodeId.DEFAULT_ID;
 
     protected String                        consequenceName;
 
diff --git a/drools-core/src/main/java/org/drools/core/reteoo/TupleImpl.java 
b/drools-core/src/main/java/org/drools/core/reteoo/TupleImpl.java
index 885fe9a394..fea2b07301 100644
--- a/drools-core/src/main/java/org/drools/core/reteoo/TupleImpl.java
+++ b/drools-core/src/main/java/org/drools/core/reteoo/TupleImpl.java
@@ -79,7 +79,7 @@ public abstract class TupleImpl implements Tuple<TupleImpl> {
         setSink(sink);
         this.handle = factHandle;
         if ( leftTupleMemoryEnabled ) {
-            factHandle.addTupleInPosition( this );
+            factHandle.addLastLeftTuple( this );
         }
     }
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to