/** * Copyright 2011-2015 John Ericksen * * 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.androidtransfuse.gen; import com.sun.codemodel.*; import org.androidtransfuse.TransfuseAnalysisException; import org.androidtransfuse.adapter.ASTArrayType; import org.androidtransfuse.adapter.ASTType; import org.androidtransfuse.adapter.PackageClass; import org.androidtransfuse.validation.Validator; import javax.inject.Inject; import java.util.ArrayList; import java.util.List; /** * Utility class unifying the creation of a basic class from a PackageClass * * Annotates the generated class with the recommended annotation: * `@Generated(value = "org.androidtransfuse.TransfuseAnnotationProcessor", date = "2001-07-04T12:08:56.235-0700")` * * @author John Ericksen */ public class ClassGenerationUtil { private final JCodeModel codeModel; private final ClassGenerationStrategy classGenerationStrategy; private final Validator validator; @Inject public ClassGenerationUtil(JCodeModel codeModel, ClassGenerationStrategy classGenerationStrategy, Validator validator) { this.codeModel = codeModel; this.classGenerationStrategy = classGenerationStrategy; this.validator = validator; } public JDefinedClass defineClass(PackageClass className) throws JClassAlreadyExistsException { JPackage jPackage = codeModel._package(className.getPackage()); JDefinedClass definedClass = jPackage._class(className.getClassName()); classGenerationStrategy.annotateGenerated(definedClass); definedClass.annotate(SuppressWarnings.class).paramArray("value").param("unchecked").param("deprecation"); return definedClass; } public JType type(Class clazz){ return codeModel._ref(clazz); } public JType type(ASTType astType){ try { return codeModel.parseType(astType.getName()); } catch (ClassNotFoundException e) { validator.error("Unable to parse type " + astType.getName()).element(astType).build(); throw new TransfuseAnalysisException("Unable to parse type " + astType.getName(), e); } catch (ExceptionInInitializerError e){ // Tried to initialize an Android class return codeModel.directClass(astType.getName()); } catch (NoClassDefFoundError e){ return codeModel.directClass(astType.getName()); } } public JClass ref(PackageClass packageClass){ return ref(packageClass.getFullyQualifiedName()); } public JClass ref(ASTType astType){ String typeName = astType.getName(); if(astType instanceof ASTArrayType){ return ref(typeName.substring(0, typeName.length() - 2)).array(); } return ref(typeName); } public JClass narrowRef(ASTType astType){ JClass reference = ref(astType); if(astType.getGenericArgumentTypes().size() > 0){ List<JClass> genericParameterRefs = new ArrayList<JClass>(); for (ASTType genericParam : astType.getGenericArgumentTypes()) { genericParameterRefs.add(narrowRef(genericParam)); } reference = reference.narrow(genericParameterRefs); } return reference; } public JClass ref(String typeName){ return codeModel.directClass(typeName); } public JClass ref(Class<?> clazz) { return codeModel.ref(clazz); } }