package jadex.base.gui.componenttree; import jadex.base.service.remote.ProxyAgent; import jadex.bridge.IComponentDescription; import jadex.bridge.IComponentIdentifier; import jadex.bridge.IComponentManagementService; import jadex.bridge.IComponentStep; import jadex.bridge.IInternalAccess; import jadex.commons.Future; import jadex.commons.IFuture; import jadex.commons.SGUI; import jadex.commons.concurrent.DelegationResultListener; import jadex.commons.concurrent.IResultListener; import jadex.commons.concurrent.SwingDefaultResultListener; import jadex.commons.gui.CombiIcon; import jadex.commons.service.IService; import jadex.micro.IMicroExternalAccess; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import javax.swing.Icon; import javax.swing.JTree; import javax.swing.Timer; import javax.swing.UIDefaults; /** * Node that represents a remote component and blends in the * tree of components as virtual children of this node. */ public class ProxyComponentTreeNode extends ComponentTreeNode { //-------- constants -------- /** * The image icons. */ protected static final UIDefaults icons = new UIDefaults(new Object[] { "overlay_proxy_noconnection", SGUI.makeIcon(ProxyComponentTreeNode.class, "/jadex/base/gui/images/overlay_proxy_noconnection.png"), "overlay_proxy_connection", SGUI.makeIcon(ProxyComponentTreeNode.class, "/jadex/base/gui/images/overlay_proxy_connection.png"), }); //-------- attribute -------- /** The remote component identifier.*/ protected IComponentIdentifier cid; /** The connection state. */ protected boolean connected; /** The auto refresh timer. */ protected Timer timer; //-------- constructors -------- /** * Create a new service container node. */ public ProxyComponentTreeNode(final IComponentTreeNode parent, ComponentTreeModel model, JTree tree, IComponentDescription desc, IComponentManagementService cms, ComponentIconCache iconcache) { super(parent, model, tree, desc, cms, iconcache); this.connected = false; timer = new Timer(10000, new ActionListener() { public void actionPerformed(ActionEvent e) { // hmm?! with or without subtree? refresh(true, false); } }); timer.start(); } /** * Called when the node is removed or the tree is closed. */ public void dispose() { timer.stop(); } /** * Get the cid. * @return the cid. */ public IComponentIdentifier getComponentIdentifier() { if(cid==null) getRemoteComponentIdentifier(); return cid; } /** * Get the icon for a node. */ public Icon getIcon() { Icon ret = null; Icon base = super.getIcon(); if(base!=null) { ret = new CombiIcon(new Icon[]{base, connected? icons.getIcon("overlay_proxy_connection"): icons.getIcon("overlay_proxy_noconnection")}); } return ret; } /** * Asynchronously search for children. * Called once for each node. * Should call setChildren() once children are found. */ protected void searchChildren(final boolean force) { getRemoteComponentIdentifier().addResultListener(new SwingDefaultResultListener() { public void customResultAvailable(Object source, Object result) { final Future future = new Future(); searchChildren(cms, ProxyComponentTreeNode.this, desc, cid, iconcache, future, force) .addResultListener(new SwingDefaultResultListener() { public void customResultAvailable(Object source, Object result) { setChildren((List)result).addResultListener(new DelegationResultListener(future)); connected = true; } public void customExceptionOccurred(Object source, Exception exception) { setChildren(Collections.EMPTY_LIST); connected = false; // exception.printStackTrace(); } }); } public void customExceptionOccurred(Object source, Exception exception) { setChildren(Collections.EMPTY_LIST); connected = false; // exception.printStackTrace(); } }); } /** * Create a string representation. */ public String toString() { return cid==null? desc.getName().getLocalName(): desc.getName().getLocalName()+"("+cid+")"; } /** * Asynchronously search for children. * Called once for each node. * Should call setChildren() once children are found. */ protected static IFuture searchChildren(final IComponentManagementService cms, final IComponentTreeNode parentnode, final IComponentDescription desc, final IComponentIdentifier cid, final ComponentIconCache iconcache, final // future for determining when services can be added to service container. Future future, final boolean force) { final Future ret = new Future(); final List children = new ArrayList(); final boolean ready[] = new boolean[2]; // 0: children, 1: services; IComponentTreeNode tmp = parentnode; while(!(tmp instanceof ProxyComponentTreeNode)) tmp = tmp.getParent(); final ProxyComponentTreeNode proxy = (ProxyComponentTreeNode)tmp; cms.getExternalAccess(proxy.getDescription().getName()).addResultListener(new IResultListener() { public void resultAvailable(Object source, Object result) { final IMicroExternalAccess exta = (IMicroExternalAccess)result; exta.scheduleStep(new IComponentStep() { public Object execute(IInternalAccess ia) { ProxyAgent pa = (ProxyAgent)ia; pa.getVirtualChildren(cid, force).addResultListener(new SwingDefaultResultListener() { public void customResultAvailable(Object source, Object result) { IComponentDescription[] descs = (IComponentDescription[]) ((Collection)result).toArray(new IComponentDescription[((Collection)result).size()]); for(int i=0; i<descs.length; i++) { IComponentTreeNode node = proxy.getModel().getNode(descs[i].getName()); if(node==null) { node = new VirtualComponentTreeNode(parentnode, proxy.getModel(), proxy.getTree(), descs[i], cms, iconcache); } // System.err.println(proxy.getModel().hashCode()+", "+ready.hashCode()+" searchChildren.add "+node); children.add(node); } ready[0] = true; if(ready[0] && ready[1]) { ret.setResult(children); } } public void customExceptionOccurred(Object source, Exception exception) { // 2 parallel search branches, i.e. one may fail first ret.setExceptionIfUndone(exception); } }); return null; } }); exta.scheduleStep(new IComponentStep() { public Object execute(IInternalAccess ia) { ProxyAgent pa = (ProxyAgent)ia; pa.getRemoteServices(cid).addResultListener(new SwingDefaultResultListener() { public void customResultAvailable(Object source, Object result) { List services = (List)result; if(services!=null && !services.isEmpty()) { ServiceContainerNode scn = (ServiceContainerNode) proxy.getModel().getNode(desc.getName().getName()+"ServiceContainer"); if(scn==null) scn = new ServiceContainerNode(parentnode, proxy.getModel(), proxy.getTree(), null); // System.err.println(proxy.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)proxy.getModel().getNode(service.getServiceIdentifier()); if(sn==null) sn = new ServiceNode(scn, proxy.getModel(), proxy.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]) { ret.setResult(children); } } public void customExceptionOccurred(Object source, Exception exception) { // 2 parallel search branches, i.e. one may fail first ret.setExceptionIfUndone(exception); } }); return null; } }); } public void exceptionOccurred(Object source, Exception exception) { ret.setException(exception); } }); return ret; } /** * Get the remote component identifier. * @return The remote identifier. */ public IFuture getRemoteComponentIdentifier() { final Future ret = new Future(); if(cid==null) { cms.getExternalAccess(desc.getName()).addResultListener(new IResultListener() { public void resultAvailable(Object source, Object result) { final IMicroExternalAccess exta = (IMicroExternalAccess)result; exta.scheduleStep(new IComponentStep() { public Object execute(IInternalAccess ia) { ProxyAgent pa = (ProxyAgent)ia; cid = pa.getRemotePlatformIdentifier(); ret.setResult(cid); return null; } }); } public void exceptionOccurred(Object source, Exception exception) { ret.setException(exception); } }); } else { ret.setResult(cid); } return ret; } /** * Get the connected. * @return the connected. */ public boolean isConnected() { return connected; } }