package jadex.application.space.envsupport.environment;
import jadex.application.model.MComponentType;
import jadex.application.model.MSpaceInstance;
import jadex.application.runtime.IApplication;
import jadex.application.runtime.ISpace;
import jadex.application.space.envsupport.IObjectCreator;
import jadex.application.space.envsupport.MEnvSpaceInstance;
import jadex.application.space.envsupport.MEnvSpaceType;
import jadex.application.space.envsupport.MObjectType;
import jadex.application.space.envsupport.MObjectTypeProperty;
import jadex.application.space.envsupport.dataview.IDataView;
import jadex.application.space.envsupport.environment.ComponentActionList.ActionEntry;
import jadex.application.space.envsupport.environment.space2d.Space2D;
import jadex.application.space.envsupport.evaluation.DefaultDataProvider;
import jadex.application.space.envsupport.evaluation.IObjectSource;
import jadex.application.space.envsupport.evaluation.ITableDataConsumer;
import jadex.application.space.envsupport.evaluation.ITableDataProvider;
import jadex.application.space.envsupport.evaluation.SpaceObjectSource;
import jadex.application.space.envsupport.math.Vector2Double;
import jadex.application.space.envsupport.observer.gui.ObserverCenter;
import jadex.application.space.envsupport.observer.perspective.IPerspective;
import jadex.bridge.CreationInfo;
import jadex.bridge.IComponentDescription;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.ICMSComponentListener;
import jadex.bridge.IComponentManagementService;
import jadex.commons.IFuture;
import jadex.commons.IPropertyObject;
import jadex.commons.ThreadSuspendable;
import jadex.commons.collection.MultiCollection;
import jadex.commons.concurrent.DefaultResultListener;
import jadex.commons.concurrent.IResultListener;
import jadex.commons.meta.IPropertyMetaDataSet;
import jadex.commons.service.SServiceProvider;
import jadex.commons.service.library.ILibraryService;
import jadex.javaparser.IParsedExpression;
import jadex.javaparser.IValueFetcher;
import jadex.javaparser.SimpleValueFetcher;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* Abstract base class for environment space.
*/
public abstract class AbstractEnvironmentSpace extends SynchronizedPropertyObject implements IEnvironmentSpace, ISpace
{
//-------- attributes --------
/** The space name. */
protected String name;
/** The context. */
protected IApplication application;
/** The space object types. */
protected Map objecttypes;
/** The space object meta data **/
protected Map objecttypesMeta;
/** The object task types. */
protected Map tasktypes;
/** The space process types. */
protected Map processtypes;
/** The percepttypes. */
protected Map percepttypes;
/** Available component actions. */
protected Map actions;
/** The percept generators. */
protected Map perceptgenerators;
/** The percept processors. */
protected MultiCollection perceptprocessors;
/** Avatar mappings. */
protected MultiCollection avatarmappings;
/** Initial avatar settings (aid -> [type, props]). */
protected Map initialavatars;
/** Data view mappings. */
protected MultiCollection dataviewmappings;
/** The environment processes. */
protected Map processes;
/** Long/ObjectIDs (keys) and environment objects (values). */
protected Map spaceobjects;
/** Types of EnvironmentObjects and lists of EnvironmentObjects of that type (typed view). */
protected Map spaceobjectsbytype;
protected Map spaceobjectsbyowner;
/** Object id counter for new ids. */
protected AtomicCounter objectidcounter;
/** Task id counter for new ids. */
protected AtomicCounter taskidcounter;
/** The list of scheduled component actions. */
protected ComponentActionList actionlist;
/** The list of scheduled percepts. */
protected PerceptList perceptlist;
/** Available views */
protected Map views;
/** The environment listeners. */
protected List listeners;
/** The fetcher. */
protected SimpleValueFetcher fetcher;
/** The data providers (name -> provider). */
protected Map dataproviders;
/** The data consumers. */
protected Map dataconsumers;
/** The zombie objects. */
protected Map zombieobjects;
//-------- constructors --------
/**
* Create an environment space
*/
public AbstractEnvironmentSpace()
{
super(null, new Object());
this.views = new HashMap();
this.avatarmappings = new MultiCollection();
this.dataviewmappings = new MultiCollection();
this.actions = new HashMap();
this.processtypes = new HashMap();
this.tasktypes = new HashMap();
this.processes = new HashMap();
this.percepttypes = new HashMap();
this.perceptgenerators = new HashMap();
this.perceptprocessors = new MultiCollection();
this.objecttypes = new HashMap();
this.objecttypesMeta = new HashMap();
this.spaceobjects = new HashMap();
this.zombieobjects = new HashMap();
this.spaceobjectsbytype = new HashMap();
this.spaceobjectsbyowner = new HashMap();
this.objectidcounter = new AtomicCounter();
this.taskidcounter = new AtomicCounter();
this.actionlist = new ComponentActionList(this);
this.perceptlist = new PerceptList(this);
this.dataproviders = new HashMap();
this.dataconsumers = new HashMap();
}
/**
* Create a space.
*/
public void initSpace(final IApplication context, MSpaceInstance config, IValueFetcher pfetcher) throws Exception
{
MEnvSpaceInstance si = (MEnvSpaceInstance)config;
final MEnvSpaceType mspacetype = (MEnvSpaceType)config.getType();
final SimpleValueFetcher fetcher = new SimpleValueFetcher(pfetcher);
fetcher.setValue("$space", this);
this.setFetcher(fetcher);
List mspaceprops = mspacetype.getPropertyList("properties");
MEnvSpaceInstance.setProperties(this, mspaceprops, fetcher);
List spaceprops = si.getPropertyList("properties");
MEnvSpaceInstance.setProperties(this, spaceprops, fetcher);
this.application = context;
if(this instanceof Space2D) // Hack?
{
Double width = si.getProperty("width")!=null? (Double)si.getProperty("width"): (Double)mspacetype.getProperty("width");
Double height = si.getProperty("height")!=null? (Double)si.getProperty("height"): (Double)mspacetype.getProperty("height");
((Space2D)this).setAreaSize(Vector2Double.getVector2(width, height));
// System.out.println("areasize: "+width+" "+height);
}
// Create space object types.
List objecttypes = mspacetype.getPropertyList("objecttypes");
if(objecttypes!=null)
{
for(int i=0; i<objecttypes.size(); i++)
{
MObjectType mobjecttype = (MObjectType)objecttypes.get(i);
// List props = (List)mobjecttype.get("properties");
// Map properties = null;
// if(props!=null)
// {
// properties = new LinkedHashMap();
// Map propertiesMetaData = new HashMap();
// for(int j=0; j<props.size(); j++)
// {
// Map prop = (Map)props.get(j);
// properties.put(prop.get("name"), prop);
// }
// }
// Map properties = convertProperties(props, fetcher);
// System.out.println("Adding environment object type: "+(String)getProperty(mobjecttype, "name")+" "+props);
// for(Iterator it = mobjecttype.iterator(); it.hasNext();)
// System.out.println(((MObjectTypeProperty)it.next()).getType());
this.addSpaceObjectType(mobjecttype.getName(), mobjecttype);
}
}
// Add avatar mappings.
List avmappings = mspacetype.getPropertyList("avatarmappings");
if(avmappings!=null)
{
for(int i=0; i<avmappings.size(); i++)
{
AvatarMapping mapping = (AvatarMapping)avmappings.get(i);
// String componenttype = (String)MEnvSpaceInstance.getProperty(mmapping, "componenttype");
// String avatartype = (String)(String)MEnvSpaceInstance.getProperty(mmapping, "objecttype");
// Boolean createavatar = (Boolean)MEnvSpaceInstance.getProperty(mmapping, "createavatar");
// Boolean createcomponent = (Boolean)MEnvSpaceInstance.getProperty(mmapping, "createcomponent");
// Boolean killavatar = (Boolean)MEnvSpaceInstance.getProperty(mmapping, "killavatar");
// Boolean killcomponent = (Boolean)MEnvSpaceInstance.getProperty(mmapping, "killcomponent");
//
// AvatarMapping mapping = new AvatarMapping(componenttype, avatartype);
// if(createavatar!=null)
// mapping.setCreateAvatar(createavatar.booleanValue());
// if(createcomponent!=null)
// mapping.setCreateComponent(createcomponent.booleanValue());
// if(killavatar!=null)
// mapping.setKillAvatar(killavatar.booleanValue());
// if(killcomponent!=null)
// mapping.setKillComponent(killcomponent.booleanValue());
//
this.addAvatarMappings(mapping);
}
}
// Create space percept types.
List percepttypes = mspacetype.getPropertyList("percepttypes");
if(percepttypes!=null)
{
for(int i=0; i<percepttypes.size(); i++)
{
Map mpercepttype = (Map)percepttypes.get(i);
PerceptType pt = new PerceptType();
pt.setName((String)MEnvSpaceInstance.getProperty(mpercepttype, "name"));
List atypes = (List)mpercepttype.get("componenttypes");
pt.setComponentTypes(atypes==null? null: new HashSet(atypes));
List otypes = (List)mpercepttype.get("objecttypes");
pt.setObjectTypes(otypes==null? null: new HashSet(otypes));
// System.out.println("Adding environment percept type: "+pt);
this.addPerceptType(pt);
}
}
// Create space actions.
List spaceactions = mspacetype.getPropertyList("actiontypes");
if(spaceactions!=null)
{
for(int i=0; i<spaceactions.size(); i++)
{
Map maction = (Map)spaceactions.get(i);
ISpaceAction action = (ISpaceAction)((Class)MEnvSpaceInstance.getProperty(maction, "clazz")).newInstance();
List props = (List)maction.get("properties");
MEnvSpaceInstance.setProperties(action, props, fetcher);
// System.out.println("Adding environment action: "+MEnvSpaceInstance.getProperty(maction, "name"));
this.addSpaceAction((String)MEnvSpaceInstance.getProperty(maction, "name"), action);
}
}
// Create process types.
List processtypes = mspacetype.getPropertyList("processtypes");
if(processtypes!=null)
{
for(int i=0; i<processtypes.size(); i++)
{
Map mprocess = (Map)processtypes.get(i);
// ISpaceProcess process = (ISpaceProcess)((Class)MEnvSpaceInstance.getProperty(mprocess, "clazz")).newInstance();
List props = (List)mprocess.get("properties");
String name = (String)MEnvSpaceInstance.getProperty(mprocess, "name");
Class clazz = (Class)MEnvSpaceInstance.getProperty(mprocess, "clazz");
// System.out.println("Adding environment process: "+MEnvSpaceInstance.getProperty(mprocess, "name"));
this.addSpaceProcessType(name, clazz, props);
}
}
// Create task types.
List tasks = mspacetype.getPropertyList("tasktypes");
if(tasks!=null)
{
for(int i=0; i<tasks.size(); i++)
{
Map mtask = (Map)tasks.get(i);
List props = (List)mtask.get("properties");
String name = (String)MEnvSpaceInstance.getProperty(mtask, "name");
Class clazz = (Class)MEnvSpaceInstance.getProperty(mtask, "clazz");
// System.out.println("Adding object task: "+MEnvSpaceInstance.getProperty(mtask, "name"));
this.addObjectTaskType(name, clazz, props);
}
}
// Create percept generators.
List gens = mspacetype.getPropertyList("perceptgenerators");
if(gens!=null)
{
for(int i=0; i<gens.size(); i++)
{
Map mgen = (Map)gens.get(i);
IPerceptGenerator gen = (IPerceptGenerator)((Class)MEnvSpaceInstance.getProperty(mgen, "clazz")).newInstance();
List props = (List)mgen.get("properties");
MEnvSpaceInstance.setProperties(gen, props, fetcher);
// System.out.println("Adding environment percept generator: "+MEnvSpaceInstance.getProperty(mgen, "name"));
this.addPerceptGenerator(MEnvSpaceInstance.getProperty(mgen, "name"), gen);
}
}
// Create percept processors.
List pmaps = mspacetype.getPropertyList("perceptprocessors");
if(pmaps!=null)
{
for(int i=0; i<pmaps.size(); i++)
{
Map mproc = (Map)pmaps.get(i);
IPerceptProcessor proc = (IPerceptProcessor)((Class)MEnvSpaceInstance.getProperty(mproc, "clazz")).newInstance();
List props = (List)mproc.get("properties");
MEnvSpaceInstance.setProperties(proc, props, fetcher);
String componenttype = (String)MEnvSpaceInstance.getProperty(mproc, "componenttype");
List ptypes = (List)mproc.get("percepttypes");
this.addPerceptProcessor(componenttype, ptypes==null? null: new HashSet(ptypes), proc);
}
}
// Create initial objects.
List objects = (List)si.getPropertyList("objects");
if(objects!=null)
{
for(int i=0; i<objects.size(); i++)
{
Map mobj = (Map)objects.get(i);
List mprops = (List)mobj.get("properties");
int num = 1;
if(mobj.containsKey("number"))
{
num = ((Number)MEnvSpaceInstance.getProperty(mobj, "number")).intValue();
}
for(int j=0; j<num; j++)
{
fetcher.setValue("$number", new Integer(j));
Map props = MEnvSpaceInstance.convertProperties(mprops, fetcher);
this.createSpaceObject((String)MEnvSpaceInstance.getProperty(mobj, "type"), props, null);
}
}
}
// Register initial avatars
List avatars = (List)si.getPropertyList("avatars");
if(avatars!=null)
{
for(int i=0; i<avatars.size(); i++)
{
Map mobj = (Map)avatars.get(i);
List mprops = (List)mobj.get("properties");
String owner = (String)MEnvSpaceInstance.getProperty(mobj, "owner");
if(owner==null)
throw new RuntimeException("Attribute 'owner' required for avatar: "+mobj);
IComponentIdentifier ownerid = null;
IComponentManagementService ces = ((IComponentManagementService)SServiceProvider.getServiceUpwards
(context.getServiceProvider(), IComponentManagementService.class).get(new ThreadSuspendable()));
if(owner.indexOf("@")!=-1)
ownerid = ces.createComponentIdentifier((String)owner, false);
else
ownerid = ces.createComponentIdentifier((String)owner, true);
Map props = MEnvSpaceInstance.convertProperties(mprops, fetcher);
this.addInitialAvatar(ownerid, (String)MEnvSpaceInstance.getProperty(mobj, "type"), props);
}
}
// Create initial processes.
List procs = (List)si.getPropertyList("processes");
if(procs!=null)
{
for(int i=0; i<procs.size(); i++)
{
Map mproc = (Map)procs.get(i);
List mprops = (List)mproc.get("properties");
Map props = MEnvSpaceInstance.convertProperties(mprops, fetcher);
this.createSpaceProcess((String)MEnvSpaceInstance.getProperty(mproc, "type"), props);
// System.out.println("Create space process: "+MEnvSpaceInstance.getProperty(mproc, "type"));
}
}
// Create initial space actions.
List actions = (List)si.getPropertyList("spaceactions");
if(actions!=null)
{
for(int i=0; i<actions.size(); i++)
{
Map action = (Map)actions.get(i);
List ps = (List)action.get("parameters");
Map params = null;
if(ps!=null)
{
params = new HashMap();
for(int j=0; j<ps.size(); j++)
{
Map param = (Map)ps.get(j);
IParsedExpression exp = (IParsedExpression)param.get("value");
params.put(param.get("name"), exp.getValue(fetcher));
}
}
// System.out.println("Performing initial space action: "+getProperty(action, "type"));
this.performSpaceAction((String)MEnvSpaceInstance.getProperty(action, "type"), params);
}
}
// Map themes = new HashMap();
List sourceviews = mspacetype.getPropertyList("dataviews");
if(sourceviews!=null)
{
for(int i=0; i<sourceviews.size(); i++)
{
Map sourceview = (Map)sourceviews.get(i);
if(MEnvSpaceInstance.getProperty(sourceview, "objecttype")==null)
{
Map viewargs = new HashMap();
viewargs.put("sourceview", sourceview);
viewargs.put("space", this);
IDataView view = (IDataView)((IObjectCreator)MEnvSpaceInstance.getProperty(sourceview, "creator")).createObject(viewargs);
this.addDataView((String)MEnvSpaceInstance.getProperty(sourceview, "name"), view);
}
else
{
this.addDataViewMapping((String)MEnvSpaceInstance.getProperty(sourceview, "objecttype"), sourceview);
}
}
}
// Create the data providers.
List providers = mspacetype.getPropertyList("dataproviders");
List tmp = si.getPropertyList("dataproviders");
if(providers==null && tmp!=null)
providers = tmp;
else if(providers!=null && tmp!=null)
providers.addAll(tmp);
// System.out.println("data providers: "+providers);
if(providers!=null)
{
for(int i=0; i<providers.size(); i++)
{
Map dcol = (Map)providers.get(i);
List sources = (List)dcol.get("source");
IObjectSource[] provs = new IObjectSource[sources.size()];
for(int j=0; j<sources.size(); j++)
{
Map source = (Map)sources.get(j);
String varname = source.get("name")!=null? (String)source.get("name"): "$object";
String objecttype = (String)source.get("objecttype");
boolean aggregate = source.get("aggregate")!=null? ((Boolean)source.get("aggregate")).booleanValue(): false;
IParsedExpression dataexp = (IParsedExpression)source.get("content");
IParsedExpression includeexp = (IParsedExpression)source.get("includecondition");
provs[j] = new SpaceObjectSource(varname, this, objecttype, aggregate, dataexp, includeexp);
}
String tablename = (String)MEnvSpaceInstance.getProperty(dcol, "name");
List subdatas = (List)dcol.get("data");
String[] columnnames = new String[subdatas.size()];
IParsedExpression[] exps = new IParsedExpression[subdatas.size()];
for(int j=0; j<subdatas.size(); j++)
{
Map subdata = (Map)subdatas.get(j);
columnnames[j] = (String)MEnvSpaceInstance.getProperty(subdata, "name");
exps[j] = (IParsedExpression)MEnvSpaceInstance.getProperty(subdata, "content");
}
ITableDataProvider tprov = new DefaultDataProvider(this, provs, tablename, columnnames, exps);
this.addDataProvider(tablename, tprov);
}
}
// Create the data consumers.
List consumers = mspacetype.getPropertyList("dataconsumers");
tmp = si.getPropertyList("dataconsumers");
if(consumers==null && tmp!=null)
consumers = tmp;
else if(consumers!=null && tmp!=null)
consumers.addAll(tmp);
// System.out.println("data consumers: "+consumers);
if(consumers!=null)
{
for(int i=0; i<consumers.size(); i++)
{
Map dcon = (Map)consumers.get(i);
String name = (String)MEnvSpaceInstance.getProperty(dcon, "name");
Class clazz = (Class)MEnvSpaceInstance.getProperty(dcon, "class");
ITableDataConsumer con = (ITableDataConsumer)clazz.newInstance();
MEnvSpaceInstance.setProperties(con, (List)dcon.get("properties"), fetcher);
con.setProperty("envspace", this);
this.addDataConsumer(name, con);
}
}
List observers = si.getPropertyList("observers");
if(observers!=null)
{
for(int i=0; i<observers.size(); i++)
{
Map observer = (Map)observers.get(i);
final String title = MEnvSpaceInstance.getProperty(observer, "name")!=null? (String)MEnvSpaceInstance.getProperty(observer, "name"): "Default Observer";
final Boolean killonexit = (Boolean)MEnvSpaceInstance.getProperty(observer, "killonexit");
List plugs = (List)observer.get("plugins");
final List plugins = plugs!=null ? new ArrayList() : null;
if(plugs!=null)
{
for(int j=0; j<plugs.size(); j++)
{
Map plug = (Map)plugs.get(j);
Class clazz = (Class)MEnvSpaceInstance.getProperty(plug, "clazz");
IPropertyObject po = (IPropertyObject)clazz.newInstance();
MEnvSpaceInstance.setProperties(po, (List)plug.get("properties"), fetcher);
plugins.add(po);
}
}
SServiceProvider.getService(context.getServiceProvider(), ILibraryService.class).addResultListener(new DefaultResultListener()
{
public void resultAvailable(Object source, Object result)
{
final ObserverCenter oc = new ObserverCenter(title, AbstractEnvironmentSpace.this, (ILibraryService)result, plugins,
killonexit!=null ? killonexit.booleanValue() : true);
SServiceProvider.getServiceUpwards(context.getServiceProvider(), IComponentManagementService.class).addResultListener(new DefaultResultListener()
{
public void resultAvailable(Object source, final Object result)
{
((IComponentManagementService)result).addComponentListener(context.getComponentIdentifier(), new ICMSComponentListener()
{
public void componentRemoved(IComponentDescription desc, Map results)
{
((IComponentManagementService)result).removeComponentListener(context.getComponentIdentifier(), this);
oc.dispose();
}
public void componentChanged(IComponentDescription desc)
{
}
public void componentAdded(IComponentDescription desc)
{
}
});
}
});
List perspectives = mspacetype.getPropertyList("perspectives");
for(int j=0; j<perspectives.size(); j++)
{
Map sourcepers = (Map)perspectives.get(j);
Map args = new HashMap();
args.put("object", sourcepers);
args.put("fetcher", fetcher);
try
{
IPerspective persp = (IPerspective)((IObjectCreator)MEnvSpaceInstance.getProperty(sourcepers, "creator")).createObject(args);
List props = (List)sourcepers.get("properties");
MEnvSpaceInstance.setProperties(persp, props, fetcher);
oc.addPerspective((String)MEnvSpaceInstance.getProperty(sourcepers, "name"), persp);
}
catch(Exception e)
{
System.out.println("Exception while creating perspective: "+sourcepers);
e.printStackTrace();
}
}
}
});
}
}
// Create the environment executor.
Map mse = (Map)MEnvSpaceInstance.getProperty(mspacetype.getProperties(), "spaceexecutor");
IParsedExpression exp = (IParsedExpression)MEnvSpaceInstance.getProperty(mse, "expression");
ISpaceExecutor exe = null;
if(exp!=null)
{
exe = (ISpaceExecutor)exp.getValue(fetcher); // Executor starts itself
}
else
{
exe = (ISpaceExecutor)((Class)MEnvSpaceInstance.getProperty(mse, "clazz")).newInstance();
List props = (List)mse.get("properties");
MEnvSpaceInstance.setProperties(exe, props, fetcher);
}
if(exe!=null)
exe.start();
}
//-------- methods --------
/**
* Add a space type.
* @param typename The type name.
* @param properties The MobjectType.
*/
public void addSpaceObjectType(String typename, IPropertyMetaDataSet mobjecttype)
{
synchronized(monitor)
{
objecttypes.put(typename, mobjecttype);
}
}
/**
* Remove a space object type.
* @param typename The type name.
*/
public void removeSpaceObjectType(String typename)
{
synchronized(monitor)
{
objecttypes.remove(typename);
// Kill running process instances also?
}
}
/**
* Add a space process type.
* @param typename The type name.
* @param properties The properties.
*/
public void addSpaceProcessType(String typename, Class clazz, List properties)
{
synchronized(monitor)
{
processtypes.put(typename, new Object[]{clazz, properties});
}
}
/**
* Remove a space process type.
* @param typename The type name.
*/
public void removeSpaceProcessType(String typename)
{
synchronized(monitor)
{
processtypes.remove(typename);
}
}
/**
* Creates a space process.
* @param typename The type name.
* @param properties The properties.
*/
public void createSpaceProcess(String typename, Map properties)
{
synchronized(monitor)
{
Object id;
do
{
id = objectidcounter.getNext();
}
while(spaceobjects.containsKey(id));
// Prepare properties (runtime props override type props).
Object[] procinfo = (Object[])processtypes.get(typename);
if(procinfo==null)
throw new RuntimeException("Unknown space process: "+typename);
try
{
ISpaceProcess process = (ISpaceProcess)((Class)procinfo[0]).newInstance();
properties = mergeProperties((List)procinfo[1], properties);
if(properties!=null)
{
for(Iterator it = properties.keySet().iterator(); it.hasNext(); )
{
String propname = (String)it.next();
process.setProperty(propname, properties.get(propname));
}
}
process.setProperty(ISpaceProcess.ID, id);
processes.put(id, process);
}
catch(Exception e)
{
e.printStackTrace();
throw new RuntimeException("Could not create space process: "+typename, e);
}
// process.start(this); // Done by executor.
}
}
/**
* Add a object task type.
* @param typename The type name.
* @param properties The properties.
*/
public void addObjectTaskType(String typename, Class clazz, List properties)
{
synchronized(monitor)
{
tasktypes.put(typename, new Object[]{clazz, properties});
}
}
/**
* Remove an object task type.
* @param typename The type name.
*/
public void removeObjectTaskType(String typename)
{
synchronized(monitor)
{
tasktypes.remove(typename);
}
}
/**
* Creates an object task.
* @param typename The type name.
* @param properties The properties.
* @return The task id.
*/
public Object createObjectTask(String typename, Map properties, Object objectid)
{
synchronized(monitor)
{
// System.out.println("add task: "+typename+" "+objectid+" "+properties);
// Prepare properties (runtime props override type props).
Object[] taskinfo = (Object[])tasktypes.get(typename);
if(taskinfo==null)
throw new RuntimeException("Unknown space task: "+typename);
try
{
IObjectTask task = (IObjectTask)((Class)taskinfo[0]).newInstance();
// todo: ensure uniqueness?!
Object id = taskidcounter.getNext();
task.setProperty(IObjectTask.PROPERTY_ID, id);
properties = mergeProperties((List) taskinfo[1], properties);
if(properties!=null)
{
for(Iterator it = properties.keySet().iterator(); it.hasNext(); )
{
String propname = (String)it.next();
task.setProperty(propname, properties.get(propname));
}
}
SpaceObject object = (SpaceObject)getSpaceObject(objectid);
object.addTask(task);
return id;
}
catch(Exception e)
{
throw new RuntimeException("Could not create space task: "+typename, e);
}
}
}
/**
* Remove an object task.
* @param typename The type name.
* @param properties The properties.
*/
public void removeObjectTask(Object taskid, Object objectid)
{
synchronized(monitor)
{
// System.out.println("remove task: "+taskid+" "+objectid);
SpaceObject so = (SpaceObject)getSpaceObject(objectid);
so.removeTask(taskid, null);
}
}
/**
* Add a result listener to an object task.
* The listener result will be the task id.
* If the task is already finished, the listener will be notified.
*/
public void addTaskListener(Object taskid, Object objectid, IResultListener listener)
{
SpaceObject so = (SpaceObject)getSpaceObject(objectid);
so.addTaskListener(taskid, listener);
}
/**
* Remove a result listener from an object task.
*/
public void removeTaskListener(Object taskid, Object objectid, IResultListener listener)
{
SpaceObject so = (SpaceObject)getSpaceObject(objectid);
so.removeTaskListener(taskid, listener);
}
/**
* Returns then names of the space processes.
* @return the names of the space processes
*/
public Set getSpaceProcessNames()
{
synchronized(monitor)
{
return new HashSet(processes.keySet());
}
}
/**
* Returns a space process.
* @param id ID of the space process
* @return the space process or null if not found
*/
public ISpaceProcess getSpaceProcess(Object id)
{
synchronized(monitor)
{
return (ISpaceProcess)processes.get(id);
}
}
/**
* Removes a space process.
* @param id ID of the space process
*/
public void removeSpaceProcess(Object id)
{
synchronized(monitor)
{
ISpaceProcess process = (ISpaceProcess)processes.remove(id);
if(process!=null)
process.shutdown(this);
}
}
/**
* Creates an object in this space.
* @param type the object's type
* @param properties initial properties (may be null)
* @param tasks initial task list (may be null)
* @return the object's ID
*/
public final ISpaceObject createSpaceObject(final String typename, Map properties, List tasks)
{
if(!objecttypes.containsKey(typename))
throw new RuntimeException("Unknown space object type: "+typename);
ISpaceObject ret;
synchronized(monitor)
{
// Generate id.
Object id;
do
{
id = objectidcounter.getNext();
}
while(spaceobjects.containsKey(id) || zombieobjects.containsKey(id));
// Prepare properties (runtime props override type props).
MObjectType mObjectType = (MObjectType)objecttypes.get(typename);
properties = mergeProperties(mObjectType, properties);
// Create the object.
ret = new SpaceObject(id, mObjectType, properties, tasks, monitor, this);
spaceobjects.put(id, ret);
// Store in owner objects.
if(properties!=null && properties.containsKey(ISpaceObject.PROPERTY_OWNER))
{
IComponentIdentifier owner = (IComponentIdentifier)properties.get(ISpaceObject.PROPERTY_OWNER);
List ownerobjects = (List)spaceobjectsbyowner.get(owner);
if(ownerobjects == null)
{
ownerobjects = new ArrayList();
spaceobjectsbyowner.put(owner, ownerobjects);
}
ownerobjects.add(ret);
}
}
initSpaceObject(ret);
return ret;
}
/**
* Creates a zombie object in this space.
* Zombies are not (yet) visible in the space and must be inited separately.
* @param type the object's type
* @param properties initial properties (may be null)
* @param tasks initial task list (may be null)
* @return the object's ID
*/
public ISpaceObject createSpaceObjectZombie(final String typename, Map properties, List tasks)
{
if(!objecttypes.containsKey(typename))
throw new RuntimeException("Unknown space object type: "+typename);
ISpaceObject ret;
synchronized(monitor)
{
// Generate id.
Object id;
do
{
id = objectidcounter.getNext();
}
while(spaceobjects.containsKey(id) || zombieobjects.containsKey(id));
// Prepare properties (runtime props override type props).
MObjectType mObjectType = (MObjectType)objecttypes.get(typename);
properties = mergeProperties(mObjectType, properties);
// Create the object.
ret = new SpaceObject(id, mObjectType, properties, tasks, monitor, this);
zombieobjects.put(id, ret);
// Store in owner objects.
if(properties!=null && properties.containsKey(ISpaceObject.PROPERTY_OWNER))
{
IComponentIdentifier owner = (IComponentIdentifier)properties.get(ISpaceObject.PROPERTY_OWNER);
List ownerobjects = (List)spaceobjectsbyowner.get(owner);
if(ownerobjects == null)
{
ownerobjects = new ArrayList();
spaceobjectsbyowner.put(owner, ownerobjects);
}
ownerobjects.add(ret);
}
}
return ret;
}
/**
* Creates an object in this space.
* @param type the object's type
* @param properties initial properties (may be null)
* @param tasks initial task list (may be null)
* @param listeners initial listeners (may be null)
* @return the object's ID
*/
public void initSpaceObject(final ISpaceObject ret)
{
synchronized(monitor)
{
if(zombieobjects.containsKey(ret.getId()))
{
zombieobjects.remove(ret.getId());
spaceobjects.put(ret.getId(), ret);
}
// Store in type objects.
List typeobjects = (List)spaceobjectsbytype.get(ret.getType());
if(typeobjects == null)
{
typeobjects = new ArrayList();
spaceobjectsbytype.put(ret.getType(), typeobjects);
}
typeobjects.add(ret);
// Create view(s) for the object if any.
if(dataviewmappings!=null && dataviewmappings.getCollection(ret.getType())!=null)
{
for(Iterator it=dataviewmappings.getCollection(ret.getType()).iterator(); it.hasNext(); )
{
try
{
Map sourceview = (Map)it.next();
Map viewargs = new HashMap();
viewargs.put("sourceview", sourceview);
viewargs.put("space", this);
viewargs.put("object", ret);
IDataView view = (IDataView)((IObjectCreator)MEnvSpaceInstance.getProperty(sourceview, "creator")).createObject(viewargs);
addDataView((String)MEnvSpaceInstance.getProperty(sourceview, "name")+"_"+ret.getId(), view);
}
catch(Exception e)
{
if(e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
}
}
// Possibly create component.
for(Iterator it=avatarmappings.keySet().iterator(); it.hasNext(); )
{
String componenttype = (String)it.next();
AvatarMapping mapping = getAvatarMapping(componenttype, ret.getType());
if(mapping!=null && mapping.isCreateComponent())
{
// final Object fid = id;
// String name = null;
if(mapping.getComponentName()!=null)
{
// SimpleValueFetcher fetch = new SimpleValueFetcher();
// fetch.setValue("$space", this);
// fetch.setValue("$object", ret);
name = (String)mapping.getComponentName().getValue(getFetcher());
}
final String compotype = componenttype;
SServiceProvider.getServiceUpwards(application.getServiceProvider(), IComponentManagementService.class).addResultListener(new DefaultResultListener()
{
public void resultAvailable(Object source, Object result)
{
IComponentManagementService cms = (IComponentManagementService)result;
IComponentIdentifier cid = cms.generateComponentIdentifier(ret.getType());
setOwner(ret.getId(), cid);
IFuture future = cms.createComponent(cid.getLocalName(), getContext().getComponentFilename(compotype),
new CreationInfo(null, null, getContext().getComponentIdentifier(), false, getContext().getAllImports()), null);
future.addResultListener(new IResultListener()
{
public void resultAvailable(Object source, Object result)
{
}
public void exceptionOccurred(Object source, Exception exception)
{
// Todo: propagate exception: kills application!?
exception.printStackTrace();
}
});
}
});
}
}
}
if(listeners!=null)
{
EnvironmentEvent event = new EnvironmentEvent(EnvironmentEvent.OBJECT_CREATED, this, ret, null, null);
for(int i=0; i<listeners.size(); i++)
{
IEnvironmentListener lis = (IEnvironmentListener)listeners.get(i);
lis.dispatchEnvironmentEvent(event);
}
}
}
/**
* Add type properties to runtime properties.
* Runtime properties have precedence if specified.
* @param typeprops The type properties (if any).
* @param properties The runtime properties or null.
* @return The merged runtime properties.
*/
protected Map mergeProperties(Collection typeprops, Map properties)
{
if(typeprops!=null)
{
if(properties==null)
properties = new HashMap();
for(Iterator it=typeprops.iterator(); it.hasNext(); )
{
Map prop = (Map)it.next();
String propname = (String)prop.get("name");
if(!properties.containsKey(propname))
{
IParsedExpression exp = (IParsedExpression)prop.get("value");
if(exp!=null)
{
boolean dyn = ((Boolean)prop.get("dynamic")).booleanValue();
if(dyn)
properties.put(propname, exp);
else
properties.put(propname, exp.getValue(fetcher));
}
}
}
}
return properties;
}
/**
* Add type properties to runtime properties.
* Runtime properties have precedence if specified.
* @param typeprops The type
* @param properties The runtime properties or null.
* @return The merged runtime properties.
*/
protected Map mergeProperties(IPropertyMetaDataSet mObjectType, Map properties)
{
if (mObjectType != null) {
if (properties == null)
properties = new HashMap();
for (Iterator it = mObjectType.iterator(); it.hasNext(); ) {
MObjectTypeProperty property = (MObjectTypeProperty)it.next();
// System.out.println(property.getName());
if (!properties.containsKey(property.getName())) {
IParsedExpression exp = (IParsedExpression)property.getValue();
if (exp != null) {
if (property.isDynamic())
properties.put(property.getName(), exp);
else
properties.put(property.getName(), exp.getValue(fetcher));
}
}
}
}
return properties;
}
/**
* Destroys an object in this space.
* @param id the object's ID
*/
public void destroySpaceObject(final Object id)
{
// System.out.println("destroy so: "+id);
SpaceObject obj;
synchronized(monitor)
{
obj = (SpaceObject)spaceobjects.get(id);
if(obj==null)
throw new RuntimeException("No object found for id: "+id);
String objecttype = obj.getType();
// Possibly kill component.
final IComponentIdentifier component = (IComponentIdentifier)obj.getProperty(ISpaceObject.PROPERTY_OWNER);
if(component!=null)
{
String componenttype = getContext().getComponentType(component);
AvatarMapping mapping = getAvatarMapping(componenttype, objecttype);
if(mapping.isKillComponent())
{
SServiceProvider.getServiceUpwards(getContext().getServiceProvider(), IComponentManagementService.class)
.addResultListener(new DefaultResultListener()
{
public void resultAvailable(Object source, Object result)
{
((IComponentManagementService)result).destroyComponent(component);
}
});
}
}
// Mark obsolete actions
ActionEntry[] actions = actionlist.getActionEntries();
for(int i=0; i<actions.length; i++)
{
Object actorid = actions[i].parameters.get(ISpaceAction.ACTOR_ID);
if(actorid!=null)
{
ISpaceObject so = getAvatar((IComponentIdentifier)actorid);
if(so!=null)
{
Object avatarid = so.getId();
if(avatarid==id)
{
actions[i].invalid = true;
}
}
}
}
// shutdown and jettison tasks
obj.clearTasks();
// remove object
spaceobjects.remove(id);
List typeobjs = (List)spaceobjectsbytype.get(objecttype);
typeobjs.remove(obj);
if(typeobjs.size()==0)
spaceobjectsbytype.remove(obj.getType());
if(obj.getProperty(ISpaceObject.PROPERTY_OWNER)!=null)
{
List ownedobjs = (List)spaceobjectsbyowner.get(obj.getProperty(ISpaceObject.PROPERTY_OWNER));
ownedobjs.remove(obj);
if(ownedobjs.size()==0)
spaceobjectsbyowner.remove(obj.getProperty(ISpaceObject.PROPERTY_OWNER));
}
// Remove view(s) for the object if any.
if(dataviewmappings!=null && dataviewmappings.getCollection(objecttype)!=null)
{
for(Iterator it=dataviewmappings.getCollection(objecttype).iterator(); it.hasNext(); )
{
Map sourceview = (Map)it.next();
removeDataView((String)MEnvSpaceInstance.getProperty(sourceview, "name")+"_"+id);
}
}
}
// signal removal
// // hmm? what about calling destroy on object? could it do sth. else than throwing event?
// ObjectEvent event = new ObjectEvent(ObjectEvent.OBJECT_REMOVED);
// event.setParameter("space_name", getName());
// obj.fireObjectEvent(event);
if(listeners!=null)
{
EnvironmentEvent ev = new EnvironmentEvent(EnvironmentEvent.OBJECT_DESTROYED, this, obj, null, null);
for(int i=0; i<listeners.size(); i++)
{
IEnvironmentListener lis = (IEnvironmentListener)listeners.get(i);
lis.dispatchEnvironmentEvent(ev);
}
}
}
/**
* Returns an object in this space.
* @param id the object's ID
* @return the object in this space
*/
public ISpaceObject getSpaceObject(Object id)
{
synchronized(monitor)
{
ISpaceObject ret = (ISpaceObject)spaceobjects.get(id);
if(ret==null)
throw new RuntimeException("Space object not found: "+id);
return ret;
}
}
/**
* Returns an object in this space.
* @param id the object's ID
* @return the object in this space
*/
public ISpaceObject getSpaceObject0(Object id)
{
synchronized(monitor)
{
return (ISpaceObject)spaceobjects.get(id);
}
}
/**
* Get all space object of a specific type.
* @param type The space object type.
* @return The space objects of the desired type.
*/
public ISpaceObject[] getSpaceObjectsByType(String type)
{
List obs = (List)spaceobjectsbytype.get(type);
return obs==null? new ISpaceObject[0]: (ISpaceObject[])obs.toArray(new ISpaceObject[obs.size()]);
}
/**
* Adds an avatar mapping.
* @param componenttype The component type.
* @param objecttype The object type to represent the component.
*/
public void addAvatarMappings(AvatarMapping mapping)
{
synchronized(monitor)
{
this.avatarmappings.put(mapping.getComponentType(), mapping);
}
}
/**
* Remove an avatar mapping.
* @param componenttype The component type.
* @param objecttype The object type to represent the component.
*/
public void removeAvatarMappings(AvatarMapping mapping)
{
synchronized(monitor)
{
this.avatarmappings.remove(mapping.getComponentType(), mapping);
}
}
/**
* Adds an space action.
* @param actionId the action ID
* @param action the action
*/
public void addSpaceAction(String id, ISpaceAction action)
{
synchronized(monitor)
{
actions.put(id, action);
}
}
/**
* Adds an space action.
* @param actionId the action ID
* @param action the action
*/
public ISpaceAction getSpaceAction(String id)
{
ISpaceAction ret = (ISpaceAction)actions.get(id);
if(ret==null)
{
throw new RuntimeException("No such space action: "+id);
}
return ret;
}
/**
* Removes an space action.
* @param actionId the action ID
*/
public void removeSpaceAction(String id)
{
synchronized(monitor)
{
actions.remove(id);
}
}
/**
* Schedules an space action.
* @param id Id of the action
* @param parameters parameters for the action (may be null)
* @param listener the result listener
*/
public void performSpaceAction(String id, Map parameters, IResultListener listener)
{
synchronized(monitor)
{
actionlist.scheduleComponentAction(getSpaceAction(id), parameters, listener);
}
}
/**
* Performs a space action.
* @param id Id of the action
* @param parameters parameters for the action (may be null)
* @return return value of the action
*/
public Object performSpaceAction(String id, Map parameters)
{
synchronized(monitor)
{
ISpaceAction action = (ISpaceAction)actions.get(id);
if(action==null)
throw new RuntimeException("Action not found: "+id);
return action.perform(parameters, this);
}
}
/**
* Create a percept for the given component.
* @param typename The percept type.
* @param data The content of the percept (if any).
* @param component The component that should receive the percept.
*/
public void createPercept(String typename, Object data, IComponentIdentifier component, ISpaceObject avatar)
{
synchronized(monitor)
{
// if(!percepttypes.containsKey(typename))
// throw new RuntimeException("Unknown percept type: "+typename);
// System.out.println("New percept: "+typename+", "+data+", "+component);
String componenttype = application.getComponentType(component);
List procs = (List)perceptprocessors.get(componenttype);
IPerceptProcessor proc = null;
if(procs!=null)
{
for(int i=0; i<procs.size() && proc==null; i++)
{
Object[] tmp = (Object[])procs.get(i);
if(tmp[0]==null || ((Collection)tmp[0]).contains(typename))
proc = (IPerceptProcessor)tmp[1];
}
}
if(proc!=null)
perceptlist.schedulePercept(typename, data, component, avatar, proc);
else
System.out.println("Warning: No processor for percept: "+typename+", "+data+", "+component+", "+avatar);
}
}
/**
* Get the owner of an object.
* @param id The id.
* @return The owner.
*/
public IComponentIdentifier getOwner(Object id)
{
synchronized(monitor)
{
ISpaceObject obj = getSpaceObject(id);
if(obj==null)
throw new RuntimeException("Space object not found: "+id);
return (IComponentIdentifier)obj.getProperty(ISpaceObject.PROPERTY_OWNER);
}
}
/**
* Set the owner of an object.
* @param id The object id.
* @param pos The object owner.
*/
public void setOwner(Object id, IComponentIdentifier owner)
{
synchronized(monitor)
{
ISpaceObject obj = getSpaceObject(id);
if(obj==null)
throw new RuntimeException("Space object not found: "+id);
Object oldowner = obj.getProperty(ISpaceObject.PROPERTY_OWNER);
if(oldowner!=null)
{
List ownedobjs = (List)spaceobjectsbyowner.get(oldowner);
ownedobjs.remove(obj);
if(ownedobjs.size()==0)
spaceobjectsbyowner.remove(oldowner);
}
if(owner!=null)
{
List ownedobjs = (List)spaceobjectsbyowner.get(owner);
if(ownedobjs==null)
{
ownedobjs = new ArrayList();
spaceobjectsbyowner.put(owner, ownedobjs);
}
ownedobjs.add(obj);
}
obj.setProperty(ISpaceObject.PROPERTY_OWNER, owner);
}
}
/**
* Get the avatar objects.
* @return The avatar objects.
*/
public ISpaceObject[] getAvatars(IComponentIdentifier owner)
{
synchronized(monitor)
{
List ownedobjs = (List)spaceobjectsbyowner.get(owner);
return ownedobjs==null? new ISpaceObject[0]: (ISpaceObject[])ownedobjs.toArray(new ISpaceObject[ownedobjs.size()]);
}
}
/**
* Get the avatar objects.
* @return The avatar objects.
*/
public IComponentIdentifier[] getComponents()
{
synchronized(monitor)
{
return (IComponentIdentifier[])spaceobjectsbyowner.keySet().toArray(new IComponentIdentifier[spaceobjectsbyowner.keySet().size()]);
}
}
/**
* Get the avatar object.
* @return The avatar object.
*/
public ISpaceObject getAvatar(IComponentIdentifier owner)
{
synchronized(monitor)
{
ISpaceObject ret = null;
List ownedobjs = (List)spaceobjectsbyowner.get(owner);
if(ownedobjs!=null)
{
if(ownedobjs.size()>1)
throw new RuntimeException("More than one avatar for component: "+owner);
else if(ownedobjs.size()==1)
ret = (ISpaceObject)ownedobjs.get(0);
}
return ret;
}
}
/**
* Get the avatar object.
* @return The avatar object.
*/
public ISpaceObject getAvatar(IComponentIdentifier owner, String fullname)
{
ISpaceObject ret = getAvatar(owner);
// Create avatar on the fly if componentAdded not yet called.
if(ret==null)
{
ret = createAvatar(owner, fullname, true);
}
return ret;
}
/**
* Create an avatar.
*/
protected ISpaceObject createAvatar(IComponentIdentifier owner, String fullname, boolean zombie)
{
ISpaceObject ret = null;
// Possibly add or create avatar(s) if any.
if(initialavatars!=null && initialavatars.containsKey(owner))
{
Object[] ia = (Object[])initialavatars.get(owner);
String objecttype = (String)ia[0];
Map props = (Map)ia[1];
if(props==null)
props = new HashMap();
props.put(ISpaceObject.PROPERTY_OWNER, owner);
ret = zombie ? createSpaceObjectZombie(objecttype, props, null)
: createSpaceObject(objecttype, props, null);
}
else
{
String componenttype = application.getComponentType(owner);
if(componenttype==null && fullname!=null)
{
List atypes = application.getApplicationType().getMComponentTypes();
for(int i=0; i<atypes.size(); i++)
{
final MComponentType atype = (MComponentType)atypes.get(i);
String tmp = atype.getFilename().replace('/', '.');
if(tmp.indexOf(fullname)!=-1)
{
componenttype = atype.getName();
break;
}
}
}
if(componenttype!=null && avatarmappings.getCollection(componenttype)!=null)
{
for(Iterator it=avatarmappings.getCollection(componenttype).iterator(); it.hasNext(); )
{
AvatarMapping mapping = (AvatarMapping)it.next();
// Only create avatar if it has none
if(mapping.isCreateAvatar() && !spaceobjectsbyowner.containsKey(owner))
{
Map props = new HashMap();
props.put(ISpaceObject.PROPERTY_OWNER, owner);
ret = zombie ? createSpaceObjectZombie(mapping.getObjectType(), props, null)
: createSpaceObject(mapping.getObjectType(), props, null);
}
}
}
}
return ret;
}
/**
* Adds a view to the space.
* @param name name of the view
* @param view the view
*/
public void addDataView(String name, IDataView view)
{
synchronized (monitor)
{
views.put(name, view);
}
}
/**
* Removes a view from the space.
* @param name name of the view
*/
public void removeDataView(String name)
{
synchronized (monitor)
{
views.remove(name);
}
}
/**
* Gets a specific view.
* @param name name of the view
* @return the view
*/
public IDataView getDataView(String name)
{
synchronized (monitor)
{
return (IDataView) views.get(name);
}
}
/**
* Get all available dataviews in this space.
* @return all available dataviews
*/
public Map getDataViews()
{
synchronized (monitor)
{
return new HashMap(views);
}
}
/**
* Add a mapping from object type to data view
* @param objecttype The object type.
* @param view Settings for view creation.
*/
public void addDataViewMapping(String objecttype, Map view)
{
synchronized(monitor)
{
dataviewmappings.put(objecttype, view);
}
}
/**
* Add an environment listener.
* @param listener The environment listener.
*/
public void addEnvironmentListener(IEnvironmentListener listener)
{
synchronized(monitor)
{
if(listeners==null)
listeners = new ArrayList();
listeners.add(listener);
}
}
/**
* Remove an environment listener.
* @param listener The environment listener.
*/
public void removeEnvironmentListener(IEnvironmentListener listener)
{
synchronized(monitor)
{
listeners.remove(listener);
if(listeners.size()==0)
listeners = null;
}
}
/**
* Adds a percept generator.
* @param id The percept generator id.
* @param gen The percept generator.
*/
public void addPerceptGenerator(Object id, IPerceptGenerator gen)
{
synchronized(monitor)
{
addEnvironmentListener(gen);
perceptgenerators.put(id, gen);
}
}
/**
* Remove a percept generator.
* @param id The percept generator id.
*/
public void removePerceptGenerator(Object id)
{
synchronized(monitor)
{
removeEnvironmentListener((IEnvironmentListener)perceptgenerators.remove(id));
}
}
/**
* Add a percept processor.
* @param componenttype The component type.
* @param proc The percept processor.
*/
public void addPerceptProcessor(String componenttype, Set percepttypes, IPerceptProcessor proc)
{
synchronized(monitor)
{
perceptprocessors.put(componenttype, new Object[]{percepttypes, proc});
}
}
/**
* remove a percept processor.
* @param componenttype The component type.
* @param proc The percept processor.
*/
public void removePerceptProcessor(String componenttype, IPerceptProcessor proc)
{
synchronized(monitor)
{
List procs = (List)perceptprocessors.get(componenttype);
for(int i=0; i<procs.size(); i++)
{
Object[] tmp = (Object[])procs.get(i);
if(proc.equals(tmp[1]))
{
perceptprocessors.remove(componenttype, tmp);
break;
}
}
}
}
/**
* Add a space percept type.
* @param typename The percept name.
* @param objecttypes The objecttypes.
* @param componenttypes The componenttypes.
*/
public void addPerceptType(PerceptType percepttype)
{
synchronized(monitor)
{
percepttypes.put(percepttype.getName(), percepttype);
}
}
/**
* Remove a space process type.
* @param typename The type name.
*/
public void removePerceptType(String typename)
{
synchronized(monitor)
{
percepttypes.remove(typename);
}
}
/**
* Get a space percept type.
* @param percepttype The name of the percept type.
* @return The percept type.
*/
public PerceptType getPerceptType(String percepttype)
{
synchronized(monitor)
{
return (PerceptType)percepttypes.get(percepttype);
}
}
//-------- ISpace methods --------
/**
* Called when an component was added.
*/
public void componentAdded(IComponentIdentifier aid)//, String type)
{
synchronized(monitor)
{
// Possibly add or create avatar(s) if any.
List ownedobjs = (List)spaceobjectsbyowner.get(aid);
if(ownedobjs==null)
{
createAvatar(aid, null, false);
}
else
{
// Init zombie avatars.
for(Iterator it=ownedobjs.iterator(); it.hasNext(); )
{
ISpaceObject obj = (ISpaceObject)it.next();
if(!spaceobjects.containsKey(obj.getId()))
{
initSpaceObject(obj);
}
}
}
if(perceptgenerators!=null)
{
for(Iterator it=perceptgenerators.keySet().iterator(); it.hasNext(); )
{
IPerceptGenerator gen = (IPerceptGenerator)perceptgenerators.get(it.next());
gen.componentAdded(aid, this);
}
}
}
}
/**
* Called when an component was removed.
*/
public void componentRemoved(IComponentIdentifier aid)
{
// System.out.println("comp removed: "+aid);
synchronized(monitor)
{
String componenttype = application.getComponentType(aid);
// Possibly kill avatars of that component.
if(componenttype!=null && avatarmappings.getCollection(componenttype)!=null)
{
ISpaceObject[] avatars = getAvatars(aid);
if(avatars!=null)
{
for(int i=0; i<avatars.length; i++)
{
String avatartype = avatars[i].getType();
AvatarMapping mapping = getAvatarMapping(componenttype, avatartype);
if(mapping!=null && mapping.isKillAvatar())
{
destroySpaceObject(avatars[i].getId());
}
}
}
}
if(perceptgenerators!=null)
{
for(Iterator it=perceptgenerators.keySet().iterator(); it.hasNext(); )
{
IPerceptGenerator gen = (IPerceptGenerator)perceptgenerators.get(it.next());
gen.componentRemoved(aid, this);
}
}
}
// Remove the owned object too?
}
/**
* Get the context.
* @return The context.
*/
public IApplication getContext()
{
return application;
}
/**
* Terminate the space.
*/
public void terminate()
{
}
/**
* Returns a property.
* @param name name of the property
* @return the property
*/
public Object getProperty(String name)
{
synchronized(monitor)
{
Object ret = super.getProperty(name);
if(ret instanceof IParsedExpression)
{
ret = ((IParsedExpression) ret).getValue(getFetcher());
}
return ret;
}
}
/**
* Get the value fetcher.
* @return The fetcher.
*/
public SimpleValueFetcher getFetcher()
{
if(fetcher==null)
{
this.fetcher = new SimpleValueFetcher();
fetcher.setValue("$space", this);
}
return this.fetcher;
}
/**
* Set the fetcher.
* @param fetcher The fetcher to set.
*/
public void setFetcher(SimpleValueFetcher fetcher)
{
this.fetcher = fetcher;
}
/**
* Get the space objects.
*/
// Hack!!! getSpaceObjecs() implemented in Space2D???
public Collection getSpaceObjectsCollection()
{
return spaceobjects.values();
}
/**
* Get the processes.
*/
public Collection getProcesses()
{
return processes.values();
}
/**
* Get the list of scheduled component actions
*/
public ComponentActionList getComponentActionList()
{
return actionlist;
}
/**
* Get the list of scheduled percepts.
*/
public PerceptList getPerceptList()
{
return perceptlist;
}
/**
* Get the views.
*/
public Collection getViews()
{
return views.values();
}
/**
* Fire an environment event.
* @param event The event.
*/
protected void fireEnvironmentEvent(EnvironmentEvent event)
{
IEnvironmentListener[] alisteners = null;
synchronized(monitor)
{
if(listeners!=null)
alisteners = (IEnvironmentListener[])listeners.toArray(new IEnvironmentListener[listeners.size()]);
}
if(alisteners!=null)
{
for(int i=0; i<alisteners.length; i++)
{
alisteners[i].dispatchEnvironmentEvent(event);
}
}
}
/**
* Fire an object event.
* @param object The object.
* @param property The changed property.
* @param value The new property value.
*/
protected void fireObjectEvent(SpaceObject object, String property, Object value)
{
boolean fire = false;
synchronized(monitor)
{
MObjectType props = (MObjectType)objecttypes.get(object.getType());
if (props != null) {
MObjectTypeProperty prop = (MObjectTypeProperty)props.getProperty(property);
fire = prop != null && prop.isEvent();
}
}
if(fire)
fireEnvironmentEvent(new EnvironmentEvent(EnvironmentEvent.OBJECT_PROPERTY_CHANGED, this, object, property, value));
}
/**
* Synchronized counter class
*/
private class AtomicCounter
{
long count_;
public AtomicCounter()
{
count_ = 0;
}
public synchronized Long getNext()
{
return new Long(count_++);
}
}
/**
* Initial settings for the avatar of a specific component.
* @param ownerid The component id.
* @param type The object type.
* @param props The properties for the object (if any).
*/
public void addInitialAvatar(IComponentIdentifier ownerid, String type, Map props)
{
synchronized(monitor)
{
if(initialavatars==null)
initialavatars = new HashMap();
initialavatars.put(ownerid, new Object[]{type, props});
}
}
/**
* Get the avatar mapping for an component avatar combination.
*/
protected AvatarMapping getAvatarMapping(String componenttype, String avatartype)
{
AvatarMapping mapping = null;
for(Iterator it=avatarmappings.getCollection(componenttype).iterator(); mapping==null && it.hasNext(); )
{
AvatarMapping test = (AvatarMapping)it.next();
if(avatartype.equals(test.getObjectType()))
mapping = test;
}
return mapping;
}
/**
* Add a new data provider.
* @param name The name.
* @param provider The provider.
*/
public void addDataProvider(String name, ITableDataProvider provider)
{
dataproviders.put(name, provider);
}
/**
* Get a data provider.
* @param name The name.
* @return The provider.
*/
public ITableDataProvider getDataProvider(String name)
{
return (ITableDataProvider)dataproviders.get(name);
}
/**
* Add a new data consumer.
* @param consumer The consumer.
*/
public void addDataConsumer(String name, ITableDataConsumer consumer)
{
dataconsumers.put(name, consumer);
}
/**
* Get a data consumer.
* @param name The name.
* @return The consumer.
*/
public ITableDataConsumer getDataConsumer(String name)
{
return (ITableDataConsumer)dataconsumers.get(name);
}
/**
* Get the data consumers.
* @return The data consumers.
*/
public Collection getDataConsumers()
{
return dataconsumers.values();
}
}