org.opennms.netmgt.bsm.vaadin.adminpage.BusinessServiceTreeTable.java Source code

Java tutorial

Introduction

Here is the source code for org.opennms.netmgt.bsm.vaadin.adminpage.BusinessServiceTreeTable.java

Source

/*******************************************************************************
 * This file is part of OpenNMS(R).
 *
 * Copyright (C) 2016 The OpenNMS Group, Inc.
 * OpenNMS(R) is Copyright (C) 1999-2016 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.netmgt.bsm.vaadin.adminpage;

import java.nio.charset.Charset;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.message.BasicNameValuePair;
import org.opennms.netmgt.bsm.service.BusinessServiceManager;
import org.opennms.netmgt.bsm.service.BusinessServiceStateMachine;
import org.opennms.netmgt.bsm.service.model.BusinessService;
import org.opennms.netmgt.bsm.service.model.Status;
import org.opennms.netmgt.bsm.service.model.graph.BusinessServiceGraph;
import org.opennms.netmgt.vaadin.core.TransactionAwareUI;
import org.opennms.netmgt.vaadin.core.UIHelper;

import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Lists;
import com.vaadin.data.util.BeanItem;
import com.vaadin.data.util.ContainerHierarchicalWrapper;
import com.vaadin.server.ExternalResource;
import com.vaadin.server.FontAwesome;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Link;
import com.vaadin.ui.Table;
import com.vaadin.ui.TreeTable;

/**
 * {@link TreeTable} for {@link BusinessServiceRow} objects.
 */
public class BusinessServiceTreeTable extends TreeTable {

    private final BusinessServiceManager businessServiceManager;

    public BusinessServiceTreeTable(BusinessServiceManager businessServiceManager) {
        this.businessServiceManager = Objects.requireNonNull(businessServiceManager);

        setSizeFull();
        setContainerDataSource(new BusinessServiceContainer());

        // Add the "LINKS" columns
        addGeneratedColumn("links", new Table.ColumnGenerator() {
            private static final long serialVersionUID = 7113848887128656685L;

            @Override
            public Object generateCell(Table source, Object itemId, Object columnId) {
                final HorizontalLayout layout = new HorizontalLayout();
                final BusinessServiceStateMachine stateMachine = businessServiceManager.getStateMachine();
                final BusinessService businessService = getItem(itemId).getBean().getBusinessService();
                final Status status = stateMachine.getOperationalStatus(businessService);
                if (status != null) {
                    // Build the query string
                    final List<BasicNameValuePair> urlParms = Lists.newArrayList(
                            new BasicNameValuePair("focus-vertices", businessService.getId().toString()),
                            new BasicNameValuePair("szl", "1"),
                            new BasicNameValuePair("layout", "Hierarchy Layout"),
                            new BasicNameValuePair("provider", "Business Services"));
                    final String queryString = URLEncodedUtils.format(urlParms, Charset.forName("UTF-8"));

                    // Generate the link
                    final Link link = new Link("View in Topology UI",
                            new ExternalResource(String.format("/opennms/topology?%s", queryString)));
                    link.setIcon(FontAwesome.EXTERNAL_LINK_SQUARE);
                    // This app is typically access in an iframe, so we open the URL in a new window/tab
                    link.setTargetName("_blank");
                    layout.addComponent(link);
                    layout.setComponentAlignment(link, Alignment.MIDDLE_CENTER);
                } else {
                    Label label = new Label("N/A");
                    label.setDescription("Try reloading the daemon and refreshing the table.");
                    label.setWidth(null);
                    layout.addComponent(label);
                }
                return layout;
            }
        });

        // add edit and delete buttons
        addGeneratedColumn("edit / delete", new Table.ColumnGenerator() {
            private static final long serialVersionUID = 7113848887128656685L;

            @Override
            public Object generateCell(Table source, Object itemId, Object columnId) {
                HorizontalLayout layout = new HorizontalLayout();
                layout.setSpacing(true);

                Button editButton = new Button("Edit", FontAwesome.PENCIL_SQUARE_O);
                editButton.setId("editButton-" + getItem(itemId).getBean().getName());

                editButton.addClickListener(UIHelper.getCurrent(TransactionAwareUI.class)
                        .wrapInTransactionProxy((Button.ClickListener) event -> {
                            final Long businessServiceId = getItem(itemId).getBean().getBusinessService().getId();
                            BusinessService businessService = businessServiceManager
                                    .getBusinessServiceById(businessServiceId);
                            final BusinessServiceEditWindow window = new BusinessServiceEditWindow(businessService,
                                    businessServiceManager);
                            window.addCloseListener(e -> refresh());

                            getUI().addWindow(window);
                        }));
                layout.addComponent(editButton);

                Button deleteButton = new Button("Delete", FontAwesome.TRASH_O);
                deleteButton.setId("deleteButton-" + getItem(itemId).getBean().getName());

                deleteButton.addClickListener((Button.ClickListener) event -> {
                    final Long businessServiceId = getItem(itemId).getBean().getBusinessService().getId();
                    BusinessService businessService = businessServiceManager
                            .getBusinessServiceById(businessServiceId);
                    if (businessService.getParentServices().isEmpty()
                            && businessService.getChildEdges().isEmpty()) {
                        UIHelper.getCurrent(TransactionAwareUI.class).runInTransaction(() -> {
                            businessServiceManager.getBusinessServiceById(businessServiceId).delete();
                            refresh();
                        });
                    } else {
                        new org.opennms.netmgt.vaadin.core.ConfirmationDialog()
                                .withOkAction((org.opennms.netmgt.vaadin.core.ConfirmationDialog.Action) UIHelper
                                        .getCurrent(TransactionAwareUI.class).wrapInTransactionProxy(
                                                new org.opennms.netmgt.vaadin.core.ConfirmationDialog.Action() {
                                                    @Override
                                                    public void execute(
                                                            org.opennms.netmgt.vaadin.core.ConfirmationDialog window) {
                                                        businessServiceManager
                                                                .getBusinessServiceById(businessServiceId).delete();
                                                        refresh();
                                                    }
                                                }))
                                .withOkLabel("Delete anyway").withCancelLabel("Cancel").withCaption("Warning")
                                .withDescription(
                                        "This entry is referencing or is referenced by other Business Services! Do you really want to delete this entry?")
                                .open();
                    }
                });
                layout.addComponent(deleteButton);

                return layout;
            }
        });

        setColumnExpandRatio("name", 5);
        setColumnExpandRatio("links", 1);
        setColumnExpandRatio("edit / delete", 1);
    }

    @Override
    public BeanItem<BusinessServiceRow> getItem(Object itemId) {
        return (BeanItem<BusinessServiceRow>) super.getItem(itemId);
    }

    /**
     * Refreshes table entries.
     */
    public void refresh() {
        final com.google.common.collect.Table<Long, Optional<Long>, Boolean> expandState = getCurrentExpandState();
        final BusinessServiceContainer newContainer = new BusinessServiceContainer();

        // Build a graph using all of the business services stored in the database
        // We don't use the existing graph, since it only contains the services know by the state machine
        List<BusinessService> allBusinessServices = businessServiceManager.getAllBusinessServices();
        final BusinessServiceGraph graph = businessServiceManager.getGraph(allBusinessServices);

        // Recursively generate the table rows, starting with the roots
        graph.getVerticesByLevel(0).stream().filter(v -> v.getBusinessService() != null)
                .sorted((v1, v2) -> v1.getBusinessService().getName().compareTo(v2.getBusinessService().getName()))
                .forEach(v -> newContainer.addRow(graph, v));

        // Make it hierarchical
        Hierarchical hierarchicalContainer = createHierarchicalContainer(newContainer);

        // Update datasource
        setContainerDataSource(hierarchicalContainer);
        setVisibleColumns("name", "links", "edit / delete"); // reset visible columns

        // Restore the previous collapsed state
        List<BusinessServiceRow> rows = getItemIds().stream().map(itemId -> getItem(itemId).getBean())
                .collect(Collectors.toList());
        applyExpandState(expandState, rows);
    }

    private void applyExpandState(com.google.common.collect.Table<Long, Optional<Long>, Boolean> collapseState,
            List<BusinessServiceRow> rows) {
        for (BusinessServiceRow row : rows) {
            Boolean wasCollapsed = collapseState.get(row.getBusinessService().getId(),
                    Optional.ofNullable(row.getParentBusinessServiceId()));
            setCollapsed(row.getRowId(), wasCollapsed != null ? wasCollapsed : true); // Collapse by default
            if (hasChildren(row.getRowId())) {
                applyExpandState(collapseState, getChildren(row.getRowId()).stream()
                        .map(itemId -> getItem(itemId).getBean()).collect(Collectors.toList()));
            }
        }
    }

    private com.google.common.collect.Table<Long, Optional<Long>, Boolean> getCurrentExpandState() {
        // Gather the current collapse state
        final com.google.common.collect.Table<Long, Optional<Long>, Boolean> collapseState = HashBasedTable
                .create();
        for (Object itemId : getItemIds()) {
            final BusinessServiceRow row = getItem(itemId).getBean();
            collapseState.put(row.getBusinessService().getId(),
                    Optional.ofNullable(row.getParentBusinessServiceId()), isCollapsed(itemId));
        }
        return collapseState;
    }

    private static Hierarchical createHierarchicalContainer(BusinessServiceContainer newContainer) {
        final ContainerHierarchicalWrapper hierarchicalContainer = new ContainerHierarchicalWrapper(newContainer);

        // Set child/parent relation
        for (Map.Entry<Long, Long> eachEntry : newContainer.getRowIdToParentRowIdMapping().entrySet()) {
            hierarchicalContainer.setParent(eachEntry.getKey(), eachEntry.getValue());
        }

        // Disable the collapse flag on items without any children
        for (Object itemId : hierarchicalContainer.getItemIds()) {
            hierarchicalContainer.setChildrenAllowed(itemId, hierarchicalContainer.hasChildren(itemId));
        }
        return hierarchicalContainer;
    }
}