All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jadex.extension.envsupport.environment.AbstractEnvironmentSpace Maven / Gradle / Ivy

Go to download

The Jadex kernel extension envsupport allows for using 2D spaces in concert with components.

There is a newer version: 3.0.117
Show newest version
package jadex.extension.envsupport.environment;

import java.io.PrintWriter;
import java.io.StringWriter;
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;

import javax.swing.SwingUtilities;

import jadex.bridge.BasicComponentIdentifier;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.IComponentStep;
import jadex.bridge.IExternalAccess;
import jadex.bridge.IInternalAccess;
import jadex.bridge.component.IExecutionFeature;
import jadex.bridge.component.IMonitoringComponentFeature;
import jadex.bridge.modelinfo.SubcomponentTypeInfo;
import jadex.bridge.service.RequiredServiceInfo;
import jadex.bridge.service.search.SServiceProvider;
import jadex.bridge.service.types.cms.CMSComponentDescription;
import jadex.bridge.service.types.cms.CreationInfo;
import jadex.bridge.service.types.cms.ICMSComponentListener;
import jadex.bridge.service.types.cms.IComponentDescription;
import jadex.bridge.service.types.cms.IComponentManagementService;
import jadex.bridge.service.types.monitoring.IMonitoringEvent;
import jadex.bridge.service.types.monitoring.IMonitoringService.PublishEventLevel;
import jadex.commons.IFilter;
import jadex.commons.IPropertyObject;
import jadex.commons.IValueFetcher;
import jadex.commons.collection.MultiCollection;
import jadex.commons.future.CounterResultListener;
import jadex.commons.future.DefaultResultListener;
import jadex.commons.future.DelegationResultListener;
import jadex.commons.future.Future;
import jadex.commons.future.IFuture;
import jadex.commons.future.IIntermediateFutureCommandResultListener;
import jadex.commons.future.IResultListener;
import jadex.commons.future.ISubscriptionIntermediateFuture;
import jadex.commons.meta.IPropertyMetaDataSet;
import jadex.extension.envsupport.IObjectCreator;
import jadex.extension.envsupport.MEnvSpaceInstance;
import jadex.extension.envsupport.MEnvSpaceType;
import jadex.extension.envsupport.MObjectType;
import jadex.extension.envsupport.MObjectTypeProperty;
import jadex.extension.envsupport.dataview.IDataView;
import jadex.extension.envsupport.environment.ComponentActionList.ActionEntry;
import jadex.extension.envsupport.environment.space2d.Space2D;
import jadex.extension.envsupport.environment.space3d.Space3D;
import jadex.extension.envsupport.evaluation.DefaultDataProvider;
import jadex.extension.envsupport.evaluation.IObjectSource;
import jadex.extension.envsupport.evaluation.ITableDataConsumer;
import jadex.extension.envsupport.evaluation.ITableDataProvider;
import jadex.extension.envsupport.evaluation.SpaceObjectSource;
import jadex.extension.envsupport.math.Vector2Double;
import jadex.extension.envsupport.math.Vector3Double;
import jadex.extension.envsupport.observer.gui.IObserverCenter;
import jadex.extension.envsupport.observer.gui.ObserverCenter;
import jadex.extension.envsupport.observer.perspective.IPerspective;
import jadex.javaparser.IParsedExpression;
import jadex.javaparser.SimpleValueFetcher;

/**
 *  Abstract base class for environment space. 
 */
public abstract class AbstractEnvironmentSpace	extends SynchronizedPropertyObject	implements IEnvironmentSpace
{
	//-------- attributes --------
		
	/** The context. */
	protected IExternalAccess exta;
	
	/** 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 (cid -> [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;
	
	/** Space objects by owner. */
	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;
	
	/** The observers. */
	protected List observercenters;
	
	/** The class loader. */
	protected ClassLoader	classloader;
	
	protected IInternalAccess ia;
	protected MEnvSpaceInstance config;
	protected IValueFetcher pfetcher;
	

	//-------- 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();
		
		this.observercenters = new ArrayList();
	}
	
	public void	setInitData(IInternalAccess ia, MEnvSpaceInstance config, IValueFetcher pfetcher)
	{
		this.ia	= ia;
		this.config	= config;
		this.pfetcher	= pfetcher;
	}
	
	/**
	 *  Create a space.
	 */
	public IFuture	initSpace()
	{
		final Future	ret	= new Future();
		
//		if(ia.getModel().getFullName().equals("jadex.bdibpmn.examples.marsworld.MarsWorld"))
//			System.out.println("Initing space: "+this);

		
		try
		{
			this.classloader	= ia.getClassLoader();
			final MEnvSpaceType	mspacetype	= (MEnvSpaceType)config.getType();
			
			final SimpleValueFetcher fetcher = new SimpleValueFetcher(pfetcher);
			fetcher.setValue("$space", this);
			this.setFetcher(fetcher);
			
			List mspaceprops = mspacetype.getPropertyList("properties");
			MEnvSpaceType.setProperties(this, mspaceprops, fetcher);
			List spaceprops = config.getPropertyList("properties");
			MEnvSpaceType.setProperties(this, spaceprops, fetcher);
			
			this.exta = ia.getExternalAccess();
			if(this instanceof Space2D) // Hack?
			{
				Double width = config.getProperty("width")!=null? (Double)config.getProperty("width"): (Double)mspacetype.getProperty("width");
				Double height = config.getProperty("height")!=null? (Double)config.getProperty("height"): (Double)mspacetype.getProperty("height");
				((Space2D)this).setAreaSize(Vector2Double.getVector2(width, height));
			}
			if(this instanceof Space3D) // Hack?
			{
				Double width = config.getProperty("width")!=null? (Double)config.getProperty("width"): (Double)mspacetype.getProperty("width");
				Double height = config.getProperty("height")!=null? (Double)config.getProperty("height"): (Double)mspacetype.getProperty("height");
				Double depth = config.getProperty("depth")!=null? (Double)config.getProperty("depth"): (Double)mspacetype.getProperty("depth");
				((Space3D)this).setAreaSize(Vector3Double.getVector3(width,depth, height));
			}
			// Create space object types.
			List objecttypes = mspacetype.getPropertyList("objecttypes");
			if(objecttypes!=null)
			{
				for(int i=0; i	ocsdone	= new Future();
			List observers = config.getPropertyList("observers");
			if(observers!=null)
			{
				CounterResultListener	crl1	= new CounterResultListener(observers.size(), new DelegationResultListener(ocsdone));
				
				for(int i=0; i	ocdone	= new Future();
					ocdone.addResultListener(crl1);
	
					List perspectives = mspacetype.getPropertyList("perspectives");
					CounterResultListener	crl2	= new CounterResultListener(perspectives.size(), new DelegationResultListener(ocdone));
					for(int j=0; j(ret)
			{
				public void customResultAvailable(Void result)
				{
//					if(ia.getModel().getFullName().equals("jadex.bdibpmn.examples.marsworld.MarsWorld"))
//						System.out.println("Inited observers: "+this);
					
					Map mse = (Map)MEnvSpaceType.getProperty(mspacetype.getProperties(), "spaceexecutor");
					if(mse!=null)
					{
						IParsedExpression exp = (IParsedExpression)MEnvSpaceType.getProperty(mse, "expression");
						ISpaceExecutor exe = null;
						if(exp!=null)
						{
							exe = (ISpaceExecutor)exp.getValue(fetcher);	// Executor starts itself
						}
						else
						{
							try
							{
								exe = (ISpaceExecutor)((Class)MEnvSpaceType.getProperty(mse, "clazz")).newInstance();
								List props = (List)mse.get("properties");
								MEnvSpaceType.setProperties(exe, props, fetcher);
							}
							catch(Exception e)
							{
								ret.setException(e);
							}
						}
						if(exe!=null)
							exe.start();
					}
					ret.setResultIfUndone(result);
				}
			});
		}
		catch(Exception e)
		{
			ret.setException(e);
		}

		// In case of errors dispose observer centers if any.
		ret.addResultListener(new IResultListener()
		{
			public void resultAvailable(Void result)
			{
			}

			public void exceptionOccurred(Exception exception)
			{
				exception.printStackTrace();
				SwingUtilities.invokeLater(new Runnable()
				{
					public void run()
					{
						for(int i=0; observercenters!=null && i waitForTask(Object taskid, Object objectid)
	{
		final Future ret = new Future(); 
		SpaceObject so = (SpaceObject)getSpaceObject(objectid);
		so.addTaskListener(taskid, new IResultListener()
		{
			public void resultAvailable(Object result)
			{
				ret.setResultIfUndone(null);
			}
			
			public void exceptionOccurred(Exception exception)
			{
				ret.setExceptionIfUndone(exception);
			}
		});
		return ret;
	}
	
	/**
	 * 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);
			if(properties!=null)
				properties = new HashMap(properties);
			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))
			{
				Object owner = 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))
			{
				Object owner = 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 initproperties initial properties (may be null)
	 * @param tasks initial task list (may be null)
	 * @param listeners initial listeners (may be null)
	 */
	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.get(ret.getType())!=null)
			{
				for(Iterator it=dataviewmappings.get(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)MEnvSpaceType.getProperty(sourceview, "creator")).createObject(viewargs);
						addDataView((String)MEnvSpaceType.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;
					
					getExternalAccess().getFileName(compotype).addResultListener(new DefaultResultListener()
					{
						public void resultAvailable(Object result)
						{
							final String filename = (String)result;
							
							SServiceProvider.getService(exta, IComponentManagementService.class, RequiredServiceInfo.SCOPE_PLATFORM).addResultListener(new DefaultResultListener()
							{
								public void resultAvailable(Object result)
								{
									IComponentManagementService cms = (IComponentManagementService)result;
									// cannot be dummy cid because agent calls getAvatar(cid) in init and needs its avatar
									// the cid must be the final cid of the component hence it creates unique ids
///									IComponentIdentifier cid = cms.generateComponentIdentifier(SUtil.createUniqueId(compotype, 3), getExternalAccess().getComponentIdentifier().getName().replace("@", "."));
									// SUtil.createUniqueId(compotype, 3) might lead to conflicts due to race conditions. Use object id as it is really unique.
//									IComponentIdentifier cid = cms.generateComponentIdentifier(compotype+"_"+ret.getId(), getExternalAccess().getComponentIdentifier().getName().replace("@", "."));
									// todo: can fail?
									IComponentIdentifier cid = new BasicComponentIdentifier(compotype+"_"+ret.getId(), getExternalAccess().getComponentIdentifier());
//									IComponentIdentifier cid = new ComponentIdentifier("dummy@hummy");
									// Hack!!! Should have actual description and not just name and local type!?
									CMSComponentDescription desc = new CMSComponentDescription();
									desc.setName(cid);
									desc.setLocalType(compotype);
									setOwner(ret.getId(), desc);
//									System.out.println("env create: "+cid);
									IFuture	future	= cms.createComponent(cid.getLocalName(), filename,
										new CreationInfo(null, null, getExternalAccess().getComponentIdentifier(), false, getExternalAccess().getModel().getAllImports()), null);
									future.addResultListener(new IResultListener()
									{
										public void resultAvailable(Object result)
										{
//											System.out.println("env created: "+result);
//											setOwner(ret.getId(), (IComponentIdentifier)result);
										}
										
										public void exceptionOccurred(final Exception exception)
										{
											exta.scheduleStep(new IComponentStep()
											{
												public IFuture execute(IInternalAccess ia)
												{
													// Todo: Propagate exception to kill application!
													StringWriter	sw	= new StringWriter();
													exception.printStackTrace(new PrintWriter(sw));
													ia.getLogger().severe("Could not create component: "+compotype+"\n"+exception);
													return IFuture.DONE;
												}
											});
										}
									});
								}
							});
						}
					});
				}
			}
		}
		
		if(listeners!=null)
		{
			EnvironmentEvent event = new EnvironmentEvent(EnvironmentEvent.OBJECT_CREATED, this, ret, null, null);
			for(int i=0; i1)
					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(IComponentDescription 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(IComponentDescription 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	= owner.getLocalType();
			if(componenttype==null && fullname!=null)
			{
				SubcomponentTypeInfo[] atypes = exta.getModel().getSubcomponentTypes();
				for(int i=0; i 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();
	}
	
	/**
	 *  Initialize the extension.
	 *  Called once, when the extension is created.
	 */
	public IFuture	init()
	{
//		space = (ISpace)getClazz().newInstance();

		final Future	ret	= new Future();
		
		initSpace().addResultListener(ia.getComponentFeature(IExecutionFeature.class).createResultListener(new DelegationResultListener(ret)
		{
			public void customResultAvailable(Void result)
			{
//				System.out.println("inited space");
				
//				ia.addComponentListener(new IComponentListener()
//				{
//					IFilter filter = new IFilter()
//					{
//						public boolean filter(Object obj)
//						{
//							IComponentChangeEvent event = (IComponentChangeEvent)obj;
//							return event.getSourceCategory().equals(StatelessAbstractInterpreter.TYPE_COMPONENT);
//						}
//					};
//					public IFilter getFilter()
//					{
//						return filter;
//					}
//					
//					public IFuture eventOccured(IComponentChangeEvent cce)
//					{
//						if(cce.getEventType().equals(IComponentChangeEvent.EVENT_TYPE_CREATION))
//						{
////									System.out.println("add: "+cce.getDetails());
//							componentAdded((IComponentDescription)cce.getDetails());
//						}
//						else if(cce.getEventType().equals(IComponentChangeEvent.EVENT_TYPE_DISPOSAL))
//						{
////									System.out.println("rem: "+cce.getComponent());
//							componentRemoved((IComponentDescription)cce.getDetails());
//						}
//						return IFuture.DONE;
//					}
//				});
				
				final ISubscriptionIntermediateFuture sub = ia.getComponentFeature(IMonitoringComponentFeature.class).subscribeToEvents(new IFilter()
				{
					public boolean filter(IMonitoringEvent obj)
					{
						return obj.getType().endsWith(IMonitoringEvent.SOURCE_CATEGORY_COMPONENT)
							|| obj.getType().equals(IMonitoringEvent.TYPE_SUBSCRIPTION_START);
					}
				}, false, PublishEventLevel.COARSE);
				
//				System.out.println("sub add: "+this);
				sub.addResultListener(new IIntermediateFutureCommandResultListener()
				{
					public void resultAvailable(Collection result)
					{
					}
					
					public void intermediateResultAvailable(IMonitoringEvent result)
					{
//						System.out.println("rec: "+result);
						if(result.getType().equals(IMonitoringEvent.TYPE_SUBSCRIPTION_START))
						{
//							System.out.println("space subscribed");
							ret.setResult(null);
						}
						else if(result.getType().startsWith(IMonitoringEvent.EVENT_TYPE_CREATION))
						{
//							System.out.println("add: "+result);
							componentAdded((IComponentDescription)result.getProperty("details"));	
						}
						else if(result.getType().startsWith(IMonitoringEvent.EVENT_TYPE_DISPOSAL))
						{
							componentRemoved((IComponentDescription)result.getProperty("details"));
						}
					}
					
				    public void finished()
				    {
//				    	System.out.println("fini");
				    }
				    
				    public void exceptionOccurred(Exception e)
				    {
				    	e.printStackTrace();
				    }
				    
				    public void commandAvailable(Object command)
				    {
				    	// ignore timer updates
				    }
				});
			}
		}));	
		return ret;
	}
	
	/**
	 *  Terminate the extension.
	 *  Called once, when the extension is terminated.
	 */
	public IFuture terminate()
	{
//		System.err.println("terminate space: "+exta.getComponentIdentifier());
		final Future	ret	= new Future();
		final IObserverCenter[]	ocs	= (IObserverCenter[])observercenters.toArray(new IObserverCenter[observercenters.size()]);
		SwingUtilities.invokeLater(new Runnable()
		{
			public void run()
			{
				try
				{
					for(int i=0; i