package org.objectweb.proactive.ic2d.gui.jobmonitor;

import org.objectweb.proactive.core.ProActiveException;
import org.objectweb.proactive.core.body.rmi.RemoteBodyAdapter;
import org.objectweb.proactive.core.runtime.ProActiveRuntime;
import org.objectweb.proactive.core.runtime.rmi.*;
import org.objectweb.proactive.ic2d.gui.IC2DGUIController;
import org.objectweb.proactive.ic2d.gui.jobmonitor.data.DataAssociation;

import java.rmi.*;
import java.rmi.registry.*;

import java.util.*;


public class NodeExploration implements JobMonitorConstants {
    private static final String PA_JVM = "PA_JVM";
    private int maxDepth;
    private DataAssociation asso;
    private Vector filteredJobs;
    private IC2DGUIController controller;
    private Map aos;
    private Set visitedVM;

    public NodeExploration(DataAssociation asso, Vector filteredJobs,
        IC2DGUIController controller) {
        this.maxDepth = 1;
        this.asso = asso;
        this.filteredJobs = filteredJobs;
        this.controller = controller;
        this.aos = new HashMap();
    }

    public int getMaxDepth() {
        return maxDepth;
    }

    public void setMaxDepth(int maxDepth) {
        if (maxDepth > 0) {
            this.maxDepth = maxDepth;
        }
    }

    public void exploreHost(String hostname, int port) {
        try {
            visitedVM = new TreeSet();
            Registry registry = LocateRegistry.getRegistry(hostname, port);
            String[] list = registry.list();

            for (int idx = 0; idx < list.length; ++idx) {
                String id = list[idx];
                if (id.indexOf(PA_JVM) != -1) {
                    RemoteProActiveRuntime r = (RemoteProActiveRuntime) registry.lookup(id);
                    List x = new ArrayList();
                    try {
                        ProActiveRuntime part = new RemoteProActiveRuntimeAdapter(r);
                        x.add(part);

                        ProActiveRuntime[] runtimes = r.getProActiveRuntimes();
                        x.addAll(Arrays.asList(runtimes));

                        for (int i = 0, size = x.size(); i < size; ++i) {
                            handleProActiveRuntime((ProActiveRuntime) x.get(i), 1);
                        }
                    } catch (ProActiveException e) {
                        //						System.out.println ("Unexpected ProActive exception caught while obtaining runtime reference from the RemoteProActiveRuntime instance - The RMI reference might be dead: " + e);
                        //						e.printStackTrace();
                    } catch (RemoteException e) {
                        //						System.out.println ("Unexpected remote exception caught while getting proactive runtimes: " + e);
                        //						e.printStackTrace();
                    }
                }
            }
        } catch (RemoteException e) {
            //			System.out.println("Unexpected exception caught while getting registry reference: " + e);
            //			e.printStackTrace();
        } catch (NotBoundException e) {
            //			System.out.println("Unexpected not bound exception caught while looking up object reference: " + e);
            //			e.printStackTrace();
        } finally {
            visitedVM = null;
        }
    }

    private void handleProActiveRuntime(ProActiveRuntime pr, int depth)
        throws ProActiveException {
    	
    	if (pr instanceof RemoteProActiveRuntime && !(pr instanceof RemoteProActiveRuntimeAdapter))
    		pr = new RemoteProActiveRuntimeAdapter((RemoteProActiveRuntime) pr);

        String vmName = pr.getVMInformation().getName();
    	
        if (isJobFiltered(pr.getJobID()) || visitedVM.contains(vmName))
            return;
   
        visitedVM.add(vmName);

        String jobId = pr.getJobID();
        String hostname = pr.getVMInformation().getInetAddress()
                            .getCanonicalHostName();

        asso.addChild(JOB, jobId, vmName);

        String[] nodes = pr.getLocalNodeNames();

        //		System.out.println ("Found " + nodes.length + " nodes on this runtime");
        for (int i = 0; i < nodes.length; ++i) {
            String nodeName = nodes[i];
            String vnName = pr.getVNName(nodeName);

            ArrayList activeObjects = null;
            try {
                activeObjects = pr.getActiveObjects(nodeName);
            } catch (ProActiveException e) {
                controller.log("Unexpected ProActive exception caught while obtaining the active objects list",
                    e);
            }

            asso.addChild(JVM, vmName, nodeName);
            asso.addChild(HOST, hostname, JVM, vmName);
            if (vnName != null) {
                asso.addChild(VN, vnName, NODE, nodeName);
            }
            if (activeObjects != null)
            	handleActiveObjects(nodeName, activeObjects);
        }

        if (depth < maxDepth) {
        	ProActiveRuntime[] runtimes = pr.getProActiveRuntimes();
            for (int i = 0; i < runtimes.length; ++i)
                handleProActiveRuntime(runtimes[i], depth + 1);
        }
    }

    private void handleActiveObjects(String nodeName, ArrayList activeObjects) {
        for (int i = 0, size = activeObjects.size(); i < size; ++i) {
            ArrayList aoWrapper = (ArrayList) activeObjects.get(i);
            RemoteBodyAdapter rba = (RemoteBodyAdapter) aoWrapper.get(0);

            //			System.out.println ("Active object " + (i + 1) + " / " + size + " class: " + aoWrapper.get (1));
            String className = (String) aoWrapper.get(1);
            if (className.equalsIgnoreCase(
                        "org.objectweb.proactive.ic2d.spy.Spy")) {
                continue;
            }

            className = className.substring(className.lastIndexOf(".") + 1);
            String aoName = (String) aos.get(rba.getID());
            if (aoName == null) {
                aoName = className + "#" + (aos.size() + 1);
                aos.put(rba.getID(), aoName);
            }

            asso.addChild(NODE, nodeName, aoName);
        }
    }

    private boolean isJobFiltered(String jobId) {
        for (int i = 0, size = filteredJobs.size(); i < size; ++i) {
            String job = (String) filteredJobs.get(i);
            if (job.equalsIgnoreCase(jobId)) {
                return true;
            }
        }

        return false;
    }
}

@@ -914,17 +914,17 @@
 Depth = 
-1
+4
 ;%0A      

Use the node exploration by default