org.netxms.ui.eclipse.objectview.widgets.ObjectStatusMap.java Source code

Java tutorial

Introduction

Here is the source code for org.netxms.ui.eclipse.objectview.widgets.ObjectStatusMap.java

Source

/**
 * NetXMS - open source network management system
 * Copyright (C) 2003-2015 Victor Kirhenshtein
 *
 * This program 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 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
package org.netxms.ui.eclipse.objectview.widgets;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ScrolledComposite;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IViewPart;
import org.netxms.client.NXCSession;
import org.netxms.client.SessionListener;
import org.netxms.client.SessionNotification;
import org.netxms.client.objects.AbstractNode;
import org.netxms.client.objects.AbstractObject;
import org.netxms.client.objects.Cluster;
import org.netxms.client.objects.Container;
import org.netxms.client.objects.ServiceRoot;
import org.netxms.ui.eclipse.console.resources.SharedColors;
import org.netxms.ui.eclipse.objectbrowser.api.ObjectContextMenu;
import org.netxms.ui.eclipse.objectview.api.ObjectDetailsProvider;
import org.netxms.ui.eclipse.shared.ConsoleSharedData;

/**
 * Widget showing "heat" map of nodes under given root object
 */
public class ObjectStatusMap extends ScrolledComposite implements ISelectionProvider {
    private IViewPart viewPart;
    private long rootObjectId;
    private NXCSession session;
    private Composite dataArea;
    private List<Composite> sections = new ArrayList<Composite>();
    private Map<Long, ObjectStatusWidget> statusWidgets = new HashMap<Long, ObjectStatusWidget>();
    private ISelection selection = null;
    private Set<ISelectionChangedListener> selectionListeners = new HashSet<ISelectionChangedListener>();
    private MenuManager menuManager;
    private Font titleFont;
    private boolean groupObjects = true;
    private int severityFilter = 0xFF;
    private SortedMap<Integer, ObjectDetailsProvider> detailsProviders = new TreeMap<Integer, ObjectDetailsProvider>();
    private Set<Runnable> refreshListeners = new HashSet<Runnable>();

    /**
     * @param parent
     * @param style
     */
    public ObjectStatusMap(IViewPart viewPart, Composite parent, int style) {
        super(parent, style | SWT.V_SCROLL);

        initDetailsProviders();

        this.viewPart = viewPart;
        session = (NXCSession) ConsoleSharedData.getSession();
        final SessionListener sessionListener = new SessionListener() {
            @Override
            public void notificationHandler(SessionNotification n) {
                if (n.getCode() == SessionNotification.OBJECT_CHANGED)
                    onObjectChange((AbstractObject) n.getObject());
                else if (n.getCode() == SessionNotification.OBJECT_DELETED)
                    onObjectDelete(n.getSubCode());
            }
        };
        session.addListener(sessionListener);
        addDisposeListener(new DisposeListener() {
            @Override
            public void widgetDisposed(DisposeEvent e) {
                session.removeListener(sessionListener);
            }
        });

        setBackground(SharedColors.getColor(SharedColors.OBJECT_TAB_BACKGROUND, getDisplay()));
        setExpandHorizontal(true);
        setExpandVertical(true);
        addControlListener(new ControlAdapter() {
            public void controlResized(ControlEvent e) {
                Rectangle r = getClientArea();
                setMinSize(dataArea.computeSize(r.width, SWT.DEFAULT));
            }
        });

        dataArea = new Composite(this, SWT.NONE);
        setContent(dataArea);
        GridLayout layout = new GridLayout();
        layout.verticalSpacing = 10;
        dataArea.setLayout(layout);
        dataArea.setBackground(getBackground());

        titleFont = JFaceResources.getFontRegistry().getBold(JFaceResources.BANNER_FONT);

        menuManager = new MenuManager();
        menuManager.setRemoveAllWhenShown(true);
        menuManager.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager manager) {
                fillContextMenu(manager);
            }
        });
    }

    /**
     * Fill context menu
     * @param mgr Menu manager
     */
    protected void fillContextMenu(IMenuManager manager) {
        ObjectContextMenu.fill(manager, (viewPart != null) ? viewPart.getSite() : null, this);
    }

    /**
     * @param objectId
     */
    public void setRootObject(long objectId) {
        rootObjectId = objectId;
        refresh();
    }

    /**
     * Refresh form
     */
    public void refresh() {
        for (Composite s : sections)
            s.dispose();
        sections.clear();

        synchronized (statusWidgets) {
            statusWidgets.clear();
        }

        if (groupObjects)
            buildSection(rootObjectId, ""); //$NON-NLS-1$
        else
            buildFlatView();
        dataArea.layout(true, true);

        Rectangle r = getClientArea();
        setMinSize(dataArea.computeSize(r.width, SWT.DEFAULT));

        for (Runnable l : refreshListeners)
            l.run();
    }

    /**
     * Build flat view - all nodes in one group
     */
    private void buildFlatView() {
        AbstractObject root = session.findObjectById(rootObjectId);
        if ((root == null)
                || !((root instanceof Container) || (root instanceof ServiceRoot) || (root instanceof Cluster)))
            return;

        List<AbstractObject> objects = new ArrayList<AbstractObject>(
                root.getAllChilds(new int[] { AbstractObject.OBJECT_NODE, AbstractObject.OBJECT_CLUSTER }));

        // apply severity filter
        if ((severityFilter & 0x1F) != 0x1F) {
            Iterator<AbstractObject> it = objects.iterator();
            while (it.hasNext()) {
                AbstractObject o = it.next();
                if (((1 << o.getStatus().getValue()) & severityFilter) == 0) {
                    it.remove();
                }
            }
        }

        Collections.sort(objects, new Comparator<AbstractObject>() {
            @Override
            public int compare(AbstractObject o1, AbstractObject o2) {
                return o1.getObjectName().compareToIgnoreCase(o2.getObjectName());
            }
        });

        final Composite clientArea = new Composite(dataArea, SWT.NONE);
        clientArea.setBackground(getBackground());
        GridData gd = new GridData();
        gd.grabExcessHorizontalSpace = true;
        gd.horizontalAlignment = SWT.FILL;
        clientArea.setLayoutData(gd);
        RowLayout clayout = new RowLayout();
        clayout.marginBottom = 0;
        clayout.marginTop = 0;
        clayout.marginLeft = 0;
        clayout.marginRight = 0;
        clayout.type = SWT.HORIZONTAL;
        clayout.wrap = true;
        clayout.pack = false;
        clientArea.setLayout(clayout);
        sections.add(clientArea);

        for (AbstractObject o : objects) {
            if (!((o instanceof AbstractNode) || (o instanceof Cluster)))
                continue;

            addObjectElement(clientArea, o);
        }
    }

    /**
     * Build section of the form corresponding to one container
     */
    private void buildSection(long rootId, String namePrefix) {
        AbstractObject root = session.findObjectById(rootId);
        if ((root == null)
                || !((root instanceof Container) || (root instanceof ServiceRoot) || (root instanceof Cluster)))
            return;

        List<AbstractObject> objects = new ArrayList<AbstractObject>(Arrays.asList(root.getChildsAsArray()));
        Collections.sort(objects, new Comparator<AbstractObject>() {
            @Override
            public int compare(AbstractObject o1, AbstractObject o2) {
                return o1.getObjectName().compareToIgnoreCase(o2.getObjectName());
            }
        });

        Composite section = null;
        Composite clientArea = null;

        // Add nodes and clusters
        for (AbstractObject o : objects) {
            if (!((o instanceof AbstractNode) || (o instanceof Cluster)))
                continue;

            if (((1 << o.getStatus().getValue()) & severityFilter) == 0)
                continue;

            if (section == null) {
                section = new Composite(dataArea, SWT.NONE);
                section.setBackground(getBackground());
                GridData gd = new GridData();
                gd.grabExcessHorizontalSpace = true;
                gd.horizontalAlignment = SWT.FILL;
                section.setLayoutData(gd);

                GridLayout layout = new GridLayout();
                layout.marginHeight = 0;
                layout.marginWidth = 0;
                section.setLayout(layout);

                final Label title = new Label(section, SWT.NONE);
                title.setBackground(getBackground());
                title.setFont(titleFont);
                title.setText(namePrefix + root.getObjectName());

                clientArea = new Composite(section, SWT.NONE);
                clientArea.setBackground(getBackground());
                gd = new GridData();
                gd.grabExcessHorizontalSpace = true;
                gd.horizontalAlignment = SWT.FILL;
                clientArea.setLayoutData(gd);
                RowLayout clayout = new RowLayout();
                clayout.marginBottom = 0;
                clayout.marginTop = 0;
                clayout.marginLeft = 0;
                clayout.marginRight = 0;
                clayout.type = SWT.HORIZONTAL;
                clayout.wrap = true;
                clayout.pack = false;
                clientArea.setLayout(clayout);

                sections.add(section);
            }

            addObjectElement(clientArea, o);
        }

        // Add subcontainers
        for (AbstractObject o : objects) {
            if (!(o instanceof Container) && !(o instanceof ServiceRoot) && !(o instanceof Cluster))
                continue;

            buildSection(o.getObjectId(), namePrefix + root.getObjectName() + " / "); //$NON-NLS-1$
        }
    }

    /**
     * @param object
     */
    private void addObjectElement(final Composite parent, final AbstractObject object) {
        ObjectStatusWidget w = new ObjectStatusWidget(parent, object);
        w.setBackground(getBackground());
        w.addMouseListener(new MouseListener() {
            @Override
            public void mouseUp(MouseEvent e) {
            }

            @Override
            public void mouseDown(MouseEvent e) {
                setSelection(new StructuredSelection(object));
                if (e.button == 1)
                    callDetailsProvider(object);
            }

            @Override
            public void mouseDoubleClick(MouseEvent e) {
            }
        });

        // Create popup menu
        Menu menu = menuManager.createContextMenu(w);
        w.setMenu(menu);

        // Register menu for extension.
        if (viewPart != null)
            viewPart.getSite().registerContextMenu(menuManager, this);

        synchronized (statusWidgets) {
            statusWidgets.put(object.getObjectId(), w);
        }
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
     */
    @Override
    public void addSelectionChangedListener(ISelectionChangedListener listener) {
        selectionListeners.add(listener);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection()
     */
    @Override
    public ISelection getSelection() {
        return selection;
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener)
     */
    @Override
    public void removeSelectionChangedListener(ISelectionChangedListener listener) {
        selectionListeners.remove(listener);
    }

    /* (non-Javadoc)
     * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection)
     */
    @Override
    public void setSelection(ISelection selection) {
        this.selection = selection;
        SelectionChangedEvent event = new SelectionChangedEvent(this, selection);
        for (ISelectionChangedListener l : selectionListeners)
            l.selectionChanged(event);
    }

    /**
     * @return the groupObjects
     */
    public boolean isGroupObjects() {
        return groupObjects;
    }

    /**
     * @param groupObjects the groupObjects to set
     */
    public void setGroupObjects(boolean groupObjects) {
        this.groupObjects = groupObjects;
    }

    /**
     * Initialize object details providers
     */
    private void initDetailsProviders() {
        // Read all registered extensions and create tabs
        final IExtensionRegistry reg = Platform.getExtensionRegistry();
        IConfigurationElement[] elements = reg
                .getConfigurationElementsFor("org.netxms.ui.eclipse.objectview.objectDetailsProvider"); //$NON-NLS-1$
        for (int i = 0; i < elements.length; i++) {
            try {
                final ObjectDetailsProvider provider = (ObjectDetailsProvider) elements[i]
                        .createExecutableExtension("class"); //$NON-NLS-1$
                int priority;
                try {
                    priority = Integer.parseInt(elements[i].getAttribute("priority")); //$NON-NLS-1$
                } catch (NumberFormatException e) {
                    priority = 65535;
                }
                detailsProviders.put(priority, provider);
            } catch (CoreException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    }

    /**
     * Call object details provider
     * 
     * @param node
     */
    private void callDetailsProvider(AbstractObject object) {
        for (ObjectDetailsProvider p : detailsProviders.values()) {
            if (p.canProvideDetails(object)) {
                p.provideDetails(object, viewPart);
                break;
            }
        }
    }

    /**
     * Handle object change
     */
    private void onObjectChange(final AbstractObject object) {
        if (!((object instanceof AbstractNode) || (object instanceof Container) || (object instanceof Cluster)
                || (object instanceof ServiceRoot)))
            return;

        synchronized (statusWidgets) {
            final ObjectStatusWidget w = statusWidgets.get(object.getObjectId());
            if (w != null) {
                getDisplay().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        if (!w.isDisposed())
                            w.updateObject(object);
                    }
                });
            } else if ((object.getObjectId() == rootObjectId) || object.isChildOf(rootObjectId)) {
                getDisplay().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        if (!isDisposed())
                            refresh();
                    }
                });
            }
        }
    }

    /**
     * Handle object delete
     */
    private void onObjectDelete(long objectId) {
        synchronized (statusWidgets) {
            if (statusWidgets.containsKey(objectId)) {
                getDisplay().asyncExec(new Runnable() {
                    @Override
                    public void run() {
                        if (!isDisposed())
                            refresh();
                    }
                });
            }
        }
    }

    /**
     * @return
     */
    public int getSeverityFilter() {
        return severityFilter;
    }

    /**
     * @param severityFilter
     */
    public void setSeverityFilter(int severityFilter) {
        this.severityFilter = severityFilter;
    }

    /**
     * @param listener
     */
    public void addRefreshListener(Runnable listener) {
        refreshListeners.add(listener);
    }

    /**
     * @param listener
     */
    public void removeRefreshListener(Runnable listener) {
        refreshListeners.remove(listener);
    }
}