Package org.gwtoolbox.bean.rebind

Source Code of org.gwtoolbox.bean.rebind.BeanInfoRegistryGenerator

/*
* Copyright 2002-2008 the original author or authors.
*
* 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.gwtoolbox.bean.rebind;

import com.google.gwt.core.ext.Generator;
import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JPackage;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import org.gwtoolbox.bean.client.BeanInfo;
import org.gwtoolbox.bean.client.BeanInfoRegistry;
import org.gwtoolbox.bean.rebind.scan.TypeScanner;
import org.gwtoolbox.bean.rebind.selector.BeanClassSelector;
import org.gwtoolbox.bean.rebind.validation.config.BeanValidationConfigHolder;
import org.gwtoolbox.bean.rebind.validation.config.ValidationConfigLoader;
import org.gwtoolbox.commons.generator.rebind.EasyTreeLogger;
import org.gwtoolbox.commons.generator.rebind.LoggingUtils;

import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
* Generate the BeanInfoRegistry. This generator scans the the packages (configured using the @BeanScan annotation)
* and picks up all beans. The bean need to be annotated with the annotation as specified in the @BeanScan annotation
* (by default the @Bean is picked up).
*
* @author Uri Boness
*/
public class BeanInfoRegistryGenerator extends Generator {

    public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException {
        try {
            LoggingUtils.setLogger(new EasyTreeLogger(logger));
            return doGenerate(logger, context, typeName);
        } catch (Exception e) {
            logger.log(TreeLogger.ERROR, null, e);
            throw new UnableToCompleteException();
        } finally {
            LoggingUtils.clearLogger();
        }
    }

    public String doGenerate(TreeLogger logger, GeneratorContext context, String typeName) throws Exception {

        EasyTreeLogger easyLogger = new EasyTreeLogger(logger);

        JClassType type = context.getTypeOracle().findType(typeName);
        String packageName = type.getPackage().getName();
        String simpleName = type.getSimpleSourceName();

        String generatedClassName = "gtx__" + simpleName + "Impl";
        String qualifiedBeanClassName = packageName + "." + generatedClassName;
        SourceWriter sourceWriter = getSourceWriter(logger, context, type, packageName, generatedClassName);
        if (sourceWriter == null) {
            return qualifiedBeanClassName;
        }

        // scanning all types and loading configurations
        TypeOracle typeOracle = context.getTypeOracle();
        TypeScanner scanner = new TypeScanner(easyLogger, context);
        BeanConfigLoader beanConfigLoader = new BeanConfigLoader(typeOracle);
        ValidationConfigLoader validationConfigLoader = new ValidationConfigLoader(typeOracle);

        try {
            scanner.scan(beanConfigLoader, validationConfigLoader);

            List<JClassType> beanTypes = new ArrayList<JClassType>();
            for (BeanRegistryConfig config : beanConfigLoader.getBeanRegistryConfigs()) {
                beanTypes.addAll(scanBeans(easyLogger, context, config.getBeanClassSelector(), config.getPatterns()));
            }

            write(easyLogger, sourceWriter, context, generatedClassName, beanTypes);
            sourceWriter.commit(logger);

        } finally {
            BeanValidationConfigHolder.clear();
        }

        return qualifiedBeanClassName;
    }


    protected SourceWriter getSourceWriter(
            TreeLogger logger,
            GeneratorContext context,
            JClassType superClass,
            String packageName,
            String simpleClassName) {

        PrintWriter printWriter = context.tryCreate(logger, packageName, simpleClassName);

        if (printWriter == null) {
            return null;
        }

        ClassSourceFileComposerFactory composerFactory = new ClassSourceFileComposerFactory(packageName, simpleClassName);

        composerFactory.setSuperclass(superClass.getQualifiedSourceName());

        //TODO add imports here
        composerFactory.addImport(BeanInfoRegistry.class.getName());
        composerFactory.addImport(BeanInfo.class.getName());
        composerFactory.addImport(Map.class.getName());
        composerFactory.addImport(HashMap.class.getName());

        return composerFactory.createSourceWriter(context, printWriter);
    }

    protected void write(
            EasyTreeLogger logger,
            SourceWriter writer,
            GeneratorContext context,
            String classSimpleName,
            List<JClassType> beanTypes) throws UnableToCompleteException {

        writer.println();
        writeFields(logger, writer, context, classSimpleName, beanTypes);
        writeInterfaceMethods(logger, writer, context);
    }

    protected void writeFields(EasyTreeLogger logger, SourceWriter writer, GeneratorContext context, String classSimpleName, List<JClassType> beanTypes)
            throws UnableToCompleteException {

        writer.println("private final Map<Class, BeanInfo> beanInfoByType = new HashMap<Class, BeanInfo>();");
        writer.println();

        writer.println("public " + classSimpleName + "() {");
        for (JClassType beanType : beanTypes) {
            String beanInfoClassName = BeanInfoGenerator.generate(logger, context, beanType);
            writer.println("    beanInfoByType.put(" + beanType.getQualifiedSourceName() + ".class, new " + beanInfoClassName + "(this));");
        }
        writer.println("}");
    }

    protected void writeInterfaceMethods(EasyTreeLogger logger, SourceWriter writer, GeneratorContext context) {

        writer.beginJavaDocComment();
        writer.println("BeanInfoRegistry Interface Methods");
        writer.endJavaDocComment();
        writer.println();


        writer.println("public boolean hasBeanInfo(Class type) {");
        writer.println("    return beanInfoByType.containsKey(type);");
        writer.println("}");
        writer.println();

        writer.println("public BeanInfo getBeanInfo(Class type) {");
        writer.println("    return (BeanInfo) beanInfoByType.get(type);");
        writer.println("}");
        writer.println();

    }


    private List<JClassType> scanBeans(
            EasyTreeLogger logger,
            GeneratorContext context,
            BeanClassSelector beanSelector,
            Pattern[] patterns) {

        List<JClassType> beanTypes = new ArrayList<JClassType>();
        for (Pattern pattern : patterns) {
            JPackage[] allPackages = context.getTypeOracle().getPackages();
            for (JPackage currentPackage : allPackages) {
                logger.debug("Scanning package '" + currentPackage.getName() + "'...");
                if (!pattern.matcher(currentPackage.getName()).matches()) {
                    continue;
                }
                EasyTreeLogger packageLogger = logger.branchInfo("Scanning package '" + currentPackage.getName() + "'");
                scanPackage(packageLogger, context, beanSelector, currentPackage, beanTypes);
            }
        }
        return beanTypes;
    }

    private void scanPackage(
            EasyTreeLogger logger,
            GeneratorContext context,
            BeanClassSelector beanSelector,
            JPackage pkg,
            List<JClassType> list) {

        JClassType[] types = pkg.getTypes();
        for (JClassType type : types) {

            if (logger.isLoggable(TreeLogger.Type.DEBUG)) {
                logger.debug("Processing type '" + type.getQualifiedSourceName() + "'");
            }

            if (beanSelector.isBean(type)) {
                logger.info("Found bean '" + type.getQualifiedSourceName() + "'");
                list.add(type);
            }
        }
    }

}
TOP

Related Classes of org.gwtoolbox.bean.rebind.BeanInfoRegistryGenerator

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.