org.opennms.features.vaadin.dashboard.dashlets.SummaryDashlet.java Source code

Java tutorial

Introduction

Here is the source code for org.opennms.features.vaadin.dashboard.dashlets.SummaryDashlet.java

Source

/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2013-2014 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2014 The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc.
 *
 * OpenNMS(R) is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * OpenNMS(R) 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 Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with OpenNMS(R).  If not, see:
 *      http://www.gnu.org/licenses/
 *
 * For more information contact:
 *     OpenNMS(R) Licensing <license@opennms.org>
 *     http://www.opennms.org/
 *     http://www.opennms.com/
 *******************************************************************************/

package org.opennms.features.vaadin.dashboard.dashlets;

import com.vaadin.server.Page;
import com.vaadin.server.Sizeable;
import com.vaadin.server.ThemeResource;
import com.vaadin.ui.*;
import org.opennms.core.criteria.CriteriaBuilder;
import org.opennms.features.vaadin.dashboard.model.*;
import org.opennms.netmgt.dao.api.AlarmDao;
import org.opennms.netmgt.model.OnmsAlarm;
import org.opennms.netmgt.model.OnmsSeverity;

/**
 * This class implements a {@link Dashlet} for testing purposes.
 *
 * @author Christian Pape
 */
public class SummaryDashlet extends AbstractDashlet {

    /**
     * The {@link AlarmDao} used
     */
    private AlarmDao m_alarmDao;
    /**
     * Timeslot to use
     */
    private long m_timeslot = 3600;
    /**
     * boosted value
     */
    private boolean m_boosted = false;
    /**
     * Trend identifiers
     */
    private static int TREND_NORTH = 4;
    private static int TREND_NORTHEAST = 3;
    private static int TREND_EAST = 2;
    private static int TREND_SOUTHEAST = 1;
    private static int TREND_SOUTH = 0;

    private DashletComponent m_dashboardComponent;
    private DashletComponent m_wallboardComponent;

    /**
     * Constructor for instantiating new objects.
     *
     * @param dashletSpec the {@link DashletSpec} to be used
     */
    public SummaryDashlet(String name, DashletSpec dashletSpec, AlarmDao alarmDao) {
        super(name, dashletSpec);
        /**
         * Setting the member fields
         */
        m_alarmDao = alarmDao;
    }

    /**
     * Returns a human-readable {@link String} representation of a timestamp in the past.
     *
     * @param secondsAll the timestamp to be used
     * @return a human-readable representation
     */
    public String getHumanReadableFormat(long secondsAll) {
        long seconds = secondsAll;
        long minutes = 0;
        long hours = 0;
        long days = 0;

        if (seconds / 60 > 0) {
            long rest = seconds % 60;
            minutes = seconds / 60;
            seconds = rest;
        }

        if (minutes / 60 > 0) {
            long rest = minutes % 60;
            hours = minutes / 60;
            minutes = rest;
        }

        if (hours / 24 > 0) {
            long rest = hours % 24;
            days = hours / 24;
            hours = rest;
        }

        String output = "";

        if (days > 0) {
            output += days + "d";
        }
        if (hours > 0) {
            output += hours + "h";
        }
        if (minutes > 0) {
            output += minutes + "m";
        }
        if (seconds > 0) {
            output += seconds + "s";
        }

        return output;
    }

    /**
     * Computes the trend for acknowledged and not acknowledged alarms
     *
     * @param ack    number of acknowledged alarms
     * @param notAck number of unacknowledged alarms
     * @return the trend value
     */
    private int computeTrend(int ack, int notAck) {
        if (ack == notAck) {
            return TREND_EAST;
        } else {
            if (notAck == 0) {
                return TREND_NORTH;
            } else {
                if (ack == 0) {
                    return TREND_NORTH;
                } else {
                    double ratio = (double) ack / (double) notAck;

                    if (ratio < 0.5) {
                        return TREND_SOUTH;
                    } else {
                        if (ratio < 1) {
                            return TREND_SOUTHEAST;
                        } else {
                            if (ratio > 2) {
                                return TREND_NORTH;
                            } else {
                                return TREND_NORTHEAST;
                            }
                        }
                    }
                }
            }
        }
    }

    private Component getLegend(String entity) {
        HorizontalLayout horizontalLayout = new HorizontalLayout();

        horizontalLayout.setSpacing(true);
        horizontalLayout.addStyleName("summary");
        horizontalLayout.addStyleName("global");

        Label labelx = new Label(entity);
        labelx.addStyleName("summary-font-legend");

        Image ackdImage = new Image(null, new ThemeResource("img/acknowledged.png"));
        ackdImage.setWidth(16, Sizeable.Unit.PIXELS);

        Image unackdImage = new Image(null, new ThemeResource("img/unacknowledged.png"));
        unackdImage.setWidth(16, Sizeable.Unit.PIXELS);

        Label dummyLabel = new Label();
        dummyLabel.setWidth(32, Sizeable.Unit.PIXELS);

        horizontalLayout.addComponent(labelx);
        horizontalLayout.addComponent(ackdImage);
        horizontalLayout.addComponent(unackdImage);
        horizontalLayout.addComponent(dummyLabel);

        horizontalLayout.setComponentAlignment(ackdImage, Alignment.TOP_RIGHT);
        horizontalLayout.setComponentAlignment(unackdImage, Alignment.TOP_RIGHT);

        horizontalLayout.setExpandRatio(labelx, 4.0f);
        horizontalLayout.setExpandRatio(ackdImage, 1.0f);
        horizontalLayout.setExpandRatio(unackdImage, 1.0f);
        horizontalLayout.setExpandRatio(dummyLabel, 1.0f);

        horizontalLayout.setWidth(375, Sizeable.Unit.PIXELS);

        return horizontalLayout;
    }

    /**
     * Returns the component showing the alarms and the trends by severity
     *
     * @return the {@link Component}
     */
    private Component getComponentSeverity(int width) {
        VerticalLayout verticalLayout = new VerticalLayout();

        int overallSum = 0;
        int severitySum = 0;

        verticalLayout.addComponent(getLegend("Severity"));

        for (OnmsSeverity onmsSeverity : OnmsSeverity.values()) {
            HorizontalLayout horizontalLayout = new HorizontalLayout();
            horizontalLayout.setSpacing(true);
            horizontalLayout.addStyleName("summary");
            horizontalLayout.addStyleName(onmsSeverity.name().toLowerCase());

            int acknowledged = countBySeverity(true, m_timeslot, onmsSeverity);
            int notAcknowledged = countBySeverity(false, m_timeslot, onmsSeverity);

            Label labelSeverity = new Label(onmsSeverity.getLabel());
            labelSeverity.addStyleName("summary-font");
            Label labelAcknowledge = new Label(String.valueOf(acknowledged));
            labelAcknowledge.addStyleName("summary-font");
            Label labelNotAcknowledged = new Label(String.valueOf(notAcknowledged));
            labelNotAcknowledged.addStyleName("summary-font");

            horizontalLayout.addComponent(labelSeverity);
            horizontalLayout.addComponent(labelAcknowledge);
            horizontalLayout.addComponent(labelNotAcknowledged);

            int status = computeTrend(acknowledged, notAcknowledged);

            severitySum += onmsSeverity.getId();
            overallSum += onmsSeverity.getId() * status;

            Image image = new Image(null, new ThemeResource("img/a" + status + ".png"));
            image.setWidth(width, Sizeable.Unit.PIXELS);
            horizontalLayout.addComponent(image);

            horizontalLayout.setExpandRatio(labelSeverity, 4.0f);
            horizontalLayout.setExpandRatio(labelAcknowledge, 1.0f);
            horizontalLayout.setExpandRatio(labelNotAcknowledged, 1.0f);
            horizontalLayout.setExpandRatio(image, 1.0f);

            horizontalLayout.setComponentAlignment(image, Alignment.TOP_CENTER);

            horizontalLayout.setWidth(375, Sizeable.Unit.PIXELS);
            verticalLayout.addComponent(horizontalLayout);
        }

        int globalTrend = (int) Math.max(0,
                Math.min(4, Math.round(((double) overallSum) / ((double) severitySum))));

        Image image = new Image(null, new ThemeResource("img/a" + globalTrend + ".png"));
        image.setWidth(width * 8, Sizeable.Unit.PIXELS);

        VerticalLayout globalTrendLayout = new VerticalLayout();
        globalTrendLayout.setSpacing(true);
        globalTrendLayout.addStyleName("summary");
        globalTrendLayout.addStyleName("global");
        globalTrendLayout.setSizeFull();

        Label labelTitle = new Label("Alarms trend by severity");
        labelTitle.addStyleName("summary-font");
        labelTitle.setSizeUndefined();

        Label labelTimeslot = new Label("(" + getHumanReadableFormat(m_timeslot) + ")");
        labelTimeslot.addStyleName("summary-font");
        labelTimeslot.setSizeUndefined();

        globalTrendLayout.addComponent(labelTitle);
        globalTrendLayout.addComponent(labelTimeslot);
        globalTrendLayout.addComponent(image);

        globalTrendLayout.setWidth(375, Sizeable.Unit.PIXELS);

        globalTrendLayout.setComponentAlignment(labelTitle, Alignment.MIDDLE_CENTER);
        globalTrendLayout.setComponentAlignment(labelTimeslot, Alignment.MIDDLE_CENTER);
        globalTrendLayout.setComponentAlignment(image, Alignment.MIDDLE_CENTER);

        globalTrendLayout.setExpandRatio(labelTitle, 1.0f);

        verticalLayout.addComponent(globalTrendLayout, 0);

        m_boosted = (globalTrend > 2);

        return verticalLayout;
    }

    /**
     * Returns the component showing the alarms and the trends by severity
     *
     * @return the {@link Component}
     */
    private Component getComponentUei(int width) {
        VerticalLayout verticalLayout = new VerticalLayout();

        int overallSum = 0;
        int severitySum = 0;

        verticalLayout.addComponent(getLegend("UEI"));

        String[] ueis = { "uei.opennms.org/nodes/nodeLostService", "uei.opennms.org/nodes/interfaceDown",
                "uei.opennms.org/nodes/nodeDown" };

        for (int i = 0; i < ueis.length; i++) {
            String uei = ueis[i];
            HorizontalLayout horizontalLayout = new HorizontalLayout();
            horizontalLayout.setSpacing(true);
            horizontalLayout.addStyleName("summary");

            if (i == 0) {
                horizontalLayout.addStyleName(OnmsSeverity.MINOR.name().toLowerCase());
            } else {
                if (i == 1) {
                    horizontalLayout.addStyleName(OnmsSeverity.MINOR.name().toLowerCase());
                } else {
                    horizontalLayout.addStyleName(OnmsSeverity.MAJOR.name().toLowerCase());
                }
            }

            int acknowledged = countByUei(true, m_timeslot, uei);
            int notAcknowledged = countByUei(false, m_timeslot, uei);

            Label labelSeverity = new Label(uei.replace("uei.opennms.org/nodes/", ""));
            labelSeverity.addStyleName("summary-font");
            Label labelAcknowledge = new Label(String.valueOf(acknowledged));
            labelAcknowledge.addStyleName("summary-font");
            Label labelNotAcknowledged = new Label(String.valueOf(notAcknowledged));
            labelNotAcknowledged.addStyleName("summary-font");

            horizontalLayout.addComponent(labelSeverity);
            horizontalLayout.addComponent(labelAcknowledge);
            horizontalLayout.addComponent(labelNotAcknowledged);

            int status = computeTrend(acknowledged, notAcknowledged);

            severitySum += i;
            overallSum += i * status;

            Image image = new Image(null, new ThemeResource("img/a" + status + ".png"));
            image.setWidth(width, Sizeable.Unit.PIXELS);
            horizontalLayout.addComponent(image);

            horizontalLayout.setExpandRatio(labelSeverity, 4.0f);
            horizontalLayout.setExpandRatio(labelAcknowledge, 1.0f);
            horizontalLayout.setExpandRatio(labelNotAcknowledged, 1.0f);
            horizontalLayout.setExpandRatio(image, 1.0f);

            horizontalLayout.setComponentAlignment(image, Alignment.TOP_CENTER);

            horizontalLayout.setWidth(375, Sizeable.Unit.PIXELS);
            verticalLayout.addComponent(horizontalLayout);
        }

        int globalTrend = (int) Math.max(0,
                Math.min(4, Math.round(((double) overallSum) / ((double) severitySum))));

        Image image = new Image(null, new ThemeResource("img/a" + globalTrend + ".png"));
        image.setWidth(width * 8, Sizeable.Unit.PIXELS);

        VerticalLayout globalTrendLayout = new VerticalLayout();
        globalTrendLayout.setSpacing(true);
        globalTrendLayout.addStyleName("summary");
        globalTrendLayout.addStyleName("global");
        globalTrendLayout.setSizeFull();

        Label labelTitle = new Label("Alarms trend by UEI");
        labelTitle.addStyleName("summary-font");
        labelTitle.setSizeUndefined();

        Label labelTimeslot = new Label("(" + getHumanReadableFormat(m_timeslot) + ")");
        labelTimeslot.addStyleName("summary-font");
        labelTimeslot.setSizeUndefined();

        globalTrendLayout.addComponent(labelTitle);
        globalTrendLayout.addComponent(labelTimeslot);
        globalTrendLayout.addComponent(image);

        globalTrendLayout.setWidth(375, Sizeable.Unit.PIXELS);

        globalTrendLayout.setComponentAlignment(labelTitle, Alignment.MIDDLE_CENTER);
        globalTrendLayout.setComponentAlignment(labelTimeslot, Alignment.MIDDLE_CENTER);
        globalTrendLayout.setComponentAlignment(image, Alignment.MIDDLE_CENTER);

        globalTrendLayout.setExpandRatio(labelTitle, 1.0f);

        verticalLayout.addComponent(globalTrendLayout, 0);

        m_boosted = (globalTrend > 2);

        return verticalLayout;
    }

    /**
     * Searches for alarms with the given criterias and returns the number found.
     *
     * @param acknowledged search for acknowledged or unacknowledged alarms
     * @param age          the age of the alarms
     * @param onmsSeverity the {@link OnmsSeverity} to search for
     * @return number of alarms found
     */
    public int countBySeverity(boolean acknowledged, long age, OnmsSeverity onmsSeverity) {
        CriteriaBuilder criteriaBuilder = new CriteriaBuilder(OnmsAlarm.class);

        if (acknowledged) {
            criteriaBuilder.isNotNull("alarmAckUser");
        } else {
            criteriaBuilder.isNull("alarmAckUser");
        }

        criteriaBuilder.eq("severity", onmsSeverity);

        criteriaBuilder.sql("EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - lastEventTime) < " + age);

        return m_alarmDao.countMatching(criteriaBuilder.toCriteria());
    }

    /**
     * Searches for alarms with the given criterias and returns the number found.
     *
     * @param acknowledged search for acknowledged or unacknowledged alarms
     * @param age          the age of the alarms
     * @param uei          search for alarms with the specified uei
     * @return number of alarms found
     */
    public int countByUei(boolean acknowledged, long age, String uei) {
        CriteriaBuilder criteriaBuilder = new CriteriaBuilder(OnmsAlarm.class);

        if (acknowledged) {
            criteriaBuilder.isNotNull("alarmAckUser");
        } else {
            criteriaBuilder.isNull("alarmAckUser");
        }

        criteriaBuilder.eq("uei", uei);

        criteriaBuilder.sql("EXTRACT(EPOCH FROM CURRENT_TIMESTAMP - lastEventTime) < " + age);

        return m_alarmDao.countMatching(criteriaBuilder.toCriteria());
    }

    @Override
    public DashletComponent getWallboardComponent() {
        if (m_wallboardComponent == null) {
            m_wallboardComponent = new AbstractDashletComponent() {
                private HorizontalLayout m_horizontalLayout = new HorizontalLayout();

                {
                    m_horizontalLayout.setCaption(getName());
                    m_horizontalLayout.setSizeFull();
                }

                /**
                 * Injects CSS styles in the current page
                 */
                private void injectWallboardStyles() {
                    Page.getCurrent().getStyles()
                            .add(".summary.cleared { background: #000000; border-left: 15px solid #858585; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.normal { background: #000000; border-left: 15px solid #336600; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.indeterminate {  background: #000000; border-left: 15px solid #999; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.warning { background: #000000; border-left: 15px solid #FFCC00; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.minor { background: #000000;  border-left: 15px solid #FF9900; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.major { background: #000000; border-left: 15px solid #FF3300; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.critical { background: #000000; border-left: 15px solid #CC0000; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.global { background: #000000; border-left: 15px solid #000000; }");
                    Page.getCurrent().getStyles().add(".summary { padding: 5px 5px; margin: 1px; }");
                    Page.getCurrent().getStyles().add(
                            ".summary-font { font-size: 24px; line-height: normal; text-align: right; color: #3ba300; }");
                    Page.getCurrent().getStyles().add(
                            ".summary-font-legend { font-size: 16px; line-height: normal; text-align: right; color: #3ba300; }");
                }

                @Override
                public void refresh() {
                    m_timeslot = 3600;

                    try {
                        m_timeslot = Math.max(1,
                                Integer.parseInt(getDashletSpec().getParameters().get("timeslot")));
                    } catch (NumberFormatException numberFormatException) {
                        /**
                         * Just ignore
                         */
                    }

                    m_horizontalLayout.removeAllComponents();

                    injectWallboardStyles();

                    Component severity = getComponentSeverity(32);
                    Component uei = getComponentUei(32);

                    m_horizontalLayout.addComponent(severity);
                    m_horizontalLayout.addComponent(uei);

                    m_horizontalLayout.setSizeFull();
                    m_horizontalLayout.setComponentAlignment(severity, Alignment.TOP_CENTER);
                    m_horizontalLayout.setComponentAlignment(uei, Alignment.TOP_CENTER);
                }

                @Override
                public Component getComponent() {
                    return m_horizontalLayout;
                }

                @Override
                public boolean isBoosted() {
                    return SummaryDashlet.this.m_boosted;
                }
            };
        }

        return m_wallboardComponent;
    }

    @Override
    public DashletComponent getDashboardComponent() {
        if (m_dashboardComponent == null) {
            m_dashboardComponent = new AbstractDashletComponent() {
                private HorizontalLayout m_horizontalLayout = new HorizontalLayout();

                {
                    m_horizontalLayout.setCaption(getName());
                    m_horizontalLayout.setSizeFull();
                }

                /**
                 * Injects CSS styles in the current page
                 */
                private void injectDashboardStyles() {
                    Page.getCurrent().getStyles()
                            .add(".summary.cleared { background: #000000; border-left: 8px solid #858585; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.normal { background: #000000; border-left: 8px solid #336600; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.indeterminate {  background: #000000; border-left: 8px solid #999; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.warning { background: #000000; border-left: 8px solid #FFCC00; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.minor { background: #000000;  border-left: 8px solid #FF9900; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.major { background: #000000; border-left: 8px solid #FF3300; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.critical { background: #000000; border-left: 8px solid #CC0000; }");
                    Page.getCurrent().getStyles()
                            .add(".summary.global { background: #000000; border-left: 8px solid #000000; }");
                    Page.getCurrent().getStyles().add(".summary { padding: 5px 5px; margin: 1px; }");
                    Page.getCurrent().getStyles().add(
                            ".summary-font { font-size: 17px; line-height: normal; text-align: right; color: #3ba300; }");
                    Page.getCurrent().getStyles().add(
                            ".summary-font-legend { font-size: 9px; line-height: normal; text-align: right; color: #3ba300; }");
                }

                @Override
                public void refresh() {
                    m_timeslot = 3600;

                    try {
                        m_timeslot = Math.max(1,
                                Integer.parseInt(getDashletSpec().getParameters().get("timeslot")));
                    } catch (NumberFormatException numberFormatException) {
                        /**
                         * Just ignore
                         */
                    }

                    m_horizontalLayout.removeAllComponents();

                    Accordion accordion = new Accordion();
                    accordion.setSizeFull();

                    injectDashboardStyles();

                    Component severity = getComponentSeverity(16);
                    Component uei = getComponentUei(16);

                    VerticalLayout v1 = new VerticalLayout(severity);
                    v1.setSizeFull();
                    v1.setComponentAlignment(severity, Alignment.MIDDLE_CENTER);
                    v1.setMargin(true);
                    accordion.addTab(v1, "by Severity");

                    VerticalLayout v2 = new VerticalLayout(uei);
                    v2.setSizeFull();
                    v2.setComponentAlignment(uei, Alignment.MIDDLE_CENTER);
                    v2.setMargin(true);
                    accordion.addTab(v2, "by Uei");

                    m_horizontalLayout.addComponent(accordion);
                }

                @Override
                public Component getComponent() {
                    return m_horizontalLayout;
                }

                @Override
                public boolean isBoosted() {
                    return SummaryDashlet.this.m_boosted;
                }
            };
        }

        return m_dashboardComponent;
    }
}