com.bstek.dorado.view.config.definition.ViewConfigDefinition.java Source code

Java tutorial

Introduction

Here is the source code for com.bstek.dorado.view.config.definition.ViewConfigDefinition.java

Source

/*
 * This file is part of Dorado 7.x (http://dorado7.bsdn.org).
 * 
 * Copyright (c) 2002-2012 BSTEK Corp. All rights reserved.
 * 
 * This file is dual-licensed under the AGPLv3 (http://www.gnu.org/licenses/agpl-3.0.html) 
 * and BSDN commercial (http://www.bsdn.org/licenses) licenses.
 * 
 * If you are unsure which license is appropriate for your use, please contact the sales department
 * at http://www.bstek.com/contact.
 */

package com.bstek.dorado.view.config.definition;

import java.util.Enumeration;
import java.util.Map;

import org.aopalliance.intercept.MethodInterceptor;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.jexl2.JexlContext;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.reflect.MethodUtils;

import com.bstek.dorado.annotation.ResourceInjection;
import com.bstek.dorado.config.definition.CreationContext;
import com.bstek.dorado.config.definition.Definition;
import com.bstek.dorado.config.definition.DefinitionManager;
import com.bstek.dorado.core.Context;
import com.bstek.dorado.core.bean.BeanWrapper;
import com.bstek.dorado.core.el.ExpressionHandler;
import com.bstek.dorado.core.resource.ListableResourceBundle;
import com.bstek.dorado.data.config.definition.DataProviderDefinition;
import com.bstek.dorado.data.config.definition.DataResolverDefinition;
import com.bstek.dorado.data.config.definition.DataTypeDefinition;
import com.bstek.dorado.data.config.definition.ListenableObjectDefinition;
import com.bstek.dorado.data.provider.manager.DataProviderManager;
import com.bstek.dorado.data.resolver.manager.DataResolverManager;
import com.bstek.dorado.data.type.manager.DataTypeManager;
import com.bstek.dorado.util.proxy.BeanExtender;
import com.bstek.dorado.util.proxy.BeanExtenderMethodInterceptor;
import com.bstek.dorado.view.PrivateDataProviderManager;
import com.bstek.dorado.view.PrivateDataResolverManager;
import com.bstek.dorado.view.PrivateDataTypeManager;
import com.bstek.dorado.view.ViewState;
import com.bstek.dorado.view.config.PrivateDataProviderDefinitionManager;
import com.bstek.dorado.view.config.PrivateDataResolverDefinitionManager;
import com.bstek.dorado.view.config.PrivateDataTypeDefinitionManager;
import com.bstek.dorado.view.manager.ViewConfig;
import com.bstek.dorado.view.manager.ViewCreationContext;
import com.bstek.dorado.view.resource.ViewResourceManager;
import com.bstek.dorado.web.DoradoContext;

/**
 * @author Benny Bao (mailto:benny.bao@bstek.com)
 * @since 2011-7-11
 */
public class ViewConfigDefinition extends ListenableObjectDefinition {
    private static final String[] DEFAULT_PROPERTIES = new String[] { "caption", "label", "title" };
    private static final Class<?>[] CONSTRUCTOR_ARG_TYPES = new Class<?>[] { String.class };
    private static final String VIEW_STATE_ATTRIBUTE_KEY = ViewState.class.getName();

    public static final String ARGUMENT = "argument";
    public static final String RESOURCE_RELATIVE_DEFINITION = "resourceRelativeDefinition";

    private Map<String, Object> arguments;
    private Map<String, Object> viewContext;
    private ViewDefinition viewDefinition;

    private PrivateDataTypeDefinitionManager dataTypeDefinitionManager;
    private PrivateDataProviderDefinitionManager dataProviderDefinitionManager;
    private PrivateDataResolverDefinitionManager dataResolverDefinitionManager;

    public ViewConfigDefinition(PrivateDataTypeDefinitionManager dataTypeDefinitionManager,
            PrivateDataProviderDefinitionManager dataProviderDefinitionManager,
            PrivateDataResolverDefinitionManager dataResolverDefinitionManager) throws Exception {
        setConstructorArgTypes(CONSTRUCTOR_ARG_TYPES);

        this.dataTypeDefinitionManager = dataTypeDefinitionManager;
        this.dataProviderDefinitionManager = dataProviderDefinitionManager;
        this.dataResolverDefinitionManager = dataResolverDefinitionManager;

        dataTypeDefinitionManager.setViewConfigDefinition(this);
        dataProviderDefinitionManager.setViewConfigDefinition(this);
        dataResolverDefinitionManager.setViewConfigDefinition(this);
    }

    /**
     * ??DataType??
     */
    public DefinitionManager<DataTypeDefinition> getDataTypeDefinitionManager() {
        return dataTypeDefinitionManager;
    }

    /**
     * ??DataProvider??
     */
    public DefinitionManager<DataProviderDefinition> getDataProviderDefinitionManager() {
        return dataProviderDefinitionManager;
    }

    /**
     * ??DataResolver??
     */
    public DefinitionManager<DataResolverDefinition> getDataResolverDefinitionManager() {
        return dataResolverDefinitionManager;
    }

    /**
     * ?Map?
     * 
     * @return ?Map?Map?????
     */
    public Map<String, Object> getArguments() {
        return arguments;
    }

    public void setArguments(Map<String, Object> arguments) {
        this.arguments = arguments;
    }

    public Map<String, Object> getViewContext() {
        return viewContext;
    }

    public void setViewContext(Map<String, Object> viewContext) {
        this.viewContext = viewContext;
    }

    public ViewDefinition getViewDefinition() {
        return viewDefinition;
    }

    public void setViewDefinition(ViewDefinition viewDefinition) {
        this.viewDefinition = viewDefinition;
    }

    private void throwInvalidResourceKey(String key) {
        throw new IllegalArgumentException("Invalid resource key \"" + key + "\".");
    }

    protected void injectResourceString(ViewConfig viewConfig, String key, String resourceString) throws Exception {
        Object object = viewConfig;
        ResourceInjection resourceInjection = object.getClass().getAnnotation(ResourceInjection.class);

        String[] sections = StringUtils.split(key, ".");
        int len = sections.length;
        for (int i = 0; i < len; i++) {
            String section = sections[i];
            boolean isObject = section.charAt(0) == '#';
            if (isObject) {
                section = section.substring(1);
            }

            if (i == 0 && section.equals("view")) {
                object = viewConfig.getView();
            } else if (isObject) {
                if (object == viewConfig) {
                    object = viewConfig.getDataType(section);
                    if (object == null && viewConfig.getView() != null) {
                        object = viewConfig.getView().getViewElement(section);
                    }
                } else {
                    if (resourceInjection == null) {
                        throwInvalidResourceKey(key);
                    }
                    String methodName = resourceInjection.subObjectMethod();
                    if (StringUtils.isEmpty(methodName)) {
                        throwInvalidResourceKey(key);
                    }
                    object = MethodUtils.invokeExactMethod(object, methodName, new String[] { section });
                }
                if (object == null) {
                    break;
                }
                resourceInjection = object.getClass().getAnnotation(ResourceInjection.class);

                if (i == len - 1) {
                    String[] defaultProperties;
                    if (resourceInjection == null) {
                        defaultProperties = DEFAULT_PROPERTIES;
                    } else {
                        defaultProperties = resourceInjection.defaultProperty();
                    }

                    boolean found = false;
                    for (String property : defaultProperties) {
                        if (PropertyUtils.isWriteable(object, property)) {
                            if (PropertyUtils.getSimpleProperty(object, property) == null) {
                                PropertyUtils.setSimpleProperty(object, property, resourceString);
                            }
                            found = true;
                            break;
                        }
                    }
                    if (!found) {
                        throwInvalidResourceKey(key);
                    }
                }
            } else {
                if (i == len - 1) {
                    if (PropertyUtils.getSimpleProperty(object, section) == null) {
                        PropertyUtils.setSimpleProperty(object, section, resourceString);
                    }
                } else {
                    object = PropertyUtils.getSimpleProperty(object, section);
                }
            }
        }
    }

    @Override
    protected Object doCreate(CreationContext context, Object[] constuctorArgs) throws Exception {
        Context doradoContext = Context.getCurrent();
        ExpressionHandler expressionHandler = (ExpressionHandler) doradoContext.getServiceBean("expressionHandler");
        JexlContext jexlContext = expressionHandler.getJexlContext();

        Object originArgumentsVar = jexlContext.get(ARGUMENT);
        jexlContext.set(ARGUMENT, arguments);

        Definition resourceRelativeDefinition = (Definition) jexlContext.get(RESOURCE_RELATIVE_DEFINITION);
        jexlContext.set(RESOURCE_RELATIVE_DEFINITION, this);

        Object oldDtdm = doradoContext.getAttribute(Context.THREAD, "privateDataTypeDefinitionManager");
        Object oldDpdm = doradoContext.getAttribute(Context.THREAD, "privateDataProviderDefinitionManager");
        Object oldDrdm = doradoContext.getAttribute(Context.THREAD, "privateDataResolverDefinitionManager");

        doradoContext.setAttribute(Context.THREAD, "privateDataTypeDefinitionManager",
                dataTypeDefinitionManager.duplicate());
        doradoContext.setAttribute(Context.THREAD, "privateDataProviderDefinitionManager",
                dataProviderDefinitionManager.duplicate());
        doradoContext.setAttribute(Context.THREAD, "privateDataResolverDefinitionManager",
                dataResolverDefinitionManager.duplicate());
        try {
            ViewConfig viewConfig = (ViewConfig) super.doCreate(context, constuctorArgs);

            ViewResourceManager viewResourceManager = (ViewResourceManager) doradoContext
                    .getServiceBean("viewResourceManager");
            ListableResourceBundle bundle = (ListableResourceBundle) viewResourceManager.getBundle(this);
            if (bundle != null) {
                for (Enumeration<String> enumeration = bundle.getKeys(); enumeration.hasMoreElements();) {
                    String key = enumeration.nextElement();
                    if (key.charAt(0) == '#') {
                        String resourceString = bundle.getString(key);
                        injectResourceString(viewConfig, key, resourceString);
                    }
                }
            }

            return viewConfig;
        } finally {
            jexlContext.set(ARGUMENT, originArgumentsVar);
            jexlContext.set(RESOURCE_RELATIVE_DEFINITION, resourceRelativeDefinition);

            doradoContext.setAttribute(Context.THREAD, "privateDataTypeDefinitionManager", oldDtdm);
            doradoContext.setAttribute(Context.THREAD, "privateDataProviderDefinitionManager", oldDpdm);
            doradoContext.setAttribute(Context.THREAD, "privateDataResolverDefinitionManager", oldDrdm);
        }
    }

    @Override
    protected BeanWrapper createObject(CreationInfo creationInfo, Object[] constuctorArgs,
            MethodInterceptor[] methodInterceptors, CreationContext context) throws Exception {
        ViewState viewState = (ViewState) Context.getCurrent().getAttribute(VIEW_STATE_ATTRIBUTE_KEY);
        if (viewState == null || ViewState.rendering.equals(viewState)) {
            if (viewContext != null && !viewContext.isEmpty()) {
                DoradoContext doradoContext = DoradoContext.getCurrent();
                for (Map.Entry<String, Object> entry : viewContext.entrySet()) {
                    doradoContext.setAttribute(DoradoContext.VIEW, entry.getKey(),
                            getFinalValueOrExpression(entry.getValue(), context));
                }
            }
        }

        BeanExtenderMethodInterceptor bemi = new BeanExtenderMethodInterceptor();
        if (methodInterceptors == null) {
            methodInterceptors = new MethodInterceptor[] { bemi };
        } else {
            MethodInterceptor[] newMis = new MethodInterceptor[methodInterceptors.length + 1];
            System.arraycopy(methodInterceptors, 0, newMis, 0, methodInterceptors.length);
            newMis[methodInterceptors.length] = bemi;
            methodInterceptors = newMis;
        }

        BeanWrapper wrapper = super.createObject(creationInfo, constuctorArgs, methodInterceptors, context);
        BeanExtender.setExProperty(wrapper.getBean(), "viewConfigDefinition", this);
        return wrapper;
    }

    @Override
    protected void doInitObject(Object object, CreationInfo creationInfo, CreationContext context)
            throws Exception {
        ViewCreationContext viewCreationContext = (ViewCreationContext) context;
        ViewConfig viewConfig = (ViewConfig) object;
        viewCreationContext.setViewConfig(viewConfig);
        try {
            super.doInitObject(object, creationInfo, context);

            Context doradoContext = Context.getCurrent();
            PrivateDataTypeDefinitionManager innerDataTypeDefinitionManager = (PrivateDataTypeDefinitionManager) doradoContext
                    .getAttribute(Context.THREAD, "privateDataTypeDefinitionManager");
            PrivateDataProviderDefinitionManager innerDataProviderDefinitionManager = (PrivateDataProviderDefinitionManager) doradoContext
                    .getAttribute(Context.THREAD, "privateDataProviderDefinitionManager");
            PrivateDataResolverDefinitionManager innerDataResolverDefinitionManager = (PrivateDataResolverDefinitionManager) doradoContext
                    .getAttribute(Context.THREAD, "privateDataResolverDefinitionManager");

            PrivateDataTypeManager dataTypeManager = new PrivateDataTypeManager(
                    (DataTypeManager) doradoContext.getServiceBean("dataTypeManager"),
                    innerDataTypeDefinitionManager, innerDataProviderDefinitionManager,
                    innerDataResolverDefinitionManager);

            PrivateDataProviderManager dataProviderManager = new PrivateDataProviderManager(
                    (DataProviderManager) doradoContext.getServiceBean("dataProviderManager"),
                    innerDataTypeDefinitionManager, innerDataProviderDefinitionManager,
                    innerDataResolverDefinitionManager);

            PrivateDataResolverManager dataResolverManager = new PrivateDataResolverManager(
                    (DataResolverManager) doradoContext.getServiceBean("dataResolverManager"),
                    innerDataTypeDefinitionManager, innerDataProviderDefinitionManager,
                    innerDataResolverDefinitionManager);

            viewConfig.setDataTypeManager(dataTypeManager);
            viewConfig.setDataProviderManager(dataProviderManager);
            viewConfig.setDataResolverManager(dataResolverManager);

            ViewState viewState = (ViewState) Context.getCurrent().getAttribute(ViewState.class.getName());
            if (viewState == null || ViewState.rendering.equals(viewState)) {
                viewDefinition.create(context, new Object[] { viewConfig });
            }
        } finally {
            viewCreationContext.setViewConfig(null);
        }
    }
}