de.decidr.ui.view.WorkflowInstanceViewerComponent.java Source code

Java tutorial

Introduction

Here is the source code for de.decidr.ui.view.WorkflowInstanceViewerComponent.java

Source

/*
 * The DecidR Development Team licenses this file to you under
 * the Apache License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package de.decidr.ui.view;

import java.util.List;
import java.util.Map;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.vaadin.terminal.PaintException;
import com.vaadin.terminal.PaintTarget;
import com.vaadin.ui.AbstractComponent;
import com.vaadin.ui.ClientWidget;

import de.decidr.model.annotations.Reviewed;
import de.decidr.model.annotations.Reviewed.State;
import de.decidr.model.exceptions.MonitoringException;
import de.decidr.model.exceptions.TransactionException;
import de.decidr.model.facades.WorkflowInstanceFacade;
import de.decidr.model.logging.DefaultLogger;
import de.decidr.model.schema.webservice.odemanagement.TScopeStatus;
import de.decidr.ui.beans.WorkflowInstanceBean;
import de.decidr.ui.main.DecidrUI;
import de.decidr.ui.main.ModelFacades;
import de.decidr.ui.view.client.ui.VWorkflowInstanceViewer;
import de.decidr.ui.view.windows.InformationDialogComponent;
import de.decidr.ui.view.windows.TransactionErrorDialogComponent;

/**
 * This class represents the server side component of the instance viewer widget
 * which is integrated into the Vaadin web portal. It is used to communicate
 * with the client side of the instance viewer widget.
 * 
 * @author Wolfgang Fellger
 */
@Reviewed(reviewers = { "unknown" }, lastRevision = "0", currentReviewState = State.NeedsReview)
@ClientWidget(VWorkflowInstanceViewer.class)
public class WorkflowInstanceViewerComponent extends AbstractComponent {

    private static final long serialVersionUID = -2284244108529453835L;

    private Logger logger = DefaultLogger.getLogger(WorkflowModelEditorComponent.class);

    private final WorkflowInstanceBean instanceBean;
    private final WorkflowInstanceFacade instanceFacade;

    private List<String> variableIDs;

    /**
     * Initializes the server side components which are needed to gain access to
     * the database.
     * 
     * @throws TransactionException
     *             Iff the transaction is aborted for any reason.
     */
    public WorkflowInstanceViewerComponent(WorkflowInstanceBean instance) throws TransactionException {
        super();
        this.instanceBean = instance;
        this.instanceFacade = ModelFacades.getWorkflowInstanceFacade();

        this.setSizeFull();
        this.setImmediate(true);
    }

    @SuppressWarnings("unchecked")
    @Override
    public void changeVariables(Object source, Map variables) {
        super.changeVariables(source, variables);
        logger.debug("[Instance Viewer] Received update from client...");
        /**
         * When the clients requests an update, it sets one of these variables.
         * To "send" data to the client, we must trigger a repaint, which will
         * then update variables, which will then make Vaadin actually send
         * stuff.
         */
        if (variables.containsKey(VWorkflowInstanceViewer.ACTIVITY_INFO_VAR)) {
            logger.debug("[Instance Viewer] Event: Update activity info");
            this.requestRepaint();
        } else if (variables.containsKey(VWorkflowInstanceViewer.INSTANCE_VARIABLES_VAR)) {
            logger.debug("[Instance Viewer] Event: Update instance variables");
            Object o = variables.get(VWorkflowInstanceViewer.INSTANCE_VARIABLES_VAR);
            if (o instanceof Object[]) {
                try {
                    variableIDs = new Vector<String>();
                    for (Object item : (Object[]) o) {
                        if (o != null) {
                            variableIDs.add(item.toString());
                        }
                    }
                    this.requestRepaint();

                } catch (Exception e) {
                    ;
                }
            }
        }
    }

    @Override
    public void paintContent(PaintTarget target) throws PaintException {
        super.paintContent(target);
        try {

            target.addVariable(this, VWorkflowInstanceViewer.DWDL_VAR, getDWDL());
            if (variableIDs != null) {
                target.addVariable(this, VWorkflowInstanceViewer.INSTANCE_VARIABLES_VAR,
                        getInstanceVariables(variableIDs));
                variableIDs = null;
            }
            target.addVariable(this, VWorkflowInstanceViewer.ACTIVITY_INFO_VAR, getActivityInfo());
        } catch (MonitoringException e) {
            DecidrUI.getCurrent().getMainWindow().addWindow(new InformationDialogComponent(
                    "Monitoring encountered an error.\n\nMessage: " + e.getLocalizedMessage(), "Monitoring error"));
        } catch (TransactionException e) {
            DecidrUI.getCurrent().getMainWindow().addWindow(new TransactionErrorDialogComponent(e));
        }
    }

    /**
     * Retrieve current activity information from ODE and return as JSON.
     * 
     * @return JSON string containing activity info
     * @throws TransactionException
     */
    private String getActivityInfo() throws TransactionException {
        Map<String, TScopeStatus> activities = instanceFacade.getActivityInfo(this.instanceBean.getId());
        return mapToJSON(activities);
    }

    /**
     * Retrieve current values of instance variables from ODE.
     * 
     * @return JSON string containing instance variables
     * @throws TransactionException
     *             Iff the transaction is aborted for any reason.
     */
    private String getInstanceVariables(List<String> variableIds) throws TransactionException {
        Map<String, String> variables = instanceFacade.getInstanceVariables(this.instanceBean.getId(), variableIds);
        return mapToJSON(variables);
    }

    /**
     * Retrieve DWDL of the workflow instance's model.
     * 
     * @return XML string containing DWDL.
     */
    private String getDWDL() {
        return new String(this.instanceBean.getModel().getDwdl());
    }

    /**
     * Escape string for use as JSON string literal.
     */
    private String escapeJSON(String value) {
        StringBuilder sb = new StringBuilder(value.length());
        for (char c : value.toCharArray()) {
            if (c == '"') {
                sb.append("\\\"");
            } else if (c == '\\') {
                sb.append("\\\\");
            } else if (Character.isISOControl(c)) {
                sb.append(String.format("\\x%02x", Integer.valueOf(c)));
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * Convert any Map to a JSON object, by calling toString on both keys and
     * values.
     * 
     * @param map
     *            Map to convert to JSON. May be null.
     * @return JSON string encoding a JSON object which maps strings to strings.
     */
    private String mapToJSON(Map<?, ?> map) {
        if (map == null) {
            return "{}";
        }
        StringBuilder result = new StringBuilder();
        boolean first = true;
        result.append("{");
        for (Object key : map.keySet()) {
            if (first) {
                first = false;
            } else {
                result.append(",\n");
            }
            result.append('"');
            result.append(key.toString());
            result.append("\": \"");

            result.append(escapeJSON(map.get(key).toString()));
            result.append('"');
        }
        result.append("}");
        return result.toString();
    }

}