All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.drools.core.datasources.CursoredDataSource Maven / Gradle / Ivy

/*
 * Copyright 2017 Red Hat, Inc. and/or its affiliates.
 *
 * 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 org.drools.core.datasources;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;

import org.drools.core.RuleBaseConfiguration.AssertBehaviour;
import org.drools.core.WorkingMemoryEntryPoint;
import org.drools.core.common.ClassAwareObjectStore;
import org.drools.core.common.EqualityKey;
import org.drools.core.common.InternalFactHandle;
import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.common.InternalWorkingMemoryEntryPoint;
import org.drools.core.common.ObjectStore;
import org.drools.core.common.PropagationContextFactory;
import org.drools.core.factmodel.traits.TraitTypeEnum;
import org.drools.core.phreak.PropagationEntry;
import org.drools.core.phreak.PropagationEntry.AbstractPropagationEntry;
import org.drools.core.phreak.PropagationList;
import org.drools.core.phreak.SynchronizedPropagationList;
import org.drools.core.reteoo.EntryPointNode;
import org.drools.core.reteoo.LeftTuple;
import org.drools.core.reteoo.ObjectTypeConf;
import org.drools.core.reteoo.ObjectTypeNode;
import org.drools.core.reteoo.RightTuple;
import org.drools.core.spi.Activation;
import org.drools.core.spi.FactHandleFactory;
import org.drools.core.spi.PropagationContext;
import org.drools.core.spi.Tuple;
import org.drools.core.util.bitmask.BitMask;
import org.kie.api.runtime.rule.EntryPoint;
import org.kie.api.runtime.rule.FactHandle;
import org.kie.api.runtime.rule.RuleUnit;

import static java.util.Arrays.asList;
import static org.drools.core.common.DefaultFactHandle.determineIdentityHashCode;
import static org.drools.core.reteoo.PropertySpecificUtil.allSetButTraitBitMask;
import static org.drools.core.reteoo.PropertySpecificUtil.calculatePositiveMask;
import static org.drools.core.reteoo.PropertySpecificUtil.getAccessibleProperties;

public class CursoredDataSource implements InternalDataSource {

    private InternalWorkingMemory workingMemory;

    private ObjectStore objectStore = new ClassAwareObjectStore( AssertBehaviour.IDENTITY, null );

    private Map propagationsMap = new HashMap<>();

    private RuleUnit.Identity currentUnit;
    private EntryPoint currentEntryPoint;

    private List inserted;

    public CursoredDataSource() { }

    public CursoredDataSource( InternalWorkingMemory workingMemory ) {
        this.workingMemory = workingMemory;
    }

    public void setWorkingMemory( InternalWorkingMemory workingMemory ) {
        this.workingMemory = workingMemory;
        if (inserted != null) {
            inserted.forEach( this::insertIntoWm );
            inserted = null;
        }
    }

    @Override
    public FactHandle insert( T object ) {
        if (workingMemory != null) {
            return insertIntoWm( object );
        }

        if (inserted == null) {
            inserted = new ArrayList<>();
        }
        inserted.add(object);
        return null;
    }

    private FactHandle insertIntoWm( T object ) {
        FactHandleFactory fhFactory = workingMemory.getFactHandleFactory();
        DataSourceFactHandle factHandle = new DataSourceFactHandle( this, fhFactory.getNextId(), fhFactory.getNextRecency(), object );
        objectStore.addHandle( factHandle, object );
        propagate( () -> new Insert( factHandle ) );
        return factHandle;
    }

    @Override
    public void update(FactHandle handle, T object, String... modifiedProperties) {
        BitMask mask = modifiedProperties == null || modifiedProperties.length == 0 ?
                       allSetButTraitBitMask() :
                       calculatePositiveMask( asList(modifiedProperties), getAccessibleProperties( workingMemory.getKnowledgeBase(), object.getClass() ) );
        internalUpdate((DataSourceFactHandle) handle, object, mask, Object.class, null);
    }

    @Override
    public void update(FactHandle fh, Object obj, BitMask mask, Class modifiedClass, Activation activation) {
        DataSourceFactHandle dataSourceFactHandle = ( (DataSourceFactHandle) ( (InternalFactHandle) fh ).getParentHandle() );
        internalUpdate( dataSourceFactHandle, obj, mask, modifiedClass, activation );
    }

    private void internalUpdate( DataSourceFactHandle dataSourceFactHandle, Object obj, BitMask mask, Class modifiedClass, Activation activation ) {
        propagate( () -> new Update( dataSourceFactHandle, obj, mask, modifiedClass, activation ) );
    }

    private void propagate( Supplier s ) {
        propagationsMap.forEach( (ruId, list) -> {
            if (ruId.equals( currentUnit )) {
                workingMemory.getPropagationList().addEntry( s.get().setEntryPoint( currentEntryPoint ) );
            } else {
                list.addEntry( s.get() );
            }
        } );
    }

    @Override
    public void delete(FactHandle fh) {
        DataSourceFactHandle dsFh = (DataSourceFactHandle) fh;
        objectStore.removeHandle( dsFh );
        propagate( () -> new Delete( dsFh, null ) );
    }

    @Override
    public void bind(RuleUnit unit, WorkingMemoryEntryPoint ep) {
        setWorkingMemory( ep.getInternalWorkingMemory() );
        PropagationList propagationList = propagationsMap.get( unit.getUnitIdentity() );
        if (propagationList != null) {
            flush( ep, propagationList.takeAll() );
        } else {
            Iterator fhs = objectStore.iterateFactHandles();
            while (fhs.hasNext()) {
                new Insert( (DataSourceFactHandle) fhs.next() ).execute( ep );
            }
            propagationsMap.put( unit.getUnitIdentity(), new SynchronizedPropagationList( ((WorkingMemoryEntryPoint)ep).getInternalWorkingMemory()) );
        }
        currentUnit = unit.getUnitIdentity();
        currentEntryPoint = ep;
    }

    private void flush( EntryPoint ep, PropagationEntry currentHead ) {
        for (PropagationEntry entry = currentHead; entry != null; entry = entry.getNext()) {
            ((AbstractDataSourcePropagation)entry).execute(ep);
        }
    }

    @Override
    public void unbind(RuleUnit unit) {
        currentUnit = null;
        currentEntryPoint = null;
    }

    @Override
    public Iterator iterator() {
        return inserted != null ? inserted.iterator() : (Iterator) objectStore.iterateObjects();
    }

    static abstract class AbstractDataSourcePropagation extends AbstractPropagationEntry {

        private EntryPoint ep;

        public AbstractDataSourcePropagation setEntryPoint( EntryPoint ep ) {
            this.ep = ep;
            return this;
        }

        @Override
        public void execute( InternalWorkingMemory wm ) {
            execute( ep );
        }

        public abstract void execute( EntryPoint ep );
    }

    static class Insert extends AbstractDataSourcePropagation {

        private final DataSourceFactHandle dsFactHandle;

        Insert( DataSourceFactHandle factHandle ) {
            this.dsFactHandle = factHandle;
        }

        @Override
        public void execute( EntryPoint entryPoint ) {
            WorkingMemoryEntryPoint ep = (WorkingMemoryEntryPoint) entryPoint;
            ObjectTypeConf typeConf = ep.getObjectTypeConfigurationRegistry()
                                        .getObjectTypeConf( ep.getEntryPoint(), dsFactHandle.getObject() );

            InternalFactHandle handleForEp = dsFactHandle.createFactHandleFor( ep, typeConf );
            RuleUnit ruleUnit = ep.getInternalWorkingMemory().getRuleUnitExecutor().getCurrentRuleUnit();
            dsFactHandle.childHandles.put( ruleUnit.getUnitIdentity(), handleForEp );

            PropagationContextFactory pctxFactory = ( (InternalWorkingMemoryEntryPoint) ep ).getPctxFactory();
            PropagationContext context = pctxFactory.createPropagationContext( ep.getInternalWorkingMemory().getNextPropagationIdCounter(),
                                                                               PropagationContext.Type.INSERTION,
                                                                               null,
                                                                               null,
                                                                               handleForEp,
                                                                               ep.getEntryPoint() );
            for ( ObjectTypeNode otn : typeConf.getObjectTypeNodes() ) {
                otn.propagateAssert( handleForEp, context, ep.getInternalWorkingMemory() );
            }
        }
    }

    static class Update extends AbstractDataSourcePropagation {

        private final DataSourceFactHandle dsFactHandle;
        private final Object object;
        private final BitMask mask;
        private final Class modifiedClass;
        private final Activation activation;

        Update( DataSourceFactHandle factHandle, Object object, BitMask mask, Class modifiedClass, Activation activation ) {
            this.dsFactHandle = factHandle;
            this.object = object;
            this.mask = mask;
            this.modifiedClass = modifiedClass;
            this.activation = activation;
        }

        @Override
        public void execute( EntryPoint entryPoint ) {
            WorkingMemoryEntryPoint ep = (WorkingMemoryEntryPoint) entryPoint;
            ObjectTypeConf typeConf = ep.getObjectTypeConfigurationRegistry()
                                        .getObjectTypeConf( ep.getEntryPoint(), object );

            RuleUnit ruleUnit = ep.getInternalWorkingMemory().getRuleUnitExecutor().getCurrentRuleUnit();
            InternalFactHandle handle = dsFactHandle.childHandles.get(ruleUnit.getUnitIdentity() );

            PropagationContextFactory pctxFactory = ( (InternalWorkingMemoryEntryPoint) ep ).getPctxFactory();
            PropagationContext context = pctxFactory.createPropagationContext( ep.getInternalWorkingMemory().getNextPropagationIdCounter(),
                                                                               PropagationContext.Type.MODIFICATION,
                                                                               activation == null ? null : activation.getRule(),
                                                                               activation == null ? null : activation.getTuple().getTupleSink(),
                                                                               handle,
                                                                               ep.getEntryPoint(),
                                                                               mask,
                                                                               modifiedClass,
                                                                               null);

            EntryPointNode.propagateModify( handle, context, typeConf, ep.getInternalWorkingMemory() );
        }
    }

    static class Delete extends AbstractDataSourcePropagation {

        private final DataSourceFactHandle dsFactHandle;
        private final Activation activation;

        Delete( DataSourceFactHandle factHandle, Activation activation ) {
            this.dsFactHandle = factHandle;
            this.activation = activation;
        }

        @Override
        public void execute( EntryPoint entryPoint ) {
            WorkingMemoryEntryPoint ep = (WorkingMemoryEntryPoint) entryPoint;
            ObjectTypeConf typeConf = ep.getObjectTypeConfigurationRegistry()
                                        .getObjectTypeConf( ep.getEntryPoint(), dsFactHandle.getObject() );

            RuleUnit ruleUnit = ep.getInternalWorkingMemory().getRuleUnitExecutor().getCurrentRuleUnit();
            InternalFactHandle handle = dsFactHandle.childHandles.get(ruleUnit.getUnitIdentity() );

            PropagationContextFactory pctxFactory = ( (InternalWorkingMemoryEntryPoint) ep ).getPctxFactory();
            PropagationContext context = pctxFactory.createPropagationContext( ep.getInternalWorkingMemory().getNextPropagationIdCounter(),
                                                                               PropagationContext.Type.DELETION,
                                                                               activation == null ? null : activation.getRule(),
                                                                               activation == null ? null : activation.getTuple().getTupleSink(),
                                                                               handle,
                                                                               ep.getEntryPoint() );

            ep.getEntryPointNode().propagateRetract(handle, context, typeConf, ep.getInternalWorkingMemory());
        }
    }

    public static class DataSourceFactHandle implements InternalFactHandle {

        private final InternalDataSource dataSource;
        private Object object;

        private final Map childHandles = new HashMap<>();

        private final int id;
        private long recency;

        private final int identityHashCode;

        private boolean negated = false;

        DataSourceFactHandle( InternalDataSource dataSource, int id, long recency, Object object ) {
            this.dataSource = dataSource;
            this.id = id;
            this.recency = recency;
            this.object = object;
            identityHashCode = determineIdentityHashCode( object );
        }

        InternalFactHandle createFactHandleFor(WorkingMemoryEntryPoint ep, ObjectTypeConf conf) {
            InternalFactHandle fh = ep.getHandleFactory().newFactHandle( id, object, recency, conf, ep.getInternalWorkingMemory(), ep );
            fh.setNegated( negated );
            fh.setParentHandle( this );
            return fh;
        }

        @Override
        public InternalDataSource getDataSource() {
            return dataSource;
        }

        @Override
        public int getId() {
            return id;
        }

        @Override
        public Object getObject() {
            return object;
        }

        @Override
        public boolean isNegated() {
            return negated;
        }

        @Override
        public void setNegated( boolean negated ) {
            this.negated = negated;
        }

        @Override
        public int getIdentityHashCode() {
            return identityHashCode;
        }

        @Override
        public long getRecency() {
            return recency;
        }

        @Override
        public void setRecency( long recency ) {
            this.recency = recency;
        }

        @Override
        public String getObjectClassName() {
            return object.getClass().getName();
        }

        @Override
        public void setObject( Object object ) {
            this.object = object;
        }

        @Override
        public void setEqualityKey( EqualityKey key ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.setEqualityKey -> TODO" );

        }

        @Override
        public EqualityKey getEqualityKey() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.getEqualityKey -> TODO" );

        }

        @Override
        public void invalidate() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.invalidate -> TODO" );

        }

        @Override
        public boolean isValid() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.isValid -> TODO" );

        }

        @Override
        public int getObjectHashCode() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.getObjectHashCode -> TODO" );

        }

        @Override
        public boolean isDisconnected() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.isDisconnected -> TODO" );

        }

        @Override
        public boolean isEvent() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.isEvent -> TODO" );

        }

        @Override
        public boolean isTraitOrTraitable() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.isTraitOrTraitable -> TODO" );

        }

        @Override
        public boolean isTraitable() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.isTraitable -> TODO" );

        }

        @Override
        public boolean isTraiting() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.isTraiting -> TODO" );

        }

        @Override
        public TraitTypeEnum getTraitType() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.getTraitType -> TODO" );

        }

        @Override
        public RightTuple getFirstRightTuple() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.getFirstRightTuple -> TODO" );

        }

        @Override
        public LeftTuple getFirstLeftTuple() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.getFirstLeftTuple -> TODO" );

        }

        @Override
        public WorkingMemoryEntryPoint getEntryPoint() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.getEntryPoint -> TODO" );

        }

        @Override
        public void setEntryPoint( WorkingMemoryEntryPoint ep ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.setEntryPoint -> TODO" );

        }

        @Override
        public InternalFactHandle clone() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.clone -> TODO" );

        }

        @Override
        public String toExternalForm() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.toExternalForm -> TODO" );

        }

        @Override
        public void disconnect() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.disconnect -> TODO" );

        }

        @Override
        public void addFirstLeftTuple( LeftTuple leftTuple ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.addFirstLeftTuple -> TODO" );

        }

        @Override
        public void addLastLeftTuple( LeftTuple leftTuple ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.addLastLeftTuple -> TODO" );

        }

        @Override
        public void removeLeftTuple( LeftTuple leftTuple ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.removeLeftTuple -> TODO" );

        }

        @Override
        public void clearLeftTuples() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.clearLeftTuples -> TODO" );

        }

        @Override
        public void clearRightTuples() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.clearRightTuples -> TODO" );

        }

        @Override
        public void addFirstRightTuple( RightTuple rightTuple ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.addFirstRightTuple -> TODO" );

        }

        @Override
        public void addLastRightTuple( RightTuple rightTuple ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.addLastRightTuple -> TODO" );

        }

        @Override
        public void removeRightTuple( RightTuple rightTuple ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.removeRightTuple -> TODO" );

        }

        @Override
        public void addTupleInPosition( Tuple tuple ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.addTupleInPosition -> TODO" );

        }

        @Override
        public  K as( Class klass ) throws ClassCastException {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.as -> TODO" );

        }

        @Override
        public boolean isExpired() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.isExpired -> TODO" );

        }

        @Override
        public boolean isPendingRemoveFromStore() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.isPendingRemoveFromStore -> TODO" );

        }

        @Override
        public void forEachRightTuple( Consumer rightTupleConsumer ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.forEachRightTuple -> TODO" );

        }

        @Override
        public void forEachLeftTuple( Consumer leftTupleConsumer ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.forEachLeftTuple -> TODO" );

        }

        @Override
        public RightTuple findFirstRightTuple( Predicate rightTuplePredicate ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.findFirstRightTuple -> TODO" );

        }

        @Override
        public LeftTuple findFirstLeftTuple( Predicate lefttTuplePredicate ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.findFirstLeftTuple -> TODO" );

        }

        @Override
        public void setFirstLeftTuple( LeftTuple firstLeftTuple ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.setFirstLeftTuple -> TODO" );

        }

        @Override
        public LinkedTuples detachLinkedTuples() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.detachLinkedTuples -> TODO" );

        }

        @Override
        public LinkedTuples detachLinkedTuplesForPartition( int i ) {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.detachLinkedTuplesForPartition -> TODO" );

        }

        @Override
        public LinkedTuples getLinkedTuples() {
            throw new UnsupportedOperationException( "org.drools.core.datasources.CursoredDataSource.DataSourceFactHandle.getLinkedTuples -> TODO" );

        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy