org.carewebframework.cal.ui.reporting.drilldown.DrillDownDisplay.java Source code

Java tutorial

Introduction

Here is the source code for org.carewebframework.cal.ui.reporting.drilldown.DrillDownDisplay.java

Source

/**
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
 * If a copy of the MPL was not distributed with this file, You can obtain one at
 * http://mozilla.org/MPL/2.0/.
 *
 * This Source Code Form is also subject to the terms of the Health-Related Additional
 * Disclaimer of Warranty and Limitation of Liability available at
 * http://www.carewebframework.org/licensing/disclaimer.
 */
package org.carewebframework.cal.ui.reporting.drilldown;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Date;

import ca.uhn.fhir.model.dstu.composite.IdentifierDt;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.carewebframework.api.security.SecurityUtil;
import org.carewebframework.cal.ui.reporting.Constants;
import org.carewebframework.common.DateUtil;
import org.carewebframework.common.StrUtil;
import org.carewebframework.ui.zk.PopupDialog;
import org.carewebframework.ui.zk.ZKUtil;

import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Button;
import org.zkoss.zul.Column;
import org.zkoss.zul.Div;
import org.zkoss.zul.Grid;
import org.zkoss.zul.Label;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.Row;

/**
 * Class which extends Popup. Subclasses should provide implementation of method addRows(). This is
 * the popup dialog that displays the detail information for a data object in a grid view. If
 * {@link SecurityUtil#hasDebugRole()}, the dataObject is interrogated and the classes get/bean
 * methods are invoked and displayed on the display as well.
 */
public class DrillDownDisplay extends PopupDialog {

    private class DebugLink extends DrillDownIconBase<Object> implements EventListener<Event> {

        private static final long serialVersionUID = 1L;

        private final String title;

        public DebugLink(Object dataObject, String title) {
            super(dataObject, DrillDownDisplay.class);
            this.title = title;
        }

        @Override
        public void onEvent(Event event) throws Exception {
            DrillDownDisplay ddd = new DrillDownDisplay(DrillDownDisplay.this, dataObject, title);
            ddd.setDebug(debug);
            ddd.owner = DrillDownDisplay.this;
            ddd.btnCloseAll.setVisible(true);
            ddd.show();
        }

        @Override
        protected void attachEventListener() {
            addEventListener(Events.ON_CLICK, this);
        }
    }

    private static final Log log = LogFactory.getLog(DrillDownDisplay.class);

    private static final long serialVersionUID = 1L;

    private Grid grid;

    private Column colLabel;

    private Column colValue;

    private Button btnCloseAll;

    private Object dataObject;

    private boolean resizing = false;

    private DrillDownDisplay owner = null;

    private boolean debug = SecurityUtil.hasDebugRole();

    /**
     * Subclasses a zul listbox for displaying multiple values in a single grid cell. Prevents
     * selection of entries in the list by resetting the state to no selection.
     *
     * @author dmartin
     */
    private class MultiListbox extends org.zkoss.zul.Listbox implements EventListener<Event> {

        private static final long serialVersionUID = 1L;

        private String defaultValue = null;

        /**
         * Creates the list box to fill the parent cell. Capture select and click events to undo any
         * selection that might occur.
         *
         * @param defaultValue The default value.
         */
        public MultiListbox(String defaultValue) {
            super();
            this.defaultValue = defaultValue;
            setWidth("100%");
            setHeight("100%");
            setStyle("background:white;border:none");
            setDisabled(true);
            addEventListener(Events.ON_SELECT, this);
            addEventListener(Events.ON_CLICK, this);
        }

        /**
         * Reset the list box state to no selection.
         */
        @Override
        public void onEvent(Event event) {
            if (getSelectedIndex() != -1) {
                setSelectedIndex(-1);
            }

            return;
        }

        /**
         * Add an item to the list box.
         *
         * @param value = Value of item to add.
         */
        public void addItem(String value) {
            Listitem item = new Listitem();
            item.setLabel(value);
            appendChild(item);

            if (value.equalsIgnoreCase(defaultValue)) {
                item.setStyle("font-style:italic");
            }
        }
    }

    /**
     * Create the dialog.
     *
     * @param parent The parent component.
     * @param dataObject The data object.
     * @param title The dialog title.
     */
    public DrillDownDisplay(Component parent, Object dataObject, String title) {
        super(parent, title);
        setDataObject(dataObject);
        setWidth("600px");

        try {
            Executions.createComponents(
                    ZKUtil.loadCachedPageDefinition(Constants.RESOURCE_PREFIX + "drillDownDisplay.zul"), this,
                    null);
            ZKUtil.wireController(this);
            adjustGrid();
        } catch (Exception e) {
            log.error("Error creating drilldown display dialog.", e);
        }
    }

    /**
     * Subclasses need implement the following method to add rows to the display.
     */
    public void addRows() {
    }

    /**
     * Add a link for drilldown of objects.
     *
     * @param dataObject Object for drilldown.
     * @param title Title for dialog.
     */
    private void addLink(Object dataObject, String title) {
        if (debugObject(dataObject, true)) {
            Component cell = getLastRow().getFirstChild();
            cell.appendChild(new DebugLink(dataObject, title));
        }
    }

    /**
     * Returns the last row added.
     *
     * @return The last row added.
     */
    private Row getLastRow() {
        return (Row) grid.getRows().getLastChild();
    }

    /**
     * When debug is true, dataObject is interrogated and the classes get/bean methods are invoked
     * and displayed on the display as well.
     *
     * @param dataObject Object to interrogate.
     * @param checkOnly If true, only checks to see if the object has additional debug info.
     * @return True if the object is a type for which additional debug info is available..
     */
    private boolean debugObject(Object dataObject, boolean checkOnly) {
        if (dataObject != null) {
            Row row;
            Class<?> clazz = dataObject.getClass();

            if (!checkOnly) {
                log.debug("Adding Verbose DrillDown Object Debug Information");
                addRow("-------DEBUG--------", clazz.getName());
                row = getLastRow();
                row.appendChild(new Label());
                row.setSclass(Constants.SCLASS_DRILLDOWN_GRID);
            }

            try {
                Object[] params = null;
                //Method[] methods = clazz.getDeclaredMethods();
                Method[] methods = clazz.getMethods();

                if (!(dataObject instanceof String)) {
                    for (Method method : methods) {
                        if (Modifier.PUBLIC == method.getModifiers()) {
                            // Assumes getter methods
                            if (method.getName().startsWith("get")
                                    && method.getGenericParameterTypes().length == 0) {
                                if (checkOnly) {
                                    return true;
                                }

                                Object invokedObject = method.invoke(getDataObject(), params);
                                String methodName = method.getName();
                                addRowViaObject(methodName, invokedObject);
                                addLink(invokedObject, clazz.getName() + "." + methodName);
                            }
                        }
                    }
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }

        return false;
    }

    /**
     * Show the popup dialog, populating it with detail information for the specified data object.
     */
    @Override
    public void show() {
        addRows();

        if (debug) {
            debugObject(dataObject, false);
        }

        if (grid.getRows().getChildren().size() > 20) {
            grid.setHeight("600px");
        }

        super.show();
    }

    /**
     * Adds a detail row for a generic object.
     *
     * @param header The row header.
     * @param value The object to add.
     */
    protected void addRowViaObject(String header, Object value) {
        if (value instanceof String) {
            addRow(header, (String) value);
        } else if (value instanceof Date) {
            addRow(header, (Date) value);
        } else if (value instanceof IdentifierDt) {
            addRow(header, ((IdentifierDt) value).getValue().getValue());
        } else {
            addRow(header, value == null ? "" : String.valueOf(value));
        }
    }

    /**
     * Add a row containing the specified header (left column) and value (right column). If
     * log.isDebugEnabled() is false then don't add row for empty or null values
     *
     * @param header Text for header column
     * @param value Text for value column
     */
    protected void addRow(String header, String value) {
        if ((value == null || value.length() == 0) && !debug) {
            return;
        }

        Label lbl = new Label();
        lbl.setValue(value);
        lbl.setTooltiptext(value);
        addRow(header, lbl);
    }

    /**
     * Add a row containing the specified header (left column) and value (right column).
     *
     * @param header Text for header column
     * @param value Text for value column
     */
    protected void addRow(String header, Integer value) {
        addRow(header, value == null ? "" : Integer.toString(value));
    }

    /**
     * Add a row containing the specified header (left column) and value (right column).
     *
     * @param header Text for header column
     * @param value Text for value column
     */
    protected void addRow(String header, Long value) {
        addRow(header, value == null ? "" : Long.toString(value));
    }

    /**
     * Add a row containing the specified header (left column) and value (right column).
     *
     * @param header Text for header column
     * @param value Date object
     */
    protected void addRow(String header, Date value) {
        try {
            addRow(header, DateUtil.formatDate(value));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            addRow(header, e.getMessage());
        }
    }

    /**
     * Add a row containing the specified header (left column) and value (right column).
     *
     * @param header Text for header column
     * @param value Concept object
     */
    protected void addRow(String header, IdentifierDt value) {
        addRow(header, value == null ? "" : value.getValue().toString());
    }

    /**
     * Add a row containing a multi-valued list.
     *
     * @param header Text for header column
     * @param list Iterable object of string values
     * @param dflt Value to mark as default
     */
    protected void addRow(String header, Iterable<String> list, String dflt) {
        if (list == null) {
            return;
        }

        MultiListbox container = new MultiListbox(dflt);

        for (String val : list) {
            container.addItem(val);
        }

        if (container.getItems().size() > 0 || debug) {
            addRow(header, container);
        }
    }

    /**
     * Add a row containing the specified header (left column) and value container (right column).
     *
     * @param header Text for header column
     * @param container Object containing text value(s)
     */
    protected void addRow(String header, Component container) {
        Row row = new Row();
        grid.getRows().appendChild(row);
        Div div = new Div();
        Label label = new Label(header + ":");
        label.setMultiline(true);
        label.setMaxlength(40);
        label.setStyle("font-weight:bold;word-wrap:word-break");
        row.appendChild(div);
        row.appendChild(label);
        row.appendChild(container);
    }

    public void onClick$btnClose() {
        detach();
    }

    public void onClick$btnCloseAll() {
        detach();

        if (owner != null) {
            owner.onClick$btnCloseAll();
        }
    }

    @Override
    public void onResize(String newHeight, String newWidth) {
        if (!resizing) {
            try {
                resizing = true;
                adjustGrid();
            } finally {
                resizing = false;
            }
        }
    }

    private void adjustGrid() {
        int w = (StrUtil.extractInt(getWidth()) - 40) / 3;
        colLabel.setWidth(w + "px");
        colValue.setWidth((w * 2) + "px");
    }

    public Grid getGrid() {
        return grid;
    }

    public Object getDataObject() {
        return dataObject;
    }

    public void setDataObject(Object dataObject) {
        this.dataObject = dataObject;
    }

    public void setDebug(boolean debug) {
        this.debug = debug;
    }

    public boolean isDebug() {
        return debug;
    }

}