package org.jactr.core.production.request;
/*
* default logging
*/
import java.util.Collection;
import java.util.Collections;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.chunk.ISymbolicChunk;
import org.jactr.core.chunktype.IChunkType;
import org.jactr.core.model.IModel;
import org.jactr.core.production.VariableBindings;
import org.jactr.core.production.condition.CannotMatchException;
import org.jactr.core.production.condition.match.ChunkTypeMatchFailure;
import org.jactr.core.slot.ISlot;
/**
* request based on a chunktype and slot pattern. Predominantly used in
* specifying retrievals, but also chunktype based request from modules.
*
* @author harrison
*/
public class ChunkTypeRequest extends SlotBasedRequest
{
/**
* Logger definition
*/
static private final transient Log LOGGER = LogFactory
.getLog(ChunkTypeRequest.class);
private IChunkType _chunkType;
private int _hashCode = -1;
@SuppressWarnings("unchecked")
public ChunkTypeRequest(IChunkType chunkType)
{
this(chunkType, Collections.EMPTY_LIST);
}
public ChunkTypeRequest(IChunkType chunkType,
Collection<? extends ISlot> slots)
{
super(slots);
_chunkType = chunkType;
}
/**
* create a request that directly mirrors this chunk. All of its slots are
* turned directly into equality conditions.
*
* @param chunk
*/
public ChunkTypeRequest(IChunk chunk)
{
this(chunk.getSymbolicChunk().getChunkType(), chunk.getSymbolicChunk()
.getSlots());
}
@Override
public ChunkTypeRequest clone()
{
return new ChunkTypeRequest(_chunkType, _slots);
}
public IChunkType getChunkType()
{
return _chunkType;
}
/**
* same idea as {@link IRequest#bind(IModel, VariableBindings, boolean)}
*
* @param testChunk
* @param model
* @param bindings
* @return
* @throws CannotMatchException
*/
public int bind(IChunk testChunk, IModel model, VariableBindings bindings,
boolean iterativeCall) throws CannotMatchException
{
IChunkType chunkType = getChunkType();
if (chunkType != null && !testChunk.isA(chunkType))
throw new CannotMatchException(new ChunkTypeMatchFailure(chunkType,
testChunk));
ISymbolicChunk sChunk = testChunk.getSymbolicChunk();
return super.bind(model, sChunk.getName(), sChunk, bindings, iterativeCall);
}
/**
* NOTE: this is hideous inefficient
*
* @return
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
// TODO cache..
StringBuilder sb = new StringBuilder("[");
sb.append(_chunkType).append(":");
for (ISlot slot : getConditionalAndLogicalSlots())
sb.append(slot).append(" ");
sb.append("]");
return sb.toString();
}
@Override
public int hashCode()
{
if (_hashCode == -1)
return computeHashCode();
else
return _hashCode;
}
public void lockHash()
{
_hashCode = computeHashCode();
}
public int computeHashCode()
{
final int prime = 31;
int result = super.hashCode();
result = prime * result + (_chunkType == null ? 0 : _chunkType.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (!super.equals(obj)) return false;
if (getClass() != obj.getClass()) return false;
ChunkTypeRequest other = (ChunkTypeRequest) obj;
if (_chunkType == null)
{
if (other._chunkType != null) return false;
}
else if (!_chunkType.equals(other._chunkType)) return false;
return true;
}
}