package jadex.base.gui.componenttree;
import jadex.bridge.IComponentDescription;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.IComponentManagementService;
import jadex.bridge.IExternalAccess;
import jadex.commons.Future;
import jadex.commons.IFuture;
import jadex.commons.concurrent.DelegationResultListener;
import jadex.commons.concurrent.SwingDefaultResultListener;
import jadex.commons.service.IService;
import jadex.commons.service.IServiceContainer;
import jadex.commons.service.SServiceProvider;
import java.util.ArrayList;
import java.util.List;
import javax.swing.Icon;
import javax.swing.JComponent;
import javax.swing.JTree;
/**
* Node object representing a service container.
*/
public class ComponentTreeNode extends AbstractComponentTreeNode implements IActiveComponentTreeNode
{
//-------- attributes --------
/** The component description. */
protected IComponentDescription desc;
/** The component management service. */
protected final IComponentManagementService cms;
/** The icon cache. */
protected final ComponentIconCache iconcache;
/** The properties component (if any). */
protected ComponentProperties propcomp;
//-------- constructors --------
/**
* Create a new service container node.
*/
public ComponentTreeNode(IComponentTreeNode parent, ComponentTreeModel model, JTree tree, IComponentDescription desc,
IComponentManagementService cms, ComponentIconCache iconcache)
{
super(parent, model, tree);
assert desc!=null;
this.desc = desc;
this.cms = cms;
this.iconcache = iconcache;
model.registerNode(this);
}
//-------- AbstractComponentTreeNode methods --------
/**
* Get the id used for lookup.
*/
public Object getId()
{
return desc.getName();
}
/**
* Get the icon for a node.
*/
public Icon getIcon()
{
return iconcache.getIcon(this, desc.getType());
}
/**
* Refresh the node.
* @param recurse Recursively refresh subnodes, if true.
*/
public void refresh(boolean recurse, boolean force)
{
cms.getComponentDescription(desc.getName()).addResultListener(new SwingDefaultResultListener()
{
public void customResultAvailable(Object source, Object result)
{
ComponentTreeNode.this.desc = (IComponentDescription)result;
getModel().fireNodeChanged(ComponentTreeNode.this);
}
public void customExceptionOccurred(Object source, Exception exception)
{
// ignore
}
});
super.refresh(recurse, force);
}
/**
* Asynchronously search for children.
* Should call setChildren() once children are found.
*/
protected void searchChildren(boolean force)
{
final List children = new ArrayList();
final boolean ready[] = new boolean[2]; // 0: children, 1: services;
final Future future = new Future(); // future for determining when services can be added to service container.
cms.getChildren(desc.getName()).addResultListener(new SwingDefaultResultListener()
{
public void customResultAvailable(Object source, Object result)
{
final IComponentIdentifier[] achildren = (IComponentIdentifier[])result;
final int[] childcnt = new int[]{0};
if(achildren!=null && achildren.length > 0)
{
for(int i=0; i<achildren.length; i++)
{
cms.getComponentDescription(achildren[i]).addResultListener(new SwingDefaultResultListener()
{
public void customResultAvailable(Object source, Object result)
{
IComponentDescription desc = (IComponentDescription)result;
IComponentTreeNode node = getModel().getNode(desc.getName());
if(node==null)
{
createComponentNode(desc).addResultListener(new SwingDefaultResultListener()
{
public void customResultAvailable(Object source, Object result)
{
// System.err.println(getModel().hashCode()+", "+ready.hashCode()+" searchChildren.add "+result);
children.add(result);
childcnt[0]++;
// Last child? -> inform listeners
if(childcnt[0] == achildren.length)
{
ready[0] = true;
if(ready[0] && ready[1])
{
setChildren(children).addResultListener(new DelegationResultListener(future));
}
}
}
public void customExceptionOccurred(Object source, Exception exception)
{
// May happen, when component removed in mean time.
childcnt[0]++;
// Last child? -> inform listeners
if(childcnt[0] == achildren.length)
{
ready[0] = true;
if(ready[0] && ready[1])
{
setChildren(children).addResultListener(new DelegationResultListener(future));
}
}
}
});
}
else
{
// System.err.println(getModel().hashCode()+", "+ready.hashCode()+" searchChildren.add "+node);
children.add(node);
childcnt[0]++;
// Last child? -> inform listeners
if(childcnt[0] == achildren.length)
{
ready[0] = true;
if(ready[0] && ready[1])
{
setChildren(children).addResultListener(new DelegationResultListener(future));
}
}
}
}
public void customExceptionOccurred(Object source, Exception exception)
{
childcnt[0]++;
// Last child? -> inform listeners
if(childcnt[0] == achildren.length)
{
ready[0] = true;
if(ready[0] && ready[1])
{
setChildren(children).addResultListener(new DelegationResultListener(future));
}
}
}
});
}
}
else
{
ready[0] = true;
if(ready[0] && ready[1])
{
setChildren(children).addResultListener(new DelegationResultListener(future));
}
}
}
public void customExceptionOccurred(Object source, Exception exception)
{
// ignore
}
});
// Search services and only add container node when services are found.
cms.getExternalAccess(desc.getName()).addResultListener(new SwingDefaultResultListener()
{
public void customResultAvailable(Object source, Object result)
{
final IExternalAccess ea = (IExternalAccess)result;
SServiceProvider.getDeclaredServices(ea.getServiceProvider()).addResultListener(new SwingDefaultResultListener()
{
public void customResultAvailable(Object source, Object result)
{
List services = (List)result;
if(services!=null && !services.isEmpty())
{
ServiceContainerNode scn = (ServiceContainerNode)getModel().getNode(desc.getName().getName()+"ServiceContainer");
if(scn==null)
scn = new ServiceContainerNode(ComponentTreeNode.this, getModel(), getTree(), (IServiceContainer)ea.getServiceProvider());
// System.err.println(getModel().hashCode()+", "+ready.hashCode()+" searchChildren.add "+scn);
children.add(0, scn);
final List subchildren = new ArrayList();
for(int i=0; i<services.size(); i++)
{
IService service = (IService)services.get(i);
ServiceNode sn = (ServiceNode)getModel().getNode(service.getServiceIdentifier());
if(sn==null)
sn = new ServiceNode(scn, getModel(), getTree(), service);
subchildren.add(sn);
}
final ServiceContainerNode node = scn;
future.addResultListener(new SwingDefaultResultListener()
{
public void customResultAvailable(Object source, Object result)
{
node.setChildren(subchildren);
}
public void customExceptionOccurred(Object source, Exception exception)
{
// Shouldn't happen???
}
});
}
ready[1] = true;
if(ready[0] && ready[1])
{
setChildren(children).addResultListener(new DelegationResultListener(future));
}
}
public void customExceptionOccurred(Object source, Exception exception)
{
ready[1] = true;
if(ready[0] && ready[1])
{
setChildren(children).addResultListener(new DelegationResultListener(future));
}
}
});
}
public void customExceptionOccurred(Object source, Exception exception)
{
// May happen, when components already removed.
}
});
}
//-------- methods --------
/**
* Create a new component node.
*/
public IFuture createComponentNode(final IComponentDescription desc)
{
final Future ret = new Future();
cms.getExternalAccess(desc.getName()).addResultListener(new SwingDefaultResultListener()
{
public void customResultAvailable(Object source, Object result)
{
IComponentTreeNode node = getModel().getNode(desc.getName());
if(node==null)
{
IExternalAccess exta = (IExternalAccess)result;
boolean proxy = "jadex.base.service.remote.Proxy".equals(exta.getModel().getFullName());
if(proxy)
{
node = new ProxyComponentTreeNode(ComponentTreeNode.this, getModel(), getTree(), desc, cms, iconcache);
}
else
{
node = new ComponentTreeNode(ComponentTreeNode.this, getModel(), getTree(), desc, cms, iconcache);
}
}
ret.setResult(node);
}
public void customExceptionOccurred(Object source, Exception exception)
{
ret.setException(exception);
}
});
return ret;
}
/**
* Create a string representation.
*/
public String toString()
{
return desc.getName().getLocalName();
}
/**
* Get the component description.
*/
public IComponentDescription getDescription()
{
return desc;
}
/**
* Get the component id.
*/
public IComponentIdentifier getComponentIdentifier()
{
return desc!=null? desc.getName(): null;
}
/**
* Set the component description.
*/
public void setDescription(IComponentDescription desc)
{
this.desc = desc;
if(propcomp!=null)
{
propcomp.setDescription(desc);
propcomp.repaint();
}
}
/**
* True, if the node has properties that can be displayed.
*/
public boolean hasProperties()
{
return true;
}
/**
* Get or create a component displaying the node properties.
* Only to be called if hasProperties() is true;
*/
public JComponent getPropertiesComponent()
{
if(propcomp==null)
{
propcomp = new ComponentProperties();
}
propcomp.setDescription(desc);
return propcomp;
}
}