blob: 26c17b95b4e6e71049cdea8704b1f2a240bdfc4f [file] [log] [blame]
/*
* 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();
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) {
for (ObjectTypeConf otc : otcr.values()) {
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.RightInputAdaterNode: {
_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());
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());
}
}