org.protempa.SliceConsequence Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of protempa-framework Show documentation
Show all versions of protempa-framework Show documentation
Protempa Framework is the core of Protempa.
/*
* #%L
* Protempa Framework
* %%
* Copyright (C) 2012 - 2013 Emory University
* %%
* 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.
* #L%
*/
package org.protempa;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
import org.drools.WorkingMemory;
import org.drools.spi.Consequence;
import org.drools.spi.KnowledgeHelper;
import org.protempa.proposition.AbstractParameter;
import org.protempa.proposition.Proposition;
import org.protempa.proposition.ProviderBasedUniqueIdFactory;
import org.protempa.proposition.Segment;
import org.protempa.proposition.Sequence;
import org.protempa.proposition.TemporalProposition;
import org.protempa.proposition.UniqueIdFactory;
/**
* The consequence part of a rule for computing a temporal slice.
*
* @author Andrew Post
*/
final class SliceConsequence implements Consequence {
private static final long serialVersionUID = -7485083104777547624L;
private final SliceDefinition def;
private final PropositionCopier copier;
private final DerivationsBuilder derivationsBuilder;
/*
* A sublist index range for performing the slice. This will not necessarily
* be the same as the {@link SliceDefinition}'s index range. If the slice
* definition's min index is negative, the input propositions are sorted in
* reverse chronological order, and these two fields will store the index
* range to be sliced for the reversed propositions. See the constructor for
* the logic that is performed.
*/
private final int minIndex;
private final int maxIndex;
/*
* Whether or not to sort the propositions in reverse or forward
* chronological order. We don't just store the comparator to use because
* this class implements {@link Serializable} and the comparator may not be
* serializable.
*/
private final boolean reverse;
/*
* Whether or not the slice should be considered as a single merged interval
* spanning from the min index to the max index.
*/
private final boolean merged;
/**
* Constructs a consequence instance with a definition of the temporal slice
* to compute and a derivations builder for recording links between computed
* temporal slices and the intervals from which they were derived.
*
* @param def
* a {@link SliceDefinition} corresponding to this rule.
* @param listener
* a {@link DerivationsBuilder}.
*/
SliceConsequence(SliceDefinition def, DerivationsBuilder listener) {
assert def != null : "def cannot be null";
assert listener != null : "listener cannot be null";
this.def = def;
this.derivationsBuilder = listener;
int minInd = def.getMinIndex();
int maxInd = def.getMaxIndex();
if (minInd < 0) {
this.minIndex = -maxInd;
this.maxIndex = -minInd;
this.reverse = true;
} else {
this.minIndex = minInd;
this.maxIndex = maxInd;
this.reverse = false;
}
this.merged = def.isMergedInterval();
this.copier = new PropositionCopier(def.getPropositionId(), listener);
}
/**
* Called when there exist the minimum necessary number of intervals with
* the specified proposition id in order to compute the temporal slice
* corresponding to this rule.
*
* @param arg0
* a {@link KnowledgeHelper}
* @param arg1
* a {@link WorkingMemory}
*
* @see JBossRuleCreator
*/
@Override
public void evaluate(KnowledgeHelper arg0, WorkingMemory arg1) {
@SuppressWarnings("unchecked")
List pl = (List) arg0
.get(arg0.getDeclaration("result"));
Comparator comp;
if (this.reverse) {
comp = ProtempaUtil.REVERSE_TEMP_PROP_COMP;
} else {
comp = ProtempaUtil.TEMP_PROP_COMP;
}
Collections.sort(pl, comp);
this.copier.grab(arg1);
if (this.merged) {
mergedInterval(arg0, pl);
} else {
for (ListIterator itr = pl
.listIterator(this.minIndex); itr.hasNext()
&& itr.nextIndex() < this.maxIndex;) {
TemporalProposition o = itr.next();
o.accept(this.copier);
}
}
this.copier.release();
}
private void mergedInterval(KnowledgeHelper kh, List pl) {
JBossRulesDerivedLocalUniqueIdValuesProvider provider =
new JBossRulesDerivedLocalUniqueIdValuesProvider(kh.getWorkingMemory(), def.getPropositionId());
UniqueIdFactory factory = new ProviderBasedUniqueIdFactory(provider);
List slice = new ArrayList<>();
for (ListIterator itr = pl.listIterator(); itr
.hasNext() && itr.nextIndex() < this.maxIndex;) {
slice.add(itr.next());
}
Segment segment = new Segment<>(
new Sequence<>(def.getPropositionId(), slice));
AbstractParameter result = AbstractParameterFactory.getFromAbstraction(
def.getPropositionId(), factory.getInstance(), segment, slice, null, null, null, null);
kh.getWorkingMemory().insert(result);
for (Proposition p : segment) {
this.derivationsBuilder.propositionAsserted(p, result);
}
}
}