/*
* Copyright 2011 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.chance.common;
import org.drools.chance.distribution.Distribution;
import org.drools.chance.distribution.DistributionStrategies;
/**
* Abstract class for the structures holding the imperfect information regarding a single bean's field.
*
* This structure mimics the field's value, actually storing a Distribution over that field's domain.
* i.e. if Person.age is the target field, this structure will e.g. hold one (or more) Distribution<Integer>.
* A Distribution maps one or more elements of that domain to an Degree. The semantics is determined on
* a case-by-case basis. For example, it may be a discrete probability distribution, or a fuzzy set (possibility
* distribution), or a basic mass assignment, etc...
*
* See ImperfectFieldImpl for the rationale and ImperfectHistoryField
*
*
*/
public abstract class AbstractImperfectField<T> implements ImperfectField<T> {
/**
* Reference to a Strategy class holding all the algorithms for the manipulation of this field's distribution
*/
protected DistributionStrategies<T> strategies;
/**
* Basic constructor
* @param strategies a reference to the Strategy class with the logic for handling this field's distribution
*/
public AbstractImperfectField(DistributionStrategies<T> strategies){
this.strategies = strategies;
}
/**
* "By value" setter. Creates a (degenerate) distribution with full degree assigned to the value
* @param value the value used to create a degenerate distribution
*/
public void setValue(T value) {
setValue(strategies.toDistribution(value));
}
public void setValue(T value, boolean update) {
setValue(strategies.toDistribution(value),update);
}
/**
* Setter. Overrides the previous distribution, if any)
* @param dist A distribution over a bean's field domain
*/
public void setValue(Distribution<T> dist) {
setValue(dist, isSet());
}
/**
* Setter
* @param dist A distribution over a bean's field domain
* @param update if true, the new distribution dist will be merged with the current distribution, according to
* this instance's strategies. If false, the new distribution will override the previous one.
*/
public abstract void setValue(Distribution<T> dist, boolean update);
/**
* Predicate.
* @return true if the current field has already been set, or is still to be initialized
*/
public abstract boolean isSet();
/**
* Getter
* @return converts the current distribution to a crisp value (according to the current strategies "toCrispValue").
* The value returned belongs to the same domain the distribution is defined on (e.g. an Distribution<String> will
* return a String when crispified)
*/
public T getCrisp(){
return strategies.toCrispValue(getCurrent());
}
/**
* Tries to access a "previous" value of this field. Every "set" operation on the field counts
* as a step.
*
* @param time a non-positive integer value.
* @return The value the field had before the last #time set operations, if possible.
* 0 corresponds to the current value.
* @throws IndexOutOfBoundsException
*/
public abstract Distribution<T> getPast(int time) throws IndexOutOfBoundsException;
/**
* @return the current distribution for this field
*/
public abstract Distribution<T> getCurrent();
/**
* Getter
* @return the current Strategies used to manipulate this field's distribution
*/
public DistributionStrategies<T> getStrategies() {
return strategies;
}
/**
* Setter.
* Do not change the strategy at runtime, unless you REALLY
* know what you're doing. So, no public API for this
* @param factory the new Strategies used to manipulate this field's distribution
*/
protected void setStrategies(DistributionStrategies<T> factory) {
this.strategies = factory;
}
/**
* updates the current distribution, merging it with the provided one, using the current strategies.
* Convenience method that calls "setValue" with update set to true
* @param fieldBit the new distribution to merge with the current one
*/
public void update(Distribution<T> fieldBit) {
this.setValue( fieldBit, true );
}
/**
* updates the current distribution, by converting the provided value into a (degenerate) distribution
* and merging it with the current one.
* (In many cases, this operation could still return a degenerate distribution centered on value)
* @param value the value to merge with the current distribution
*/
public void update(T value) {
this.update(strategies.toDistribution(value));
}
}