@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); }
private void generateClass(TreeLogger logger, GeneratorContext context) { // get print writer that receives the source code PrintWriter printWriter = null; printWriter = context.tryCreate(logger, packageName, className); // print writer if null, source code has ALREADY been generated, return if (printWriter == null) { return; } // init composer, set class properties, create source writer ClassSourceFileComposerFactory composer = null; composer = new ClassSourceFileComposerFactory(packageName, className); composer.addImplementedInterface("org.pentaho.ui.xul.gwt.binding.TypeController"); composer.addImport("org.pentaho.ui.xul.gwt.binding.*"); composer.addImport("java.util.Map"); composer.addImport("java.util.HashMap"); composer.addImport("org.pentaho.ui.xul.XulException"); SourceWriter sourceWriter = null; sourceWriter = composer.createSourceWriter(context, printWriter); // generator constructor source code generateConstructor(sourceWriter); writeMethods(sourceWriter); // close generated class sourceWriter.outdent(); sourceWriter.println("}"); // commit generated class context.commit(logger, printWriter); }
/** * 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); }
public PrintWriter getPrintWrite(String name) { PrintWriter writer = generatorContext.tryCreate(logger, packageName, name); if (writer != null) { writers.add(writer); } return writer; }
@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; }
/** 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(); }
/** * @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(); }
@Ignore("can only be ran once I make the code changes to mock out the composer factory") @Test public void generate_shouldNotAttemptToSetupTheLoggerOnTheSourceWriter() throws UnableToCompleteException { when(context.tryCreate(logger, packageName, className)).thenReturn(null); assertBundleClass(runGenerator()); verifyBundleInterfaceWasSetOnTheComposer(); verifyZeroInteractions(sourceWriter); }
@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; }
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; } }
@Ignore("can only be ran once I make the code changes to mock out the composer factory") @Test public void generate_shouldSetTheLoggerOnTheSourceWriter() throws Exception { StubPrintWriter contextWriter = new StubPrintWriter(); when(context.tryCreate(logger, packageName, className)).thenReturn(contextWriter); when(composerFactory.createSourceWriter(context, contextWriter)).thenReturn(sourceWriter); assertBundleClass(runGenerator()); verifyBundleInterfaceWasSetOnTheComposer(); verify(sourceWriter).commit(logger); }
@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); }
/** * 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 static boolean ensureProviderClass( TreeLogger logger, String packageName, String simpleName0, String canonical, String qualifiedSourceName, GeneratorContext ctx) { String simpleName = SourceUtil.toSourceName(simpleName0); String generatedName = InjectionUtils.generatedProviderName(simpleName); String cleanedCanonical = SourceUtil.toSourceName(canonical); logger.log(Type.DEBUG, "Creating provider for " + packageName + "." + generatedName); PrintWriter printWriter = ctx.tryCreate(logger, packageName, generatedName); if (printWriter == null) { logger.log(Type.TRACE, "Already generated " + generatedName); return false; } logger.log( Type.TRACE, "Newly Generating provider " + generatedName + " <- " + qualifiedSourceName); ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(packageName, generatedName); composer.setSuperclass(SingletonInitializer.class.getName() + "<" + simpleName0 + ">"); composer.addImport(cleanedCanonical); composer.addImport(GWT.class.getName()); composer.addImport(SingletonProvider.class.getName()); SourceWriter sw = composer.createSourceWriter(ctx, printWriter); sw.println("@Override"); sw.println("public " + simpleName + " initialValue(){"); sw.indent(); sw.print("return GWT.<" + cleanedCanonical + ">create("); sw.print(SourceUtil.toSourceName(qualifiedSourceName) + ".class"); sw.println(");"); sw.outdent(); sw.println("}"); sw.println(); // now, print a static final provider instance sw.print("public static final SingletonProvider<"); sw.print(simpleName0 + "> "); sw.print("theProvider = "); sw.println("new " + generatedName + "();"); sw.commit(logger); return true; }
/** * Generate the implementation for a single locale, overriding from its parent only data that has * changed in this locale. * * @param logger * @param context * @param targetClass * @param locale * @param superClassName * @param currencies the set of currencies defined in this locale * @param allCurrencyData map of currency code -> unparsed CurrencyInfo for that code * @param defCurrencyCode default currency code for this locale * @return fully-qualified class name generated */ private String generateOneLocale( TreeLogger logger, GeneratorContext context, JClassType targetClass, GwtLocale locale, String superClassName, String[] currencies, Map<String, CurrencyInfo> allCurrencyData, String defCurrencyCode) { String packageName = targetClass.getPackage().getName(); String className = targetClass.getName().replace('.', '_') + "_" + locale.getAsString(); PrintWriter pw = context.tryCreate(logger, packageName, className); if (pw != null) { ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, className); factory.setSuperclass(superClassName); factory.addImport(CURRENCY_DATA); factory.addImport(JAVASCRIPTOBJECT); factory.addImport(HASHMAP); SourceWriter writer = factory.createSourceWriter(context, pw); if (defCurrencyCode != null) { CurrencyInfo currencyInfo = allCurrencyData.get(defCurrencyCode); if (currencyInfo == null) { // Synthesize a null info if the specified default wasn't found. currencyInfo = new CurrencyInfo(defCurrencyCode, null, null); allCurrencyData.put(defCurrencyCode, currencyInfo); } writer.println(); writer.println("@Override"); writer.println("protected CurrencyData getDefaultJava() {"); writer.println(" return " + currencyInfo.getJava() + ";"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected native CurrencyData getDefaultNative() /*-{"); writer.println(" return " + currencyInfo.getJson() + ";"); writer.println("}-*/;"); } if (currencies.length > 0) { writeCurrencyMethodJava(writer, currencies, allCurrencyData); writeCurrencyMethodNative(writer, currencies, allCurrencyData); writeNamesMethodJava(writer, currencies, allCurrencyData); writeNamesMethodNative(writer, currencies, allCurrencyData); } writer.commit(logger); } return packageName + "." + className; }
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); }
private PropertyOracle mockPropertyOracle() { when(context.getPropertyOracle()).thenReturn(propertyOracle); return propertyOracle; }
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(); }
private String buildRpcInterfaces( TreeLogger logger, GeneratorContext context, RequestQueueModel model) { String rqType = model.getRequestQueueInterfaceName(); int lastDot = rqType.lastIndexOf('.'); String packageName = rqType.substring(0, lastDot - 1); String serviceSourceName = rqType.substring(lastDot).replace('.', '_') + "_ImplRPC"; String asyncSourceName = serviceSourceName + "Async"; PrintWriter pw = context.tryCreate(logger, packageName, asyncSourceName); if (pw == null) { return packageName + "." + serviceSourceName; } // Create async class ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, asyncSourceName); factory.addImplementedInterface(ServiceQueueBaseAsync.class.getName()); factory.makeInterface(); SourceWriter asyncSw = factory.createSourceWriter(context, pw); // Create service class pw = context.tryCreate(logger, packageName, serviceSourceName); assert pw != null; factory = new ClassSourceFileComposerFactory(packageName, serviceSourceName); factory.addImplementedInterface(ServiceQueueBase.class.getName()); factory.makeInterface(); SourceWriter serviceSw = factory.createSourceWriter(context, pw); // write out service and async int i = 0; for (AsyncServiceModel service : model.getServices()) { for (AsyncServiceMethodModel method : service.getMethods()) { String methodName = "a" + ++i; asyncSw.println("void %1$s(", methodName); serviceSw.println("%2$s %1$s(", methodName, method.getReturnTypeName()); asyncSw.indent(); serviceSw.indent(); boolean firstArgument = true; int argIndex = 0; for (JType arg : method.getArgTypes()) { if (!firstArgument) { asyncSw.println(","); serviceSw.println(","); } firstArgument = false; if (arg.isPrimitive() != null) { JPrimitiveType t = arg.isPrimitive(); asyncSw.println("%2$s arg%1$d", argIndex, t.getQualifiedBoxedSourceName()); serviceSw.println("%2$s arg%1$d", argIndex, t.getQualifiedBoxedSourceName()); } else { asyncSw.println("%2$s arg%1$d", argIndex, arg.getParameterizedQualifiedSourceName()); serviceSw.println("%2$s arg%1$d", argIndex, arg.getParameterizedQualifiedSourceName()); } argIndex++; } if (!firstArgument) { asyncSw.print(", "); } // TODO return type boxing asyncSw.println( "%1$s<%2$s>callback);", AsyncCallback.class.getName(), method.getReturnTypeName()); serviceSw.print(")"); if (!method.getThrowables().isEmpty()) { serviceSw.print(" throws "); boolean firstThrowable = true; for (JClassType throwable : method.getThrowables()) { if (!firstThrowable) { serviceSw.print(", "); } firstThrowable = false; serviceSw.print(throwable.getQualifiedSourceName()); } } serviceSw.println(";"); asyncSw.outdent(); serviceSw.outdent(); } } asyncSw.commit(logger); serviceSw.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(); }
protected void tryWriteMetaInf( TreeLogger logger, Class<?> cls, JClassType impl, GeneratorContext context) { String serviceInterface = cls.getName(); String serviceImplementation = impl.getQualifiedBinaryName(); ArrayList<File> outputDirs = new ArrayList<File>(); PropertyOracle properties = context.getPropertyOracle(); try { File root = new File(""); if (root.getAbsolutePath().endsWith("war")) root = new File(root.getAbsolutePath().replace(separator + "war", "") + separator); else root = new File(root.getAbsolutePath()); ConfigurationProperty output = properties.getConfigurationProperty("xinject.output.dir"); for (String dir : output.getValues()) { File f = new File(root, dir); if (f.isDirectory()) { outputDirs.add(f); f = new File(f, "META-INF" + separator + "services"); if (!f.exists()) { if (!f.mkdirs()) { logger.log( Type.WARN, "Unable to create META-INF" + separator + "services " + " in " + f.getAbsolutePath() + " " + "Please ensure this directory exists, and is writable."); } } } else { logger.log( Type.WARN, "Missing xinject output directory: " + f.getAbsolutePath() + ". " + "Please set xinject.output.dir to existing source directories; current value: " + output.getValues()); } } } catch (BadPropertyValueException e1) { logger.log(Type.WARN, "Unexpected propery exception for xinject.output.dir", e1); } try { String prefix = ".." + separator + "WEB-INF" + separator + "classes" + separator + "META-INF" + separator + "singletons" + separator; // TODO use a typed artifact to let the linker have a peak if it needs to OutputStream res = context.tryCreateResource(logger, prefix + serviceInterface); res.write(serviceImplementation.getBytes()); context.commitResource(logger, res).setVisibility(Visibility.Public); } catch (UnableToCompleteException e) { logger.log(Type.ERROR, "Couldn't write java services to META-INF/singeltons", e); } catch (IOException e) { logger.log( Type.ERROR, "Couldn't write java services to META-INF/singletons; please ensure the war folder has full write access and the disk is not full.", e); e.printStackTrace(); } logger.log( Type.TRACE, "Saving META-INF/singletons for " + serviceInterface + " -> " + serviceImplementation); exports: for (File output : outputDirs) { String knownContent = null; // check for existing META-INF/singletons entries, so we don't clobber anything File existing = new File(output, "META-INF" + separator + "services" + separator + serviceInterface); logger.log(Type.TRACE, "Saving ServiceLoader descriptor to " + existing.getAbsolutePath()); if (existing.isFile()) { // need to read in existing manifest, and skip if service already exists BufferedReader reader = null; FileInputStream in = null; try { in = new FileInputStream(existing); reader = new BufferedReader(new InputStreamReader(in)); String line; StringBuilder b = new StringBuilder(); while ((line = reader.readLine()) != null) { if (line.equals(serviceImplementation)) { // the service impl already exists; skip to next output dir // TODO put in a flag to override top permission. try { ConfigurationProperty prop = context .getPropertyOracle() .getConfigurationProperty("xinject.overwrite.existing"); List<String> values = prop.getValues(); if (values.size() > 0) if (values.get(0).matches("true")) { // if we're supposed to overwrite the value, but it's already on top if (b.length() == 0) { continue exports; // skip the file write } continue; // this erases the existing value so we can put it back over top. // it also skips the breaking-continue below. } } catch (BadPropertyValueException e) { logger.log(Type.TRACE, "", e); } // if we've found the service, and are not allowed to move it to top, continue exports; // carry on in the loop above. } b.append(line + "\n"); } knownContent = b.toString().substring(0, b.length() - 1); } catch (IOException e) { logger.log( Type.WARN, "Received io exception writing META-INF/service for " + existing.getAbsolutePath()); } finally { try { if (in != null) in.close(); if (reader != null) reader.close(); } catch (IOException e) { } } } // save a new java service descriptor FileWriter writer = null; try { try { boolean exists = existing.isFile(); if (!exists) { if (!existing.createNewFile()) { logger.log(Type.WARN, "Could not create output file for " + existing); continue exports; } } writer = new FileWriter(existing, false); if (knownContent == null) { writer.append(serviceImplementation); } else { writer.append(serviceImplementation); writer.append('\n'); writer.append(knownContent); } } finally { if (writer != null) { writer.close(); } } } catch (IOException e) { logger.log( Type.WARN, "File write exception trying to save META-INF/singletons for " + existing, e); } } }
public static InjectionCallbackArtifact ensureAsyncInjected( TreeLogger logger, String packageName, String className, String outputClass, GeneratorContext ctx) throws UnableToCompleteException { GwtInjectionMap gwtInjectionMap = getInjectionMap(logger, ctx); InjectionCallbackArtifact artifact = gwtInjectionMap.getOrCreateArtifact(ctx, packageName, className); if (artifact.isTargetUnbound()) { artifact.bindTo(outputClass); ensureProviderClass( logger, packageName, artifact.getSimpleName(), artifact.getCanonicalName(), artifact.getBoundTarget(), ctx); logger = logger.branch( Type.TRACE, "Creating asynchronous callback for " + artifact.getCanonicalName() + " -> " + outputClass); String generatedName = InjectionUtils.generatedAsyncProviderName(artifact.getGeneratedName()); String implPackage = artifact.getImplementationPackage(); PrintWriter printWriter = ctx.tryCreate(logger, implPackage, generatedName); if (printWriter == null) { logger.log( Type.WARN, "Could not create the source writer for " + implPackage + "." + generatedName); return artifact; } artifact.addCallback(implPackage + "." + generatedName + ".Deproxy"); ctx.commitArtifact(logger, artifact); ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(implPackage, generatedName); composer.setPrivacy("public final"); composer.addImport(com.google.gwt.core.client.GWT.class.getName()); composer.addImport(RunAsyncCallback.class.getName()); composer.addImport(Fifo.class.getName()); composer.addImport(JsFifo.class.getName()); composer.addImport(AsyncProxy.class.getName()); composer.addImport(ApplyMethod.class.getName()); composer.addImport(ReceivesValue.class.getName()); composer.addImport(ReceiverAdapter.class.getCanonicalName()); composer.addImport(artifact.getCanonicalName()); String simpleName = artifact.getSimpleName(); SourceWriter sw = composer.createSourceWriter(ctx, printWriter); sw.println(); sw.println("static final class Callbacks implements ApplyMethod{"); sw.indent(); sw.println("public void apply(Object ... args){"); sw.println("}"); sw.outdent(); sw.println("}"); sw.println(); sw.println("static final class Deproxy implements ReceivesValue<" + simpleName + ">{"); sw.indent(); sw.println("public final void set(final " + simpleName + " value){"); sw.indentln("getter = new ReceiverAdapter<" + simpleName + ">(value);"); sw.println("}"); sw.outdent(); sw.println("}"); sw.println(); sw.println( "private static final class Proxy implements ReceivesValue<ReceivesValue<" + simpleName + ">>{"); sw.indent(); sw.println("public final void set(final ReceivesValue<" + simpleName + "> receiver){"); sw.indent(); sw.print("GWT.runAsync("); sw.println(artifact.getCanonicalName() + ".class,new Request(receiver));"); sw.outdent(); sw.println("}"); sw.outdent(); sw.println("}"); sw.println(); sw.println("private static final class Request"); sw.indent(); sw.println("extends AsyncProxy<" + simpleName + "> "); sw.println("implements RunAsyncCallback{"); DefermentWriter defer = new DefermentWriter(sw); defer.setStrategy(DefermentStrategy.NONE); sw.println("private static final Fifo<ReceivesValue<" + simpleName + ">> pending ="); sw.indentln("JsFifo.newFifo();"); sw.println(); sw.println("protected Request(ReceivesValue<" + simpleName + "> receiver){"); sw.indentln("accept(receiver);"); sw.println("}"); sw.println(); sw.println("@Override"); sw.println("protected final Fifo<ReceivesValue<" + simpleName + ">> pending(){"); sw.indentln("return pending;"); sw.println("}"); sw.println(); sw.println("protected final void dispatch(){"); sw.indentln("go();"); sw.println("}"); sw.println(); sw.println("public final void onSuccess(){"); sw.indent(); defer.printStart(); sw.println("final " + simpleName + " value = "); sw.print(packageName + "." + InjectionUtils.generatedProviderName(simpleName)); sw.println(".theProvider.get();"); sw.println(); sw.print("final ApplyMethod callbacks = GWT.create("); sw.print(packageName + ".impl." + generatedName + ".Callbacks.class"); sw.println(");"); sw.println("callbacks.apply(value);"); sw.println(); sw.println("apply(value);"); sw.outdent(); sw.println("}"); sw.outdent(); defer.printFinish(); sw.println("}"); sw.println(); sw.println( "private static ReceivesValue<ReceivesValue<" + simpleName + ">> getter = new Proxy();"); sw.println(); sw.println("static void request(final ReceivesValue<" + simpleName + "> request){"); sw.indentln("getter.set(request);"); sw.println("}"); sw.println(); sw.println("static void go(){"); sw.indentln("request(null);"); sw.println("}"); sw.println(); sw.println("private " + generatedName + "(){}"); sw.commit(logger); } else { assert artifact.getBoundTarget().equals(outputClass) : "The injection target " + artifact.getCanonicalName() + " was bound " + "to " + artifact.getBoundTarget() + ", but you tried to bind it again, " + "to a different class: " + outputClass; } return artifact; }
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; }
public void commit() { for (PrintWriter writer : writers) { generatorContext.commit(logger, writer); } }
/** * Generate a class which can select between alternate implementations at runtime based on the * runtime locale. * * @param logger TreeLogger instance for log messages * @param context GeneratorContext for generating source files * @param targetClass class to generate * @param compileLocale the compile-time locale we are generating for * @param locales set of all locales to generate * @return fully-qualified class name that was generated */ private String generateRuntimeSelection( TreeLogger logger, GeneratorContext context, JClassType targetClass, GwtLocale compileLocale, Set<GwtLocale> locales) { String packageName = targetClass.getPackage().getName(); String className = targetClass.getName().replace('.', '_') + "_" + compileLocale.getAsString() + "_runtimeSelection"; PrintWriter pw = context.tryCreate(logger, packageName, className); if (pw != null) { ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, className); factory.setSuperclass(targetClass.getQualifiedSourceName()); factory.addImport(CURRENCY_DATA); factory.addImport(JAVASCRIPTOBJECT); factory.addImport(HASHMAP); factory.addImport("com.google.gwt.i18n.client.LocaleInfo"); SourceWriter writer = factory.createSourceWriter(context, pw); writer.println("private CurrencyList instance;"); writer.println(); writer.println("@Override"); writer.println("protected CurrencyData getDefaultJava() {"); writer.println(" ensureInstance();"); writer.println(" return instance.getDefaultJava();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected CurrencyData getDefaultNative() {"); writer.println(" ensureInstance();"); writer.println(" return instance.getDefaultNative();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected HashMap<String, CurrencyData> loadCurrencyMapJava() {"); writer.println(" ensureInstance();"); writer.println(" return instance.loadCurrencyMapJava();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected JavaScriptObject loadCurrencyMapNative() {"); writer.println(" ensureInstance();"); writer.println(" return instance.loadCurrencyMapNative();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected HashMap<String, String> loadNamesMapJava() {"); writer.println(" ensureInstance();"); writer.println(" return instance.loadNamesMapJava();"); writer.println("}"); writer.println(); writer.println("@Override"); writer.println("protected JavaScriptObject loadNamesMapNative() {"); writer.println(" ensureInstance();"); writer.println(" return instance.loadNamesMapNative();"); writer.println("}"); writer.println(); writer.println("private void ensureInstance() {"); writer.indent(); writer.println("if (instance != null) {"); writer.println(" return;"); writer.println("}"); boolean fetchedLocale = false; Map<String, Set<GwtLocale>> localeMap = new TreeMap<String, Set<GwtLocale>>(); String compileLocaleClass = processChildLocale(logger, context, targetClass, localeMap, compileLocale); if (compileLocaleClass == null) { // already gave warning, just use default implementation return null; } for (GwtLocale runtimeLocale : locales) { processChildLocale(logger, context, targetClass, localeMap, runtimeLocale); } for (Entry<String, Set<GwtLocale>> entry : localeMap.entrySet()) { if (!fetchedLocale) { writer.println("String runtimeLocale = LocaleInfo.getCurrentLocale().getLocaleName();"); fetchedLocale = true; } boolean firstLocale = true; String generatedClass = entry.getKey(); if (compileLocaleClass.equals(generatedClass)) { // The catch-all will handle this continue; } writer.print("if ("); for (GwtLocale locale : entry.getValue()) { if (firstLocale) { firstLocale = false; } else { writer.println(); writer.print(" || "); } writer.print("\"" + locale.toString() + "\".equals(runtimeLocale)"); } writer.println(") {"); writer.println(" instance = new " + generatedClass + "();"); writer.println(" return;"); writer.println("}"); } writer.println("instance = new " + compileLocaleClass + "();"); writer.outdent(); writer.println("}"); writer.commit(logger); } return packageName + "." + className; }
@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(); }