package jadex.rules.state.javaimpl;
import jadex.rules.state.OAVTypeModel;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
/**
* An object holding the state as
* OAV triples (object, attribute, value).
*/
public class OAVMixedWeakState extends OAVAbstractState
{
//-------- attributes --------
/** The objects table (oid -> content map). */
protected Map objects;
/** The weak objects (object id -> content map). */
protected Map weakobjects;
//-------- constructors --------
/**
* Create a new empty OAV state representation.
*/
public OAVMixedWeakState(OAVTypeModel tmodel)
{
super(tmodel);
this.objects = new LinkedHashMap();
this.weakobjects = new WeakHashMap();
// this.nocheck = true;
/* new Thread(new Runnable()
{
public void run()
{
int old_dsize = 0;
int old_wsize = 0;
int old_osize = 0;
int old_ousize = 0;
int old_psize = 0;
int old_rsize = 0;
int old_tsize = 0;
while(true)
{
try
{
Thread.sleep(10000);
}
catch(InterruptedException e)
{
}
// int dsize = deletedobjects.size();
int wsize = weakobjects.size();
// int osize = objects.size();
// int ousize = objectusages.size();
// int psize = pcls!=null ? pcls.size() : 0;
// int rsize = rootobjects.size();
// int tsize = types.size();
// if(dsize>old_dsize)
// System.out.println("dsize@"+OAVMixedWeakState.this.hashCode()+": "+dsize);
if(wsize!=old_wsize)
System.out.println("wsize@"+OAVMixedWeakState.this.hashCode()+": "+wsize);
// if(osize>old_osize)
// System.out.println("osize@"+OAVMixedWeakState.this.hashCode()+": "+osize);
// if(ousize>old_ousize)
// System.out.println("ousize@"+OAVMixedWeakState.this.hashCode()+": "+ousize);
// if(psize>old_psize)
// System.out.println("psize@"+OAVMixedWeakState.this.hashCode()+": "+psize);
// if(rsize>old_rsize)
// System.out.println("rsize@"+OAVMixedWeakState.this.hashCode()+": "+rsize);
// if(tsize>old_tsize)
// System.out.println("tsize@"+OAVMixedWeakState.this.hashCode()+": "+tsize);
// Calculate number of objects per type.
// Run on synchronizator to avoid concurrent modification.
Runnable cmd = new Runnable()
{
public void run()
{
// Sum up occurrences of types.
// final Map cnts = new HashMap();
// for(Iterator it=types.values().iterator(); it.hasNext(); )
// {
// Object type = it.next();
// Integer cnt = (Integer)cnts.get(type);
// if(cnt!=null)
// cnt = new Integer(cnt.intValue()+1);
// else
// cnt = new Integer(1);
// cnts.put(type, cnt);
// }
final Map cnts = new HashMap();
for(Iterator it=weakobjects.keySet().iterator(); it.hasNext(); )
{
Object id = it.next();
Object type = getType(id);
Integer cnt = (Integer)cnts.get(type);
if(cnt!=null)
cnt = new Integer(cnt.intValue()+1);
else
cnt = new Integer(1);
cnts.put(type, cnt);
}
// Sort types by number.
Map sorted = new TreeMap(new Comparator()
{
public int compare(Object t2, Object t1)
{
int ret = ((Integer)cnts.get(t1)).intValue() - ((Integer)cnts.get(t2)).intValue();
if(ret==0 && t1!=t2)
ret = t1.hashCode() - t2.hashCode();
return ret;
}
});
sorted.putAll(cnts);
if(cnts.size()>0)
System.out.println("objects@"+OAVMixedWeakState.this.hashCode()+": "+sorted);
// try
// {
// System.out.print("checkcyc[");
// List cycles = findCycle(weakobjects.keySet());
// if(cycles!=null && cycles.size()>0)
// System.out.println("WAHHHHHHHHHH: "+cycles);
// System.out.println("]");
// }
// catch(Exception e)
// {
// e.printStackTrace();
// }
}
};
if(synchronizator!=null)
synchronizator.invokeLater(cmd);
else
cmd.run();
// old_dsize = Math.max(old_dsize, dsize);
old_wsize = wsize;//Math.max(old_wsize, wsize);
// old_osize = Math.max(old_osize, osize);
// old_ousize = Math.max(old_ousize, ousize);
// old_psize = Math.max(old_psize, psize);
// old_rsize = Math.max(old_rsize, rsize);
// old_tsize = Math.max(old_tsize, tsize);
}
}
}).start();*/
}
/**
* Ultimately remove an object (oid), when there are no more external or internal references.
*/
protected void removeObject(Object id)
{
// #ifndef MIDP
assert nocheck || generator.isId(id);
// #endif
// Remove the object itself (needs to be done before removing its references to avoid recursion)
Map content = (Map)objects.remove(id);
weakobjects.put(id, content);
// objectspertype.remove(types.get(id), id);
if(content==null)
throw new RuntimeException("Object not found: "+id);
deletedobjects.put(id, content);
assert getObjectUsages(id)==null || getObjectUsages(id).isEmpty() : getObjectUsages(id);
objectusages.remove(id);
// type will be removed in notifyEventListeners()
}
//--------- methods --------
/**
* Add an external usage of a state object (oid). This prevents
* the oav object of being garbage collected as long
* as external references are present.
* @param id The oav object id.
* @param external The user object.
*/
public void addExternalObjectUsage(Object id, Object external)
{
// #ifndef MIDP
assert nocheck || generator.isId(id);
// #endif
}
/**
* Remove an external usage of a state object (oid). This allows
* the oav object of being garbage collected when no
* further external references and no internal references
* are present.
* @param id The oav object id.
* @param external The state external object.
*/
public void removeExternalObjectUsage(Object id, Object external)
{
// #ifndef MIDP
assert nocheck || generator.isId(id);
// #endif
}
/**
* Test if an object is externally used.
* @param id The id.
* @return True, if externally used.
*/
protected boolean isExternallyUsed(Object id)
{
return weakobjects.containsKey(id);
}
//-------- internal helper classes --------
/**
* Get an object map for its id.
* @param id The id.
* @return The object map.
*/
protected Map getObject0(Object id)
{
Map ret = super.getObject0(id);
if(ret==null)
ret = (Map)weakobjects.get(id);
return ret;
}
/**
* Test if reading the object (oid) is allowed.
* Reading is allowed on removed objects as long as there are external references.
* @param id The object (oid).
* @return True, if valid.
*/
protected boolean checkValidStateObjectRead(Object id)
{
// #ifndef MIDP
assert nocheck || generator.isId(id);
// #endif
return checkValidStateObject(id) || weakobjects.containsKey(id);
}
//-------- internal object handling --------
/**
* Internally create an object.
* @param id The id.
* @return The content map of the new object.
*/
protected Map internalCreateObject(Object id)
{
Map content = new LinkedHashMap();
objects.put(id, content);
return content;
}
/**
* Remove an object from the state objects.
* @param id The id.
* @return The content map of the object.
*/
protected Map internalRemoveObject(Object id)
{
return (Map)objects.remove(id);
}
/**
* Get the object content of an object.
* @param id The id.
* @return The content map of the object.
*/
protected Map internalGetObjectContent(Object id)
{
return (Map)objects.get(id);
}
/**
* Test if an object is contained in the state.
* @param id The id.
* @return True, if object is contained.
*/
protected boolean internalContainsObject(Object id)
{
return objects.containsKey(id);
}
/**
* Test how many object are contained in the state.
* @return The number of objects.
*/
protected int internalObjectsSize()
{
return objects.size();
}
/**
* Get a set of the internal state objects.
* @return A set of the state objects.
*/
protected Set internalGetObjects()
{
return objects.keySet();
}
}