/*
* Created on Sep 21, 2004 Copyright (C) 2001-4, Anthony Harrison anh23@pitt.edu
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version. This library is distributed in the hope that it will be
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
* General Public License for more details. You should have received a copy of
* the GNU Lesser General Public License along with this library; if not, write
* to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
* 02111-1307 USA
*/
package org.jactr.core.slot;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jactr.core.buffer.IActivationBuffer;
import org.jactr.core.chunk.IChunk;
import org.jactr.core.chunktype.IChunkType;
import org.jactr.core.model.IModel;
import org.jactr.core.production.IProduction;
/**
* @author harrison TODO To change the template for this generated type comment
* go to Window - Preferences - Java - Code Style - Code Templates
*/
public class BasicSlot implements ISlot, Comparable<ISlot>
{
static private final transient Log LOGGER = LogFactory
.getLog(BasicSlot.class);
private Object _value;
private String _name;
/**
* we cache the toString representation since it will be called so frequently,
* however this creates a ton of strings that are actually relatively short
* lived, so we use references to hold onto it for a short term
*/
private Reference<String> _toString;
public BasicSlot(String name)
{
this(name, null);
}
public BasicSlot(String name, Object value)
{
setNameInternal(name);
setValueInternal(value);
}
public BasicSlot(ISlot slot)
{
this(slot.getName(), slot.getValue());
}
/**
* @see org.jactr.core.slot.ISlot#getValue()
*/
final public Object getValue()
{
return _value;
}
/**
* @see org.jactr.core.slot.ISlot#getName()
*/
final public String getName()
{
return _name;
}
/**
* @see org.jactr.core.slot.ISlot#equalValues(java.lang.Object)
*/
public boolean equalValues(Object test)
{
if (test instanceof ISlot) test = ((ISlot) test).getValue();
/*
* equalValues test==null returns true only if _value==null
*/
if (_value == null) if (test == null)
return true;
else
return false;
if (isVariableValue() && test != null)
return true;
else if (_value instanceof String && test instanceof String)
return ((String) _value).equalsIgnoreCase((String) test);
else
return _value.equals(test);
}
/**
* equality is only defined as equal names
*
* @see java.lang.Object#equals(java.lang.Object)
*/
/**
* @see org.jactr.core.utils.Duplicateable#duplicate()
*/
@Override
public BasicSlot clone()
{
return new BasicSlot(_name, _value);
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + (_name == null ? 0 : _name.hashCode());
result = prime * result + (_value == null ? 0 : _value.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
BasicSlot other = (BasicSlot) obj;
if (_name == null)
{
if (other._name != null) return false;
}
else if (!_name.equals(other._name)) return false;
if (_value == null)
{
if (other._value != null) return false;
}
else if (!_value.equals(other._value)) return false;
return true;
}
/**
* checks to see if the slot value is a variable. Three things must be true:<br>
* 1) the value must be a string <br>
* 2) it must start with "=" <br>
* 3) it must have no white spaces (so that resolvable strings such as "=chunk
* has been retrieved" can be resolved dynamically) <br>
*
* @see org.jactr.core.slot.IConditionalSlot#isVariable()
*/
public boolean isVariableValue()
{
Object value = getValue();
if (value instanceof String)
{
String str = (String) value;
return str.startsWith("=") && str.indexOf(' ') == -1;
}
return false;
}
@Deprecated
public boolean isVariable()
{
return isVariableValue();
}
/**
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(ISlot compSlot)
{
return getName().compareTo(compSlot.getName());
}
@Override
public String toString()
{
synchronized (this)
{
if (_toString == null)
_toString = new WeakReference<String>(createToString());
}
return _toString.get();
}
protected void clearToString()
{
synchronized (this)
{
_toString = null;
}
}
protected String createToString()
{
return String.format("%1$s(%2$s)", getName(), getValue());
}
/**
* set the value of the slot, returning the prior value
*
* @param value
* @return
*/
final protected Object setValueInternal(Object value)
{
if (value != null
&& !(value instanceof String || value instanceof Number
|| value instanceof Boolean || value instanceof StringBuilder /*
* SB
* is
* used
* internally
* during
* build
* phase
*/
|| value instanceof IChunk || value instanceof IChunkType
|| value instanceof IProduction || value instanceof IActivationBuffer || value instanceof IModel))
LOGGER
.warn(String
.format(
"Unexpected slot value found. Not critical, but could cause issues down the line. [%s : %s]",
value, value.getClass().getSimpleName()));
Object old = _value;
_value = value;
clearToString();
return old;
}
final protected Object setNameInternal(String name)
{
String old = _name;
_name = name;
clearToString();
return old;
}
}