/*
* Created on 13/12/2009 01:34:18
*/
package br.pucrio.inf.les.bdijade.core;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import br.pucrio.inf.les.bdijade.belief.Belief;
import br.pucrio.inf.les.bdijade.event.BeliefEvent;
import br.pucrio.inf.les.bdijade.event.BeliefListener;
import br.pucrio.inf.les.bdijade.event.BeliefEvent.Action;
import br.pucrio.inf.les.bdijade.exception.BeliefAlreadyExistsException;
/**
* This class represents a belief base of a capability. It aggregates its
* knowledge.
*
* @author ingrid
*/
public class BeliefBase implements Serializable {
private static final long serialVersionUID = -6411530721625492882L;
private final Set<BeliefListener> beliefListeners;
private final Map<String, Belief<?>> beliefs;
private Capability capability;
/**
* Creates a belief base.
*/
public BeliefBase() {
this(null);
}
/**
* Creates a belief base associated with a capability and adds the beliefs
* in the provided belief set.
*
* @param beliefs
* the initial beliefs
*/
public BeliefBase(Set<Belief<?>> beliefs) {
this.capability = null;
this.beliefListeners = new HashSet<BeliefListener>();
this.beliefs = new HashMap<String, Belief<?>>();
if (beliefs != null) {
for (Belief<?> belief : beliefs) {
addBelief(belief);
}
}
}
/**
* Adds a belief to the belief base.
*
* @param belief
* the belief to be added.
*/
public void addBelief(Belief<?> belief) {
if (!hasBelief(belief.getName())) {
belief.addBeliefBase(this);
this.beliefs.put(belief.getName(), belief);
notifyBeliefChanged(new BeliefEvent(belief, Action.BELIEF_ADDED));
} else {
throw new BeliefAlreadyExistsException(belief);
}
}
/**
* Adds a belief listener to be notified about changes in the belief base.
*
* @param beliefListener
* the listener to be added.
*/
public void addBeliefListener(BeliefListener beliefListener) {
this.beliefListeners.add(beliefListener);
}
/**
* Adds a belief to the belief base. It overrides a belief, if it already
* exists.
*
* @param belief
* the belief to be added or updated.
*/
public void addOrUpdateBelief(Belief<?> belief) {
if (hasBelief(belief.getName())) {
updateBelief(belief.getName(), belief.getValue());
} else {
addBelief(belief);
}
}
/**
* Retrieves a belief from the belief base.
*
* @param name
* the name of the belief to be retrieved.
* @return the belief. Null if no belief is found.
*/
public Belief<?> getBelief(String name) {
return this.beliefs.get(name);
}
/**
* @return the beliefListeners
*/
public Set<BeliefListener> getBeliefListeners() {
return beliefListeners;
}
/**
* @return the beliefs
*/
public Set<Belief<?>> getBeliefs() {
Set<Belief<?>> beliefValues = new HashSet<Belief<?>>(beliefs.size());
for (Belief<?> belief : beliefs.values())
beliefValues.add(belief);
return beliefValues;
}
/**
* Return a list of all belief values from this belief base.
*
* @return the beliefValues
*/
public List<Object> getBeliefValues() {
List<Object> beliefValues = new ArrayList<Object>(beliefs.size());
for (Belief<?> belief : beliefs.values())
beliefValues.add(belief.getValue());
return beliefValues;
}
/**
* @return the capability
*/
public Capability getCapability() {
return capability;
}
/**
* Checks if a belief is part of the belief base.
*
* @param name
* the belief to be checked
* @return true if the belief base contains the belief.
*/
public boolean hasBelief(String name) {
return this.beliefs.containsKey(name);
}
/**
* Initialize the belief base, adding initial beliefs.
*/
protected void init() {
}
/**
* Notifies the capability associate with this BeliefBase that a belief was
* modified.
*
* @param beliefChanged
* the belief that was changed
*/
private void notifyBeliefChanged(BeliefEvent beliefChanged) {
for (BeliefListener beliefListener : beliefListeners) {
beliefListener.update(beliefChanged);
}
}
/**
* Removes a belief from the belief base.
*
* @param name
* the name of the belief to be removed.
* @return the belief was removed, null if it is not part of the belief
* base.
*/
public Belief<?> removeBelief(String name) {
Belief<?> belief = this.beliefs.remove(name);
if (belief != null) {
belief.removeBeliefBase(this);
notifyBeliefChanged(new BeliefEvent(belief, Action.BELIEF_REMOVED));
}
return belief;
}
/**
* Removes a belief listener.
*
* @param beliefListener
* the listener to be removed.
*/
public void removeBeliefListener(BeliefListener beliefListener) {
this.beliefListeners.remove(beliefListener);
}
/**
* This method is an empty place holder for subclasses. It may be invoked to
* review beliefs from this belief base.
*/
public void reviewBeliefs() {
}
/**
* Sets the capability of this belief base. If the capability was already
* set, it throws a {@link RuntimeException}. After setting the capability,
* the {@link #init()} method is invoked.
*
* @param capability
* the capability to set
*/
public void setCapability(Capability capability) {
if (this.capability != null) {
throw new RuntimeException(
"BeliefBase already binded to another capability!");
}
this.capability = capability;
this.init();
}
/**
* Gets the size of this belief base (the number of beliefs).
*
* @return the size of this belief base.
*/
public int size() {
return this.beliefs.size();
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return new StringBuffer("BeliefBase = ").append(this.getBeliefs())
.toString();
}
/**
* Update the value of a belief in the belief base. In case the belief is
* not present in the belief base, nothing is performed and the method
* returns false. If the type of the new value being provided, it is still
* going to subscribe the previous value.
*
* @param name
* the belief to be updated.
* @param value
* the new value to the belief.
* @return true if the belief was update.
*/
@SuppressWarnings("unchecked")
public boolean updateBelief(String name, Object value) {
Belief belief = this.beliefs.get(name);
if (belief == null) {
return false;
}
Object oldValue = belief.getValue();
belief.setValue(value);
notifyBeliefChanged(new BeliefEvent(belief, Action.BELIEF_UPDATED,
oldValue));
return true;
}
}