@Override protected void doAddFieldsAndRequirements( TreeLogger logger, GeneratorContext generatorContext, FieldsImpl fields, ClientBundleRequirements requirements) throws UnableToCompleteException { JType booleanType; JType stringType; try { booleanType = generatorContext.getTypeOracle().parse("boolean"); stringType = generatorContext.getTypeOracle().parse("java.lang.String"); } catch (TypeOracleException e) { logger.log(TreeLogger.ERROR, "Expected type not in type oracle", e); throw new UnableToCompleteException(); } // GWT.getModuleBaseURL().startsWith("https") String isHttpsIdent = fields.define( booleanType, "isHttps", "GWT.getModuleBaseURL().startsWith(\"https\")", true, true); resourceContext.setIsHttpsIdent(isHttpsIdent); // CHECKSTYLE_OFF // "mhtml:" + GWT.getModuleBaseURL() + "partialPath!cid:" // CHECKSTYLE_ON bundleBaseIdent = fields.define(stringType, "bundleBase", null, true, true); resourceContext.setBundleBaseIdent(bundleBaseIdent); }
/** Implement additional methods defined in {@link AbstractUiCommonModelEditorDriver} */ @Override protected void writeAdditionalContent( TreeLogger logger, GeneratorContext context, EditorModel model, SourceWriter sw) throws UnableToCompleteException { TypeOracle typeOracle = context.getTypeOracle(); baseModelType = eraseType( typeOracle.findType("org.ovirt.engine.ui.uicommonweb.models.Model")); // $NON-NLS-1$ entityModelType = eraseType( typeOracle.findType( "org.ovirt.engine.ui.uicommonweb.models.EntityModel")); //$NON-NLS-1$ listModelType = eraseType( typeOracle.findType("org.ovirt.engine.ui.uicommonweb.models.ListModel")); // $NON-NLS-1$ hasCleanupType = eraseType(typeOracle.findType("org.ovirt.engine.ui.uicommonweb.HasCleanup")); // $NON-NLS-1$ this.logger = logger; this.model = model; this.sw = sw; logger.log(Type.DEBUG, "Starting to write additional Driver code"); // $NON-NLS-1$ writeListenerMap(); writeEventMap(); writeOwnerModels(); writeCleanup(); }
@Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { this.logger = logger; typeOracle = context.getTypeOracle(); try { // find XulEventSource implementors implementingTypes = new ArrayList<JClassType>(); JClassType eventSourceType = typeOracle.getType("org.pentaho.ui.xul.XulEventSource"); for (JClassType type : typeOracle.getTypes()) { if (type.isAssignableTo(eventSourceType)) { implementingTypes.add(type); } } // get classType and save instance variables JClassType classType = typeOracle.getType(typeName); packageName = classType.getPackage().getName(); className = classType.getSimpleSourceName() + "Impl"; // Generate class source code generateClass(logger, context); } catch (Exception e) { // record to logger that Map generation threw an exception logger.log(TreeLogger.ERROR, "Error generating BindingContext!!!", e); } // return the fully qualifed name of the class generated return packageName + "." + className; }
/** * @param logger * @param context * @param baseIntf */ public DeviceAdaptiveProxyCreator( TreeLogger logger, GeneratorContext context, JClassType baseIntf) { super(logger, context, baseIntf, false); deviceAdaptiveControllerClass = context.getTypeOracle().findType(DeviceAdaptiveController.class.getCanonicalName()); deviceAdaptiveClass = context.getTypeOracle().findType(DeviceAdaptive.class.getCanonicalName()); hasHandlersClass = context.getTypeOracle().findType(HasHandlers.class.getCanonicalName()); initializeTemplateParser(); view = templateParser.getTemplateView(template, baseIntf.getQualifiedSourceName(), device); initializeController(view); viewFactoryCreator = new DeviceAdaptiveViewFactoryCreator( context, logger, view, getDeviceFeatures(), controllerName, getModule()); viewClassName = viewFactoryCreator.create(); }
/** * Erases the {@link MetaClassFactory} cache, then populates it with types discovered via GWT's * TypeOracle. The reason for the initial flush of the MetaClassFactory is to support hot redeploy * in Dev Mode. The reason for doing this operation at all is so that the overridden class * definitions (super-source classes) are used in preference to the Java reflection based class * definitions. * * @param context The GeneratorContext supplied by the GWT compiler. Not null. * @param logger The TreeLogger supplied by the GWT compiler. Not null. */ public static void populateMetaClassFactoryFromTypeOracle( final GeneratorContext context, final TreeLogger logger) { // if we're in production mode -- it means we're compiling, and we do not need to accommodate // dynamically // changing classes. Therefore, do a NOOP after the first successful call. if (typeOraclePopulated && (context.equals(populatedFrom.get()) || EnvUtil.isProdMode())) { return; } final TypeOracle typeOracle = context.getTypeOracle(); MetaClassFactory.emptyCache(); if (typeOracle != null) { final Set<String> translatable = new HashSet<String>(RebindUtils.findTranslatablePackages(context)); translatable.remove("java.lang"); translatable.remove("java.lang.annotation"); for (final JClassType type : typeOracle.getTypes()) { if (!translatable.contains(type.getPackage().getName())) { logger.log( com.google.gwt.core.ext.TreeLogger.Type.DEBUG, "Skipping non-translatable " + type.getQualifiedSourceName()); continue; } if (type.isAnnotation() != null || type.getQualifiedSourceName().equals("java.lang.annotation.Annotation")) { logger.log( com.google.gwt.core.ext.TreeLogger.Type.DEBUG, "Caching annotation type " + type.getQualifiedSourceName()); if (!MetaClassFactory.canLoadClass(type.getQualifiedBinaryName())) { throw new RuntimeException( "a new annotation has been introduced (" + type.getQualifiedSourceName() + "); " + "you cannot currently introduce new annotations in devmode. Please restart."); } MetaClassFactory.pushCache( JavaReflectionClass.newUncachedInstance( MetaClassFactory.loadClass(type.getQualifiedBinaryName()))); } else { logger.log( com.google.gwt.core.ext.TreeLogger.Type.DEBUG, "Caching translatable type " + type.getQualifiedSourceName()); MetaClassFactory.pushCache(GWTClass.newInstance(typeOracle, type)); } } } typeOraclePopulated = true; populatedFrom = new SoftReference<GeneratorContext>(context); }
protected static boolean isCallbackInjected( TreeLogger logger, String packageName, String simpleSourceName, GeneratorContext context) { try { JClassType type = context .getTypeOracle() .findType(packageName + "." + InjectionUtils.generatedCallbackName(simpleSourceName)); return type != null; } catch (Exception e) { return false; } }
@Override public String generate(TreeLogger treeLogger, GeneratorContext generatorContext, String s) throws UnableToCompleteException { GinjectorGenerator ginjectorGenerator = new GinjectorGenerator(); JClassType clazz = generatorContext.getTypeOracle().findType(s); GinExtension[] ginExtensions = null; if (clazz.isAnnotationPresent(GinExtensions.class)) { ginExtensions = clazz.getAnnotation(GinExtensions.class).value(); } GeneratorContextWrapper gcw = new GeneratorContextWrapper(generatorContext, ginExtensions); return ginjectorGenerator.generate(treeLogger, gcw, s); }
@Override public String generate(TreeLogger logger, GeneratorContext genCtx, String fqInterfaceName) throws UnableToCompleteException { TypeOracle oracle = genCtx.getTypeOracle(); ResourceOracle resourceOracle = genCtx.getResourcesOracle(); JClassType interfaceType; try { interfaceType = oracle.getType(fqInterfaceName); } catch (NotFoundException e) { throw new RuntimeException(e); } DesignTimeUtils designTime; if (DesignTimeUtilsImpl.isDesignTime(fqInterfaceName)) { designTime = new DesignTimeUtilsImpl(); } else { designTime = DesignTimeUtilsStub.EMPTY; } String implName = interfaceType.getName().replace('.', '_') + "Impl"; implName = designTime.getImplName(implName); String packageName = interfaceType.getPackage().getName(); PrintWriterManager writers = new PrintWriterManager(genCtx, logger, packageName); PrintWriter printWriter = writers.tryToMakePrintWriterFor(implName); if (printWriter != null) { generateOnce( interfaceType, implName, printWriter, logger, oracle, resourceOracle, genCtx.getPropertyOracle(), writers, designTime); } return packageName + "." + implName; }
/** * Generate an implementation for the given type. * * @param logger error logger * @param context generator context * @param typeName target type name * @return generated class name * @throws UnableToCompleteException */ @Override public final String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { assert CURRENCY_LIST.equals(typeName); TypeOracle typeOracle = context.getTypeOracle(); PropertyOracle propertyOracle = context.getPropertyOracle(); LocaleUtils localeUtils = LocaleUtils.getInstance(logger, propertyOracle, context); GwtLocale locale = localeUtils.getCompileLocale(); Set<GwtLocale> runtimeLocales = localeUtils.getRuntimeLocales(); JClassType targetClass; try { targetClass = typeOracle.getType(typeName); } catch (NotFoundException e) { logger.log(TreeLogger.ERROR, "No such type", e); throw new UnableToCompleteException(); } if (runtimeLocales.isEmpty()) { return generateLocaleTree(logger, context, targetClass, locale); } CachedGeneratorContext cachedContext = new CachedGeneratorContext(context); return generateRuntimeSelection(logger, cachedContext, targetClass, locale, runtimeLocales); }
public void build( TreeLogger logger, SourceBuilder<ModelMagic> builder, GeneratorContext ctx, JClassType type) throws UnableToCompleteException { ModelMagic models = builder.getPayload(); ModelGenerator generator = new ModelGenerator(builder); // Step one; determine if we already have a concrete type or not. // TODO if JClassType is final, we need to wrap it using a delegate model. JClassType concrete; // ClassBuffer cb = builder.getClassBuffer(); JClassType root = models.getRootType(logger, ctx); if (type.isInterface() == null && type != root) { concrete = type; generator.setSuperClass(type.getQualifiedSourceName()); } else { // We have an interface on our hands; search for an existing or // buildable model. // search for a supertype to inherit. Anything that extends Model, // does not implement any method we do implement, preferred type // being the one that implements the most interfaces possible final JClassType model; try { model = ctx.getTypeOracle().getType(Model.class.getName()); } catch (NotFoundException e) { logger.log( Type.ERROR, "Cannot load " + Model.class.getName() + "; " + "make sure you have xapi-gwt-model:sources.jar on classpath."); throw new UnableToCompleteException(); } concrete = model; for (JClassType supertype : concrete.getFlattenedSupertypeHierarchy()) { // Only interfaces explicitly extending Model become concrete. if (ModelGeneratorGwt.canBeSupertype(type, supertype)) { // prefer the concrete type with the most methods in common. concrete = supertype; } } if (concrete == null || concrete == model) { concrete = models.getRootType(logger, ctx); generator.setSuperClass(concrete.getQualifiedSourceName()); } else { // We have to make sure this concrete supertype is created. if (!models.hasModel(concrete.getQualifiedSourceName())) { // Concrete type is not cached. Build it now. RebindResult result = ModelGeneratorGwt.execImpl(logger, ctx, concrete.getQualifiedSourceName()); generator.setSuperClass(result.getResultTypeName()); } } } // This will probably become jsni, if we can avoid jso interface sickness... generator.createFactory(type.getQualifiedSourceName()); HasModelFields fieldMap = new HasModelFields(); fieldMap.setDefaultSerializable(type.getAnnotation(Serializable.class)); for (JMethod method : methods.keySet()) { if (!toGenerate.contains(ModelGeneratorGwt.toSignature(method))) { logger.log( Type.TRACE, "Skipping method defined in supertype: " + method.getJsniSignature()); continue; } Annotation[] annos = methods.get(method); String methodName = method.getName(); String returnType = method.getReturnType().getQualifiedSourceName(); String params = ModelGeneratorGwt.typeToParameterString(method.getParameterTypes()); // TODO: check imports if we are safe to use simple name. returnType = method.getReturnType().getSimpleSourceName(); IsType returns = X_Source.binaryToSource(method.getReturnType().getQualifiedBinaryName()); IsType[] parameters = ModelGeneratorGwt.toTypes(method.getParameterTypes()); GetterFor getter = method.getAnnotation(GetterFor.class); if (getter != null) { String name = getter.value(); if (name.length() == 0) { name = ModelUtil.stripGetter(method.getName()); } ModelField field = fieldMap.getOrMakeField(name); field.setType(returnType); assert parameters.length == 0 : "A getter method cannot have parameters. " + "Generated code requires using getter methods without args. You provided " + method.getJsniSignature(); grabAnnotations(logger, models, fieldMap, method, annos, type); field.addGetter(returns, methodName); continue; } SetterFor setter = method.getAnnotation(SetterFor.class); if (setter != null) { String name = setter.value(); if (name.length() == 0) name = ModelUtil.stripSetter(method.getName()); grabAnnotations(logger, models, fieldMap, method, annos, type); continue; } if (method.getAnnotation(DeleterFor.class) != null) { implementAction(logger, generator, method, models, annos); continue; } // No annotation. We have to guess the type. boolean isVoid = method.getReturnType().isPrimitive() == JPrimitiveType.VOID; boolean isGetter = methodName.startsWith("get") || methodName.startsWith("is") || methodName.startsWith("has"); boolean isSetter, isAction; if (isGetter) { assert !isVoid : "Cannot have a void return type with method name " + methodName + "; getter prefixes get(), is() and has() must return a type."; isSetter = false; isAction = false; } else { isSetter = methodName.startsWith("set") || methodName.startsWith("add") || methodName.startsWith("put") || methodName.startsWith("rem") || methodName.startsWith("remove"); if (isSetter) { isAction = false; } else { isAction = true; } } if (isVoid) { // definitely a setter / action method. if (isSetter) { MethodBuffer mb = generator.createMethod(returnType, methodName, params); implementSetter(logger, mb, method, models, fieldMap, annos); } else if (isAction) { implementAction(logger, generator, method, models, annos); } else { MethodBuffer mb = generator.createMethod(returnType, methodName, params); implementException(logger, mb, method); } } else { if (isGetter) { String name = ModelUtil.stripGetter(method.getName()); ModelField field = fieldMap.getOrMakeField(name); field.setType(returnType); field.addGetter(returns, methodName); grabAnnotations(logger, models, fieldMap, method, annos, type); } else if (isSetter) { MethodBuffer mb = generator.createMethod(returnType, methodName, params); implementSetter(logger, mb, method, models, fieldMap, annos); } else if (isAction) { implementAction(logger, generator, method, models, annos); } else { MethodBuffer mb = generator.createMethod(returnType, methodName, params); implementException(logger, mb, method); } } } generator.generateModel( X_Source.toType(builder.getPackage(), builder.getClassBuffer().getSimpleName()), fieldMap); }
public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { // .println("Introspector Generate."); try { this.objectType = context.getTypeOracle().getType("java.lang.Object"); } catch (NotFoundException ex) { logger.log(TreeLogger.ERROR, typeName, ex); return null; } List<BeanResolver> introspectables = this.getIntrospectableTypes(logger, context.getTypeOracle()); MethodWrapper[] methods = this.findMethods(logger, introspectables); ClassSourceFileComposerFactory mcf = new ClassSourceFileComposerFactory(this.packageName, this.methodsImplementationName); mcf.addImport(Method.class.getCanonicalName()); PrintWriter methodsPrintWriter = context.tryCreate(logger, this.packageName, this.methodsImplementationName); if (methodsPrintWriter != null) { SourceWriter methodsWriter = mcf.createSourceWriter(context, methodsPrintWriter); this.writeMethods(logger, methods, methodsWriter); methodsWriter.println("}"); context.commit(logger, methodsPrintWriter); } ClassSourceFileComposerFactory cfcf = new ClassSourceFileComposerFactory(this.packageName, this.implementationName); cfcf.addImplementedInterface(typeName); cfcf.addImport("java.util.HashMap"); cfcf.addImport(Method.class.getCanonicalName()); cfcf.addImport(com.totsp.gwittir.introspection.Property.class.getCanonicalName()); cfcf.addImport(com.totsp.gwittir.introspection.BeanDescriptor.class.getCanonicalName()); PrintWriter printWriter = context.tryCreate(logger, packageName, implementationName); if (printWriter == null) { // .println( "Introspector Generate skipped."); return packageName + "." + implementationName; } SourceWriter writer = cfcf.createSourceWriter(context, printWriter); this.writeIntrospectables(logger, introspectables, methods, writer); this.writeResolver(introspectables, writer); writer.println( "private HashMap<Class,BeanDescriptor> beanDescriptorLookup = new HashMap<Class,BeanDescriptor>();"); writer.println(); writer.println("public BeanDescriptor getDescriptor( Object object ){ "); writer.indent(); writer.println( "if( object == null ) throw new NullPointerException(\"Attempt to introspect null object\");"); writer.println( "if( object instanceof " + SelfDescribed.class.getCanonicalName() + " ) return ((SelfDescribed)object).__descriptor();"); writer.println("BeanDescriptor descriptor = beanDescriptorLookup.get(object.getClass());"); writer.println("if (descriptor!=null){"); writer.indentln("return descriptor;"); writer.outdent(); writer.println("}"); writer.println("descriptor=_getDescriptor(object);"); writer.println("beanDescriptorLookup.put(object.getClass(),descriptor);"); writer.println("return descriptor;"); writer.outdent(); writer.println("}"); writer.println("private BeanDescriptor _getDescriptor( Object object ){ "); writer.indent(); for (BeanResolver resolver : introspectables) { writer.println( "if( object instanceof " + resolver.getType().getQualifiedSourceName() + " ) {"); writer.indent(); String name = resolver.getType().getQualifiedSourceName().replaceAll("\\.", "_"); logger.log(TreeLogger.DEBUG, "Writing : " + name, null); writer.print("return " + name + " == null ? " + name + " = "); this.writeBeanDescriptor(logger, resolver, methods, writer); writer.print(": " + name + ";"); writer.outdent(); writer.println("}"); } writer.println(" throw new IllegalArgumentException(\"Unknown type\" + object.getClass() ); "); writer.outdent(); writer.println("}"); writer.println("public Object createInstance(Class clazz) {"); writer.indent(); for (BeanResolver resolver : introspectables) { boolean hasPNA = false; for (JConstructor constructor : resolver.getType().getConstructors()) { if (constructor.getParameters() == null || constructor.getParameters().length == 0 && constructor.isPublic()) { hasPNA = true; break; } if (hasPNA) { break; } } writer.println( "if(clazz.equals(" + resolver.getType().getQualifiedSourceName() + ".class)){"); writer.indent(); logger.log( TreeLogger.Type.TRACE, resolver.getType().getQualifiedSourceName() + " abstract " + resolver.getType().isAbstract() + " intf " + (resolver.getType().isInterface() != null) + " def " + resolver.getType().isDefaultInstantiable()); if (resolver.getType().isAbstract() || resolver.getType().isInterface() != null) { writer.println("throw new IllegalArgumentException(clazz+\" is abstract\");"); } else if (hasPNA) { writer.println("return new " + resolver.getType().getQualifiedSourceName() + "();"); } else { writer.println( "throw new IllegalArgumentException(clazz+\" has no public no args constructor\");"); } writer.outdent(); writer.println("}"); } writer.println(" throw new IllegalArgumentException(\"Unknown type\" +clazz ); "); writer.outdent(); writer.println("}"); writer.println("HashMap<String, Class> classes = new HashMap<String, Class>();"); writer.println("public Class forName(String className){"); writer.indent(); writer.println("Class clazz = classes.get(className);"); writer.println("if(clazz != null) return clazz;"); for (BeanResolver resolver : introspectables) { writer.println( "if(className.equals(\"" + resolver.getType().getQualifiedSourceName() + "\")){"); writer.indent(); writer.println("clazz = " + resolver.getType().getQualifiedSourceName() + ".class;"); writer.println("classes.put(className, clazz);"); writer.println("return clazz;"); writer.outdent(); writer.println("}"); } writer.println("throw new IllegalArgumentException(className+\" is not introspecable.\");"); writer.outdent(); writer.println("}"); writer.outdent(); writer.println("}"); context.commit(logger, printWriter); // .println( "Introspector Generate completed."); return packageName + "." + implementationName; }
/** * @param logger * @param context * @param typeName * @param gr * @return */ public boolean isGenerate( TreeLogger logger, GeneratorContext context, String typeName, GenPredicGroup gr) { boolean result = false; if ((gr.getMyGroups() != null) && (gr.getMyGroups().size() > 0)) { for (GenPredicGroup group : gr.getMyGroups()) { switch (gr.getOperator()) { case ANY: result = result || isGenerate(logger, context, typeName, group); break; case NONE: result = !isGenerate(logger, context, typeName, group); if (!result) return false; break; case ALL: result = isGenerate(logger, context, typeName, group); if (!result) return false; default: break; } } } if ((gr.getGeneratorPredicts() != null) && (gr.getGeneratorPredicts().size() > 0)) { for (GeneratorPredicate entry : gr.getGeneratorPredicts()) { String value = null; try { switch (entry.getEPredict()) { case ASSIGNABLE: if (context .getTypeOracle() .findType(typeName) .isAssignableTo(context.getTypeOracle().getType(entry.getValue()))) { value = entry.getValue(); } else { value = typeName; } break; case TYPEIS: value = typeName; break; case PROPERTY: // ???he value = context .getPropertyOracle() .getSelectionProperty(logger, entry.getName()) .getCurrentValue(); break; default: value = null; break; } } catch (Exception e) { value = null; result = false; } if (value != null) { switch (gr.getOperator()) { case ANY: result = result || entry.getValue().equals(value); break; case NONE: result = !entry.getValue().equals(value); if (!result) return false; break; case ALL: result = entry.getValue().equals(value); if (!result) return false; default: break; } } } } return result; }
@Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { // make sure it is an interface TypeOracle oracle = context.getTypeOracle(); propertyAccessInterface = oracle.findType(Name.getSourceNameForClass(PropertyAccess.class)); modelKeyProviderInterface = oracle.findType(Name.getSourceNameForClass(ModelKeyProvider.class)); valueProviderInterface = oracle.findType(Name.getSourceNameForClass(ValueProvider.class)); labelProviderInterface = oracle.findType(Name.getSourceNameForClass(LabelProvider.class)); JClassType toGenerate = oracle.findType(typeName).isInterface(); if (toGenerate == null) { logger.log(TreeLogger.ERROR, typeName + " is not an interface type"); throw new UnableToCompleteException(); } if (!toGenerate.isAssignableTo(propertyAccessInterface)) { logger.log(Type.ERROR, "This isn't a PropertyAccess subtype..."); throw new UnableToCompleteException(); } // Get the name of the new type String packageName = toGenerate.getPackage().getName(); String simpleSourceName = toGenerate.getName().replace('.', '_') + "Impl"; PrintWriter pw = context.tryCreate(logger, packageName, simpleSourceName); if (pw == null) { return packageName + "." + simpleSourceName; } // start making the class, with basic imports ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, simpleSourceName); factory.addImplementedInterface(typeName); SourceWriter sw = factory.createSourceWriter(context, pw); // for each method, for (JMethod m : toGenerate.getOverridableMethods()) { TreeLogger l = logger.branch(Type.DEBUG, "Building method: " + m.getReadableDeclaration()); // no support for params at this time if (m.getParameters().length != 0) { l.log(Type.ERROR, "Method " + m.toString() + " must not have parameters."); throw new UnableToCompleteException(); } // ask for the types that provide the property data JClassType ret = m.getReturnType().isClassOrInterface(); final AbstractCreator c; if (ret.isAssignableTo(valueProviderInterface)) { c = new ValueProviderCreator(context, l, m); } else if (ret.isAssignableTo(modelKeyProviderInterface)) { c = new ModelKeyProviderCreator(context, l, m); } else if (ret.isAssignableTo(labelProviderInterface)) { c = new LabelProviderCreator(context, l, m); } else { logger.log(Type.ERROR, "Method uses a return type that cannot be generated"); throw new UnableToCompleteException(); } c.create(); // build the method // public ValueProvider<T, V> name() { return NameValueProvider.instance; // } sw.println("public %1$s %2$s() {", m.getReturnType().getQualifiedSourceName(), m.getName()); sw.indentln("return %1$s;", c.getInstanceExpression()); sw.println("}"); } sw.commit(logger); return factory.getCreatedClassName(); }
@Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { TypeOracle oracle = context.getTypeOracle(); // JClassType requestQueue = oracle.findType(RequestQueue.class.getName()); JClassType toGenerate = oracle.findType(typeName); if (toGenerate == null) { logger.log(TreeLogger.ERROR, typeName + " is not an interface type"); throw new UnableToCompleteException(); } String packageName = toGenerate.getPackage().getName(); String simpleSourceName = toGenerate.getName().replace('.', '_') + "_Impl"; PrintWriter pw = context.tryCreate(logger, packageName, simpleSourceName); if (pw == null) { return packageName + "." + simpleSourceName; } ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, simpleSourceName); factory.setSuperclass(AbstractRequestQueueImpl.class.getName()); factory.addImplementedInterface(typeName); SourceWriter sw = factory.createSourceWriter(context, pw); // Collect async services we need to provide access to, and the rpc calls they'll make RequestQueueModel model = collectModel(logger.branch(Type.DEBUG, "Collecting service info"), context, toGenerate); // Build a pair of RPC interfaces for serialization String realRpcInterfaceName = buildRpcInterfaces(logger.branch(Type.DEBUG, "Writing RPC interfaces"), context, model); // Build the getRealService() method String serviceQueueAsync = ServiceQueueBaseAsync.class.getName(); sw.println("public %1$s getRealService() {", serviceQueueAsync); sw.indentln( "return %3$s.<%1$s>create(%2$s.class);", serviceQueueAsync, realRpcInterfaceName, GWT.class.getName()); sw.println("}"); // Build the methods (and maybe types?) that call addRequest() for (AsyncServiceModel service : model.getServices()) { sw.println( "public %1$s %2$s() {", service.getAsyncServiceInterfaceName(), service.getDeclaredMethodName()); sw.indent(); sw.println("return new %1$s() {", service.getAsyncServiceInterfaceName()); sw.indent(); for (AsyncServiceMethodModel method : service.getMethods()) { sw.println("public void %1$s(", method.getMethodName()); StringBuilder argList = new StringBuilder(); StringBuilder types = new StringBuilder("new String[]{"); for (int i = 0; i < method.getArgTypes().size(); i++) { if (i != 0) { sw.print(", "); argList.append(", "); types.append(", "); } JType arg = method.getArgTypes().get(i); sw.print("%1$s arg%2$d", arg.getParameterizedQualifiedSourceName(), i); argList.append("arg").append(i); types.append("\"").append(escape(SerializationUtils.getRpcTypeName(arg))).append("\""); } types.append("}"); if (method.hasCallback()) { if (method.getArgTypes().size() != 0) { sw.print(", "); } sw.print( "%1$s<%2$s> callback", AsyncCallback.class.getName(), method.getReturnTypeName()); } sw.println(") {"); sw.indent(); sw.println( "addRequest(\"%1$s\", \"%2$s\",\n%3$s,\n", escape(service.getServiceName()), escape(method.getMethodName()), types.toString()); if (method.hasCallback()) { sw.indentln("callback,"); } else { sw.indentln("null,"); } sw.indentln("new Object[]{%1$s});", argList.toString()); sw.outdent(); sw.println("}"); } sw.outdent(); sw.println("};"); sw.outdent(); sw.println("}"); } sw.commit(logger); return factory.getCreatedClassName(); }
private RequestQueueModel collectModel( TreeLogger logger, GeneratorContext context, JClassType toGenerate) throws UnableToCompleteException { RequestQueueModel.Builder rqBuilder = new RequestQueueModel.Builder(); TypeOracle typeOracle = context.getTypeOracle(); JClassType requestQueue = typeOracle.findType(RequestQueue.class.getName()); JClassType asyncCallback = typeOracle.findType(AsyncCallback.class.getName()); JClassType voidType = typeOracle.findType(Void.class.getName()); rqBuilder.setRequestQueueInterfaceName(toGenerate.getParameterizedQualifiedSourceName()); AsyncServiceModel.Builder serviceBuilder = new AsyncServiceModel.Builder(); for (JMethod m : toGenerate.getMethods()) { TreeLogger serviceLogger = logger.branch(Type.DEBUG, "Reading async service " + m.getReadableDeclaration()); // Skip those defined at RequestQueue if (m.getEnclosingType().equals(requestQueue)) { continue; } JClassType returnType = m.getReturnType().isClassOrInterface(); if (returnType == null) { serviceLogger.log(Type.ERROR, "Unexpected method return type " + returnType); throw new UnableToCompleteException(); } serviceBuilder.setAsyncServiceInterfaceName(returnType.getParameterizedQualifiedSourceName()); serviceBuilder.setDeclaredMethodName(m.getName()); Service serviceAnnotation = m.getAnnotation(Service.class); if (serviceAnnotation == null) { serviceLogger.log(Type.ERROR, "Missing @Service annotation"); throw new UnableToCompleteException(); } serviceBuilder.setService(serviceAnnotation.value().getName()); AsyncServiceMethodModel.Builder methodBuilder = new AsyncServiceMethodModel.Builder(); for (JMethod asyncMethod : m.getReturnType().isClassOrInterface().getMethods()) { TreeLogger methodLogger = serviceLogger.branch( Type.DEBUG, "Reading service method " + asyncMethod.getReadableDeclaration()); List<JType> types = new ArrayList<JType>(); methodBuilder.setReturnTypeName(voidType.getParameterizedQualifiedSourceName()); boolean asyncFound = false; for (JType param : asyncMethod.getParameterTypes()) { if (asyncFound) { methodLogger.log( Type.WARN, "Already passed an AsyncCallback param - is that what you meant?"); } if (param.isClassOrInterface() != null && param.isClassOrInterface().isAssignableTo(asyncCallback)) { JClassType boxedReturnType = ModelUtils.findParameterizationOf(asyncCallback, param.isClassOrInterface())[0]; methodBuilder .setHasCallback(true) .setReturnTypeName(boxedReturnType.getParameterizedQualifiedSourceName()); asyncFound = true; continue; // should be last, check for this... } types.add(param); } Set<JClassType> throwables = new HashSet<JClassType>(); Throws t = asyncMethod.getAnnotation(Throws.class); if (t != null) { for (Class<? extends Throwable> throwable : t.value()) { throwables.add(typeOracle.findType(throwable.getName())); } } methodBuilder .setMethodName(asyncMethod.getName()) .setArgTypes(types) .setThrowables(throwables); serviceBuilder.addMethod(methodBuilder.build()); } rqBuilder.addService(serviceBuilder.build()); } return rqBuilder.build(); }