org.eclipse.wb.internal.swing.databinding.wizards.autobindings.SwingDatabindingProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.wb.internal.swing.databinding.wizards.autobindings.SwingDatabindingProvider.java

Source

/*******************************************************************************
 * Copyright (c) 2011 Google, Inc.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Google, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.wb.internal.swing.databinding.wizards.autobindings;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import org.eclipse.wb.internal.core.DesignerPlugin;
import org.eclipse.wb.internal.core.databinding.model.CodeGenerationSupport;
import org.eclipse.wb.internal.core.databinding.ui.editor.contentproviders.ChooseClassAndPropertiesConfiguration;
import org.eclipse.wb.internal.core.databinding.ui.editor.contentproviders.PropertyAdapter;
import org.eclipse.wb.internal.core.databinding.utils.CoreUtils;
import org.eclipse.wb.internal.core.databinding.wizards.autobindings.DefaultAutomaticDatabindingProvider;
import org.eclipse.wb.internal.core.databinding.wizards.autobindings.DescriptorContainer;
import org.eclipse.wb.internal.core.databinding.wizards.autobindings.IAutomaticDatabindingProvider;
import org.eclipse.wb.internal.core.databinding.wizards.autobindings.IImageLoader;
import org.eclipse.wb.internal.core.model.generation.statement.StatementGeneratorDescription;
import org.eclipse.wb.internal.core.model.variable.FieldUniqueVariableSupport;
import org.eclipse.wb.internal.core.model.variable.description.VariableSupportDescription;
import org.eclipse.wb.internal.core.utils.reflect.ReflectionUtils;
import org.eclipse.wb.internal.swing.SwingToolkitDescription;
import org.eclipse.wb.internal.swing.ToolkitProvider;
import org.eclipse.wb.internal.swing.databinding.Activator;
import org.eclipse.wb.internal.swing.databinding.model.DataBindingsCodeUtils;
import org.eclipse.wb.internal.swing.databinding.model.ObserveInfo;
import org.eclipse.wb.internal.swing.databinding.model.beans.BeanSupport;
import org.eclipse.wb.internal.swing.databinding.model.generic.ClassGenericType;
import org.eclipse.wb.internal.swing.databinding.model.generic.GenericUtils;

import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.ui.wizards.NewTypeWizardPage.ImportsManager;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;

import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * Provider for support Swing bindings API.
 * 
 * @author lobas_av
 * @coverage bindings.swing.wizard.auto
 */
public final class SwingDatabindingProvider extends DefaultAutomaticDatabindingProvider {
    private static DescriptorContainer m_componentContainer;
    private static DescriptorContainer m_strategyContainer;

    ////////////////////////////////////////////////////////////////////////////
    //
    // Constructor
    //
    ////////////////////////////////////////////////////////////////////////////
    public static IAutomaticDatabindingProvider create() {
        try {
            // check containers
            if (m_componentContainer == null && m_strategyContainer == null) {
                // load containers
                InputStream stream = Activator.getFile("templates/SwingEditors.xml");
                Map<String, DescriptorContainer> containers = DescriptorContainer.parseDescriptors(stream,
                        SwingDatabindingProvider.class.getClassLoader(), new IImageLoader() {
                            public Image getImage(String name) {
                                return Activator.getImage(name);
                            }
                        });
                IOUtils.closeQuietly(stream);
                // sets containers
                m_componentContainer = containers.get("Swing.Components");
                m_strategyContainer = containers.get("AutoBinding.UpdateStrategy");
            }
            // create provider
            return new SwingDatabindingProvider(m_componentContainer, m_strategyContainer);
        } catch (Throwable e) {
            DesignerPlugin.log(e);
            return null;
        }
    }

    private SwingDatabindingProvider(DescriptorContainer widgetContainer, DescriptorContainer strategyContainer) {
        super(widgetContainer, strategyContainer);
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // SuperClass
    //
    ////////////////////////////////////////////////////////////////////////////
    public String[] getSuperClasses() {
        return new String[] { "javax.swing.JPanel", "javax.swing.JDialog", "javax.swing.JFrame" };
    }

    public String getInitialSuperClass() {
        return "javax.swing.JPanel";
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // GUI
    //
    ////////////////////////////////////////////////////////////////////////////
    public void configure(ChooseClassAndPropertiesConfiguration configuration) {
        configuration.setPropertiesLabelProvider(new ObservePropertyAdapterLabelProvider());
        configuration.setValueScope("beans");
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Properties
    //
    ////////////////////////////////////////////////////////////////////////////
    @Override
    protected List<PropertyAdapter> getProperties0(Class<?> choosenClass) throws Exception {
        List<PropertyAdapter> adapters = Lists.newArrayList();
        BeanSupport beanSupport = new BeanSupport();
        beanSupport.doAddELProperty(false);
        beanSupport.doAddSelfProperty(false);
        ClassGenericType objectType = new ClassGenericType(choosenClass, null, null);
        for (ObserveInfo property : beanSupport.createProperties(null, objectType)) {
            adapters.add(new ObservePropertyAdapter(property));
        }
        return adapters;
    }

    ////////////////////////////////////////////////////////////////////////////
    //
    // Finish
    //
    ////////////////////////////////////////////////////////////////////////////
    public InputStream getTemplateFile(String superClassName) {
        return Activator.getFile("templates/" + ClassUtils.getShortClassName(superClassName) + ".jvt");
    }

    public String performSubstitutions(String code, ImportsManager imports) throws Exception {
        // calculate states
        boolean blockMode = useBlockMode();
        boolean lazyVariables = createLazyVariables();
        //
        DataBindingsCodeUtils.ensureDBLibraries(m_javaProject);
        CodeGenerationSupport generationSupport = new CodeGenerationSupport(CoreUtils.useGenerics(m_javaProject));
        // prepare imports
        Collection<String> importList = Sets.newHashSet();
        importList.add("java.awt.GridBagLayout");
        importList.add("java.awt.GridBagConstraints");
        importList.add("java.awt.Insets");
        importList.add("javax.swing.JLabel");
        importList.add("org.jdesktop.beansbinding.AutoBinding");
        importList.add("org.jdesktop.beansbinding.Bindings");
        importList.add("org.jdesktop.beansbinding.BeanProperty");
        //
        if (!generationSupport.useGenerics()) {
            importList.add("org.jdesktop.beansbinding.Property");
        }
        // bean class, field, name, field access
        String beanClassName = m_beanClass.getName().replace('$', '.');
        String beanClassShortName = ClassUtils.getShortClassName(beanClassName);
        String fieldPrefix = JavaCore.getOption(JavaCore.CODEASSIST_FIELD_PREFIXES);
        String fieldName = fieldPrefix + StringUtils.uncapitalize(beanClassShortName);
        //
        code = StringUtils.replace(code, "%BeanClass%", beanClassName);
        //
        if (ReflectionUtils.getConstructorBySignature(m_beanClass, "<init>()") == null) {
            code = StringUtils.replace(code, "%BeanField%", fieldName);
        } else {
            code = StringUtils.replace(code, "%BeanField%", fieldName + " = new " + beanClassName + "()");
        }
        //
        IPreferenceStore preferences = ToolkitProvider.DESCRIPTION.getPreferences();
        String accessPrefix = preferences.getBoolean(FieldUniqueVariableSupport.P_PREFIX_THIS) ? "this." : "";
        String beanFieldAccess = accessPrefix + fieldName;
        //
        code = StringUtils.replace(code, "%BeanName%", StringUtils.capitalize(beanClassShortName));
        code = StringUtils.replace(code, "%BeanFieldAccess%", accessPrefix + fieldName);
        // prepare properties
        final List<PropertyAdapter> properties = Lists.newArrayList();
        Display.getDefault().syncExec(new Runnable() {
            public void run() {
                CollectionUtils.addAll(properties, m_propertiesViewer.getCheckedElements());
            }
        });
        // prepare code
        StringBuffer componentFields = new StringBuffer();
        StringBuffer components = new StringBuffer();
        String swingContainer = StringUtils.substringBetween(code, "%Components%", "%");
        String swingContainerWithDot = "this".equals(swingContainer) ? "" : swingContainer + ".";
        //
        int propertiesCount = properties.size();
        int lastPropertyIndex = propertiesCount - 1;
        StringBuffer bindings = new StringBuffer();
        // prepare layout code
        components.append("\t\tGridBagLayout gridBagLayout = new GridBagLayout();\r\n");
        components.append("\t\tgridBagLayout.columnWidths = new int[]{0, 0, 0};\r\n");
        components.append("\t\tgridBagLayout.rowHeights = new int[]{" + StringUtils.repeat("0, ", propertiesCount)
                + "0};\r\n");
        components.append("\t\tgridBagLayout.columnWeights = new double[]{0.0, 1.0, 1.0E-4};\r\n");
        components.append("\t\tgridBagLayout.rowWeights = new double[]{"
                + StringUtils.repeat("0.0, ", propertiesCount) + "1.0E-4};\r\n");
        components.append("\t\t" + swingContainerWithDot + "setLayout(gridBagLayout);\r\n");
        //
        StringBuffer group = new StringBuffer();
        generationSupport.generateLocalName("bindingGroup");
        //
        StringBuffer lazy = new StringBuffer();
        //
        for (int i = 0; i < propertiesCount; i++) {
            String index = Integer.toString(i);
            //
            PropertyAdapter property = properties.get(i);
            Object[] editorData = m_propertyToEditor.get(property);
            SwingComponentDescriptor componentDescriptor = (SwingComponentDescriptor) editorData[0];
            //
            String propertyName = property.getName();
            // label
            addLabelCode(componentFields, components, lazy, swingContainerWithDot, blockMode, lazyVariables,
                    propertyName, index);
            //
            String componentClassName = componentDescriptor.getComponentClass();
            String componentShortClassName = ClassUtils.getShortClassName(componentClassName);
            String componentFieldName = fieldPrefix + propertyName + componentShortClassName;
            String componentFieldAccess = accessPrefix + componentFieldName;
            String componentLazyAccess = "get" + StringUtils.capitalize(propertyName) + componentShortClassName
                    + "()";
            String componentAccess = lazyVariables ? componentLazyAccess : componentFieldAccess;
            //
            importList.add(componentClassName);
            // field
            componentFields
                    .append("\r\nfield\r\n\tprivate " + componentShortClassName + " " + componentFieldName + ";");
            // component
            addComponentCode(components, lazy, swingContainerWithDot, blockMode, lazyVariables,
                    componentShortClassName, componentFieldAccess, componentLazyAccess, index);
            // binding properties
            AutoBindingUpdateStrategyDescriptor strategyDescriptor = (AutoBindingUpdateStrategyDescriptor) editorData[1];
            //
            String modelPropertyName = generationSupport.generateLocalName(propertyName, "Property");
            String targetPropertyName = generationSupport.generateLocalName(componentDescriptor.getName(1),
                    "Property");
            String bindingName = generationSupport.generateLocalName("autoBinding");
            String modelGeneric = null;
            String targetGeneric = null;
            //
            if (generationSupport.useGenerics()) {
                modelGeneric = beanClassName + ", "
                        + GenericUtils.convertPrimitiveType(property.getType().getName());
                bindings.append("\t\tBeanProperty<" + modelGeneric + "> ");
            } else {
                bindings.append("\t\tProperty ");
            }
            bindings.append(modelPropertyName + " = BeanProperty.create(\"" + propertyName + "\");\r\n");
            //
            if (generationSupport.useGenerics()) {
                targetGeneric = componentDescriptor.getComponentClass() + ", "
                        + componentDescriptor.getPropertyClass();
                bindings.append("\t\tBeanProperty<" + targetGeneric + "> ");
            } else {
                bindings.append("\t\tProperty ");
            }
            bindings.append(
                    targetPropertyName + " = BeanProperty.create(\"" + componentDescriptor.getName(1) + "\");\r\n");
            // binding
            bindings.append("\t\tAutoBinding");
            if (generationSupport.useGenerics()) {
                bindings.append("<" + modelGeneric + ", " + targetGeneric + ">");
            }
            bindings.append(" " + bindingName + " = Bindings.createAutoBinding("
                    + strategyDescriptor.getSourceCode() + ", " + beanFieldAccess + ", " + modelPropertyName + ", "
                    + componentAccess + ", " + targetPropertyName + ");\r\n");
            bindings.append("\t\t" + bindingName + ".bind();");
            //
            group.append("\t\tbindingGroup.addBinding(" + bindingName + ");");
            //
            if (i < lastPropertyIndex) {
                componentFields.append("\r\n");
                components.append("\r\n");
                bindings.append("\r\n\t\t//\r\n");
                group.append("\r\n");
            }
            //
        }
        // replace template patterns
        code = StringUtils.replace(code, "%ComponentFields%", componentFields.toString());
        code = StringUtils.replace(code, "%Components%" + swingContainer + "%", components.toString());
        code = StringUtils.replace(code, "%Bindings%", bindings.toString());
        code = StringUtils.replace(code, "%Group%", group.toString());
        code = StringUtils.replace(code, "%LAZY%", lazy.toString());
        // add imports
        for (String qualifiedTypeName : importList) {
            imports.addImport(qualifiedTypeName);
        }
        //
        return code;
    }

    private static void addLabelCode(StringBuffer componentFields, StringBuffer components, StringBuffer lazy,
            String swingContainerWithDot, boolean blockMode, boolean lazyVariables, String propertyName,
            String index) {
        String componentAccess = null;
        if (lazyVariables) {
            // field
            String fieldPrefix = JavaCore.getOption(JavaCore.CODEASSIST_FIELD_PREFIXES);
            String label = propertyName + "Label";
            componentFields.append("\r\nfield\r\n\tprivate JLabel " + fieldPrefix + label + ";\r\n");
            // lazy method
            IPreferenceStore preferences = ToolkitProvider.DESCRIPTION.getPreferences();
            String accessPrefix = preferences.getBoolean(FieldUniqueVariableSupport.P_PREFIX_THIS) ? "this." : "";
            componentAccess = "get" + StringUtils.capitalize(label) + "()";
            String labelAccess = accessPrefix + fieldPrefix + label;
            lazy.append("\r\nmethod\r\n\tprivate JLabel " + componentAccess + " {\r\n\t\tif (" + labelAccess
                    + " == null) {\r\n\t\t\t" + labelAccess + " = new JLabel(\""
                    + StringUtils.capitalize(propertyName) + ":\");\r\n\t\t}\r\n\t\treturn " + labelAccess
                    + ";\r\n\t}\r\n\r\n");
        }
        if (blockMode) {
            // block
            components.append("\t\t{\r\n");
            // component
            if (!lazyVariables) {
                componentAccess = "label";
                components.append(
                        "\t\t\tJLabel label = new JLabel(\"" + StringUtils.capitalize(propertyName) + ":\");\r\n");
            }
            // layout
            components.append("\t\t\tGridBagConstraints gbc = new GridBagConstraints();\r\n");
            components.append("\t\t\tgbc.insets = new Insets(5, 5, 5, 5);\r\n");
            components.append("\t\t\tgbc.gridx = 0;\r\n");
            components.append("\t\t\tgbc.gridy = " + index + ";\r\n");
            components.append("\t\t\t" + swingContainerWithDot + "add(" + componentAccess + ", gbc);\r\n");
            // block
            components.append("\t\t}\r\n");
        } else {
            // separator
            components.append("\t\r\n");
            // component
            if (!lazyVariables) {
                componentAccess = propertyName + "Label";
                components.append("\t\tJLabel " + componentAccess + " = new JLabel(\""
                        + StringUtils.capitalize(propertyName) + ":\");\r\n");
            }
            // layout
            String gbc = "labelGbc_" + index;
            components.append("\t\tGridBagConstraints " + gbc + " = new GridBagConstraints();\r\n");
            components.append("\t\t" + gbc + ".insets = new Insets(5, 5, 5, 5);\r\n");
            components.append("\t\t" + gbc + ".gridx = 0;\r\n");
            components.append("\t\t" + gbc + ".gridy = " + index + ";\r\n");
            components.append("\t\t" + swingContainerWithDot + "add(" + componentAccess + ", " + gbc + ");\r\n");
            // separator
            components.append("\t\r\n");
        }
    }

    private static boolean useBlockMode() {
        StatementGeneratorDescription statement = SwingToolkitDescription.INSTANCE.getGenerationSettings()
                .getStatement();
        return statement != null && "Block".equals(statement.getName());
    }

    private static boolean createLazyVariables() {
        VariableSupportDescription variable = SwingToolkitDescription.INSTANCE.getGenerationSettings()
                .getVariable();
        return variable != null && "Lazy".equals(variable.getName());
    }

    private static void addComponentCode(StringBuffer components, StringBuffer lazy, String swingContainerWithDot,
            boolean blockMode, boolean lazyVariable, String componentShortClassName, String componentFieldAccess,
            String componentLazyAccess, String index) {
        String componentAccess = null;
        if (lazyVariable) {
            // lazy method
            componentAccess = componentLazyAccess;
            lazy.append("\r\nmethod\r\n\tprivate " + componentShortClassName + " " + componentLazyAccess
                    + " {\r\n\t\tif (" + componentFieldAccess + " == null) {\r\n\t\t\t" + componentFieldAccess
                    + " = new " + componentShortClassName + "();\r\n\t\t}\r\n\t\treturn " + componentFieldAccess
                    + ";\r\n\t}\r\n\r\n");
        }
        if (blockMode) {
            // block
            components.append("\t\t{\r\n");
            // component
            if (!lazyVariable) {
                componentAccess = componentFieldAccess;
                components
                        .append("\t\t\t " + componentFieldAccess + " = new " + componentShortClassName + "();\r\n");
            }
            // layout
            components.append("\t\t\tGridBagConstraints gbc = new GridBagConstraints();\r\n");
            components.append("\t\t\tgbc.insets = new Insets(5, 0, 5, 5);\r\n");
            components.append("\t\t\tgbc.fill = GridBagConstraints.HORIZONTAL;\r\n");
            components.append("\t\t\tgbc.gridx = 1;\r\n");
            components.append("\t\t\tgbc.gridy = " + index + ";\r\n");
            components.append("\t\t\t" + swingContainerWithDot + "add(" + componentAccess + ", gbc);\r\n");
            // block
            components.append("\t\t}");
        } else {
            // separator
            components.append("\t\r\n");
            //component
            if (!lazyVariable) {
                componentAccess = componentFieldAccess;
                components.append("\t\t " + componentFieldAccess + " = new " + componentShortClassName + "();\r\n");
            }
            // layout
            String gbc = "componentGbc_" + index;
            components.append("\t\tGridBagConstraints " + gbc + " = new GridBagConstraints();\r\n");
            components.append("\t\t" + gbc + ".insets = new Insets(5, 0, 5, 5);\r\n");
            components.append("\t\t" + gbc + ".fill = GridBagConstraints.HORIZONTAL;\r\n");
            components.append("\t\t" + gbc + ".gridx = 1;\r\n");
            components.append("\t\t" + gbc + ".gridy = " + index + ";\r\n");
            components.append("\t\t" + swingContainerWithDot + "add(" + componentAccess + ", " + gbc + ");\r\n");
            // separator
            components.append("\t\t");
        }
    }
}