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

admin.astor.tools.DeviceHierarchy Maven / Gradle / Ivy

//+======================================================================
// $Source:  $
//
// Project:   Tango
//
// Description:  java source code for Tango manager tool..
//
// $Author$
//
// Copyright (C) :      2004,2005,2006,2007,2008,2009,2010,2011,2012,2013,2014,2015,
//						European Synchrotron Radiation Facility
//                      BP 220, Grenoble 38043
//                      FRANCE
//
// This file is part of Tango.
//
// Tango is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// Tango is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
// 
// You should have received a copy of the GNU General Public License
// along with Tango.  If not, see .
//
// $Revision$
//
//-======================================================================


package admin.astor.tools;

import admin.astor.*;
import static admin.astor.AstorDefs.all_ok;
import fr.esrf.Tango.DevFailed;
import fr.esrf.TangoApi.*;
import fr.esrf.TangoDs.Except;
import fr.esrf.tangoatk.widget.util.ErrorPane;

import javax.swing.*;
import javax.swing.tree.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.util.ArrayList;


public class DeviceHierarchy extends JTree implements AstorDefs {
    private static ImageIcon root_icon;
    private Astor astor = null;
    private boolean running = true;
    private Device root = null;
    private String rootname = null;
    private DeviceHierarchyPopupMenu menu;
    private DeviceHierarchyDialog parent;
    private String[] deviceNames = new String[0];
    
    @SuppressWarnings("InspectionUsingGrayColors")
    private static final Color BACKGROUND = new Color(0xf0, 0xf0, 0xf0);
    private static final String SUB_DEV_PROP_NAME = "__SubDevices";
    //===============================================================
    //===============================================================
    public DeviceHierarchy(DeviceHierarchyDialog parent, Astor astor, String name) throws DevFailed {
        super();
        this.parent = parent;
        this.astor = astor;
        setBackground(BACKGROUND);
        
        
        initNames(name);
        buildTree();
        menu = new DeviceHierarchyPopupMenu(this);
        
        this.expandRow(0);
        
        for(int i = 0; i < this.getRowCount(); i++){
            TreePath tp = this.getPathForRow(i);
            Device d = (Device)tp.getLastPathComponent();
            if(d.isDeviceFromServer){
                this.expandPath(tp);
            }
        }
    }

    //===============================================================
    private void initNames(String name) throws DevFailed {
        String [] nameSplied = name.split("/");
        
        switch (nameSplied.length) {
            case 2:    //	Is a server name
                rootname = nameSplied[0] + "/" + nameSplied[1];
                String admin = "dserver/" + rootname;
                String[] tmp = new TangoServer(admin).queryDeviceFromDb();
                deviceNames = new String[tmp.length + 1];
                System.arraycopy(tmp, 0, deviceNames, 0, tmp.length);
                deviceNames[tmp.length] = admin; //	Add amdin dev in last position
                break;
            case 3:    //	Is a device name
                rootname = "Device";
                deviceNames = new String[1];
                deviceNames[0] = nameSplied[0] + "/" + nameSplied[1]+ "/" + nameSplied[2];
                break;
            default:
                Except.throw_exception("BAD_PARAMETER",
                        "Bad device or server name",
                        "DeviceHierarchy.initNames()");
        }

        root = new Device(rootname,true);
        root.isParent = true;
        Device[] devices = new Device[deviceNames.length];
        ArrayList listOfChildren = new ArrayList<>();
        
        //create each Device class for each String find in DeviceList
        //browsed devices Create Devices class
        for (int i = 0 ; i < deviceNames.length ; i++){
            String deviceName = deviceNames[i];
            devices[i] = new Device(deviceName,true);
            
            //add Children to the large list
            addChildrenIfIsNotAlready(listOfChildren,devices[i]);
        }
        
        //find Root Device of the Server
        for (Device dev : devices){
            if(!listOfChildren.contains(dev.name)){
                dev.isRootDevice = true;
                root.add(dev);
            }
        }
    }
    //===============================================================
    //===============================================================
    private void buildTree() {
        //	Create the tree that allows one selection at a time.
        getSelectionModel().setSelectionMode
                (TreeSelectionModel.SINGLE_TREE_SELECTION);

        //	Create Tree and Tree model
        DefaultTreeModel treeModel = new DefaultTreeModel(root);
        setModel(treeModel);
        
        //Enable tool tips.
        ToolTipManager.sharedInstance().registerComponent(this);

        //  Set the icon for leaf nodes.
        TangoRenderer renderer = new TangoRenderer();
        setCellRenderer(renderer);

        //	Add Action listener
        addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                treeMouseClicked(evt);    //	for tree clicked, menu,...
            }
        });
    }
    //======================================================
    /*
     * Manage event on clicked mouse on JTree object.
     */
    //======================================================
    private void treeMouseClicked(java.awt.event.MouseEvent evt) {
        //	Set selection at mouse position
        TreePath selectedPath = getPathForLocation(evt.getX(), evt.getY());
        if (selectedPath == null)
            return;

        DefaultMutableTreeNode node =
                (DefaultMutableTreeNode) selectedPath.getPathComponent(selectedPath.getPathCount() - 1);
        Object o = node;
        int mask = evt.getModifiers();

        //  Check button clicked
        if (evt.getClickCount() == 2 && (mask & MouseEvent.BUTTON1_MASK) != 0) {
        } else if ((mask & MouseEvent.BUTTON1_MASK) != 0) {
            deviceInfo((Device)node);
        } else if ((mask & MouseEvent.BUTTON3_MASK) != 0) {
            if (node == root)
                menu.showMenu(evt, (String) o);
            else if (o instanceof Device)
                menu.showMenu(evt, (Device) o);
        }
    }
    //======================================================
    //======================================================
    private DefaultMutableTreeNode getSelectedNode() {
        return (DefaultMutableTreeNode) getLastSelectedPathComponent();
    }

    //======================================================
    //======================================================
    Object getSelectedObject() {
        DefaultMutableTreeNode node = getSelectedNode();
        if (node == null)
            return null;
        return node;
    }

    //===============================================================
    //===============================================================
    private void testDevice(Device dev) {
        AstorUtil.testDevice(parent, dev.name);
    }

    //===============================================================
    //===============================================================
    private void deviceInfo(Device dev) {
        try {
            String info = dev.getInfo();
            parent.setText(info);
        } catch (DevFailed e) {
            parent.setText(Except.str_exception(e));
        }
    }

    //===============================================================
    //===============================================================
    private void remoteShell(Device dev) {
        try {
            String hostname = dev.getHost();
            new RemoteLoginThread(hostname).start();
        } catch (DevFailed e) {
            parent.setText(Except.str_exception(e));
        }
    }

    //===============================================================
    //===============================================================
    private void hostPanel(Device dev) {
        try {
            astor.tree.displayHostInfoDialog(dev.getHost());
        } catch (DevFailed e) {
            ErrorPane.showErrorMessage(parent, null, e);
        }
    }

    //===============================================================
    //===============================================================
    void stopThread() {
        running = false;
    }

    //===============================================================
    //===============================================================
    @Override
    public String toString() {
        String str = "";
        for(int i = 0 ; i < root.getChildCount(); i++){
            Device dev = root.getDevice(i);
            str += dev.toFullString();
            for (int j = 0; j < dev.getChildCount(); j++){
                str += dev.getDevice(j).toFullString();
            }
        }
        return str;
    }

    private void addChildrenIfIsNotAlready(ArrayList listOfChildren, Device dev) {
        for(String child : dev.childrenStr){
            if(!listOfChildren.contains(child)){
                if(!dev.name.equals(child)){
                    listOfChildren.add(child);
                }
            }
        }
    }
    

    //==============================================================================
    /*
      *	The Popup menu class
      */
    //==============================================================================
    static private final int UPDATE = 0;
    static private final int TEST_DEVICE = 1;
    static private final int HOST_PANEL = 2;
    static private final int REM_LOGIN = 3;
    static private final int OFFSET = 2;    //	Label And separator

    static private String[] menuLabels = {
            "Update Dependencies",
            "Test Device",
            "Host Panel",
            "Remote Login",
    };

    private class DeviceHierarchyPopupMenu extends JPopupMenu {
        private JTree tree;
        private JLabel title;
        //=======================================================
        /*
         * Create a Popup menu
         */
        //=======================================================
        private DeviceHierarchyPopupMenu(JTree tree) {
            this.tree = tree;
            buildBtnPopupMenu();
        }

        //=======================================================
        //=======================================================
        private void buildBtnPopupMenu() {
            title = new JLabel();
            title.setFont(new java.awt.Font("Dialog", Font.BOLD, 16));
            add(title);
            add(new JPopupMenu.Separator());

            for (String menuLabel : menuLabels) {
                if (menuLabel == null)
                    add(new Separator());
                else {
                    JMenuItem btn = new JMenuItem(menuLabel);
                    btn.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent evt) {
                            deviceActionPerformed(evt);
                        }
                    });
                    add(btn);
                }
            }
        }
        //======================================================
        /*
         * Show menu on root
         */
        //======================================================
        public void showMenu(MouseEvent evt, String name) {
            //	Set selection at mouse position
            TreePath selectedPath =
                    tree.getPathForLocation(evt.getX(), evt.getY());
            if (selectedPath == null)
                return;
            tree.setSelectionPath(selectedPath);

            title.setText(name);

            //	Reset all items
            for (int i = 0; i < menuLabels.length; i++)
                getComponent(OFFSET + i).setVisible(false);

            getComponent(OFFSET /* +UPDATE*/).setVisible(true);

            show(tree, evt.getX(), evt.getY());
        }
        //======================================================
        /*
         * Show menu on Collection
         */
        //======================================================
        public void showMenu(MouseEvent evt, Device dev) {
            //	Set selection at mouse position
            TreePath selectedPath =
                    tree.getPathForLocation(evt.getX(), evt.getY());
            if (selectedPath == null)
                return;
            tree.setSelectionPath(selectedPath);
            deviceInfo(dev);

            //	Display menu only if new DeviceProxy did not failed.
            if (dev.failed == null) {
                title.setText(dev.toString());

                //	Reset all items
                getComponent(OFFSET /* + UPDATE*/).setVisible(false);
                for (int i = REM_LOGIN; i < menuLabels.length; i++)
                    getComponent(OFFSET + i).setEnabled(false);

                getComponent(OFFSET + REM_LOGIN).setEnabled(AstorUtil.osIsUnix());
                getComponent(OFFSET + HOST_PANEL).setEnabled(astor != null);
                getComponent(OFFSET + TEST_DEVICE).setEnabled(dev.state == all_ok);

                //  Manage for READ_ONLY mode
                if (Astor.rwMode==AstorDefs.READ_ONLY) {
                    getComponent(OFFSET + TEST_DEVICE).setVisible(false);
                }
                show(tree, evt.getX(), evt.getY());
            }
        }

        //======================================================
        private void deviceActionPerformed(ActionEvent evt) {
            Device dev = (Device)getSelectedNode();
            
            //	Check component source
            Object obj = evt.getSource();
            int cmdidx = 0;
            for (int i = 0; i < menuLabels.length; i++)
                if (getComponent(OFFSET + i) == obj)
                    cmdidx = i;

            switch (cmdidx) {
                case UPDATE:
                    parent.update();
                    break;
                case REM_LOGIN:
                    remoteShell(dev);
                    break;
                case HOST_PANEL:
                    hostPanel(dev);
                    break;
                case TEST_DEVICE:
                    testDevice(dev);
                    break;
            }
        }
    }
    //===============================================================
    /*
      *	Device object definition, containing its subdevices
      */
    //===============================================================
    private class Device extends DefaultMutableTreeNode {
        DeviceProxy proxy;
        DevFailed failed = null;
        String name;
        boolean too_old = false;
        boolean isParent = false;
        boolean isPopulated = false;
        boolean isRootDevice = false;
        boolean isDeviceFromServer = false;
        short state = unknown;
        String[] childrenStr;

        //===========================================================
        private Device(String name, boolean isDeviceFromServer) {
            super(name);
            AstorUtil.increaseSplashProgress(1, "checking for " + name);
            this.isDeviceFromServer = isDeviceFromServer;
            try {
                this.name = name;
                proxy = new DeviceProxy(name);
                
                new StateManager().start();

                //	If failed, check on property
                DbDatum datum = proxy.get_property(SUB_DEV_PROP_NAME);
                childrenStr = datum.extractStringArray();
                if(childrenStr.length == 1 && childrenStr[0]==""){
                    childrenStr = new String[0];
                }else{
                    isParent = true;
                }
                
            } catch (DevFailed e) {
                System.err.println(e.errors[0].desc);
                failed = e;
            }
        }

        @Override
        public boolean isLeaf() {
            return !isParent; //To change body of generated methods, choose Tools | Templates.
        }
        //===========================================================
        private Device getDevice(int i) {
            return (Device)this.getChildAt(i);
        }
        //===========================================================
        private String toFullString() {
            String toReturn = (String)this.userObject;
            toReturn += '\n';
            for (int i = 0; i < this.getChildCount(); i++) {
                Device d = this.getDevice(i);
                toReturn = toReturn + '\t' + (String)d.userObject + '\n';
            }
            toReturn += "------------------------------------------------";
            return toReturn;
        }
        
        @Override
        public int getChildCount() {
            if(isParent && this.childrenStr != null){
                if(!isPopulated){
                    isPopulated = true;
                    for(String child : this.childrenStr){
                        boolean isDeviceFromServer = isDeviceFromServer(child);
                        Device dev = new Device(child,isDeviceFromServer);
                        this.add(dev);
                    }
                }
            }
            
            return super.getChildCount();
        }

        private boolean isDeviceFromServer(String child) {
            if(child.equals(this.name)){
                return false;
            }
            for(String dev : deviceNames){
                if(dev.equals(child)){
                    return true;
                }
            }
            return false;
        }
        //===========================================================
        private class StateManager extends Thread {
            public void run() {
                while (running) {
                    try {
                        proxy.ping();
                        state = all_ok;
                    } catch (DevFailed e) {
                        state = faulty;
                    }
                    repaint();
                    try { sleep(2000); } catch (InterruptedException e) { /* */ }
                }
            }
        }

        //===========================================================
        private String getHost() throws DevFailed {
            DeviceInfo info = proxy.get_info();
            return info.hostname;
        }

        //===========================================================
        private String getInfo() throws DevFailed {
            if (failed != null)
                return Except.str_exception(failed);
            else {
                StringBuilder sb = new StringBuilder();
                if (too_old)
                    sb.append("   WARNING:  Too Old TANGO Release \n")
                            .append("             To get dependencies !!!\n")
                            .append("\n========================================================\n");
                sb.append(proxy.get_info().toString());
                sb.append("\n========================================================\n");

                try {
                    String s = proxy.status();
                    sb.append(s);
                } catch (DevFailed e) {
                    sb.append(Except.str_exception(e));
                }
                return sb.toString();
            }
        }

        //===========================================================
        @Override
        public String toString() {
            return (String)this.userObject;
        }
        //===========================================================
    }
    //===========================================================
    //	End of Device class
    //===========================================================

    
    
    //===============================================================
    /**
     * Renderer Class
     */
    //===============================================================
    private class TangoRenderer extends DefaultTreeCellRenderer {
        private Font[] fonts;

        private final int TITLE = 0;
        private final int COLLEC = 1;
        private final int LEAF = 2;
        private boolean firstPass = true;

        //===============================================================
        //===============================================================
        public TangoRenderer() {
            Utils utils = Utils.getInstance();
            root_icon = Utils.getResizedIcon(Utils.getTangoClassIcon(), 0.33);

            fonts = new Font[LEAF + 1];
            fonts[TITLE] = new Font("Dialog", Font.BOLD, 18);
            fonts[COLLEC] = new Font("Dialog", Font.BOLD, 12);
            fonts[LEAF] = new Font("Dialog", Font.PLAIN, 12);
        }
        //===============================================================
        //===============================================================
        public Component getTreeCellRendererComponent(
                JTree tree,
                Object obj,
                boolean sel,
                boolean expanded,
                boolean leaf,
                int row,
                boolean hasFocus) {

            super.getTreeCellRendererComponent(
                    tree, obj, sel,
                    expanded, leaf, row,
                    hasFocus);

            setBackgroundNonSelectionColor(BACKGROUND);
            setForeground(Color.black);
            setBackgroundSelectionColor(Color.lightGray);
            if (row == 0) {
                //	ROOT
                setFont(fonts[TITLE]);
                setIcon(root_icon);
            } else {
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) obj;

                if (node instanceof Device) {
                    setFont(fonts[COLLEC]);
                    Device device = (Device) node;
                    setIcon(AstorUtil.state_icons[device.state]);
                    if (device.too_old)
                        setBackgroundNonSelectionColor(Color.yellow);
                }
            }
            return this;
        }
    }
    //==============================================================================
    //	End of Renderer Class
    //==============================================================================

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy