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

org.drools.core.reteoo.TraitObjectTypeNode Maven / Gradle / Ivy

There is a newer version: 9.44.0.Final
Show newest version
/*
 * Copyright 2013 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.reteoo;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.BitSet;
import java.util.Collection;

import org.drools.core.base.ClassObjectType;
import org.drools.core.common.InternalFactHandle;
import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.factmodel.traits.Thing;
import org.drools.core.factmodel.traits.TraitProxy;
import org.drools.core.factmodel.traits.TraitType;
import org.drools.core.factmodel.traits.TraitTypeMap;
import org.drools.core.reteoo.builder.BuildContext;
import org.drools.core.spi.ObjectType;
import org.drools.core.spi.PropagationContext;
import org.drools.core.util.HierarchyEncoderImpl;
import org.drools.core.util.bitmask.BitMask;

public class TraitObjectTypeNode extends ObjectTypeNode {

    private BitSet typeMask;

    public TraitObjectTypeNode() { }

    public TraitObjectTypeNode( int id, EntryPointNode source, ObjectType objectType, BuildContext context ) {
        super( id, source, objectType, context );

        typeMask = context.getKnowledgeBase().getConfiguration().getComponentFactory().getTraitRegistry().getHierarchy().getCode(
                ((ClassObjectType) objectType).getClassName()
        );
    }

    public void readExternal( ObjectInput in ) throws IOException, ClassNotFoundException {
        super.readExternal( in );
        typeMask = (BitSet) in.readObject();
    }

    public void writeExternal( ObjectOutput out ) throws IOException {
        super.writeExternal( out );
        out.writeObject( typeMask );
    }


    @Override
    public void propagateAssert( InternalFactHandle factHandle, PropagationContext context, InternalWorkingMemory workingMemory ) {
        if ( isAssertAllowed( factHandle ) ) {
            super.propagateAssert( factHandle, context, workingMemory );
        }
    }

    private boolean isAssertAllowed( InternalFactHandle factHandle ) {
        if ( factHandle.isTraiting() )  {
            TraitProxy proxy = (TraitProxy) factHandle.getObject();
            BitSet vetoMask = proxy.computeInsertionVetoMask();
            boolean vetoed = ( vetoMask != null
                               && ! typeMask.isEmpty()
                               && HierarchyEncoderImpl.supersetOrEqualset( vetoMask, this.typeMask ) );

            boolean allowed = ! vetoed || sameAndNotCoveredByDescendants( (TraitProxy) factHandle.getObject(), typeMask );
            if ( allowed ) {
                //System.err.println(" INSERT PASS !! " + factHandle.getObject() + " " + ( (TraitProxy) factHandle.getObject() )._getTypeCode() + " >> " + vetoMask + " checks in " + typeMask );
                proxy.assignOtn( this.typeMask );
            } else {
                //System.err.println(" INSERT BLOCK !! " + factHandle.getObject() + " " + ( (TraitProxy) factHandle.getObject() )._getTypeCode() + " >> " + vetoMask + " checks in " + typeMask );
            }
            return allowed;
        }
        return true;
    }

    /**
     *  Edge case: due to the way traits are encoded, consider this hierarchy:
     *  A    B
     *    C
     *    D
     *  On don/insertion of C, C may be vetoed by its parents, but might have been
     *  already covered by one of its descendants (D)
     */
    private boolean sameAndNotCoveredByDescendants( TraitProxy proxy, BitSet typeMask ) {
        boolean isSameType = typeMask.equals( proxy._getTypeCode() );
        if ( isSameType ) {
            TraitTypeMap,?> ttm = (TraitTypeMap,?>) proxy.getObject()._getTraitMap();
            Collection> descs = ttm.lowerDescendants( typeMask );
            // we have to exclude the "mock" bottom proxy
            if ( descs == null || descs.isEmpty() ) {
                return true;
            } else {
                for ( Thing sub : descs ) {
                    TraitType tt = (TraitType) sub;
                    if ( tt != proxy && tt._hasTypeCode( typeMask ) ) {
                        return false;
                    }
                }
                return true;
            }
        } else {
            return false;
        }
    }

    private boolean isModifyAllowed( InternalFactHandle factHandle ) {
        if ( factHandle.isTraiting() ) {
            TraitProxy proxy = ( (TraitProxy) factHandle.getObject() );
            return proxy.listAssignedOtnTypeCodes().contains( this.typeMask );
        }
        return true;
    }


    public void modifyObject( InternalFactHandle factHandle,
                              ModifyPreviousTuples modifyPreviousTuples,
                              PropagationContext context,
                              InternalWorkingMemory workingMemory ) {

        if (!isModifyAllowed( factHandle )) {
            return;
        }

        checkDirty();

        if ( compiledNetwork != null ) {
            compiledNetwork.modifyObject( factHandle,
                    modifyPreviousTuples,
                    context.adaptModificationMaskForObjectType( objectType, workingMemory ),
                    workingMemory );
        } else {
            if ( factHandle.isTraiting() )  {
                if ( isModifyAllowed( factHandle )  ) {
                    this.sink.propagateModifyObject( factHandle,
                                                     modifyPreviousTuples,
                                                     context.adaptModificationMaskForObjectType( objectType, workingMemory ),
                                                     workingMemory );
                } else {
                    //System.err.println( ((ClassObjectType) this.getObjectType()).getClassName() + " : MODIFY BLOCK !! " + ( (TraitProxy) factHandle.getObject() ).getTraitName() + " " + ( (TraitProxy) factHandle.getObject() )._getTypeCode() + " >> " + " checks in " + typeMask );
                }
            } else {
                this.sink.propagateModifyObject( factHandle,
                                                 modifyPreviousTuples,
                                                 !context.getModificationMask().isSet(PropertySpecificUtil.TRAITABLE_BIT) ?
                                                        context.adaptModificationMaskForObjectType( objectType, workingMemory ) :
                                                        context,
                                                 workingMemory );
            }
        }
    }

    @Override
    public BitMask updateMask(BitMask mask) {
        BitMask returnMask;
        returnMask = declaredMask.clone().setAll( mask );
        inferredMask = inferredMask.setAll( returnMask );
        return returnMask;
    }

    public BitSet getLocalTypeCode() {
        return typeMask;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy