Package org.drools.marshalling.impl

Source Code of org.drools.marshalling.impl.ProtobufOutputMarshaller$RuleFlowGroupSorter

/*
* 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.marshalling.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.drools.InitialFact;
import org.drools.common.ActivationIterator;
import org.drools.common.AgendaItem;
import org.drools.common.DefaultAgenda;
import org.drools.common.EqualityKey;
import org.drools.common.EventFactHandle;
import org.drools.common.InternalFactHandle;
import org.drools.common.InternalWorkingMemory;
import org.drools.common.InternalWorkingMemoryEntryPoint;
import org.drools.common.LeftTupleIterator;
import org.drools.common.LogicalDependency;
import org.drools.common.Memory;
import org.drools.common.NamedEntryPoint;
import org.drools.common.NodeMemories;
import org.drools.common.ObjectStore;
import org.drools.common.ObjectTypeConfigurationRegistry;
import org.drools.common.QueryElementFactHandle;
import org.drools.common.RuleFlowGroupImpl;
import org.drools.common.WorkingMemoryAction;
import org.drools.core.util.LinkedListEntry;
import org.drools.core.util.ObjectHashMap;
import org.drools.core.util.ObjectHashMap.ObjectEntry;
import org.drools.marshalling.ObjectMarshallingStrategy;
import org.drools.marshalling.ObjectMarshallingStrategyStore;
import org.drools.marshalling.impl.ProtobufMessages.FactHandle;
import org.drools.marshalling.impl.ProtobufMessages.ObjectTypeConfiguration;
import org.drools.marshalling.impl.ProtobufMessages.ProcessData.Builder;
import org.drools.marshalling.impl.ProtobufMessages.Timers;
import org.drools.marshalling.impl.ProtobufMessages.Timers.Timer;
import org.drools.reteoo.AccumulateNode.AccumulateContext;
import org.drools.reteoo.AccumulateNode.AccumulateMemory;
import org.drools.reteoo.FromNode.FromMemory;
import org.drools.reteoo.LeftTuple;
import org.drools.reteoo.NodeTypeEnums;
import org.drools.reteoo.ObjectTypeConf;
import org.drools.reteoo.ObjectTypeNode.ObjectTypeNodeMemory;
import org.drools.reteoo.QueryElementNode.QueryElementNodeMemory;
import org.drools.reteoo.ReteooWorkingMemory;
import org.drools.reteoo.RightInputAdapterNode.RIAMemory;
import org.drools.reteoo.RightTuple;
import org.drools.rule.Rule;
import org.drools.runtime.rule.WorkingMemoryEntryPoint;
import org.drools.spi.AgendaGroup;
import org.drools.spi.RuleFlowGroup;
import org.drools.time.JobContext;
import org.drools.time.SelfRemovalJobContext;
import org.drools.time.Trigger;
import org.drools.time.impl.CronTrigger;
import org.drools.time.impl.IntervalTrigger;
import org.drools.time.impl.PointInTimeTrigger;
import org.drools.time.impl.PseudoClockScheduler;
import org.drools.time.impl.TimerJobInstance;

import com.google.protobuf.ByteString;

/**
* An output marshaller that uses ProtoBuf as the marshalling framework in order
* to provide backward compatibility with marshalled sessions
*
* @author etirelli
*/
public class ProtobufOutputMarshaller {

    private static ProcessMarshaller processMarshaller = createProcessMarshaller();

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

    public static void writeSession(MarshallerWriteContext context) throws IOException {

        ProtobufMessages.KnowledgeSession _session = serializeSession(context);
        PersisterHelper.writeToStreamWithHeader(context,
                _session);
    }

    private static ProtobufMessages.KnowledgeSession serializeSession(MarshallerWriteContext context) throws IOException {
        ReteooWorkingMemory wm = (ReteooWorkingMemory) context.wm;
        wm.getAgenda().unstageActivations();

        ProtobufMessages.RuleData.Builder _ruleData = ProtobufMessages.RuleData.newBuilder();

        final boolean multithread = wm.isPartitionManagersActive();
        if (multithread) {
            wm.stopPartitionManagers();
        }

        long time = 0;
        if (context.wm.getTimerService() instanceof PseudoClockScheduler) {
            time = context.clockTime;
        }
        _ruleData.setLastId(wm.getFactHandleFactory().getId());
        _ruleData.setLastRecency(wm.getFactHandleFactory().getRecency());

        InternalFactHandle handle = context.wm.getInitialFactHandle();
        if ( handle != null ) {
            ProtobufMessages.FactHandle _ifh = ProtobufMessages.FactHandle.newBuilder()
                    .setType(ProtobufMessages.FactHandle.HandleType.INITIAL_FACT)
                    .setId(handle.getId())
                    .setRecency(handle.getRecency())
                    .build();
            _ruleData.setInitialFact(_ifh);
        }

        writeAgenda(context, _ruleData);

        writeNodeMemories(context, _ruleData);

        for (WorkingMemoryEntryPoint wmep : wm.getEntryPoints().values()) {
            org.drools.marshalling.impl.ProtobufMessages.EntryPoint.Builder _epb = ProtobufMessages.EntryPoint.newBuilder();
            _epb.setEntryPointId(wmep.getEntryPointId());

            writeObjectTypeConfiguration(context,
                    ((InternalWorkingMemoryEntryPoint) wmep).getObjectTypeConfigurationRegistry(),
                    _epb);

            writeFactHandles(context,
                    _epb,
                    ((NamedEntryPoint) wmep).getObjectStore());
            _ruleData.addEntryPoint(_epb.build());
        }

        writeActionQueue(context,
                _ruleData);

        writeTruthMaintenanceSystem(context,
                _ruleData);

        ProtobufMessages.KnowledgeSession.Builder _session = ProtobufMessages.KnowledgeSession.newBuilder()
                .setMultithread(multithread)
                .setTime(time)
                .setRuleData(_ruleData.build());

        if (processMarshaller != null) {
            Builder _pdata = ProtobufMessages.ProcessData.newBuilder();
            if (context.marshalProcessInstances) {
                context.parameterObject = _pdata;
                processMarshaller.writeProcessInstances(context);
            }

            if (context.marshalWorkItems) {
                context.parameterObject = _pdata;
                processMarshaller.writeWorkItems(context);
            }

            // this now just assigns the writer, it will not write out any timer information
            context.parameterObject = _pdata;
            processMarshaller.writeProcessTimers(context);

            _session.setProcessData(_pdata.build());
        }

        Timers _timers = writeTimers(context.wm.getTimerService().getTimerJobInstances(),
                context);
        if (_timers != null) {
            _session.setTimers(_timers);
        }

        if (multithread) {
            wm.startPartitionManagers();
        }

        return _session.build();
    }

    private static void writeObjectTypeConfiguration( MarshallerWriteContext context,
                                                      ObjectTypeConfigurationRegistry otcr,
                                                      org.drools.marshalling.impl.ProtobufMessages.EntryPoint.Builder _epb ) {

        Collection<ObjectTypeConf> values = otcr.values();
        ObjectTypeConf[] otcs = values.toArray( new ObjectTypeConf[ values.size() ] );
        Arrays.sort( otcs,
                new Comparator<ObjectTypeConf>() {
                    public int compare(ObjectTypeConf o1, ObjectTypeConf o2) {
                        return o1.getTypeName().compareTo(o2.getTypeName());
                    }
                });
        for( ObjectTypeConf otc : otcs ) {
            final ObjectTypeNodeMemory memory = (ObjectTypeNodeMemory) context.wm.getNodeMemory(otc.getConcreteObjectTypeNode());
            if (memory != null && !memory.memory.isEmpty()) {
                ObjectTypeConfiguration _otc = ObjectTypeConfiguration.newBuilder()
                        .setType(otc.getTypeName())
                        .setTmsEnabled(otc.isTMSEnabled())
                        .build();
                _epb.addOtc(_otc);
            }
        }
    }

    private static void writeAgenda(MarshallerWriteContext context,
            ProtobufMessages.RuleData.Builder _ksb) throws IOException {
        InternalWorkingMemory wm = context.wm;
        DefaultAgenda agenda = (DefaultAgenda) wm.getAgenda();

        org.drools.marshalling.impl.ProtobufMessages.Agenda.Builder _ab = ProtobufMessages.Agenda.newBuilder();

        AgendaGroup[] agendaGroups = (AgendaGroup[]) agenda.getAgendaGroupsMap().values().toArray(new AgendaGroup[agenda.getAgendaGroupsMap().size()]);
        Arrays.sort(agendaGroups,
                AgendaGroupSorter.instance);
        for (AgendaGroup group : agendaGroups) {
            org.drools.marshalling.impl.ProtobufMessages.Agenda.AgendaGroup.Builder _agb = ProtobufMessages.Agenda.AgendaGroup.newBuilder();
            _agb.setName(group.getName());
            _agb.setIsActive(group.isActive());
            _ab.addAgendaGroup(_agb.build());

        }

        org.drools.marshalling.impl.ProtobufMessages.Agenda.FocusStack.Builder _fsb = ProtobufMessages.Agenda.FocusStack.newBuilder();
        LinkedList<AgendaGroup> focusStack = agenda.getStackList();
        for (Iterator<AgendaGroup> it = focusStack.iterator(); it.hasNext();) {
            AgendaGroup group = it.next();
            _fsb.addGroupName(group.getName());
        }
        _ab.setFocusStack(_fsb.build());

        RuleFlowGroupImpl[] ruleFlowGroups = (RuleFlowGroupImpl[]) agenda.getRuleFlowGroupsMap().values().toArray(new RuleFlowGroupImpl[agenda.getRuleFlowGroupsMap().size()]);
        Arrays.sort(ruleFlowGroups,
                RuleFlowGroupSorter.instance);
        for (RuleFlowGroupImpl group : ruleFlowGroups) {
            org.drools.marshalling.impl.ProtobufMessages.Agenda.RuleFlowGroup.Builder _rfgb = ProtobufMessages.Agenda.RuleFlowGroup.newBuilder();
            _rfgb.setName(group.getName());
            _rfgb.setIsActive(group.isActive());
            _rfgb.setIsAutoDeactivate(group.isAutoDeactivate());

            Map<Long, String> nodeInstances = group.getNodeInstances();
            for (Map.Entry<Long, String> entry : nodeInstances.entrySet()) {
                org.drools.marshalling.impl.ProtobufMessages.Agenda.RuleFlowGroup.NodeInstance.Builder _nib = ProtobufMessages.Agenda.RuleFlowGroup.NodeInstance.newBuilder();
                _nib.setProcessInstanceId(entry.getKey());
                _nib.setNodeInstanceId(entry.getValue());
                _rfgb.addNodeInstance(_nib.build());
            }
            _ab.addRuleFlowGroup(_rfgb.build());
        }

        // serialize all dormant activations
        ActivationIterator it = ActivationIterator.iterator(wm);
        List<org.drools.spi.Activation> dormant = new ArrayList<org.drools.spi.Activation>();
        for (org.drools.spi.Activation item = (org.drools.spi.Activation) it.next(); item != null; item = (org.drools.spi.Activation) it.next()) {
            if (!item.isActive()) {
                dormant.add(item);
            }
        }
        Collections.sort(dormant, ActivationsSorter.INSTANCE);
        for (org.drools.spi.Activation activation : dormant) {
            _ab.addActivation(writeActivation(context, (AgendaItem) activation));
        }

        _ksb.setAgenda(_ab.build());
    }

    private static void writeNodeMemories(MarshallerWriteContext context,
            ProtobufMessages.RuleData.Builder _ksb) throws IOException {
        InternalWorkingMemory wm = context.wm;
        NodeMemories memories = wm.getNodeMemories();
        // only some of the node memories require special serialization handling
        // so we iterate over all of them and process only those that require it
        for (int i = 0; i < memories.length(); i++) {
            Memory memory = memories.peekNodeMemory(i);
            // some nodes have no memory, so we need to check for nulls
            if (memory != null) {
                ProtobufMessages.NodeMemory _node = null;
                switch (memory.getNodeType()) {
                    case NodeTypeEnums.AccumulateNode: {
                        _node = writeAccumulateNodeMemory(i, memory);
                        break;
                    }
                    case NodeTypeEnums.RightInputAdapterNode: {
                        _node = writeRIANodeMemory(i, memory);
                        break;
                    }
                    case NodeTypeEnums.FromNode: {
                        _node = writeFromNodeMemory(i, memory);
                        break;
                    }
                    case NodeTypeEnums.QueryElementNode: {
                        _node = writeQueryElementNodeMemory(i, memory, wm);
                        break;
                    }
                }
                if (_node != null) {
                    // not all node memories require serialization
                    _ksb.addNodeMemory(_node);
                }
            }
        }

    }

    private static ProtobufMessages.NodeMemory writeAccumulateNodeMemory(final int nodeId,
            final Memory memory) {
        // for accumulate nodes, we need to store the ID of created (result) handles
        AccumulateMemory accmem = (AccumulateMemory) memory;
        if (accmem.betaMemory.getLeftTupleMemory().size() > 0) {
            ProtobufMessages.NodeMemory.AccumulateNodeMemory.Builder _accumulate = ProtobufMessages.NodeMemory.AccumulateNodeMemory.newBuilder();

            final org.drools.core.util.Iterator tupleIter = accmem.betaMemory.getLeftTupleMemory().iterator();
            for (LeftTuple leftTuple = (LeftTuple) tupleIter.next(); leftTuple != null; leftTuple = (LeftTuple) tupleIter.next()) {
                AccumulateContext accctx = (AccumulateContext) leftTuple.getObject();
                if (accctx.result != null) {
                    FactHandle _handle = ProtobufMessages.FactHandle.newBuilder()
                            .setId(accctx.result.getFactHandle().getId())
                            .setRecency(accctx.result.getFactHandle().getRecency())
                            .build();
                    _accumulate.addContext(
                            ProtobufMessages.NodeMemory.AccumulateNodeMemory.AccumulateContext.newBuilder()
                                    .setTuple(PersisterHelper.createTuple(leftTuple))
                                    .setResultHandle(_handle)
                                    .build());
                }
            }

            return ProtobufMessages.NodeMemory.newBuilder()
                    .setNodeId(nodeId)
                    .setNodeType(ProtobufMessages.NodeMemory.NodeType.ACCUMULATE)
                    .setAccumulate(_accumulate.build())
                    .build();
        }
        return null;
    }

    private static ProtobufMessages.NodeMemory writeRIANodeMemory(final int nodeId,
            final Memory memory) {
        // for RIA nodes, we need to store the ID of the created handles
        RIAMemory mem = (RIAMemory) memory;
        if (!mem.memory.isEmpty()) {
            ProtobufMessages.NodeMemory.RIANodeMemory.Builder _ria = ProtobufMessages.NodeMemory.RIANodeMemory.newBuilder();

            final org.drools.core.util.Iterator it = mem.memory.iterator();
            // iterates over all propagated handles and assert them to the new sink
            for (ObjectEntry entry = (ObjectEntry) it.next(); entry != null; entry = (ObjectEntry) it.next()) {
                LeftTuple leftTuple = (LeftTuple) entry.getKey();
                InternalFactHandle handle = (InternalFactHandle) entry.getValue();
                FactHandle _handle = ProtobufMessages.FactHandle.newBuilder()
                        .setId(handle.getId())
                        .setRecency(handle.getRecency())
                        .build();
                _ria.addContext(ProtobufMessages.NodeMemory.RIANodeMemory.RIAContext.newBuilder()
                        .setTuple(PersisterHelper.createTuple(leftTuple))
                        .setResultHandle(_handle)
                        .build());
            }

            return ProtobufMessages.NodeMemory.newBuilder()
                    .setNodeId(nodeId)
                    .setNodeType(ProtobufMessages.NodeMemory.NodeType.RIA)
                    .setRia(_ria.build())
                    .build();
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    private static ProtobufMessages.NodeMemory writeFromNodeMemory(final int nodeId,
            final Memory memory) {
        FromMemory fromMemory = (FromMemory) memory;

        if (fromMemory.betaMemory.getLeftTupleMemory().size() > 0) {
            ProtobufMessages.NodeMemory.FromNodeMemory.Builder _from = ProtobufMessages.NodeMemory.FromNodeMemory.newBuilder();

            final org.drools.core.util.Iterator tupleIter = fromMemory.betaMemory.getLeftTupleMemory().iterator();
            for (LeftTuple leftTuple = (LeftTuple) tupleIter.next(); leftTuple != null; leftTuple = (LeftTuple) tupleIter.next()) {
                Map<Object, RightTuple> matches = (Map<Object, RightTuple>) leftTuple.getObject();
                ProtobufMessages.NodeMemory.FromNodeMemory.FromContext.Builder _context = ProtobufMessages.NodeMemory.FromNodeMemory.FromContext.newBuilder()
                        .setTuple(PersisterHelper.createTuple(leftTuple));
                for (RightTuple rightTuple : matches.values()) {
                    FactHandle _handle = ProtobufMessages.FactHandle.newBuilder()
                            .setId(rightTuple.getFactHandle().getId())
                            .setRecency(rightTuple.getFactHandle().getRecency())
                            .build();
                    _context.addHandle(_handle);
                }
                _from.addContext(_context.build());
            }

            return ProtobufMessages.NodeMemory.newBuilder()
                    .setNodeId(nodeId)
                    .setNodeType(ProtobufMessages.NodeMemory.NodeType.FROM)
                    .setFrom(_from.build())
                    .build();
        }
        return null;
    }

    private static ProtobufMessages.NodeMemory writeQueryElementNodeMemory(final int nodeId,
            final Memory memory,
            final InternalWorkingMemory wm) {
        LeftTupleIterator it = LeftTupleIterator.iterator(wm, ((QueryElementNodeMemory) memory).node);

        ProtobufMessages.NodeMemory.QueryElementNodeMemory.Builder _query = ProtobufMessages.NodeMemory.QueryElementNodeMemory.newBuilder();
        for (LeftTuple leftTuple = (LeftTuple) it.next(); leftTuple != null; leftTuple = (LeftTuple) it.next()) {
            InternalFactHandle handle = (InternalFactHandle) leftTuple.getObject();
            FactHandle _handle = ProtobufMessages.FactHandle.newBuilder()
                    .setId(handle.getId())
                    .setRecency(handle.getRecency())
                    .build();

            ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext.Builder _context = ProtobufMessages.NodeMemory.QueryElementNodeMemory.QueryContext.newBuilder()
                    .setTuple(PersisterHelper.createTuple(leftTuple))
                    .setHandle(_handle);

            LeftTuple childLeftTuple = leftTuple.getFirstChild();
            while (childLeftTuple != null) {
                RightTuple rightParent = childLeftTuple.getRightParent();
                _context.addResult(ProtobufMessages.FactHandle.newBuilder()
                        .setId(rightParent.getFactHandle().getId())
                        .setRecency(rightParent.getFactHandle().getRecency())
                        .build());
                while (childLeftTuple != null && childLeftTuple.getRightParent() == rightParent) {
                    // skip to the next child that has a different right parent
                    childLeftTuple = childLeftTuple.getLeftParentNext();
                }
            }
            _query.addContext(_context.build());
        }

        return _query.getContextCount() > 0 ?
                ProtobufMessages.NodeMemory.newBuilder()
                        .setNodeId(nodeId)
                        .setNodeType(ProtobufMessages.NodeMemory.NodeType.QUERY_ELEMENT)
                        .setQueryElement(_query.build())
                        .build()
                : null;
    }

    private static class AgendaGroupSorter
            implements
            Comparator<AgendaGroup> {

        public static final AgendaGroupSorter instance = new AgendaGroupSorter();

        public int compare(AgendaGroup group1,
                AgendaGroup group2) {
            return group1.getName().compareTo(group2.getName());
        }
    }

    private static class RuleFlowGroupSorter
            implements
            Comparator<RuleFlowGroup> {

        public static final RuleFlowGroupSorter instance = new RuleFlowGroupSorter();

        public int compare(RuleFlowGroup group1,
                RuleFlowGroup group2) {
            return group1.getName().compareTo(group2.getName());
        }
    }

    public static void writeActionQueue(MarshallerWriteContext context,
            ProtobufMessages.RuleData.Builder _session) throws IOException {

        ReteooWorkingMemory wm = (ReteooWorkingMemory) context.wm;
        if (!wm.getActionQueue().isEmpty()) {
            ProtobufMessages.ActionQueue.Builder _queue = ProtobufMessages.ActionQueue.newBuilder();

            WorkingMemoryAction[] queue = wm.getActionQueue().toArray(new WorkingMemoryAction[wm.getActionQueue().size()]);
            for (int i = queue.length - 1; i >= 0; i--) {
                _queue.addAction(queue[i].serialize(context));
            }
            _session.setActionQueue(_queue.build());
        }
    }

    public static void writeTruthMaintenanceSystem(MarshallerWriteContext context,
            ProtobufMessages.RuleData.Builder _session) throws IOException {
        ObjectHashMap assertMap = context.wm.getTruthMaintenanceSystem().getAssertMap();
        ObjectHashMap justifiedMap = context.wm.getTruthMaintenanceSystem().getJustifiedMap();

        if (!assertMap.isEmpty() || !justifiedMap.isEmpty()) {
            EqualityKey[] keys = new EqualityKey[assertMap.size()];
            org.drools.core.util.Iterator it = assertMap.iterator();
            int i = 0;
            for (org.drools.core.util.ObjectHashMap.ObjectEntry entry = (org.drools.core.util.ObjectHashMap.ObjectEntry) it.next(); entry != null; entry = (org.drools.core.util.ObjectHashMap.ObjectEntry) it.next()) {
                EqualityKey key = (EqualityKey) entry.getKey();
                keys[i++] = key;
            }

            Arrays.sort(keys,
                    EqualityKeySorter.instance);

            ProtobufMessages.TruthMaintenanceSystem.Builder _tms = ProtobufMessages.TruthMaintenanceSystem.newBuilder();

            // write the assert map of Equality keys
            for (EqualityKey key : keys) {
                ProtobufMessages.EqualityKey.Builder _key = ProtobufMessages.EqualityKey.newBuilder();
                _key.setStatus(key.getStatus());
                _key.setHandleId(key.getFactHandle().getId());
                if (key.getOtherFactHandle() != null && !key.getOtherFactHandle().isEmpty()) {
                    for (InternalFactHandle handle : key.getOtherFactHandle()) {
                        _key.addOtherHandle(handle.getId());
                    }
                }
                _tms.addKey(_key.build());
            }

            it = justifiedMap.iterator();
            i = 0;
            for (org.drools.core.util.ObjectHashMap.ObjectEntry entry = (org.drools.core.util.ObjectHashMap.ObjectEntry) it.next(); entry != null; entry = (org.drools.core.util.ObjectHashMap.ObjectEntry) it.next()) {
                ProtobufMessages.Justification.Builder _justification = ProtobufMessages.Justification.newBuilder();
                _justification.setHandleId(((Integer) entry.getKey()).intValue());

                org.drools.core.util.LinkedList list = (org.drools.core.util.LinkedList) entry.getValue();
                for (LinkedListEntry node = (LinkedListEntry) list.getFirst(); node != null; node = (LinkedListEntry) node.getNext()) {
                    LogicalDependency dependency = (LogicalDependency) node.getObject();
                    org.drools.spi.Activation activation = dependency.getJustifier();
                    ProtobufMessages.Activation _activation = ProtobufMessages.Activation.newBuilder()
                            .setPackageName(activation.getRule().getPackage())
                            .setRuleName(activation.getRule().getName())
                            .setTuple(PersisterHelper.createTuple(activation.getTuple()))
                            .build();
                    _justification.addActivation(_activation);
                }
                _tms.addJustification(_justification.build());
            }
            _session.setTms(_tms.build());
        }
    }

    public static class EqualityKeySorter
            implements Comparator<EqualityKey> {

        public static final EqualityKeySorter instance = new EqualityKeySorter();

        public int compare(EqualityKey key1,
                EqualityKey key2) {
            return key1.getFactHandle().getId() - key2.getFactHandle().getId();
        }
    }

    private static void writeFactHandles(MarshallerWriteContext context,
            org.drools.marshalling.impl.ProtobufMessages.EntryPoint.Builder _epb,
            ObjectStore objectStore) throws IOException {
        ObjectMarshallingStrategyStore objectMarshallingStrategyStore = context.objectMarshallingStrategyStore;

        // Write out FactHandles
        for (InternalFactHandle handle : orderFacts(objectStore)) {
            ProtobufMessages.FactHandle _handle = writeFactHandle(context,
                    objectMarshallingStrategyStore,
                    handle);

            _epb.addHandle(_handle);
        }
    }

    private static ProtobufMessages.FactHandle writeFactHandle(MarshallerWriteContext context,
            ObjectMarshallingStrategyStore objectMarshallingStrategyStore,
            InternalFactHandle handle) throws IOException {
        ProtobufMessages.FactHandle.Builder _handle = ProtobufMessages.FactHandle.newBuilder();

        _handle.setType(getHandleType(handle));
        _handle.setId(handle.getId());
        _handle.setRecency(handle.getRecency());
        _handle.setEntryPoint( handle.getEntryPoint().getEntryPointId() );

        if (_handle.getType() == ProtobufMessages.FactHandle.HandleType.EVENT) {
            // is event
            EventFactHandle efh = (EventFactHandle) handle;
            _handle.setTimestamp(efh.getStartTimestamp());
            _handle.setDuration(efh.getDuration());
            _handle.setIsExpired(efh.isExpired());
            _handle.setActivationsCount(efh.getActivationsCount());
        }

        Object object = handle.getObject();

        if (object != null) {
            ObjectMarshallingStrategy strategy = objectMarshallingStrategyStore.getStrategyObject(object);

            Integer index = context.getStrategyIndex(strategy);
            _handle.setStrategyIndex(index.intValue());
            _handle.setObject(ByteString.copyFrom(strategy.marshal(context.strategyContext.get(strategy),
                    context,
                    object)));
        }

        return _handle.build();
    }

    private static ProtobufMessages.FactHandle.HandleType getHandleType(InternalFactHandle handle) {
        if (handle instanceof EventFactHandle) {
            return ProtobufMessages.FactHandle.HandleType.EVENT;
        } else if (handle instanceof QueryElementFactHandle) {
            return ProtobufMessages.FactHandle.HandleType.QUERY;
        } else if (handle.getObject() instanceof InitialFact) {
            return ProtobufMessages.FactHandle.HandleType.INITIAL_FACT;
        }
        return ProtobufMessages.FactHandle.HandleType.FACT;
    }

    public static InternalFactHandle[] orderFacts(ObjectStore objectStore) {
        // this method is just needed for testing purposes, to allow round tripping
        int size = objectStore.size();
        InternalFactHandle[] handles = new InternalFactHandle[size];
        int i = 0;
        for (Iterator<?> it = objectStore.iterateFactHandles(); it.hasNext();) {
            handles[i++] = (InternalFactHandle) it.next();
        }

        Arrays.sort(handles,
                new HandleSorter());

        return handles;
    }

    public static InternalFactHandle[] orderFacts(List<InternalFactHandle> handlesList) {
        // this method is just needed for testing purposes, to allow round tripping
        int size = handlesList.size();
        InternalFactHandle[] handles = handlesList.toArray(new InternalFactHandle[size]);
        Arrays.sort(handles,
                new HandleSorter());

        return handles;
    }

    public static class HandleSorter
            implements
            Comparator<InternalFactHandle> {

        public int compare(InternalFactHandle h1,
                InternalFactHandle h2) {
            return h1.getId() - h2.getId();
        }
    }

    public static class ActivationsSorter
            implements Comparator<org.drools.spi.Activation> {

        public static final ActivationsSorter INSTANCE = new ActivationsSorter();

        public int compare(org.drools.spi.Activation o1,
                org.drools.spi.Activation o2) {
            int result = o1.getRule().getName().compareTo(o2.getRule().getName());
            if (result == 0) {
                LeftTuple t1 = o1.getTuple();
                LeftTuple t2 = o2.getTuple();
                while (result == 0 && t1 != null && t2 != null) {
                    result = t1.getLastHandle().getId() - t2.getLastHandle().getId();
                    t1 = t1.getParent();
                    t2 = t2.getParent();
                }
            }
            return result;
        }
    }

    public static ProtobufMessages.Activation writeActivation(MarshallerWriteContext context,
            AgendaItem agendaItem) {
        ProtobufMessages.Activation.Builder _activation = ProtobufMessages.Activation.newBuilder();

        Rule rule = agendaItem.getRule();
        _activation.setPackageName(rule.getPackage());
        _activation.setRuleName(rule.getName());

        ProtobufMessages.Tuple.Builder _tb = ProtobufMessages.Tuple.newBuilder();
        for (LeftTuple entry = agendaItem.getTuple(); entry != null; entry = entry.getParent()) {
            InternalFactHandle handle = entry.getLastHandle();
            _tb.addHandleId(handle.getId());
        }
        _activation.setTuple(_tb.build());

        _activation.setSalience(agendaItem.getSalience());
        _activation.setIsActivated(agendaItem.isActivated());

        if (agendaItem.getActivationGroupNode() != null) {
            _activation.setActivationGroup(agendaItem.getActivationGroupNode().getActivationGroup().getName());
        }

        if (agendaItem.getFactHandle() != null) {
            _activation.setHandleId(agendaItem.getFactHandle().getId());
        }

        org.drools.core.util.LinkedList<LogicalDependency> list = agendaItem.getLogicalDependencies();
        if (list != null && !list.isEmpty()) {
            for (LogicalDependency node = list.getFirst(); node != null; node = node.getNext()) {
                _activation.addLogicalDependency(((InternalFactHandle) node.getJustified()).getId());
            }
        }
        return _activation.build();
    }

    private static ProtobufMessages.Timers writeTimers(Collection<TimerJobInstance> timers,
            MarshallerWriteContext outCtx) {
        if (!timers.isEmpty()) {
            List<TimerJobInstance> sortedTimers = new ArrayList<TimerJobInstance>(timers);
            Collections.sort(sortedTimers,
                    new Comparator<TimerJobInstance>() {

                        public int compare(TimerJobInstance o1,
                                TimerJobInstance o2) {
                            return (int) (o1.getJobHandle().getId() - o2.getJobHandle().getId());
                        }
                    });

            ProtobufMessages.Timers.Builder _timers = ProtobufMessages.Timers.newBuilder();
            for (TimerJobInstance timer : sortedTimers) {
                JobContext jctx = ((SelfRemovalJobContext) timer.getJobContext()).getJobContext();
                TimersOutputMarshaller writer = outCtx.writersByClass.get(jctx.getClass());
                Timer _timer = writer.serialize(jctx, outCtx);
                _timers.addTimer(_timer);
            }
            return _timers.build();
        }
        return null;
    }

    public static ProtobufMessages.Trigger writeTrigger(Trigger trigger,
            MarshallerWriteContext outCtx) {
        if (trigger instanceof CronTrigger) {
            CronTrigger cronTrigger = (CronTrigger) trigger;
            ProtobufMessages.Trigger.CronTrigger.Builder _cron = ProtobufMessages.Trigger.CronTrigger.newBuilder()
                    .setStartTime(cronTrigger.getStartTime().getTime())
                    .setRepeatLimit(cronTrigger.getRepeatLimit())
                    .setRepeatCount(cronTrigger.getRepeatCount())
                    .setCronExpression(cronTrigger.getCronEx().getCronExpression());
            if (cronTrigger.getEndTime() != null) {
                _cron.setEndTime(cronTrigger.getEndTime().getTime());
            }
            if (cronTrigger.getNextFireTime() != null) {
                _cron.setNextFireTime(cronTrigger.getNextFireTime().getTime());
            }
            if (cronTrigger.getCalendarNames() != null) {
                for (String calendarName : cronTrigger.getCalendarNames()) {
                    _cron.addCalendarName(calendarName);
                }
            }
            return ProtobufMessages.Trigger.newBuilder()
                    .setType(ProtobufMessages.Trigger.TriggerType.CRON)
                    .setCron(_cron.build())
                    .build();
        } else if (trigger instanceof IntervalTrigger) {
            IntervalTrigger intTrigger = (IntervalTrigger) trigger;
            ProtobufMessages.Trigger.IntervalTrigger.Builder _interval = ProtobufMessages.Trigger.IntervalTrigger.newBuilder()
                    .setStartTime(intTrigger.getStartTime().getTime())
                    .setRepeatLimit(intTrigger.getRepeatLimit())
                    .setRepeatCount(intTrigger.getRepeatCount())
                    .setPeriod(intTrigger.getPeriod());
            if (intTrigger.getEndTime() != null) {
                _interval.setEndTime(intTrigger.getEndTime().getTime());
            }
            if (intTrigger.getNextFireTime() != null) {
                _interval.setNextFireTime(intTrigger.getNextFireTime().getTime());
            }
            if (intTrigger.getCalendarNames() != null) {
                for (String calendarName : intTrigger.getCalendarNames()) {
                    _interval.addCalendarName(calendarName);
                }
            }
            return ProtobufMessages.Trigger.newBuilder()
                    .setType(ProtobufMessages.Trigger.TriggerType.INTERVAL)
                    .setInterval(_interval.build())
                    .build();
        } else if (trigger instanceof PointInTimeTrigger) {
            PointInTimeTrigger pinTrigger = (PointInTimeTrigger) trigger;
            return ProtobufMessages.Trigger.newBuilder()
                    .setType(ProtobufMessages.Trigger.TriggerType.POINT_IN_TIME)
                    .setPit(ProtobufMessages.Trigger.PointInTimeTrigger.newBuilder()
                            .setNextFireTime(pinTrigger.hasNextFireTime().getTime())
                            .build())
                    .build();
        }
        throw new RuntimeException("Unable to serialize Trigger for type: " + trigger.getClass());
    }
}
TOP

Related Classes of org.drools.marshalling.impl.ProtobufOutputMarshaller$RuleFlowGroupSorter

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.