com.seanchenxi.resteasy.autobean.generator.ThrowableFactoryGenerator.java Source code

Java tutorial

Introduction

Here is the source code for com.seanchenxi.resteasy.autobean.generator.ThrowableFactoryGenerator.java

Source

/*******************************************************************************
 * Copyright 2012 Xi CHEN
 *
 * 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 com.seanchenxi.resteasy.autobean.generator;

import java.io.PrintWriter;
import java.util.HashSet;

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.TreeLogger.Type;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.JMethod;
import com.google.gwt.core.ext.typeinfo.JType;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;
import com.seanchenxi.resteasy.autobean.share.RESTService;

public class ThrowableFactoryGenerator extends Generator {

    private static HashSet<String> THROWABLES = new HashSet<String>();
    static {
        THROWABLES.add("java.lang.ArithmeticException");
        THROWABLES.add("java.lang.ArrayIndexOutOfBoundsException");
        THROWABLES.add("java.lang.ArrayStoreException");
        THROWABLES.add("java.lang.ClassCastException");
        THROWABLES.add("java.lang.Exception");
        THROWABLES.add("java.lang.IllegalArgumentException");
        THROWABLES.add("java.lang.IllegalStateException");
        THROWABLES.add("java.lang.IndexOutOfBoundsException");
        THROWABLES.add("java.lang.NegativeArraySizeException");
        THROWABLES.add("java.lang.NullPointerException");
        THROWABLES.add("java.lang.NumberFormatException");
        THROWABLES.add("java.lang.RuntimeException");
        THROWABLES.add("java.lang.StringIndexOutOfBoundsException");
        THROWABLES.add("java.lang.UnsupportedOperationException");
        THROWABLES.add("java.lang.Throwable");
    }

    @Override
    public String generate(TreeLogger logger, GeneratorContext context, String typeName)
            throws UnableToCompleteException {
        TypeOracle oracle = context.getTypeOracle();
        JClassType type = oracle.findType(typeName);
        type = type.isInterface();
        if (type == null) {
            logger.log(TreeLogger.ERROR, typeName + " is not found");
            throw new UnableToCompleteException();
        }

        String packageName = type.getPackage().getName();
        String simpleName = type.getSimpleSourceName() + "Impl";
        PrintWriter printWriter = context.tryCreate(logger, packageName, simpleName);
        if (printWriter == null) {
            return packageName + "." + simpleName;
        }

        ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, simpleName);
        factory.addImplementedInterface(typeName);
        factory.addImport(Throwable.class.getName());

        SourceWriter writer = factory.createSourceWriter(context, printWriter);
        writer.indent();
        writer.println("@Override");
        writer.println("public Throwable create(String className, String message){");
        for (String qname : getAllThrowableTypes(oracle, logger)) {
            writer.println("   if(\"" + qname + "\".equals(className)) {");
            writer.println("      return new " + qname + " (message);");
            writer.println("   }");
        }
        writer.println("   return new Throwable(message);");
        writer.println("}");
        writer.outdent();
        writer.commit(logger);
        return factory.getCreatedClassName();
    }

    private HashSet<String> getAllThrowableTypes(TypeOracle oracle, TreeLogger logger) {
        HashSet<String> set = new HashSet<String>();
        try {
            JType[] params = new JType[1];
            params[0] = oracle.parse("java.lang.String");
            JClassType[] svcTypes = oracle.getType(RESTService.class.getName()).getSubtypes();
            for (JClassType type : svcTypes) {
                for (JMethod method : type.getMethods()) {
                    for (JClassType throwable : method.getThrows()) {
                        if (null != throwable.getConstructor(params))
                            set.add(throwable.getQualifiedSourceName());
                        else
                            logger.log(Type.WARN, throwable.getQualifiedSourceName()
                                    + " will be ignored for serialization, it must at least have a constructor with string type message as parameter.");
                    }
                }
            }
        } catch (Exception e) {
            logger.log(Type.ERROR, e.getMessage(), e);
        }
        set.addAll(THROWABLES);
        return set;
    }

}