org.opennms.dashboard.server.CriteriaAddingVisitor.java Source code

Java tutorial

Introduction

Here is the source code for org.opennms.dashboard.server.CriteriaAddingVisitor.java

Source

/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2007-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.dashboard.server;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;

import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Subqueries;
import org.hibernate.type.StringType;
import org.hibernate.type.Type;
import org.opennms.dashboard.client.SurveillanceGroup;
import org.opennms.dashboard.client.Visitor;
import org.opennms.netmgt.config.surveillanceViews.Category;
import org.opennms.netmgt.config.surveillanceViews.ColumnDef;
import org.opennms.netmgt.config.surveillanceViews.RowDef;
import org.opennms.netmgt.config.surveillanceViews.View;
import org.opennms.netmgt.dao.api.CategoryDao;
import org.opennms.netmgt.model.OnmsCriteria;
import org.opennms.netmgt.model.OnmsMonitoredService;
import org.opennms.netmgt.model.OnmsNode;
import org.opennms.netmgt.model.OnmsOutage;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;

/**
 * <p>CriteriaAddingVisitor class.</p>
 *
 * @author <a href="mailto:brozow@opennms.org">Mathew Brozowski</a>
 * @author <a href="mailto:dj@opennms.org">DJ Gregor</a>
 * @author <a href="mailto:jeffg@opennms.org">Jeff Gehlbach</a>
 */
public class CriteriaAddingVisitor implements Visitor, InitializingBean {

    private OnmsCriteria m_criteria;
    private CategoryDao m_categoryDao;
    private View m_view;
    private SurveillanceView m_survView;

    /**
     * <p>Constructor for CriteriaAddingVisitor.</p>
     *
     * @param criteria a {@link org.opennms.netmgt.model.OnmsCriteria} object.
     */
    public CriteriaAddingVisitor(OnmsCriteria criteria) {
        m_criteria = criteria;
    }

    /**
     * <p>visitAll</p>
     */
    @Override
    public void visitAll() {

        addCriteriaForCategories(m_criteria, m_survView.getColumnCategories());
        addCriteriaForCategories(m_criteria, m_survView.getRowCategories());

    }

    /** {@inheritDoc} */
    @Override
    public void visitGroup(SurveillanceGroup group) {

        if (group.isColumn()) {
            addCriteriaForCategories(m_criteria, m_survView.getRowCategories());
            addCriteriaForCategories(m_criteria, m_survView.getCategoriesForColumn(group.getId()));
        } else {
            addCriteriaForCategories(m_criteria, m_survView.getColumnCategories());
            addCriteriaForCategories(m_criteria, m_survView.getCategoriesForRow(group.getId()));
        }

    }

    /** {@inheritDoc} */
    @Override
    public void visitIntersection(SurveillanceGroup row, SurveillanceGroup column) {

        addCriteriaForCategories(m_criteria, m_survView.getCategoriesForRow(row.getId()));
        addCriteriaForCategories(m_criteria, m_survView.getCategoriesForColumn(column.getId()));

    }

    /**
     * <p>addCriteriaForCategories</p>
     *
     * @param criteria a {@link org.opennms.netmgt.model.OnmsCriteria} object.
     * @param categories a {@link java.util.Set} object.
     */
    public void addCriteriaForCategories(OnmsCriteria criteria, Set<String> categories) {
        String[] categoryNames = categories.toArray(new String[categories.size()]);
        addCriteriaForCategories(criteria, categoryNames);
    }

    /**
     * <p>addCriteriaForCategories</p>
     *
     * @param criteria a {@link org.opennms.netmgt.model.OnmsCriteria} object.
     * @param categories a {@link java.lang.String} object.
     */
    public void addCriteriaForCategories(OnmsCriteria criteria, String... categories) {
        if (criteria.resultsOfType(OnmsMonitoredService.class) || criteria.resultsOfType(OnmsOutage.class)) {
            // Make a detached criteria to subselect the node IDs that are in the
            // specified surveillance categories
            DetachedCriteria categoryNodeCriteria = DetachedCriteria.forClass(OnmsNode.class, "categoryNodes");

            // HACK: Hibernate 3.6 aliases 'categoryNodes' as 'categoryNodes_' so use that for the raw SQL statement.
            // Also note that the database field that we use here is 'nodeId' but the bean property for node ID
            // in OnmsNode is 'id'.
            String sql = "categoryNodes_.nodeId in (select distinct cn.nodeId from category_node cn join categories c on cn.categoryId = c.categoryId where c.categoryName in ("
                    + commaDelimitedQuestionMarks(categories.length) + "))";
            categoryNodeCriteria.add(
                    Restrictions.sqlRestriction(sql, categories, arrayOfType(categories.length, new StringType())));

            // Join the categoryNodes IDs found by the subselect with the outer 'node' alias.
            // This requires that the criteria already has a 'node' alias to the node table.
            //
            // @see org.opennms.web.svclayer.support.DefaultRtcService#createOutageCriteria()
            // @see org.opennms.web.svclayer.support.DefaultRtcService#createServiceCriteria()
            //
            categoryNodeCriteria.add(Restrictions.eqProperty("categoryNodes.id", "node.id"));

            // Add a projection for 'id' so that the categoryNodes.id can be joined to
            // node.id in the outer criteria
            categoryNodeCriteria.setProjection(Projections.property("id"));

            // Use an exists subquery to evaluate the subselect
            criteria.add(Subqueries.exists(categoryNodeCriteria));
        } else {
            // TODO: This case assumes that the OnmsCriteria is querying an object with a 'nodeId' property.
            // I'm not sure this is ever used... I think this visitor is just for OnmsMonitoredService and 
            // OnmsOutage queries.
            String sql = "{alias}.nodeId in (select distinct cn.nodeId from category_node cn join categories c on cn.categoryId = c.categoryId where c.categoryName in ("
                    + commaDelimitedQuestionMarks(categories.length) + "))";
            criteria.add(
                    Restrictions.sqlRestriction(sql, categories, arrayOfType(categories.length, new StringType())));
        }
    }

    /**
     * <p>getView</p>
     *
     * @return a {@link org.opennms.netmgt.config.surveillanceViews.View} object.
     */
    public View getView() {
        return m_view;
    }

    /**
     * <p>setView</p>
     *
     * @param view a {@link org.opennms.netmgt.config.surveillanceViews.View} object.
     */
    public void setView(View view) {
        m_view = view;
    }

    /**
     * <p>setCategoryDao</p>
     *
     * @param categoryDao a {@link org.opennms.netmgt.dao.api.CategoryDao} object.
     */
    public void setCategoryDao(CategoryDao categoryDao) {
        m_categoryDao = categoryDao;
    }

    /**
     * <p>afterPropertiesSet</p>
     */
    @Override
    public void afterPropertiesSet() {
        Assert.state(m_view != null, "view property must be set");
        Assert.state(m_categoryDao != null, "categoryDao property must be set");

        // construct a surveillance view object that makes it easier to build queries
        m_survView = new SurveillanceView();

        m_survView.setName(m_view.getName());

        for (ColumnDef colDef : m_view.getColumns().getColumnDef()) {
            for (Category category : colDef.getCategory()) {
                m_survView.addColumnCategory(colDef.getLabel(), category.getName());
            }
        }

        for (RowDef rowDef : m_view.getRows().getRowDef()) {
            for (Category category : rowDef.getCategory()) {
                m_survView.addRowCategory(rowDef.getLabel(), category.getName());
            }
        }

    }

    private Type[] arrayOfType(int length, Type initialVal) {
        Type[] array = new Type[length];
        for (int i = 0; i < length; i++) {
            array[i] = initialVal;
        }
        return array;
    }

    /**
     * <p>commaDelimitedQuestionMarks</p>
     *
     * @param count a int.
     * @return a {@link java.lang.String} object.
     */
    public String commaDelimitedQuestionMarks(int count) {
        StringBuilder buf = new StringBuilder();
        for (int i = 0; i < count; i++) {
            if (i != 0) {
                buf.append(',');
            }
            buf.append('?');
        }
        return buf.toString();
    }

    private static class SurveillanceView {
        private String m_name;
        private MapToSetOf<String, String> m_columns = new MapToSetOf<String, String>();
        private MapToSetOf<String, String> m_rows = new MapToSetOf<String, String>();

        public void setName(String name) {
            m_name = name;
        }

        public String getName() {
            return m_name;
        }

        public void addColumnCategory(String column, String category) {
            m_columns.addValue(column, category);
        }

        public void addRowCategory(String row, String category) {
            m_rows.addValue(row, category);
        }

        public Set<String> getCategoriesForRow(String row) {
            return m_rows.getValueForKey(row);
        }

        public Set<String> getCategoriesForColumn(String column) {
            return m_columns.getValueForKey(column);
        }

        public Set<String> getRowCategories() {
            return m_rows.getAllValues();
        }

        public Set<String> getColumnCategories() {
            return m_columns.getAllValues();
        }

        public Set<String> getCategoriesForColumns(Collection<? extends String> columns) {
            return m_columns.getValuesForKeys(columns);
        }

        public Set<String> getCategoriesForRows(Collection<? extends String> rows) {
            return m_rows.getValuesForKeys(rows);
        }
    }

    private static class MapToSetOf<K, V> {

        private Map<K, Set<V>> m_map = new LinkedHashMap<K, Set<V>>();

        public void addValue(K key, V value) {
            if (!m_map.containsKey(key)) {
                m_map.put(key, new LinkedHashSet<V>());
            }
            m_map.get(key).add(value);
        }

        public Set<V> getValuesForKeys(Collection<? extends K> keys) {
            LinkedHashSet<V> values = new LinkedHashSet<V>();
            for (K key : keys) {
                values.addAll(m_map.get(key));
            }

            return values;
        }

        public Set<V> getAllValues() {
            return getValuesForKeys(m_map.keySet());
        }

        public Set<V> getValueForKey(K key) {
            return getValuesForKeys(Collections.singleton(key));
        }

    }

}