List of usage examples for com.google.gwt.user.rebind SourceWriter println
void println(String s, Object... args);
From source file:com.google.web.bindery.autobean.gwt.rebind.AutoBeanFactoryGenerator.java
License:Apache License
/** * Write an instance initializer block to populate the creators map. *//*from w ww . ja v a 2 s . c om*/ private void writeDynamicMethods(SourceWriter sw) { List<JClassType> privatePeers = new ArrayList<JClassType>(); sw.println("@Override protected void initializeCreatorMap(%s map) {", JsniCreatorMap.class.getCanonicalName()); sw.indent(); for (AutoBeanType type : model.getAllTypes()) { if (type.isNoWrap()) { continue; } String classLiteralAccessor; JClassType peer = type.getPeerType(); String peerName = ModelUtils.ensureBaseType(peer).getQualifiedSourceName(); if (peer.isPublic()) { classLiteralAccessor = peerName + ".class"; } else { privatePeers.add(peer); classLiteralAccessor = "classLit_" + peerName.replace('.', '_') + "()"; } // map.add(Foo.class, getConstructors_com_foo_Bar()); sw.println("map.add(%s, getConstructors_%s());", classLiteralAccessor, peerName.replace('.', '_')); } sw.outdent(); sw.println("}"); /* * Create a native method for each peer type that isn't public since Java * class literal references are scoped. */ for (JClassType peer : privatePeers) { String peerName = ModelUtils.ensureBaseType(peer).getQualifiedSourceName(); sw.println("private native Class<?> classLit_%s() /*-{return @%s::class;}-*/;", peerName.replace('.', '_'), peerName); } /* * Create a method that returns an array containing references to the * constructors. */ String factoryJNIName = context.getTypeOracle().findType(AutoBeanFactory.class.getCanonicalName()) .getJNISignature(); for (AutoBeanType type : model.getAllTypes()) { String peerName = ModelUtils.ensureBaseType(type.getPeerType()).getQualifiedSourceName(); String peerJNIName = ModelUtils.ensureBaseType(type.getPeerType()).getJNISignature(); /*- * private native JsArray<JSO> getConstructors_com_foo_Bar() { * return [ * BarProxyImpl::new(ABFactory), * BarProxyImpl::new(ABFactory, DelegateType) * ]; * } */ sw.println("private native %s<%s> getConstructors_%s() /*-{", JsArray.class.getCanonicalName(), JavaScriptObject.class.getCanonicalName(), peerName.replace('.', '_')); sw.indent(); sw.println("return ["); if (type.isSimpleBean()) { sw.indentln("@%s::new(%s),", type.getQualifiedSourceName(), factoryJNIName); } else { sw.indentln(","); } sw.indentln("@%s::new(%s%s)", type.getQualifiedSourceName(), factoryJNIName, peerJNIName); sw.println("];"); sw.outdent(); sw.println("}-*/;"); } }
From source file:com.google.web.bindery.autobean.gwt.rebind.AutoBeanFactoryGenerator.java
License:Apache License
/** * Create the shim instance of the AutoBean's peer type that lets us hijack * the method calls. Using a shim type, as opposed to making the AutoBean * implement the peer type directly, means that there can't be any conflicts * between methods in the peer type and methods declared in the AutoBean * implementation./* w ww . ja va 2s .c om*/ */ private void writeShim(SourceWriter sw, AutoBeanType type) throws UnableToCompleteException { // private final FooImpl shim = new FooImpl() { sw.println("private final %1$s shim = new %1$s() {", type.getPeerType().getQualifiedSourceName()); sw.indent(); for (AutoBeanMethod method : type.getMethods()) { JMethod jmethod = method.getMethod(); String methodName = jmethod.getName(); JParameter[] parameters = jmethod.getParameters(); if (isObjectMethodImplementedByShim(jmethod)) { // Skip any methods declared on Object, since we have special handling continue; } // foo, bar, baz StringBuilder arguments = new StringBuilder(); { for (JParameter param : parameters) { arguments.append(",").append(param.getName()); } if (arguments.length() > 0) { arguments = arguments.deleteCharAt(0); } } sw.println("public %s {", getBaseMethodDeclaration(jmethod)); sw.indent(); switch (method.getAction()) { case GET: /* * The getter call will ensure that any non-value return type is * definitely wrapped by an AutoBean instance. */ sw.println("%s toReturn = %s.this.getWrapped().%s();", ModelUtils.getQualifiedBaseSourceName(jmethod.getReturnType()), type.getSimpleSourceName(), methodName); // Non-value types might need to be wrapped writeReturnWrapper(sw, type, method); sw.println("return toReturn;"); break; case SET: case SET_BUILDER: // getWrapped().setFoo(foo); sw.println("%s.this.getWrapped().%s(%s);", type.getSimpleSourceName(), methodName, parameters[0].getName()); // FooAutoBean.this.set("setFoo", foo); sw.println("%s.this.set(\"%s\", %s);", type.getSimpleSourceName(), methodName, parameters[0].getName()); if (JBeanMethod.SET_BUILDER.equals(method.getAction())) { sw.println("return this;"); } break; case CALL: // XXX How should freezing and calls work together? // sw.println("checkFrozen();"); if (JPrimitiveType.VOID.equals(jmethod.getReturnType())) { // getWrapped().doFoo(params); sw.println("%s.this.getWrapped().%s(%s);", type.getSimpleSourceName(), methodName, arguments); // call("doFoo", null, params); sw.println("%s.this.call(\"%s\", null%s %s);", type.getSimpleSourceName(), methodName, arguments.length() > 0 ? "," : "", arguments); } else { // Type toReturn = getWrapped().doFoo(params); sw.println("%s toReturn = %s.this.getWrapped().%s(%s);", ModelUtils.ensureBaseType(jmethod.getReturnType()).getQualifiedSourceName(), type.getSimpleSourceName(), methodName, arguments); // Non-value types might need to be wrapped writeReturnWrapper(sw, type, method); // call("doFoo", toReturn, params); sw.println("%s.this.call(\"%s\", toReturn%s %s);", type.getSimpleSourceName(), methodName, arguments.length() > 0 ? "," : "", arguments); sw.println("return toReturn;"); } break; default: throw new RuntimeException(); } sw.outdent(); sw.println("}"); } // Delegate equals(), hashCode(), and toString() to wrapped object sw.println("@Override public boolean equals(Object o) {"); sw.indentln("return this == o || getWrapped().equals(o);"); sw.println("}"); sw.println("@Override public int hashCode() {"); sw.indentln("return getWrapped().hashCode();"); sw.println("}"); sw.println("@Override public String toString() {"); sw.indentln("return getWrapped().toString();"); sw.println("}"); // End of shim field declaration and assignment sw.outdent(); sw.println("};"); }
From source file:com.google.web.bindery.event.gwt.rebind.binder.EventBinderWriter.java
License:Apache License
private void writeBindMethodHeader(SourceWriter writer, String targetName) { writer.println("protected List<HandlerRegistration> doBindEventHandlers(" + "final %s target, EventBus eventBus) {", targetName); writer.indent();/* www . j a v a 2 s . c o m*/ writer.println("List<HandlerRegistration> registrations = new LinkedList<HandlerRegistration>();"); }
From source file:com.google.web.bindery.event.gwt.rebind.binder.EventBinderWriter.java
License:Apache License
private void writeHandlerForBindMethod(EventHandler annotation, SourceWriter writer, JMethod method, TypeOracle typeOracle) throws UnableToCompleteException { JClassType eventParameter = null;/*from ww w.j a va 2s .com*/ if (method.getParameterTypes().length == 1) { eventParameter = method.getParameterTypes()[0].isClassOrInterface(); } if (annotation.handles().length == 0 && !isAConcreteGenericEvent(eventParameter)) { logger.log(Type.ERROR, "Method " + method.getName() + " annotated with @EventHandler without event classes must have exactly " + "one argument of a concrete type assignable to GenericEvent"); throw new UnableToCompleteException(); } List<String> eventTypes = new ArrayList<String>(); if (annotation.handles().length != 0) { for (Class<? extends GenericEvent> event : annotation.handles()) { String eventTypeName = event.getCanonicalName(); JClassType eventClassType = typeOracle.findType(eventTypeName); if (eventClassType == null) { logger.log(Type.ERROR, "Can't resolve " + eventTypeName); throw new UnableToCompleteException(); } if (eventParameter != null && !eventClassType.isAssignableTo(eventParameter)) { logger.log(Type.ERROR, "Event " + eventTypeName + " isn't assignable to " + eventParameter.getName() + " in method: " + method.getName()); throw new UnableToCompleteException(); } eventTypes.add(eventClassType.getQualifiedSourceName()); } } else { eventTypes.add(eventParameter.getQualifiedSourceName()); } for (String eventType : eventTypes) { writer.println("bind(eventBus, registrations, %s.class, new GenericEventHandler() {", eventType); if (eventParameter != null) { writer.indentln("public void handleEvent(GenericEvent event) { target.%s((%s) event); }", method.getName(), eventType); } else { writer.indentln("public void handleEvent(GenericEvent event) { target.%s(); }", method.getName()); } writer.println("});"); } }
From source file:com.google.web.bindery.requestfactory.gwt.rebind.RequestFactoryGenerator.java
License:Apache License
private void writeTypeMap(SourceWriter sw) { sw.println("private static final %1$s<String, Class<?>> tokensToTypes" + " = new %1$s<String, Class<?>>();", HashMap.class.getCanonicalName()); sw.println("private static final %1$s<Class<?>, String> typesToTokens" + " = new %1$s<Class<?>, String>();", HashMap.class.getCanonicalName()); sw.println("private static final %1$s<Class<?>> entityProxyTypes = new %1$s<Class<?>>();", HashSet.class.getCanonicalName()); sw.println("private static final %1$s<Class<?>> valueProxyTypes = new %1$s<Class<?>>();", HashSet.class.getCanonicalName()); sw.println("static {"); sw.indent();//from w ww .j a va 2 s. co m for (EntityProxyModel type : model.getAllProxyModels()) { // tokensToTypes.put("Foo", Foo.class); sw.println("tokensToTypes.put(\"%s\", %s.class);", OperationKey.hash(type.getQualifiedBinaryName()), type.getQualifiedSourceName()); // typesToTokens.put(Foo.class, Foo); sw.println("typesToTokens.put(%s.class, \"%s\");", type.getQualifiedSourceName(), OperationKey.hash(type.getQualifiedBinaryName())); // fooProxyTypes.add(MyFooProxy.class); sw.println("%s.add(%s.class);", type.getType().equals(Type.ENTITY) ? "entityProxyTypes" : "valueProxyTypes", type.getQualifiedSourceName()); } sw.outdent(); sw.println("}"); // Write instance methods sw.println("@Override public String getFactoryTypeToken() {"); sw.indentln("return \"%s\";", model.getFactoryType().getQualifiedBinaryName()); sw.println("}"); sw.println("@Override protected Class getTypeFromToken(String typeToken) {"); sw.indentln("return tokensToTypes.get(typeToken);"); sw.println("}"); sw.println("@Override protected String getTypeToken(Class type) {"); sw.indentln("return typesToTokens.get(type);"); sw.println("}"); sw.println("@Override public boolean isEntityType(Class<?> type) {"); sw.indentln("return entityProxyTypes.contains(type);"); sw.println("}"); sw.println("@Override public boolean isValueType(Class<?> type) {"); sw.indentln("return valueProxyTypes.contains(type);"); sw.println("}"); }
From source file:com.msco.mil.server.com.sencha.gxt.explorer.rebind.SampleGenerator.java
License:sencha.com license
@Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { // Get access to metadata about the type to be generated TypeOracle oracle = context.getTypeOracle(); JClassType toGenerate = oracle.findType(typeName).isClass(); // 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; }// w ww . j a v a 2 s. co m // Generate an HTML file resource for every example and write the source JClassType[] types = oracle.getTypes(); // Build a ResourceOracle capable of reading java files sourceOracle = new ResourceOracleImpl(logger.branch(Type.DEBUG, "Gathering sources")); // Clean up these prefixes to not have filters PathPrefixSet prefixes = ((ResourceOracleImpl) context.getResourcesOracle()).getPathPrefixes(); sourceOracle.setPathPrefixes(new PathPrefixSet()); for (PathPrefix p : prefixes.values()) { sourceOracle.getPathPrefixes().add(new PathPrefix(p.getPrefix(), null)); } ResourceOracleImpl.refresh(logger, sourceOracle); // Load the header and footer HTML content try { String slashyPackageName = getClass().getPackage().getName().replace('.', '/'); javaHeader = Utility.getFileFromClassPath(slashyPackageName + "/header.html"); footer = Utility.getFileFromClassPath(slashyPackageName + "/footer.html"); } catch (IOException e) { logger.log(Type.ERROR, "Header or Footer failed to be read", e); throw new UnableToCompleteException(); } // Find all examples, annotated with @Detail Set<ExampleDetailModel> examples = new HashSet<ExampleDetailModel>(); Map<String, List<ExampleDetailModel>> hierarchy = new HashMap<String, List<ExampleDetailModel>>(); Set<SourceModel> exampleSources = new HashSet<SourceModel>(); for (JClassType type : types) { Example.Detail detail = type.getAnnotation(Example.Detail.class); if (detail != null) { ExampleDetailModel example = new ExampleDetailModel(logger, context, type, detail); // Collect sources to be built into html exampleSources.addAll(example.getAllSources()); List<ExampleDetailModel> exampleList = hierarchy.get(detail.category()); if (exampleList == null) { exampleList = new ArrayList<ExampleDetailModel>(); hierarchy.put(detail.category(), exampleList); } examples.add(example); exampleList.add(example); } } // Sort folders, sort within those folders List<String> folders = new ArrayList<String>(hierarchy.keySet()); Collections.sort(folders); for (List<ExampleDetailModel> contents : hierarchy.values()) { Collections.sort(contents); } // Actually build source for each type for (SourceModel type : exampleSources) { TreeLogger l = logger.branch(Type.DEBUG, "Writing HTML file for " + type.getName()); // attempt to create the output file if (type.getType() == FileType.JAVA) { writeTypeToHtml(l, context, type.getJClassType()); } else { writeFileToHtml(l, context, type.getPath()); } } // Start making the class, with basic imports ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, simpleSourceName); factory.setSuperclass(typeName); factory.addImport(Name.getSourceNameForClass(Category.class)); factory.addImport(Name.getSourceNameForClass(ImageResource.class)); factory.addImport(Name.getSourceNameForClass(GWT.class)); factory.addImport(Name.getSourceNameForClass(Example.class)); factory.addImport(Name.getSourceNameForClass(Source.class)); factory.addImport(Name.getSourceNameForClass(Source.FileType.class)); SourceWriter sw = factory.createSourceWriter(context, pw); // Write the ctor sw.println("public %1$s() {", simpleSourceName); sw.indent(); // Declare variables that will be used sw.println("Category c;"); sw.println("ImageResource icon;"); sw.println("Example e;"); sw.println("Source dir;"); Set<String> names = new HashSet<String>(); Map<JClassType, String> bundles = new HashMap<JClassType, String>(); for (String folder : folders) { // TODO escape name sw.println("c = new Category(\"%1$s\");", folder); for (ExampleDetailModel example : hierarchy.get(folder)) { // make sure the bundle to be used exists if (!bundles.containsKey(example.getClientBundleType())) { String bundleName = getNextName("bundle", names); sw.println("%1$s %2$s = GWT.create(%1$s.class);", example.getClientBundleType().getQualifiedSourceName(), bundleName); bundles.put(example.getClientBundleType(), bundleName); } // write out the example, adding it to the current category writeExample(sw, bundles.get(example.getClientBundleType()), example); } sw.println("categories.add(c);"); } sw.outdent(); sw.println("}");// end ctor sw.commit(logger); return factory.getCreatedClassName(); }
From source file:com.rhizospherejs.gwt.rebind.MappingWriter.java
License:Open Source License
private void writeMetaModelFactoryImpl(SourceWriter sw) { sw.println("private static final class %sMetaModelFactory extends MetaModelFactory {", modelClassName); sw.indent();/*from ww w .j av a 2 s . c o m*/ sw.println("public %sMetaModelFactory() {", modelClassName); sw.indentln("super();"); sw.println("}"); sw.println(); sw.println("public %sMetaModelFactory(%s attrBuilder) {", modelClassName, BridgeCapabilities.METAMODEL_ATTRIBUTE_BUILDER_CLASS); sw.indentln("super(attrBuilder);"); sw.println("}"); sw.println(); sw.println("@Override"); sw.println("protected void fillMetaModelAttributes(" + "RhizosphereMetaModel metaModel, AttributeBuilder attrBuilder) {"); sw.indent(); sw.println("Attribute attr;"); sw.println("AttributeDescriptor descriptor;"); sw.println("RhizosphereKind kind;"); for (MappableMethod modelMethod : inspector.getMappableModelMethods()) { if (!modelMethod.contributesToMetaModel()) { continue; } String labelParameter = modelMethod.getAttributeLabel() != null ? "\"" + modelMethod.getAttributeLabel() + "\"" : "null"; sw.println("attr = metaModel.newAttribute(\"%s\");", modelMethod.getAttributeName()); sw.println("descriptor = new %s();", modelMethod.getAttributeDescriptorClassName()); sw.println("kind = RhizosphereKind.valueOf(RhizosphereKind.class, \"%s\");", bridgeCapabilities.getBridgeMethod(modelMethod.getReturnType()).getRhizosphereKind().name()); sw.println("attrBuilder.fillAttribute(attr, descriptor, \"%s\", %s, kind);", modelMethod.getAttributeName(), labelParameter); sw.println(); } sw.outdent(); sw.println("}"); sw.outdent(); sw.println("}"); }
From source file:com.sencha.gxt.core.rebind.BindingPropertyGenerator.java
License:sencha.com license
@Override public String generate(TreeLogger logger, GeneratorContext context, String typeName) throws UnableToCompleteException { TypeOracle oracle = context.getTypeOracle(); JClassType toGenerate = oracle.findType(typeName).isInterface(); if (toGenerate == null) { logger.log(Type.ERROR, typeName + " is not an interface"); throw new UnableToCompleteException(); }/*from w ww.j a va 2 s .c o m*/ PropertyName annotation = toGenerate.getAnnotation(PropertyName.class); if (annotation == null) { logger.log(Type.ERROR, "Cannot generate with a @PropertyName anntation on the type"); throw new UnableToCompleteException(); } String propertyName = annotation.value(); SelectionProperty property; String value; try { property = context.getPropertyOracle().getSelectionProperty(logger, propertyName); value = property.getCurrentValue(); } catch (BadPropertyValueException e) { logger.log(Type.ERROR, "Error occured loading property: ", e); throw new UnableToCompleteException(); } String packageName = toGenerate.getPackage().getName(); String simpleSourceName = toGenerate.getName().replace('.', '_') + "_" + value; PrintWriter pw = context.tryCreate(logger, packageName, simpleSourceName); if (pw == null) { return packageName + "." + simpleSourceName; } ClassSourceFileComposerFactory factory = new ClassSourceFileComposerFactory(packageName, simpleSourceName); factory.addImplementedInterface(typeName); SourceWriter sw = factory.createSourceWriter(context, pw); for (JMethod method : toGenerate.getMethods()) { if (method.getReturnType().isPrimitive() != JPrimitiveType.BOOLEAN && !method.getReturnType().isClass() .getQualifiedSourceName().equals(Name.getSourceNameForClass(Boolean.class))) { logger.log(Type.ERROR, "Methods must return boolean or Boolean"); throw new UnableToCompleteException(); } sw.println("%1$s {", method.getReadableDeclaration(false, true, true, true, true)); PropertyValue val = method.getAnnotation(PropertyValue.class); if (val == null) { logger.log(Type.ERROR, "Method must have a @PropertyValue annotation"); throw new UnableToCompleteException(); } if (!property.getPossibleValues().contains(val.value()) && val.warn()) { logger.log(Type.WARN, "Value '" + val + "' is not present in the current set of possible values for selection property " + propertyName); } sw.indentln("return %1$b;", val.value().equals(value)); sw.println("}"); } sw.commit(logger); return factory.getCreatedClassName(); }
From source file:com.sencha.gxt.core.rebind.SafeHtmlTemplatesCreator.java
License:sencha.com license
@Override protected void create(SourceWriter sw) throws UnableToCompleteException { for (String method : methodNames) { sw.println("@Template(\"%1$s\")", escape(templates.get(method))); sw.println("SafeHtml %1$s(%2$s);", method, makeArgs(paramLists.get(method))); }//from ww w . java 2s . co m }
From source file:com.sencha.gxt.core.rebind.XTemplatesGenerator.java
License:sencha.com license
/** * Handles a given template chunk container by creating a method in the * safeHtmlTemplates impl//from ww w . jav a2 s . com * * @param sw the current sourcewriter * @param wrapper the chunk container to act recursively on * @param safeHtml creator to add new SafeHtml calls to * @param scopeContext current scope to make method calls to * @param invokables * @throws UnableToCompleteException */ private void buildSafeHtmlTemplates(String safeHtmlVar, SourceWriter sw, ContainerTemplateChunk wrapper, SafeHtmlTemplatesCreator safeHtml, Context scopeContext, MethodCollector invokables) throws UnableToCompleteException { // debugging section to see what is about to be printed sw.beginJavaDocComment(); sw.print(wrapper.toString()); sw.endJavaDocComment(); // make a new interface method for this content StringBuilder sb = new StringBuilder(); List<String> paramTypes = new ArrayList<String>(); List<String> params = new ArrayList<String>(); // write out children to local vars or to the template int argCount = 0; for (TemplateChunk chunk : wrapper.children) { if (chunk instanceof ContentChunk) { ContentChunk contentChunk = (ContentChunk) chunk; // build up the template if (contentChunk.type == ContentType.LITERAL) { sb.append(contentChunk.content); } else if (contentChunk.type == ContentType.CODE) { sb.append("{").append(argCount++).append("}"); paramTypes.add("java.lang.String"); StringBuffer expr = new StringBuffer("\"\" + ("); // parse out the quoted string literals first Matcher str = Pattern.compile("\"[^\"]+\"").matcher(contentChunk.content); TreeLogger code = logger.branch(Type.DEBUG, "Parsing code segment: \"" + contentChunk.content + "\""); int lastMatchEnd = 0; while (str.find()) { int begin = str.start(), end = str.end(); String escapedString = str.group(); String unmatched = contentChunk.content.substring(lastMatchEnd, begin); appendCodeBlockOperatorOrIdentifier(scopeContext, expr, code, unmatched); expr.append(escapedString); lastMatchEnd = end; } //finish rest of non-string-lit expression appendCodeBlockOperatorOrIdentifier(scopeContext, expr, code, contentChunk.content.substring(lastMatchEnd)); params.add(expr.append(")").toString()); code.log(Type.DEBUG, "Final compiled expression: " + expr); } else if (contentChunk.type == ContentType.REFERENCE) { sb.append("{").append(argCount++).append("}"); JType argType = scopeContext.getType(contentChunk.content); if (argType == null) { logger.log(Type.ERROR, "Reference could not be found: '" + contentChunk.content + "'. Please fix the expression in your template."); throw new UnableToCompleteException(); } paramTypes.add(argType.getParameterizedQualifiedSourceName()); params.add(scopeContext.deref(contentChunk.content)); } else { assert false : "Content type not supported + " + contentChunk.type; } } else if (chunk instanceof ControlChunk) { ControlChunk controlChunk = (ControlChunk) chunk; // build logic, get scoped name boolean hasIf = controlChunk.controls.containsKey("if"); boolean hasFor = controlChunk.controls.containsKey("for"); if (!hasIf && !hasFor) { logger.log(Type.ERROR, "<tpl> tag did not define a 'for' or 'if' attribute!"); throw new UnableToCompleteException(); } // declare a sub-template, and stash content in there, interleaving it // into the current template String subTemplate = scopeContext.declareLocalVariable("subTemplate"); String templateInBlock = scopeContext.declareLocalVariable("innerTemplate"); sb.append("{").append(argCount++).append("}"); paramTypes.add("com.google.gwt.safehtml.shared.SafeHtml"); params.add(subTemplate); sw.println("SafeHtml %1$s;", subTemplate); sw.println("SafeHtmlBuilder %1$s_builder = new SafeHtmlBuilder();", subTemplate); // find the context that should be passed to the child template final Context childScope; // if we have both for and if, if needs to wrap the for if (hasIf) { ConditionParser p = new ConditionParser(logger); List<Token> tokens = p.parse(controlChunk.controls.get("if")); StringBuilder condition = new StringBuilder(); for (Token t : tokens) { switch (t.type) { case ExpressionLiteral: condition.append(t.contents); break; case MethodInvocation: Matcher invoke = Pattern.compile("([a-zA-Z0-9\\._]+)\\:([a-zA-Z0-9_]+)\\(([^\\)]*)\\)") .matcher(t.contents); invoke.matches(); String deref = scopeContext.deref(invoke.group(1)); String methodName = invoke.group(2); String args = ""; for (String a : invoke.group(3).split(",")) { String possible = scopeContext.deref(a); args += possible == null ? a : possible; } condition.append(invokables.getMethodInvocation(methodName, deref, args)); break; case Reference: condition.append("(").append(scopeContext.deref(t.contents)).append(")"); break; default: logger.log(Type.ERROR, "Unexpected token type: " + t.type); throw new UnableToCompleteException(); } } sw.println("if (%1$s) {", condition.toString()); sw.indent(); } // if there is a for, print it out, and change scope if (hasFor) { String loopRef = controlChunk.controls.get("for"); JType collectionType = scopeContext.getType(loopRef); if (collectionType == null) { logger.log(Type.ERROR, "Reference in 'for' attribute could not be found: '" + loopRef + "'. Please fix the expression in your template."); throw new UnableToCompleteException(); } final JType localType;// type accessed within the loop final String localAccessor;// expr to access looped instance, where // %1$s is the loop obj, and %2$s is the // int index if (collectionType.isArray() != null) { localType = collectionType.isArray().getComponentType(); localAccessor = "%1$s[%2$s]"; } else {// List subtype localType = ModelUtils.findParameterizationOf(listInterface, collectionType.isClassOrInterface())[0]; localAccessor = "%1$s.get(%2$s)"; } String loopVar = scopeContext.declareLocalVariable("i"); // make sure the collection isnt null sw.println("if (%1$s != null) {", scopeContext.deref(loopRef)); sw.indent(); sw.println("for (int %1$s = 0; %1$s < %2$s; %1$s++) {", loopVar, scopeContext.derefCount(loopRef)); String itemExpr = String.format(localAccessor, scopeContext.deref(loopRef), loopVar); childScope = new Context(scopeContext, itemExpr, localType); childScope.setCountVar(loopVar); sw.indent(); } else { // if no for, use the same scope as the outer content childScope = scopeContext; } // generate a subtemplate, insert that sw.println("SafeHtml %1$s;", templateInBlock); buildSafeHtmlTemplates(templateInBlock, sw, controlChunk, safeHtml, childScope, invokables); sw.println("%1$s_builder.append(%2$s);", subTemplate, templateInBlock); // close up the blocks if (hasFor) { sw.outdent(); sw.println("}"); sw.outdent(); sw.println("}"); } if (hasIf) { sw.outdent(); sw.println("}"); } sw.println("%1$s = %1$s_builder.toSafeHtml();", subTemplate); } else { assert false : "Unsupported chunk type: " + chunk.getClass(); } } String methodName = safeHtml.addTemplate(sb.toString(), paramTypes); sw.beginJavaDocComment(); sw.println("safehtml content:"); sw.indent(); sw.println(sb.toString()); sw.outdent(); sw.println("params:"); sw.indent(); sw.print(args(params)); sw.outdent(); sw.endJavaDocComment(); sw.println("%4$s = %1$s.%2$s(%3$s);", safeHtml.getInstanceExpression(), methodName, args(params), safeHtmlVar); }