Java tutorial
/* * Copyright 2010 kk-electronic a/s. * * This file is part of KKPortal. * * KKPortal is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * KKPortal is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with KKPortal. If not, see <http://www.gnu.org/licenses/>. * */ package com.kk_electronic.gwt.rebind; import java.io.PrintWriter; import java.util.HashMap; 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.NotFoundException; import com.google.gwt.core.ext.typeinfo.TypeOracle; import com.google.gwt.inject.client.GinModules; import com.google.gwt.user.rebind.ClassSourceFileComposerFactory; import com.google.gwt.user.rebind.SourceWriter; import com.kk_electronic.kkportal.core.reflection.ClassMap; public class ClassMapGenerator extends Generator { private String packageName; private String className; private TypeOracle typeOracle; private JClassType classType; private JClassType keyType; private JClassType valueType; private TreeLogger logger; @Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { this.logger = logger; try { typeOracle = context.getTypeOracle(); classType = typeOracle.getType(typeName); packageName = classType.getPackage().getName(); className = classType.getSimpleSourceName() + "Impl"; classType.getAnnotation(GinModules.class); generateClass(logger, context); } catch (NotFoundException e) { logger.log(TreeLogger.ERROR, "Exception during ClassMap creation.", e); throw new UnableToCompleteException(); } return packageName + "." + className; } private void generateClass(TreeLogger logger, GeneratorContext context) throws UnableToCompleteException, NotFoundException { PrintWriter printWriter = context.tryCreate(logger, packageName, className); if (printWriter == null) { return; } ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(packageName, className); composer.addImport(HashMap.class.getCanonicalName()); composer.addImplementedInterface(classType.getQualifiedSourceName()); JClassType target = typeOracle.getType(ClassMap.class.getCanonicalName()); for (JClassType interfaze : classType.getImplementedInterfaces()) { if (interfaze.getErasedType().equals(target.getErasedType())) { JClassType[] genericTypes = interfaze.isParameterized().getTypeArgs(); keyType = genericTypes[0]; valueType = genericTypes[1]; } } // if (!"java.lang.String".equals(keyType.getQualifiedSourceName())){ // logger.log(TreeLogger.ERROR, "keyType must be a String for now"); // throw new UnableToCompleteException(); // } composer.addImport(keyType.getQualifiedSourceName()); composer.addImport(valueType.getQualifiedSourceName()); SourceWriter sourceWriter = composer.createSourceWriter(context, printWriter); writeMethods(sourceWriter); writeData(sourceWriter); sourceWriter.outdent(); sourceWriter.println("}"); context.commit(logger, printWriter); } private void writeData(SourceWriter sw) throws UnableToCompleteException { sw.println(); sw.println("{"); sw.indent(); for (JClassType classType : valueType.getSubtypes()) { String key = getKeyFromClass(classType); sw.println("map.put(" + key + "," + classType.getQualifiedSourceName() + ".class);"); sw.println("reversemap.put(" + classType.getQualifiedSourceName() + ".class, " + key + ");"); } sw.outdent(); sw.println("}"); } private void writeMethods(SourceWriter sw) { sw.print("private static HashMap<" + keyType.getName() + ", Class<? extends " + valueType.getName() + ">> map"); sw.println("= new HashMap<" + keyType.getName() + ", Class<? extends " + valueType.getName() + ">>();"); sw.print("private static HashMap<Class<? extends " + valueType.getName() + ">," + keyType.getName() + "> reversemap"); sw.println("= new HashMap<Class<? extends " + valueType.getName() + ">," + keyType.getName() + ">();"); sw.println(); sw.println("@Override"); sw.println("public Class<? extends " + valueType.getName() + "> getClassFromKey(" + keyType.getName() + " name) {"); sw.println(" return map.get(name);"); sw.println("}"); sw.println(); sw.println("@Override"); sw.println("public " + keyType.getName() + " getKeyFromClass(Class<? extends " + valueType.getName() + "> clazz) {"); sw.println(" return reversemap.get(clazz);"); sw.println("}"); } private String getKeyFromClass(JClassType j) throws UnableToCompleteException { MapKey x = j.getAnnotation(MapKey.class); if (x != null) { return x.value(); } if ("java.lang.String".equals(keyType.getQualifiedSourceName())) { return "\"" + escape(j.getName()) + "\""; } if ("java.lang.Integer".equals(keyType.getQualifiedSourceName())) { return String.valueOf(j.getName().hashCode()); } logger.log(TreeLogger.ERROR, "keyType can only be autogenerated for Integers and Strings - supply @MapKey annotation"); throw new UnableToCompleteException(); } }