Package org.jboss.errai.bus.rebind

Source Code of org.jboss.errai.bus.rebind.BusClientConfigGenerator$ValueBinder

/*
* Copyright 2010 JBoss, a divison Red Hat, 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.errai.bus.rebind;

import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.*;
import com.google.gwt.user.rebind.SourceWriter;
import org.jboss.errai.bus.server.ErraiBootstrapFailure;
import org.jboss.errai.bus.server.annotations.ExposeEntity;
import org.jboss.errai.bus.server.annotations.Remote;
import org.jboss.errai.bus.server.service.ErraiServiceConfigurator;
import org.jboss.errai.bus.server.service.metadata.MetaDataScanner;
import org.mvel2.templates.CompiledTemplate;
import org.mvel2.util.Make;
import org.mvel2.util.ParseTools;
import org.mvel2.util.ReflectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import static org.mvel2.templates.TemplateCompiler.compileTemplate;
import static org.mvel2.templates.TemplateRuntime.execute;

/**
* @author Mike Brock
* @author Heiko Braun
*/
public class BusClientConfigGenerator implements ExtensionGenerator {
    private Logger log = LoggerFactory.getLogger(BusClientConfigGenerator.class);

    private CompiledTemplate demarshallerGenerator;
    private CompiledTemplate marshallerGenerator;
    private CompiledTemplate rpcProxyGenerator;

    public BusClientConfigGenerator() {
        InputStream istream = this.getClass().getResourceAsStream("DemarshallerGenerator.mv");
        demarshallerGenerator = compileTemplate(istream, null);

        istream = this.getClass().getResourceAsStream("MarshallerGenerator.mv");
        marshallerGenerator = compileTemplate(istream, null);

        istream = this.getClass().getResourceAsStream("RPCProxyGenerator.mv");
        rpcProxyGenerator = compileTemplate(istream, null);
    }

    public void generate(
            GeneratorContext context, TreeLogger logger,
            SourceWriter writer, MetaDataScanner scanner, final TypeOracle oracle) {

        for (Class<?> entity : scanner.getTypesAnnotatedWith(ExposeEntity.class)) {
            generateMarshaller(loadType(oracle, entity), logger, writer);
        }

        for (Class<?> remote : scanner.getTypesAnnotatedWith(Remote.class)) {
            JClassType type = loadType(oracle, remote);
            try {
                writer.print((String) execute(rpcProxyGenerator,
                        Make.Map.<String, Object>$()
                                ._("implementationClassName", type.getName() + "Impl")
                                ._("interfaceClass", Class.forName(type.getQualifiedSourceName()))
                                ._()));
            }
            catch (Throwable t) {
                throw new ErraiBootstrapFailure(t);
            }
        }

        Properties props = scanner.getProperties("ErraiApp.properties");
        if (props != null) {
            logger.log(TreeLogger.Type.INFO, "Checking ErraiApp.properties for configured types ...");

            Iterator<Object> it = props.keySet().iterator();
            while (it.hasNext()) {

                String key = (String) it.next();

                /**
                 * Types configuration
                 */
                if (ErraiServiceConfigurator.CONFIG_ERRAI_SERIALIZABLE_TYPE.equals(key)) {
                    for (String s : props.getProperty(key).split(" ")) {
                        try {
                            generateMarshaller(oracle.getType(s.trim()), logger, writer);
                        }
                        catch (Exception e) {
                            e.printStackTrace();
                            throw new ErraiBootstrapFailure(e);
                        }
                    }
                }

                /**
                 * Entity configuration
                 */
                else if (ErraiServiceConfigurator.CONFIG_ERRAI_SERIALIZABLE_TYPE.equals(key)) {
                    for (String s : props.getProperty(key).split(" ")) {
                        try {
                            generateMarshaller(oracle.getType(s.trim()), logger, writer);
                        }
                        catch (Exception e) {
                            e.printStackTrace();
                            throw new ErraiBootstrapFailure(e);
                        }
                    }
                }
            }
        } else {
            // props not found
            log.warn("No modules found ot load. Unable to find ErraiApp.properties in the classpath");
        }
    }

    private JClassType loadType(TypeOracle oracle, Class<?> entity) {
        try {
            return oracle.getType(entity.getCanonicalName());
        }
        catch (NotFoundException e) {
            throw new RuntimeException("Failed to load type " + entity.getName(), e);
        }
    }

    private void generateMarshaller(JClassType visit, TreeLogger logger, SourceWriter writer) {
        Boolean enumType = visit.isEnum() != null;
        Map<String, Class> types = new HashMap<String, Class>();
        Map<String, ValueExtractor> getters = new HashMap<String, ValueExtractor>();
        Map<String, ValueBinder> setters = new HashMap<String, ValueBinder>();
        Map<Class, Integer> arrayConverters = new HashMap<Class, Integer>();

        try {
            JClassType scan = visit;

            do {
                for (JField f : scan.getFields()) {
                    if (f.isTransient() || f.isStatic() || f.isEnumConstant() != null) continue;

                    JClassType type = f.getType().isClassOrInterface();
                    JMethod getterMeth;
                    JMethod setterMeth;
                    if (type == null) {
                        JPrimitiveType pType = f.getType().isPrimitive();
                        Class c;
                        if (pType == null) {
                            JArrayType aType = f.getType().isArray();
                            if (aType == null) continue;

                            String name = aType.getQualifiedBinaryName();
                            int depth = 0;
                            for (int i = 0; i < name.length(); i++) {
                                if (name.charAt(i) == '[') depth++;
                                else break;
                            }

                            types.put(f.getName(), c = Class.forName(name.substring(0, depth) + getInternalRep(aType.getQualifiedBinaryName().substring(depth))));

                            arrayConverters.put(c, depth);

                        } else {
                            types.put(f.getName(), c = ParseTools.unboxPrimitive(Class.forName(pType.getQualifiedBoxedSourceName())));
                        }
                    } else {

                        types.put(f.getName(), Class.forName(type.getQualifiedBinaryName()));
                    }

                    getterMeth = getAccessorMethod(visit, f);
                    setterMeth = getSetterMethod(visit, f);

                    if (getterMeth == null) {
                        if (f.isPublic()) {
                            getters.put(f.getName(), new ValueExtractor(f));
                        } else if (visit == scan) {
                            throw new GenerationException("could not find a read accessor in class: " + visit.getQualifiedSourceName() + "; for field: " + f.getName() + "; should declare an accessor: " + ReflectionUtil.getGetter(f.getName()));
                        }
                    } else {
                        getters.put(f.getName(), new ValueExtractor(getterMeth));
                    }

                    if (setterMeth == null) {
                        if (f.isPublic()) {
                            setters.put(f.getName(), new ValueBinder(f));
                        } else if (visit == scan) {
                            throw new GenerationException("could not find a write accessor in class: " + visit.getQualifiedSourceName() + "; for field: " + f.getName() + "; should declare an accessor: " + ReflectionUtil.getSetter(f.getName()));
                        }
                    } else {
                        setters.put(f.getName(), new ValueBinder(setterMeth));
                    }


                }
            }
            while ((scan = scan.getSuperclass()) != null && !scan.getQualifiedSourceName().equals("java.lang.Object"));

        }
        catch (ClassNotFoundException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

        try {
            if (!enumType) visit.getConstructor(new JClassType[0]);
        }
        catch (NotFoundException e) {
            String errorMsg = "Type marked for serialization does not expose a default constructor: " + visit.getQualifiedSourceName();
            logger.log(TreeLogger.Type.ERROR, errorMsg, e);
            throw new GenerationException(errorMsg, e);
        }

        Map<String, Object> templateVars = Make.Map.<String, Object>$()
                ._("className", visit.getQualifiedSourceName())
                ._("canonicalClassName", visit.getQualifiedBinaryName())
                ._("fields", types.keySet())
                ._("targetTypes", types)
                ._("getters", getters)
                ._("setters", setters)
                ._("arrayConverters", arrayConverters)
                ._("enumType", enumType)._();

        String genStr;

        writer.print(genStr = (String) execute(demarshallerGenerator, templateVars));

        log.debug("generated demarshaller: \n" + genStr);

        logger.log(TreeLogger.Type.INFO, genStr);

        writer.print(genStr = (String) execute(marshallerGenerator, templateVars));

        log.debug("generated marshaller: \n" + genStr);

        logger.log(TreeLogger.Type.INFO, genStr);
        logger.log(TreeLogger.Type.INFO, "Generated marshaller/demarshaller for: " + visit.getName());
    }

    public static class ValueExtractor {
        private boolean accessor;
        private String name;

        public ValueExtractor(JMethod m) {
            accessor = true;
            name = m.getName();
        }

        public ValueExtractor(JField f) {
            accessor = false;
            name = f.getName();
        }

        @Override
        public String toString() {
            return accessor ? name + "()" : name;
        }
    }

    public static class ValueBinder {
        private boolean accessor;
        private String name;

        public ValueBinder(JMethod m) {
            accessor = true;
            name = m.getName();
        }

        public ValueBinder(JField f) {
            accessor = false;
            name = f.getName();
        }

        public String bindValue(String expr) {
            return accessor ? name + "(" + expr + ")" : "name = " + expr;
        }
    }


    private static JMethod getAccessorMethod(JClassType clazz, JField field) {
        JMethod m = null;

        if (field.getType().getQualifiedSourceName().equals("boolean"))
            m = _findGetterMethod(clazz, ReflectionUtil.getIsGetter(field.getName()));

        if (m == null)
            m = _findGetterMethod(clazz, ReflectionUtil.getGetter(field.getName()));

        if (m == null)
            m = _findGetterMethod(clazz, "get" + field.getName());

        return m;
    }

    private static JMethod getSetterMethod(JClassType clazz, JField field) {
        JMethod m = null;

        m = _findSetterMethod(clazz, field.getType(), ReflectionUtil.getSetter(field.getName()));

        if (m == null)
            m = _findSetterMethod(clazz, field.getType(), "set" + field.getName());

        return m;
    }


    private static JMethod _findGetterMethod(JClassType clazz, String methName) {
        JClassType scan = clazz;
        do {
            try {
                return scan.getMethod(methName, new JType[0]);
            }
            catch (NotFoundException e) {
                //
            }
        } while ((scan = scan.getSuperclass()) != null && !scan.getQualifiedSourceName().equals("java.lang.Object"));
        return null;
    }

    private static JMethod _findSetterMethod(JClassType clazz, JType field, String methName) {
        JClassType scan = clazz;
        do {

            try {
                return scan.getMethod(methName, new JType[]{field});
            }
            catch (NotFoundException e) {
                //
            }
        } while ((scan = scan.getSuperclass()) != null && !scan.getQualifiedSourceName().equals("java.lang.Object"));
        return null;
    }

    private String getInternalRep(String c) {
        if ("char".equals(c)) {
            return "C";
        } else if ("byte".equals(c)) {
            return "B";
        } else if ("double".equals(c)) {
            return "D";
        } else if ("float".equals(c)) {
            return "F";
        } else if ("int".equals(c)) {
            return "I";
        } else if ("long".equals(c)) {
            return "J";
        } else if ("short".equals(c)) {
            return "S";
        } else if ("boolean".equals(c)) {
            return "Z";
        }
        return "L" + c + ";";
    }


    /*public static void main(String[] args) throws Exception {
        org.jboss.errai.common.client.types.TypeHandlerFactory.addHandler(
                java.util.Collection.class,
                char[][].class,
                new org.jboss.errai.common.client.types.TypeHandler<java.util.Collection, char[][]>() {
                    public char[][] getConverted(java.util.Collection col0) {
                        char[][] a = new char[col0.size()][];


                        java.util.Iterator iter0 = col0.iterator();

                        for (int i0 = 0; i0 < a.length; i0++) {


                            java.util.Collection col1 = (java.util.Collection) iter0.next();
                            a[i0] = new char[col1.size()];


                            java.util.Iterator iter1 = col1.iterator();

                            for (int i1 = 0; i1 < a[i0].length; i1++) {
                                a[i0][i1] = org.jboss.errai.common.client.types.TypeHandlerFactory.convert(iter1.next(), java.lang.Character.class);
                            }

                        }


                        return a;
                    }

                });
    }   */
TOP

Related Classes of org.jboss.errai.bus.rebind.BusClientConfigGenerator$ValueBinder

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.