/* * BasicTreeServant.java * * Created on May 12, 2003, 11:16 AM */ package hep.aida.ref.remote.basic; import hep.aida.IAnalysisFactory; import hep.aida.IBaseHistogram; import hep.aida.IHistogram1D; import hep.aida.IHistogramFactory; import hep.aida.IManagedObject; import hep.aida.ITree; import hep.aida.ITreeFactory; import hep.aida.ref.event.AIDAListener; import hep.aida.ref.event.HistogramEvent; import hep.aida.ref.event.IsObservable; import hep.aida.ref.event.TreeEvent; import hep.aida.ref.remote.basic.interfaces.AidaTreeClient; import hep.aida.ref.remote.basic.interfaces.AidaTreeServant; import hep.aida.ref.remote.basic.interfaces.UpdateEvent; import hep.aida.ref.tree.Tree; import java.util.EventObject; import java.util.Vector; /** * Basic implementation of the AidaTreeServant, no remote stuff. * @author serbo */ public class BasicTreeServant extends Thread implements AidaTreeServant, AIDAListener { protected ITree tree; protected AidaTreeClient client; protected String clientID; protected boolean duplex; protected boolean keepRunning; protected Vector sources; protected ServerQueue queue; protected boolean useValidation; /** Creates a new instance of BasicTreeServant */ public BasicTreeServant(ITree tree, String clientID) { System.out.println("BasicTreeServant() clientID="+clientID); this.tree = tree; this.clientID = clientID; this.client = null; duplex = false; init(); } public BasicTreeServant(ITree tree, AidaTreeClient client) { System.out.println("BasicTreeServant() client="+client); this.tree = tree; this.clientID = null; this.client = client; duplex = true; init(); this.start(); // Start thread that pushes updates into the client. } // Service methods protected void init() { sources = new Vector(); queue = new ServerQueue(); useValidation = true; keepRunning = duplex; if (tree instanceof IsObservable) { ((IsObservable) tree).addListener(this); sources.add(tree); ((IsObservable) tree).setValid(this); } if (tree instanceof hep.aida.ref.tree.Tree) ((Tree) tree).setFolderIsWatched("/", true); } /** * If useValidation = true, client has to call "setValid" method after * receiving update from the ManagedObject in order to reseive next update. * If useValidation = false, client receives all updates. */ public void setUseValidation(boolean state) { useValidation = state; } public void close() { synchronized ( this ) { System.out.print("\n\tClosing BasicTreeServant ... "); keepRunning = false; if (duplex) synchronized ( queue ) { queue.notify(); } for (int i=0; i<sources.size(); i++) { IsObservable o = (IsObservable) sources.get(i); if (o != null) o.removeListener(this); } sources.clear(); sources = null; tree = null; client = null; queue.close(); queue = null; System.out.print(" Done\n"); } } // AidaTreeServant methods public java.lang.Object find(String path) { IManagedObject mo = tree.find(path); //System.out.println("BasicTreeServant.find path="+path+", mo="+mo); if (mo instanceof IsObservable && !sources.contains(mo)) { ((IsObservable) mo).addListener(this); sources.add(mo); } if (!useValidation && mo instanceof IsObservable) ((IsObservable) mo).setValid(this); return mo; } public String[] listObjectNames(String path) { //System.out.println("BasicTreeServant.listObjectNames path="+path); if (tree instanceof hep.aida.ref.tree.Tree) ((Tree) tree).setFolderIsWatched(path, true); return tree.listObjectNames(path); } public String[] listObjectTypes(String path) { //System.out.println("BasicTreeServant.listObjectTypes path="+path); if (tree instanceof hep.aida.ref.tree.Tree) ((Tree) tree).setFolderIsWatched(path, true); return tree.listObjectTypes(path); } public void setValid(String[] paths) { if (paths == null || paths.length == 0) return; for (int i=0; i<paths.length; i++) { if (paths[i] == null || paths[i].equals("") || paths[i].equals("/") ) { if (tree instanceof IsObservable) ((IsObservable) tree).setValid(this); } else { IManagedObject mo = tree.find(paths[i]); if (mo instanceof IsObservable && !sources.contains(mo)) { ((IsObservable) mo).addListener(this); sources.add(mo); } //System.out.println("BasicTreeServant.setValid: name="+mo.name()+", path="+paths[i]); if (mo instanceof IsObservable) ((IsObservable) mo).setValid(this); } } } /** * This method can be used only in non-Duplex mode. Never returns null. */ public UpdateEvent[] updates() { UpdateEvent[] events = new UpdateEvent[0]; if (!duplex) { events = queue.getEvents(); } //System.out.println("BasicTreeServant.updates: return "+events.length+" events."); return events; } // AIDAListener methods /** * Create new UpdateEvent from the EventObject and put it in the queue * of current updates. This method is called by "IsObservable" sources * to report their change of state. */ public void stateChanged(EventObject ev) { int id = -1; String pathString = ""; String nodeType = "null"; if (ev instanceof TreeEvent) { TreeEvent tev = (TreeEvent) ev; //System.out.println("BasicTreeServant.stateChanged GOT TreeEvent: id="+tev.getID()+", type="+ // tev.getType()+", flags="+tev.getFlags()+ // ", path="+(tev.getPath())[(tev.getPath()).length-1]); String[] path = tev.getPath(); if (path != null) for (int i=0; i<path.length; i++) { pathString += "/" + path[i]; } if (tev.getType() != null) nodeType = tev.getType().getName(); if (tev.getFlags() == TreeEvent.FOLDER_MASK) nodeType = "dir"; if ( tev.getID()== TreeEvent.NODE_ADDED) { id = UpdateEvent.NODE_ADDED; IManagedObject hist = tree.find(pathString); nodeType = hist.type(); } else if ( tev.getID()== TreeEvent.NODE_DELETED) id = UpdateEvent.NODE_DELETED; //else if ( tev.getID()== TreeEvent.NODE_RENAMED) id = UpdateEvent.NODE_UPDATED; else id = -1; if (tree instanceof IsObservable) ((IsObservable) tree).setValid(this); } else if (ev instanceof HistogramEvent) { IBaseHistogram hist = (IBaseHistogram) ev.getSource(); id = UpdateEvent.NODE_UPDATED; pathString = tree.findPath((IManagedObject) hist); nodeType = ((IManagedObject)hist).type(); if (!useValidation && hist instanceof IsObservable) ((IsObservable) hist).setValid(this); } if (id >= 0) { queue.schedule((UpdateEvent) (new BasicUpdateEvent(id, pathString, nodeType))); //System.out.println("TreeServant: process Event: id = "+id+", path = "+pathString+", type = "+nodeType); } } // Thread methods public void run() { while (duplex && keepRunning) { int size = 0; UpdateEvent[] events = null; try { synchronized ( queue ) { if(queue.size() == 0) queue.wait(); size = (queue == null) ? 0 : queue.size(); if (size > 0) events = queue.getEvents(); } //System.out.println("ServerQueue.run Processing: "+size); if (events == null || events.length == 0) return; client.stateChanged(events); } catch (InterruptedException e2) { System.out.println("ServerQueue Thread InterruptedException."); e2.printStackTrace(); } catch (Exception e3) { System.out.println("Problems in ServerQueue!."); e3.printStackTrace(); } // end of try/catch } // end of while } public static void main(String[] args) { java.util.Random r = new java.util.Random(); IAnalysisFactory af = IAnalysisFactory.create(); ITreeFactory tf = af.createTreeFactory(); ITree serverTree = tf.create(); ((IsObservable) serverTree).addListener(new TestBasic((Tree) serverTree)); IHistogramFactory histogramFactory = af.createHistogramFactory(serverTree); int nEntries = 1000; int xbins = 10; double xLowerEdge = -10.; double xUpperEdge = 10.; serverTree.mkdir("/dir1"); IHistogram1D h1 = histogramFactory.createHistogram1D("Hist-1",xbins,xLowerEdge,xUpperEdge); IHistogram1D h2 = histogramFactory.createHistogram1D("Hist-2",xbins,xLowerEdge,xUpperEdge); /* Fill the histogram */ for (int i=0; i<nEntries; i++) { double xval = r.nextGaussian()*3+2.; h1.fill( xval ); xval = r.nextGaussian()*3+2.; h2.fill( xval ); } System.out.println("Creating TreeServant ..."); BasicTreeServant servant = new BasicTreeServant(serverTree, "Test Servant"); try { System.out.println("Servant is ready. To add Hist-3 press ENTER"); System.in.read(); IHistogram1D h3 = histogramFactory.createHistogram1D("Hist-1",xbins,xLowerEdge,xUpperEdge); System.out.println("To call \"updates()\" press ENTER"); System.in.read(); UpdateEvent[] ue = servant.updates(); System.out.println("Got "+ue.length+" events"); for (int i=0; i<ue.length; i++) System.out.println("Event "+i+" id="+ue[i].id()+" path="+ue[i].path()+" type="+ue[i].nodeType()); } catch(Exception e) { e.printStackTrace(); } } }