Package org.drools.core.marshalling.impl

Source Code of org.drools.core.marshalling.impl.ProtobufInputMarshaller

/*
* Copyright 2010 JBoss Inc
*
* 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.marshalling.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;

import org.drools.core.SessionConfiguration;
import org.drools.core.common.AbstractWorkingMemory;
import org.drools.core.common.ActivationsFilter;
import org.drools.core.common.AgendaGroupQueueImpl;
import org.drools.core.common.DefaultFactHandle;
import org.drools.core.common.EqualityKey;
import org.drools.core.common.EventFactHandle;
import org.drools.core.common.InternalAgenda;
import org.drools.core.common.InternalFactHandle;
import org.drools.core.common.InternalRuleBase;
import org.drools.core.common.InternalWorkingMemory;
import org.drools.core.common.InternalWorkingMemoryEntryPoint;
import org.drools.core.common.NamedEntryPoint;
import org.drools.core.common.ObjectStore;
import org.drools.core.common.PropagationContextFactory;
import org.drools.core.common.QueryElementFactHandle;
import org.drools.core.common.TruthMaintenanceSystem;
import org.drools.core.common.WorkingMemoryAction;
import org.drools.core.common.WorkingMemoryFactory;
import org.drools.core.impl.EnvironmentFactory;
import org.drools.core.impl.StatefulKnowledgeSessionImpl;
import org.drools.core.marshalling.impl.ProtobufMessages.FactHandle;
import org.drools.core.marshalling.impl.ProtobufMessages.ObjectTypeConfiguration;
import org.drools.core.marshalling.impl.ProtobufMessages.RuleData;
import org.drools.core.marshalling.impl.ProtobufMessages.Timers.Timer;
import org.drools.core.phreak.PhreakTimerNode.Scheduler;
import org.drools.core.phreak.RuleAgendaItem;
import org.drools.core.phreak.RuleExecutor;
import org.drools.core.phreak.StackEntry;
import org.drools.core.process.instance.WorkItem;
import org.drools.core.reteoo.InitialFactImpl;
import org.drools.core.reteoo.LeftTuple;
import org.drools.core.reteoo.ObjectTypeConf;
import org.drools.core.reteoo.TerminalNode;
import org.drools.core.rule.EntryPointId;
import org.drools.core.spi.Activation;
import org.drools.core.spi.AgendaFilter;
import org.drools.core.spi.FactHandleFactory;
import org.drools.core.spi.GlobalResolver;
import org.drools.core.spi.PropagationContext;
import org.drools.core.time.Trigger;
import org.drools.core.time.impl.CronTrigger;
import org.drools.core.time.impl.IntervalTrigger;
import org.drools.core.time.impl.PointInTimeTrigger;
import org.drools.core.time.impl.PseudoClockScheduler;
import org.kie.api.marshalling.ObjectMarshallingStrategy;
import org.kie.api.runtime.Environment;
import org.kie.api.runtime.EnvironmentName;
import org.kie.api.runtime.rule.EntryPoint;

import com.google.protobuf.ExtensionRegistry;

/**
* An input marshaller that uses protobuf.
*
* @author etirelli
*/
public class ProtobufInputMarshaller {
    // NOTE: all variables prefixed with _ (underscore) are protobuf structs

    private static ProcessMarshaller processMarshaller = createProcessMarshaller();

    private static ProcessMarshaller createProcessMarshaller() {
        try {
            return ProcessMarshallerFactory.newProcessMarshaller();
        } catch ( IllegalArgumentException e ) {
            return null;
        }
    }

    /**
     * Stream the data into an existing session
     *
     * @param session
     * @param context
     * @return
     * @throws IOException
     * @throws ClassNotFoundException
     */
    public static AbstractWorkingMemory readSession(AbstractWorkingMemory session,
                                                    MarshallerReaderContext context) throws IOException,
                                                                                    ClassNotFoundException {

        ProtobufMessages.KnowledgeSession _session = loadAndParseSession( context );

        InternalAgenda agenda = resetSession( session,
                                             context,
                                             _session );

        readSession( _session,
                     session,
                     agenda,
                     context );

        return session;
    }

    /**
     * Create a new session into which to read the stream data
     */
    public static AbstractWorkingMemory readSession(MarshallerReaderContext context,
                                                    int id) throws IOException,
                                                           ClassNotFoundException {
        AbstractWorkingMemory session = readSession( context,
                                                     id,
                                                     EnvironmentFactory.newEnvironment(),
                                                     SessionConfiguration.getDefaultInstance() );
        return session;
    }

    public static AbstractWorkingMemory readSession(MarshallerReaderContext context,
                                                    int id,
                                                    Environment environment,
                                                    SessionConfiguration config) throws IOException,
                                                                                ClassNotFoundException {

        ProtobufMessages.KnowledgeSession _session = loadAndParseSession( context );
       
        AbstractWorkingMemory session = createAndInitializeSession( context,
                                                                    id,
                                                                    environment,
                                                                    config,
                                                                    _session );

        return readSession( _session,
                            session,
                            (InternalAgenda) session.getAgenda(),
                            context );
    }

    private static InternalAgenda resetSession(AbstractWorkingMemory session,
                                              MarshallerReaderContext context,
                                              ProtobufMessages.KnowledgeSession _session) {
        session.reset( _session.getRuleData().getLastId(),
                       _session.getRuleData().getLastRecency(),
                       1 );
        InternalAgenda agenda = (InternalAgenda) session.getAgenda();

        readAgenda( context,
                    _session.getRuleData(),
                    agenda );
        return agenda;
    }

    private static AbstractWorkingMemory createAndInitializeSession(MarshallerReaderContext context,
                                                                    int id,
                                                                    Environment environment,
                                                                    SessionConfiguration config,
                                                                    ProtobufMessages.KnowledgeSession _session) throws IOException {
        FactHandleFactory handleFactory = context.ruleBase.newFactHandleFactory( _session.getRuleData().getLastId(),
                                                                                 _session.getRuleData().getLastRecency() );

        InternalAgenda agenda = context.ruleBase.getConfiguration().getComponentFactory().getAgendaFactory().createAgenda( context.ruleBase, false );
        readAgenda( context,
                    _session.getRuleData(),
                    agenda );

        WorkingMemoryFactory wmFactory = context.ruleBase.getConfiguration().getComponentFactory().getWorkingMemoryFactory();
        AbstractWorkingMemory session = ( AbstractWorkingMemory ) wmFactory.createWorkingMemory( id,
                                                                                                 context.ruleBase,
                                                                                                 handleFactory,
                                                                                                 null,
                                                                                                 1, // pCTx starts at 1, as InitialFact is 0
                                                                                                 config,
                                                                                                 agenda,
                                                                                                 environment );
        new StatefulKnowledgeSessionImpl( session );

        return session;
    }

    private static ProtobufMessages.KnowledgeSession loadAndParseSession(MarshallerReaderContext context) throws IOException,
                                                                                                         ClassNotFoundException {
        ExtensionRegistry registry = PersisterHelper.buildRegistry( context, processMarshaller );

        ProtobufMessages.Header _header = PersisterHelper.readFromStreamWithHeaderPreloaded( context, registry );

        return ProtobufMessages.KnowledgeSession.parseFrom( _header.getPayload(), registry );
    }

    public static AbstractWorkingMemory readSession(ProtobufMessages.KnowledgeSession _session,
                                                    AbstractWorkingMemory session,
                                                    InternalAgenda agenda,
                                                    MarshallerReaderContext context) throws IOException,
                                                                                    ClassNotFoundException {
        GlobalResolver globalResolver = (GlobalResolver) context.env.get( EnvironmentName.GLOBALS );
        if ( globalResolver != null ) {
            session.setGlobalResolver( globalResolver );
        }

        if ( session.getTimerService() instanceof PseudoClockScheduler ) {
            PseudoClockScheduler clock = (PseudoClockScheduler) session.getTimerService();
            clock.advanceTime( _session.getTime(),
                               TimeUnit.MILLISECONDS );
        }

        // RuleFlowGroups need to reference the session
        //        for ( InternalAgendaGroup group : agenda.getAgendaGroupsMap().values() ) {
        //            ((RuleFlowGroupImpl) group).setWorkingMemory( session );
        //        }

        context.wm = session;

        // need to read node memories before reading the fact handles
        // because this data is required during fact propagation
        readNodeMemories( context,
                          _session.getRuleData() );

        List<PropagationContext> pctxs = new ArrayList<PropagationContext>();

        if ( context.ruleBase.getConfiguration().isPhreakEnabled() || _session.getRuleData().hasInitialFact() ) {
            ((AbstractWorkingMemory)context.wm).initInitialFact(context.ruleBase, context);
            context.handles.put( session.getInitialFactHandle().getId(), session.getInitialFactHandle() );
        }

        for ( ProtobufMessages.EntryPoint _ep : _session.getRuleData().getEntryPointList() ) {
            EntryPoint wmep = context.wm.getEntryPoints().get( _ep.getEntryPointId() );
            readFactHandles( context,
                             _ep,
                             ((NamedEntryPoint) wmep).getObjectStore(),
                             pctxs );
            readTruthMaintenanceSystem( context,
                                        wmep,
                                        _ep,
                                        pctxs );
        }

        cleanReaderContexts( pctxs );

        readActionQueue( context,
                         _session.getRuleData() );

        if ( processMarshaller != null ) {
            if ( _session.hasProcessData() ) {
                context.parameterObject = _session.getProcessData();
                processMarshaller.readProcessInstances( context );

                context.parameterObject = _session.getProcessData();
                processMarshaller.readWorkItems( context );

                // This actually does ALL timers, due to backwards compatability issues
                // It will read in old JBPM binaries, but always write to the new binary format.
                context.parameterObject = _session.getProcessData();
                processMarshaller.readProcessTimers( context );
            }
        } else {
            if ( _session.hasProcessData() ) {
                throw new IllegalStateException( "No process marshaller, unable to unmarshall process data." );
            }
        }

        if ( _session.hasTimers() ) {
            for ( ProtobufMessages.Timers.Timer _timer : _session.getTimers().getTimerList() ) {
                readTimer( context,
                           _timer );
            }
        }
        // need to process any eventual left over timer node timers
        if( ! context.timerNodeSchedulers.isEmpty() ) {
            for( Map<TupleKey, Scheduler> schedulers : context.timerNodeSchedulers.values() ) {
                for( Scheduler scheduler : schedulers.values() ) {
                    scheduler.schedule( scheduler.getTrigger() );
                }
            }
            context.timerNodeSchedulers.clear();
        }

        // remove the activations filter
        agenda.setActivationsFilter( null );

        return session;
    }

    private static void readNodeMemories(MarshallerReaderContext context,
                                         RuleData _session) {
        for ( ProtobufMessages.NodeMemory _node : _session.getNodeMemoryList() ) {
            Object memory = null;
            switch ( _node.getNodeType() ) {
                case ACCUMULATE : {
                    Map<TupleKey, ProtobufMessages.FactHandle> map = new HashMap<TupleKey, ProtobufMessages.FactHandle>();
                    for ( ProtobufMessages.NodeMemory.AccumulateNodeMemory.AccumulateContext _ctx : _node.getAccumulate().getContextList() ) {
                        map.put( PersisterHelper.createTupleKey( _ctx.getTuple() ), _ctx.getResultHandle() );
                    }
                    memory = map;
                    break;
                }
                case RIA : {
                    Map<TupleKey, ProtobufMessages.FactHandle> map = new HashMap<TupleKey, ProtobufMessages.FactHandle>();
                    for ( ProtobufMessages.NodeMemory.RIANodeMemory.RIAContext _ctx : _node.getRia().getContextList() ) {
                        map.put( PersisterHelper.createTupleKey( _ctx.getTuple() ), _ctx.getResultHandle() );
                    }
                    memory = map;
                    break;
                }
                case FROM : {
                    Map<TupleKey, List<ProtobufMessages.FactHandle>> map = new HashMap<TupleKey, List<ProtobufMessages.FactHandle>>();
                    for ( ProtobufMessages.NodeMemory.FromNodeMemory.FromContext _ctx : _node.getFrom().getContextList() ) {
                        // have to instantiate a modifiable list
                        map.put( PersisterHelper.createTupleKey( _ctx.getTuple() ), new LinkedList<ProtobufMessages.FactHandle>( _ctx.getHandleList() ) );
                    }
                    memory = map;
                    break;
                }
                case QUERY_ELEMENT : {
                    Map<TupleKey, QueryElementContext> map = new HashMap<TupleKey, QueryElementContext>();
                    for ( ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext _ctx : _node.getQueryElement().getContextList() ) {
                        // we have to use a "cloned" query element context as we need to write on it during deserialization process and the
                        // protobuf one is read-only
                        map.put( PersisterHelper.createTupleKey( _ctx.getTuple() ), new QueryElementContext( _ctx ) );
                    }
                    memory = map;
                    break;
                }
                default : {
                    throw new IllegalArgumentException( "Unknown node type " + _node.getNodeType() + " while deserializing session." );
                }
            }
            context.nodeMemories.put( _node.getNodeId(), memory );
        }
    }

    public static class QueryElementContext {
        public final ProtobufMessages.FactHandle             handle;
        public final LinkedList<ProtobufMessages.FactHandle> results;

        public QueryElementContext(ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext _ctx) {
            this.handle = _ctx.getHandle();
            this.results = new LinkedList<ProtobufMessages.FactHandle>( _ctx.getResultList() );
        }
    }

    private static void readInitialFactHandle(MarshallerReaderContext context,
                                              RuleData _session,
                                              List<PropagationContext> pctxs) {
        int ifhId = context.wm.getInitialFactHandle().getId();
        context.handles.put( ifhId,
                             context.wm.getInitialFactHandle() );

        // special case we have to handle for the initial fact
        boolean initialFactPropagated = true;
        for ( ProtobufMessages.ActionQueue.Action _action : _session.getActionQueue().getActionList() ) {
            if ( _action.getType() == ProtobufMessages.ActionQueue.ActionType.ASSERT ) {
                if ( _action.getAssert().getHandleId() == ifhId ) {
                    initialFactPropagated = false;
                    break;
                }
            }
        }
        if ( initialFactPropagated ) {
            assertHandleIntoOTN( context,
                                 context.wm,
                                 context.wm.getInitialFactHandle(),
                                 pctxs );
        }
    }

    public static void readAgenda(MarshallerReaderContext context,
                                  RuleData _ruleData,
                                  InternalAgenda agenda) {
        ProtobufMessages.Agenda _agenda = _ruleData.getAgenda();

        for ( org.drools.core.marshalling.impl.ProtobufMessages.Agenda.AgendaGroup _agendaGroup : _agenda.getAgendaGroupList() ) {
            AgendaGroupQueueImpl group = (AgendaGroupQueueImpl) agenda.getAgendaGroup( _agendaGroup.getName(), context.ruleBase );
            group.setActive( _agendaGroup.getIsActive() );
            group.setAutoDeactivate( _agendaGroup.getIsAutoDeactivate() );
            group.setClearedForRecency( _agendaGroup.getClearedForRecency() );
            group.hasRuleFlowListener( _agendaGroup.getHasRuleFlowLister() );
            group.setActivatedForRecency( _agendaGroup.getActivatedForRecency() );

            for ( org.drools.core.marshalling.impl.ProtobufMessages.Agenda.AgendaGroup.NodeInstance _nodeInstance : _agendaGroup.getNodeInstanceList() ) {
                group.addNodeInstance( _nodeInstance.getProcessInstanceId(),
                                       _nodeInstance.getNodeInstanceId() );
            }
            agenda.getAgendaGroupsMap().put( group.getName(),
                                             group );
        }
       
        for ( String _groupName : _agenda.getFocusStack().getGroupNameList() ) {
            agenda.addAgendaGroupOnStack( agenda.getAgendaGroup( _groupName ) );
        }
       
        for ( ProtobufMessages.Agenda.RuleFlowGroup _ruleFlowGroup : _agenda.getRuleFlowGroupList() ) {
            AgendaGroupQueueImpl group = (AgendaGroupQueueImpl) agenda.getAgendaGroup( _ruleFlowGroup.getName(), context.ruleBase );
            group.setActive( _ruleFlowGroup.getIsActive() );
            group.setAutoDeactivate( _ruleFlowGroup.getIsAutoDeactivate() );
           

            for ( org.drools.core.marshalling.impl.ProtobufMessages.Agenda.RuleFlowGroup.NodeInstance _nodeInstance : _ruleFlowGroup.getNodeInstanceList() ) {
                group.addNodeInstance( _nodeInstance.getProcessInstanceId(),
                                       _nodeInstance.getNodeInstanceId() );
            }
            agenda.getAgendaGroupsMap().put( group.getName(),
                                             group );
            if (group.isActive()) {
                agenda.addAgendaGroupOnStack( agenda.getAgendaGroup( group.getName() ) );
            }
        }

       

        readActivations( context,
                         _agenda.getMatchList(),
                         _agenda.getRuleActivationList() );
        agenda.setActivationsFilter( context.filter );
    }

    public static void readActionQueue(MarshallerReaderContext context,
                                       RuleData _session) throws IOException,
                                                         ClassNotFoundException {
        AbstractWorkingMemory wm = (AbstractWorkingMemory) context.wm;
        Queue<WorkingMemoryAction> actionQueue = wm.getActionQueue();
        for ( ProtobufMessages.ActionQueue.Action _action : _session.getActionQueue().getActionList() ) {
            actionQueue.offer( PersisterHelper.deserializeWorkingMemoryAction( context,
                                                                               _action ) );
        }
    }

    public static void readFactHandles(MarshallerReaderContext context,
                                       org.drools.core.marshalling.impl.ProtobufMessages.EntryPoint _ep,
                                       ObjectStore objectStore,
                                       List<PropagationContext> pctxs) throws IOException,
                                                                          ClassNotFoundException {
        InternalWorkingMemory wm = context.wm;

        EntryPoint entryPoint = context.wm.getEntryPoints().get( _ep.getEntryPointId() );
       
        // load the handles
        for ( ProtobufMessages.FactHandle _handle : _ep.getHandleList() ) {
            InternalFactHandle handle = readFactHandle( context,
                                                        entryPoint,
                                                        _handle );

            context.handles.put( handle.getId(),
                                 handle );

            if ( !_handle.getIsJustified() ) {
                // BeliefSystem handles the Object type
                if ( handle.getObject() != null ) {
                    objectStore.addHandle( handle,
                                           handle.getObject() );
                }

                // add handle to object type node
                assertHandleIntoOTN( context,
                                     wm,
                                     handle,
                                     pctxs );
            }
        }

    }

    private static void assertHandleIntoOTN(MarshallerReaderContext context,
                                            InternalWorkingMemory wm,
                                            InternalFactHandle handle,
                                            List<PropagationContext> pctxs) {
        Object object = handle.getObject();
        InternalWorkingMemoryEntryPoint ep = (InternalWorkingMemoryEntryPoint) handle.getEntryPoint();
        ObjectTypeConf typeConf = ((InternalWorkingMemoryEntryPoint) handle.getEntryPoint()).getObjectTypeConfigurationRegistry().getObjectTypeConf( ep.getEntryPoint(), object );

        PropagationContextFactory pctxFactory =((InternalRuleBase)wm.getRuleBase()).getConfiguration().getComponentFactory().getPropagationContextFactory();

        PropagationContext propagationContext = pctxFactory.createPropagationContext(wm.getNextPropagationIdCounter(), PropagationContext.INSERTION, null, null, handle, ep.getEntryPoint(), context);
        // keeping this list for a later cleanup is necessary because of the lazy propagations that might occur
        pctxs.add( propagationContext );

        ep.getEntryPointNode().assertObject( handle,
                                             propagationContext,
                                             typeConf,
                                             wm );

        propagationContext.evaluateActionQueue( wm );
        wm.executeQueuedActions();
    }

    private static void cleanReaderContexts(List<PropagationContext> pctxs) {
        for ( PropagationContext ctx : pctxs ) {
            ctx.cleanReaderContext();
        }
    }

    public static InternalFactHandle readFactHandle(MarshallerReaderContext context,
                                                    EntryPoint entryPoint,
                                                    FactHandle _handle) throws IOException,
                                                                       ClassNotFoundException {
        Object object = null;
        ObjectMarshallingStrategy strategy = null;
        if ( _handle.hasStrategyIndex() ) {
            strategy = context.usedStrategies.get( _handle.getStrategyIndex() );
            object = strategy.unmarshal( context.strategyContexts.get( strategy ),
                                         context,
                                         _handle.getObject().toByteArray(),
                                         (context.ruleBase == null) ? null : context.ruleBase.getRootClassLoader() );
        }


        EntryPointId confEP;
        if ( entryPoint != null ) {
            confEP = ((NamedEntryPoint) entryPoint).getEntryPoint();
        } else {
            confEP = context.wm.getEntryPoint();
        }
        ObjectTypeConf typeConf = context.wm.getObjectTypeConfigurationRegistry().getObjectTypeConf( confEP, object );


        InternalFactHandle handle = null;
        switch ( _handle.getType() ) {
            case FACT : {
                handle = new DefaultFactHandle( _handle.getId(),
                                                object,
                                                _handle.getRecency(),
                                                entryPoint,
                                                typeConf != null && typeConf.isTrait() );
                break;
            }
            case QUERY : {
                handle = new QueryElementFactHandle( object,
                                                     _handle.getId(),
                                                     _handle.getRecency() );
                break;
            }
            case EVENT : {
                handle = new EventFactHandle( _handle.getId(),
                                              object,
                                              _handle.getRecency(),
                                              _handle.getTimestamp(),
                                              _handle.getDuration(),
                                              entryPoint,
                                              typeConf != null && typeConf.isTrait() );
                ((EventFactHandle) handle).setExpired( _handle.getIsExpired() );
                // the event is re-propagated through the network, so the activations counter will be recalculated
                //((EventFactHandle) handle).setActivationsCount( _handle.getActivationsCount() );
                break;
            }
            default : {
                throw new IllegalStateException( "Unable to marshal FactHandle, as type does not exist:" + _handle.getType() );
            }
        }
        return handle;
    }

    public static void readTruthMaintenanceSystem(MarshallerReaderContext context,
                                                  EntryPoint wmep,
                                                  ProtobufMessages.EntryPoint _ep,
                                                  List<PropagationContext> pctxs) throws IOException,
                                                                                     ClassNotFoundException {
        TruthMaintenanceSystem tms = ((NamedEntryPoint) wmep).getTruthMaintenanceSystem();
       
        boolean wasOTCSerialized = _ep.getOtcCount() > 0; // if 0, then the OTC was not serialized (older versions of drools)
        Set<String> tmsEnabled = new HashSet<String>();
        for( ObjectTypeConfiguration _otc : _ep.getOtcList() ) {
          if( _otc.getTmsEnabled() ) {
              tmsEnabled.add( _otc.getType() );
          }
        }

        ProtobufMessages.TruthMaintenanceSystem _tms = _ep.getTms();

        for ( ProtobufMessages.EqualityKey _key : _tms.getKeyList() ) {
            InternalFactHandle handle = (InternalFactHandle) context.handles.get( _key.getHandleId() );

            // ObjectTypeConf state is not marshalled, so it needs to be re-determined
            ObjectTypeConf typeConf = context.wm.getObjectTypeConfigurationRegistry().getObjectTypeConf( ((NamedEntryPoint) handle.getEntryPoint()).getEntryPoint(),
                                                                                                         handle.getObject() );
            if ( !typeConf.isTMSEnabled() && (!wasOTCSerialized || tmsEnabled.contains(typeConf.getTypeName()) ) ) {
                typeConf.enableTMS();
            }

            EqualityKey key = new EqualityKey( handle,
                                               _key.getStatus() );
            handle.setEqualityKey( key );

            if ( key.getStatus() == EqualityKey.JUSTIFIED ) {
                // not yet added to the object stores
                ((NamedEntryPoint) handle.getEntryPoint()).getObjectStore().addHandle( handle,
                                                                                       handle.getObject() );
                // add handle to object type node
                assertHandleIntoOTN( context,
                                     context.wm,
                                     handle,
                                     pctxs );
            }

            for ( Integer factHandleId : _key.getOtherHandleList() ) {
                handle = (InternalFactHandle) context.handles.get( factHandleId.intValue() );
                key.addFactHandle( handle );
                handle.setEqualityKey( key );
            }
            tms.put( key );

            readBeliefSet( context, tms, key, _key );
        }

    }

    private static void readBeliefSet(MarshallerReaderContext context,
                                      TruthMaintenanceSystem tms,
                                      EqualityKey key,
                                      ProtobufMessages.EqualityKey _key) throws IOException,
                                                                            ClassNotFoundException {
        if( _key.hasBeliefSet() ) {
            ProtobufMessages.BeliefSet _beliefSet = _key.getBeliefSet();
            InternalFactHandle handle = (InternalFactHandle) context.handles.get( _key.getHandleId() );
            // phreak might serialize empty belief sets, so he have to handle it during deserialization
            if( _beliefSet.getLogicalDependencyCount() > 0 ) {
                for ( ProtobufMessages.LogicalDependency _logicalDependency : _beliefSet.getLogicalDependencyList() ) {
                    ProtobufMessages.Activation _activation = _logicalDependency.getActivation();
                    Activation activation = (Activation) context.filter.getTuplesCache().get(
                                                                                              PersisterHelper.createActivationKey( _activation.getPackageName(),
                                                                                                                                   _activation.getRuleName(),
                                                                                                                                   _activation.getTuple() ) ).getObject();

                    Object object = null;
                    ObjectMarshallingStrategy strategy = null;
                    if ( _logicalDependency.hasObjectStrategyIndex() ) {
                        strategy = context.usedStrategies.get( _logicalDependency.getObjectStrategyIndex() );
                        object = strategy.unmarshal( context.strategyContexts.get( strategy ),
                                                     context,
                                                     _logicalDependency.getObject().toByteArray(),
                                                     (context.ruleBase == null) ? null : context.ruleBase.getRootClassLoader() );
                    }

                    Object value = null;
                    if ( _logicalDependency.hasValueStrategyIndex() ) {
                        strategy = context.usedStrategies.get( _logicalDependency.getValueStrategyIndex() );
                        value = strategy.unmarshal( context.strategyContexts.get( strategy ),
                                                    context,
                                                    _logicalDependency.getValue().toByteArray(),
                                                    (context.ruleBase == null) ? null : context.ruleBase.getRootClassLoader() );
                    }

                    ObjectTypeConf typeConf = context.wm.getObjectTypeConfigurationRegistry().getObjectTypeConf( ((NamedEntryPoint) handle.getEntryPoint()).getEntryPoint(),
                                                                                                                 handle.getObject() );
                    tms.readLogicalDependency( handle,
                                               object,
                                               value,
                                               activation,
                                               activation.getPropagationContext(),
                                               activation.getRule(),
                                               typeConf );
                }
            } else {
                handle.getEqualityKey().setBeliefSet( tms.getBeliefSystem().newBeliefSet( handle ) );
            }
        }
    }

    private static void readActivations(MarshallerReaderContext context,
                                        List<ProtobufMessages.Activation> _dormant,
                                        List<ProtobufMessages.Activation> _rneas) {

        for ( ProtobufMessages.Activation _activation : _dormant ) {
            // this is a dormant activation
            context.filter.getDormantActivationsMap().put( PersisterHelper.createActivationKey( _activation.getPackageName(),
                                                                                                _activation.getRuleName(),
                                                                                                _activation.getTuple() ),
                                                           _activation );
        }
        for ( ProtobufMessages.Activation _activation : _rneas ) {
            // this is an active rule network evaluator
            context.filter.getRneActivations().put( PersisterHelper.createActivationKey( _activation.getPackageName(),
                                                                                         _activation.getRuleName(),
                                                                                         _activation.getTuple() ),
                                                    _activation );
        }
    }

    public static void readTimer(MarshallerReaderContext inCtx,
                                 Timer _timer) throws IOException,
                                              ClassNotFoundException {
        TimersInputMarshaller reader = inCtx.readersByInt.get( _timer.getType().getNumber() );
        reader.deserialize( inCtx, _timer );
    }

    public static Trigger readTrigger(MarshallerReaderContext inCtx,
                                      ProtobufMessages.Trigger _trigger) {
        switch ( _trigger.getType() ) {
            case CRON : {
                ProtobufMessages.Trigger.CronTrigger _cron = _trigger.getCron();
                CronTrigger trigger = new CronTrigger();
                trigger.setStartTime( new Date( _cron.getStartTime() ) );
                if ( _cron.hasEndTime() ) {
                    trigger.setEndTime( new Date( _cron.getEndTime() ) );
                }
                trigger.setRepeatLimit( _cron.getRepeatLimit() );
                trigger.setRepeatCount( _cron.getRepeatCount() );
                trigger.setCronExpression( _cron.getCronExpression() );
                if ( _cron.hasNextFireTime() ) {
                    trigger.setNextFireTime( new Date( _cron.getNextFireTime() ) );
                }
                String[] calendarNames = new String[_cron.getCalendarNameCount()];
                for ( int i = 0; i < calendarNames.length; i++ ) {
                    calendarNames[i] = _cron.getCalendarName( i );
                }
                trigger.setCalendarNames( calendarNames );
                return trigger;
            }
            case INTERVAL : {
                ProtobufMessages.Trigger.IntervalTrigger _interval = _trigger.getInterval();
                IntervalTrigger trigger = new IntervalTrigger();
                trigger.setStartTime( new Date( _interval.getStartTime() ) );
                if ( _interval.hasEndTime() ) {
                    trigger.setEndTime( new Date( _interval.getEndTime() ) );
                }
                trigger.setRepeatLimit( _interval.getRepeatLimit() );
                trigger.setRepeatCount( _interval.getRepeatCount() );
                if ( _interval.hasNextFireTime() ) {
                    trigger.setNextFireTime( new Date( _interval.getNextFireTime() ) );
                }
                trigger.setPeriod( _interval.getPeriod() );
                String[] calendarNames = new String[_interval.getCalendarNameCount()];
                for ( int i = 0; i < calendarNames.length; i++ ) {
                    calendarNames[i] = _interval.getCalendarName( i );
                }
                trigger.setCalendarNames( calendarNames );
                return trigger;
            }
            case POINT_IN_TIME : {
                PointInTimeTrigger trigger = new PointInTimeTrigger( _trigger.getPit().getNextFireTime(), null, null );
                return trigger;
            }
        }
        throw new RuntimeException( "Unable to deserialize Trigger for type: " + _trigger.getType() );

    }

    public static WorkItem readWorkItem( MarshallerReaderContext context ) {
        return processMarshaller.readWorkItem( context );
    }

    public static class PBActivationsFilter
            implements
            ActivationsFilter,
            AgendaFilter {
        private Map<ActivationKey, ProtobufMessages.Activation> dormantActivations;
        private Map<ActivationKey, ProtobufMessages.Activation> rneActivations;
        private Map<ActivationKey, LeftTuple>                   tuplesCache;
        private Queue<RuleAgendaItem>                           rneaToFire;

        public PBActivationsFilter() {
            this.dormantActivations = new HashMap<ProtobufInputMarshaller.ActivationKey, ProtobufMessages.Activation>();
            this.rneActivations = new HashMap<ProtobufInputMarshaller.ActivationKey, ProtobufMessages.Activation>();
            this.tuplesCache = new HashMap<ProtobufInputMarshaller.ActivationKey, LeftTuple>();
            this.rneaToFire = new ConcurrentLinkedQueue<RuleAgendaItem>();
        }

        public Map<ActivationKey, ProtobufMessages.Activation> getDormantActivationsMap() {
            return this.dormantActivations;
        }

        public boolean accept(Activation activation,
                              InternalWorkingMemory workingMemory,
                              TerminalNode rtn) {
            if ( activation.isRuleAgendaItem() ) {
                ActivationKey key = PersisterHelper.createActivationKey( activation.getRule().getPackageName(), activation.getRule().getName(), activation.getTuple() );
                if ( !this.rneActivations.containsKey( key ) || this.rneActivations.get( key ).getEvaluated() ) {
                    rneaToFire.add( (RuleAgendaItem) activation );
                }
                return true;
            } else {
                ActivationKey key = PersisterHelper.createActivationKey( rtn.getRule().getPackageName(), rtn.getRule().getName(), activation.getTuple() );
                // add the tuple to the cache for correlation
                this.tuplesCache.put( key, activation.getTuple() );
                // check if there was an active activation for it
                return !this.dormantActivations.containsKey( key );
            }
        }

        public Map<ActivationKey, LeftTuple> getTuplesCache() {
            return tuplesCache;
        }

        public Map<ActivationKey, ProtobufMessages.Activation> getRneActivations() {
            return rneActivations;
        }

        public void fireRNEAs(final InternalWorkingMemory wm) {
            RuleAgendaItem rai = null;
            while ( (rai = rneaToFire.poll()) != null ) {
                RuleExecutor ruleExecutor = rai.getRuleExecutor();
                ruleExecutor.reEvaluateNetwork( wm, new org.drools.core.util.LinkedList<StackEntry>(), false );
                ruleExecutor.removeRuleAgendaItemWhenEmpty( wm );
            }
        }

        @Override
        public boolean accept(Activation match) {
            ActivationKey key = PersisterHelper.createActivationKey( match.getRule().getPackageName(),
                                                                     match.getRule().getName(),
                                                                     match.getTuple() );
            // add the tuple to the cache for correlation
            this.tuplesCache.put( key, match.getTuple() );
            // check if there was an active activation for it
            return !this.dormantActivations.containsKey( key );
        }
    }

    public static class ActivationKey {

        private final String pkgName;
        private final String ruleName;
        private final int[]  tuple;

        public ActivationKey(String pkgName,
                             String ruleName,
                             int[] tuple) {
            this.pkgName = pkgName;
            this.ruleName = ruleName;
            this.tuple = tuple;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((pkgName == null) ? 0 : pkgName.hashCode());
            result = prime * result + ((ruleName == null) ? 0 : ruleName.hashCode());
            result = prime * result + Arrays.hashCode( tuple );
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if ( this == obj ) return true;
            if ( obj == null ) return false;
            if ( getClass() != obj.getClass() ) return false;
            ActivationKey other = (ActivationKey) obj;
            if ( pkgName == null ) {
                if ( other.pkgName != null ) return false;
            } else if ( !pkgName.equals( other.pkgName ) ) return false;
            if ( ruleName == null ) {
                if ( other.ruleName != null ) return false;
            } else if ( !ruleName.equals( other.ruleName ) ) return false;
            if ( !Arrays.equals( tuple, other.tuple ) ) return false;
            return true;
        }
    }

    public static class TupleKey {
        private final int[] tuple;

        public TupleKey(int[] tuple) {
            super();
            this.tuple = tuple;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + Arrays.hashCode( tuple );
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if ( this == obj ) return true;
            if ( obj == null ) return false;
            if ( getClass() != obj.getClass() ) return false;
            TupleKey other = (TupleKey) obj;
            if ( !Arrays.equals( tuple, other.tuple ) ) return false;
            return true;
        }
    }
}
TOP

Related Classes of org.drools.core.marshalling.impl.ProtobufInputMarshaller

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.