org.jboss.dashboard.ui.components.BeanHandler.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.dashboard.ui.components.BeanHandler.java

Source

/**
 * Copyright (C) 2012 JBoss Inc
 *
 * Licensed 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 org.jboss.dashboard.ui.components;

import org.jboss.dashboard.ui.formatters.FactoryURL;
import org.jboss.dashboard.ui.controller.CommandRequest;
import org.jboss.dashboard.ui.controller.CommandResponse;
import org.jboss.dashboard.ui.controller.responses.SendStreamResponse;
import org.jboss.dashboard.profiler.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.*;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.inject.Named;

public abstract class BeanHandler implements Serializable {

    private transient Logger log = LoggerFactory.getLogger(BeanHandler.class);

    private List propertyErrors = new ArrayList();
    private Set wrongFields = new HashSet();
    private Properties actionsShortcuts = new Properties();
    private Properties reverseActionsShortcuts = new Properties();
    private boolean useActionShortcuts = true;
    private boolean enableDoubleClickControl = false;
    private boolean enabledForActionHandling = false;

    public String getBeanName() {
        Named named = this.getClass().getAnnotation(Named.class);
        if (named != null)
            return named.value();
        return this.getClass().getName();
    }

    public boolean isUseActionShortcuts() {
        return useActionShortcuts;
    }

    public void setUseActionShortcuts(boolean useActionShortcuts) {
        this.useActionShortcuts = useActionShortcuts;
    }

    public boolean isEnableDoubleClickControl() {
        return enableDoubleClickControl;
    }

    public void setEnableDoubleClickControl(boolean enableDoubleClickControl) {
        this.enableDoubleClickControl = enableDoubleClickControl;
    }

    public boolean isEnabledForActionHandling() {
        return enabledForActionHandling;
    }

    public void setEnabledForActionHandling(boolean enabledForActionHandling) {
        this.enabledForActionHandling = enabledForActionHandling;
    }

    @PostConstruct
    public void start() {
        if (isUseActionShortcuts()) {
            calculateActionShortcuts();
        }
    }

    protected void calculateActionShortcuts() {
        Method[] allMethods = this.getClass().getMethods();
        TreeSet actionNames = new TreeSet();
        for (int i = 0; i < allMethods.length; i++) {
            Method method = allMethods[i];
            if (method.getName().startsWith("action")) {
                Class[] classes = method.getParameterTypes();
                if (classes != null && classes.length == 1) {
                    Class paramClass = classes[0];
                    if (paramClass.equals(CommandRequest.class)) {
                        String actionName = method.getName().substring("action".length());
                        actionNames.add(actionName);
                    }
                }
            }
        }
        int index = 0;
        for (Iterator iterator = actionNames.iterator(); iterator.hasNext(); index++) {
            String action = (String) iterator.next();
            actionsShortcuts.put(action, String.valueOf(index));
            reverseActionsShortcuts.put(String.valueOf(index), action);
        }
    }

    /**
     * Get the action name for given action name. If there is a shortcut, it will be returned, otherwise, the same name applies.
     *
     * @param actionName action name
     * @return the action name for given action name
     */
    public String getActionName(String actionName) {
        actionName = StringUtils.capitalize(actionName);
        return actionsShortcuts.getProperty(actionName, actionName);
    }

    /**
     * Get the action name for a given shortcut.
     *
     * @param shortcut the possible shortcut whose action name is to be obtained.
     * @return the action name for the given shortcut if found, or the shortcut itself if not.
     */
    public String getActionForShortcut(String shortcut) {
        String actionName = reverseActionsShortcuts.getProperty(shortcut);
        return actionName != null ? actionName : shortcut;
    }

    public synchronized CommandResponse handle(CommandRequest request, String action) throws Exception {
        if (log.isDebugEnabled())
            log.debug("Entering handle " + getBeanName() + " action: " + action);

        // Calculate the action to invoke.
        action = StringUtils.capitalize(action);
        action = reverseActionsShortcuts.getProperty(action, action);

        // Double click control.
        if (isEnableDoubleClickControl() && !isEnabledForActionHandling()) {
            // Duplicates can only be prevented in session components, and if they are enabled for that purpose
            log.warn("Discarding duplicated execution in component " + getBeanName() + ", action: " + action
                    + ". User should be advised not to double click!");
            return null;
        }

        // Invoke the component's action and keep track of the execution.
        CodeBlockTrace trace = new HandlerTrace(this, action).begin();
        try {
            String methodName = "action" + action;
            beforeInvokeAction(request, action);
            CommandResponse response = null;
            Method handlerMethod = this.getClass().getMethod(methodName, new Class[] { CommandRequest.class });
            if (log.isDebugEnabled())
                log.debug("Invoking method " + methodName + " on " + getBeanName());
            response = (CommandResponse) handlerMethod.invoke(this, new Object[] { request });
            afterInvokeAction(request, action);

            if (response == null || !(response instanceof SendStreamResponse)) {
                setEnabledForActionHandling(false);
            }

            if (log.isDebugEnabled())
                log.debug("Leaving handle " + getBeanName() + " - " + action);
            return response;
        } finally {
            trace.end();
        }
    }

    protected void beforeInvokeAction(CommandRequest request, String action) throws Exception {
    }

    protected void afterInvokeAction(CommandRequest request, String action) throws Exception {
    }

    public void addFieldError(FactoryURL property, Exception e, Object propertyValue) {
        propertyErrors.add(new FieldException("Error setting property to component", property, propertyValue, e));
        wrongFields.add(property.getFieldName());
    }

    public void clearFieldErrors() {
        propertyErrors.clear();
        wrongFields.clear();
    }

    public List getFieldErrors() {
        return Collections.unmodifiableList(propertyErrors);
    }

    public boolean hasError(String fieldName) {
        return wrongFields.contains(fieldName);
    }

    public void actionVoid(CommandRequest request) {
    }

    public static class HandlerTrace extends CodeBlockTrace {

        protected String bean;
        protected String action;
        protected Map<String, Object> context;

        public HandlerTrace(BeanHandler handler, String action) {
            super(handler.getBeanName());
            this.bean = handler.getBeanName();
            this.action = action;
            this.context = buildContext();
        }

        public CodeBlockType getType() {
            return CoreCodeBlockTypes.UI_COMPONENT;
        }

        public String getDescription() {
            return bean + (StringUtils.isBlank(action) ? "" : "." + action + "()");
        }

        public Map<String, Object> getContext() {
            return context;
        }

        protected Map<String, Object> buildContext() {
            Map<String, Object> ctx = new LinkedHashMap<String, Object>();
            ctx.put("Bean name", bean);
            if (!StringUtils.isBlank(action)) {
                ctx.put("Bean action", action);
            }

            ThreadProfile threadProfile = Profiler.lookup().getCurrentThreadProfile();
            if (threadProfile != null)
                threadProfile.addContextProperties(ctx);
            return ctx;
        }
    }
}