All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jamon.codegen.ProxyGenerator Maven / Gradle / Ivy

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package org.jamon.codegen;

import java.io.OutputStream;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.jamon.compiler.ParserErrorImpl;
import org.jamon.compiler.ParserErrorsImpl;
import org.jamon.node.LocationImpl;

public class ProxyGenerator extends AbstractSourceGenerator {
  public ProxyGenerator(TemplateDescriber describer, TemplateUnit templateUnit) {
    super(describer, templateUnit);
  }

  @Override
  public void generateSource(OutputStream out) throws java.io.IOException {
    writer = new CodeWriter(out, templateUnit.getEncoding());
    generateHeader();
    generatePrologue();
    generateImports();
    generateAnnotations();
    generateDeclaration();
    generateConstructors();
    generateIntf();
    generateImplData();
    if (templateUnit.getJamonContextType() != null) {
      generateJamonContextSetter();
    }
    generateOptionalArgs();
    generateFragmentInterfaces(false);
    if (templateUnit.isReplacing()) {
      generateReplacementConstructor();
    }
    if (!templateUnit.isParent()) {
      generateConstructImplReflective();
      generateConstructImplDirect();
      generateMakeRenderer();
      generateRender();
      generateRenderNoFlush();
    }
    if (templateUnit.isParent()) {
      generateParentRendererClass();
    }
    if (templateUnit.hasParentPath() && !templateUnit.isParent()) {
      generateMakeParentRenderer();
    }
    generateEpilogue();
    writer.finish();
  }

  private void generateImports() {
    templateUnit.printImports(writer);
  }

  private String getClassName() {
    return PathUtils.getIntfClassName(templateUnit.getName());
  }

  private String getPackageName() {
    return PathUtils.getIntfPackageName(templateUnit.getName());
  }

  private void generateHeader() {
    writer.println("// Autogenerated Jamon proxy");
    writer.println("// "
      + describer.getExternalIdentifier(templateUnit.getName()).replace('\\', '/'));
    writer.println();
  }

  private void generatePrologue() {
    String pkgName = getPackageName();
    if (pkgName.length() > 0) {
      writer.println("package " + pkgName + ";");
      writer.println();
    }
  }

  private void generateConstructors() {
    writer.println();
    writer.println("public " + getClassName() + "(" + ClassNames.TEMPLATE_MANAGER + " p_manager)");
    writer.openBlock();
    writer.println(" super(p_manager);");
    writer.closeBlock();

    writer.println();

    // We require a pass-through constructor for child templates and for replacement templates,
    // meaning that every proxy needs one.
    writer.println("protected " + getClassName() + "(String p_path)");
    writer.openBlock();
    writer.println("super(p_path);");
    writer.closeBlock();
    writer.println();

    if (!templateUnit.isParent()) {
      writer.println("public " + getClassName() + "()");
      writer.openBlock();
      writer.println(" super(\"" + templateUnit.getName() + "\");");
      writer.closeBlock();
      writer.println();
    }
  }

  private void generateFragmentInterfaces(boolean inner) {
    for (FragmentArgument farg : templateUnit.getDeclaredFragmentArgs()) {
      farg.getFragmentUnit().printInterface(writer, "public", !inner);
      writer.println();
    }
    writer.println();
  }

  private void generateReplacementConstructor() {
    writer.println();
    writer.print(
      "public static class ReplacementConstructor implements "
      + ClassNames.REPLACEMENT_CONSTRUCTOR + " ");
    writer.openBlock();
    if (templateUnit.getGenericParams().getCount() > 0) {
      writer.print("@SuppressWarnings(\"rawtypes\") ");
    }
    writer.print("@Override public " + ClassNames.TEMPLATE + " makeReplacement() ");
    writer.openBlock();
    writer.println("return new " + getClassName() + "();");
    writer.closeBlock();
    writer.closeBlock();
  }

  private void generateAnnotations() {
    if (templateUnit.isReplaceable()) {
      writer.println("@" + ClassNames.REPLACEABLE);
    }
    if (templateUnit.isReplacing()) {
      writer.print("@" + ClassNames.REPLACES);
      writer.openList("(", true);
      writer.printListElement("replacedProxy = " + getReplacedProxyClassName() + ".class");
      writer.printListElement("replacementConstructor = " + getClassName()
        + ".ReplacementConstructor.class");
      writer.closeList();
      writer.println();
    }
    writer.print("@" + ClassNames.TEMPLATE_ANNOTATION);
    writer.openList("(", true);
    writer.printListElement("signature = \"" + templateUnit.getSignature() + "\"");
    if (templateUnit.getGenericParams().getCount() > 0) {
      writer.printListElement("genericsCount = " + templateUnit.getGenericParams().getCount());
    }
    if (templateUnit.getInheritanceDepth() > 0) {
      writer.printListElement("inheritanceDepth = " + templateUnit.getInheritanceDepth());
    }
    if (templateUnit.getJamonContextType() != null) {
      writer.printListElement("jamonContextType = \"" + templateUnit.getJamonContextType() + "\"");
    }
    if (templateUnit.isReplaceable()) {
      writer.printListElement("replaceable = true");
    }
    generateArguments(templateUnit);
    generateMethodAnnotations();
    generateAbstractMethodAnnotations();
    writer.closeList(")");
    writer.println();
  }

  private void generateMethodAnnotations() {
    if (!templateUnit.getSignatureMethodUnits().isEmpty()) {
      writer.printListElement("methods = ");
      writer.openList("{", true);
      for (MethodUnit methodUnit : templateUnit.getSignatureMethodUnits()) {
        writer.printListElement("@" + ClassNames.METHOD_ANNOTATION);
        writer.openList("(", true);
        writer.printListElement("name = \"" + methodUnit.getName() + "\"");
        generateArguments(methodUnit);
        writer.closeList(")");
      }
      writer.closeList("}");
    }
  }

  private void generateAbstractMethodAnnotations() {
    if (!templateUnit.getAbstractMethodNames().isEmpty()) {
      writer.printListElement("abstractMethodNames = ");
      writer.openList("{", false);
      for (String methodName : templateUnit.getAbstractMethodNames()) {
        writer.printListElement("\"" + methodName + "\"");
      }
      writer.closeList("}");
    }
  }

  private void generateArguments(Unit p_unit) {
    generateArgumentAnnotations("requiredArguments", p_unit.getSignatureRequiredArgs());
    generateArgumentAnnotations("optionalArguments", p_unit.getSignatureOptionalArgs());
    generateFragmentAnnotations(p_unit.getFragmentArgs());
  }

  private void generateFragmentAnnotations(Collection fargs) {
    if (!fargs.isEmpty()) {
      writer.printListElement("fragmentArguments = ");
      writer.openList("{", true);
      for (FragmentArgument farg : fargs) {
        writer.printListElement("@" + ClassNames.FRAGMENT_ANNOTATION);
        writer.openList("(", true);
        writer.printListElement("name = \"" + farg.getName() + "\"");
        generateArgumentAnnotations("requiredArguments", farg.getFragmentUnit().getRequiredArgs());
        generateArgumentAnnotations("optionalArguments", farg.getFragmentUnit().getOptionalArgs());
        writer.closeList(")");
      }
      writer.closeList("}");
    }
  }

  private void generateArgumentAnnotations(
    String label, Collection args) {
    if (!args.isEmpty()) {
      writer.printListElement(label + " = ");
      writer.openList("{", true);
      for (AbstractArgument argument : args) {
        writer.printListElement(
          "@" + ClassNames.ARGUMENT_ANNOTATION + "(name = \""
          + argument.getName() + "\", type = \"" + argument.getType() + "\")");
      }
      writer.closeList("}");
    }
  }

  private void generateDeclaration() {
    generateCustomAnnotations(templateUnit.getAnnotations(), AnnotationType.PROXY);
    writer.print("public ");
    if (templateUnit.isParent()) {
      writer.print("abstract ");
    }
    writer.println("class " + getClassName()
      + templateUnit.getGenericParams().generateGenericsDeclaration());

    writer.println("  extends " + templateUnit.getProxyParentClass());
    templateUnit.printInterfaces(writer);
    writer.openBlock();
  }

  private void generateConstructImplReflective() {
    writer.println();
    writer.println("@Override");
    writer.print("public " + ClassNames.BASE_TEMPLATE + " constructImpl" + "(Class p_class)");
    writer.openBlock();
    writer.println("try");
    writer.openBlock();
    writer.println("return p_class");
    writer.indent();
    writer.println(".getConstructor(new Class [] { " + ClassNames.TEMPLATE_MANAGER + ".class"
      + ", ImplData.class })");
    writer.println(".newInstance(new Object [] { getTemplateManager(), getImplData()});");
    writer.outdent();
    writer.closeBlock();
    writer.println("catch (RuntimeException e)");
    writer.openBlock();
    writer.println("throw e;");
    writer.closeBlock();
    writer.println("catch (Exception e)");
    writer.openBlock();
    writer.println("throw new RuntimeException(e);");
    writer.closeBlock();
    writer.closeBlock();
  }

  private void generateConstructImplDirect() {
    writer.println();
    writer.println("@Override");
    writer.print("protected " + ClassNames.BASE_TEMPLATE + " constructImpl()");
    writer.openBlock();
    writer.println("return new " + PathUtils.getImplClassName(templateUnit.getName())
      + genericParamsList() + "(getTemplateManager(), getImplData());");
    writer.closeBlock();
  }

  private void generateRender() {
    writer.print((templateUnit.isParent()
        ? "protected"
        : "public") + " void render");
    writer.openList();
    writer.printListElement(ArgNames.WRITER_DECL);
    templateUnit.printRenderArgsDecl(writer);
    writer.closeList();
    writer.println();

    writer.println("  throws " + ClassNames.IOEXCEPTION);
    writer.openBlock();
    writer.print("renderNoFlush");
    writer.openList();
    writer.printListElement(ArgNames.WRITER);
    templateUnit.printRenderArgs(writer);
    writer.closeList();
    writer.println(";");
    writer.println(ArgNames.WRITER + ".flush();");
    writer.closeBlock();
  }

  private void generateRenderNoFlush() {
    writer.print(
      (templateUnit.isParent() ? "protected" : "public")
      + " void renderNoFlush");
    writer.openList();
    writer.printListElement(ArgNames.WRITER_DECL);
    templateUnit.printRenderArgsDecl(writer);
    writer.closeList();
    writer.println();

    writer.println("  throws " + ClassNames.IOEXCEPTION);
    writer.openBlock();
    if (!templateUnit.getRenderArgs().isEmpty()) {
      writer.println("ImplData" + genericParamsList() + " implData = getImplData();");
      for (AbstractArgument arg : templateUnit.getRenderArgs()) {
        writer.println("implData." + arg.getSetterName() + "(" + arg.getName() + ");");
      }
    }
    if (templateUnit.getGenericParams().getCount() > 0) {
      writer.print("@SuppressWarnings(\"unchecked\") ");
    }
    writer.print("Intf" + genericParamsList() + " instance = (Intf" + genericParamsList()
      + ") getTemplateManager().constructImpl(this");
    if (templateUnit.getJamonContextType() != null) {
      writer.print(", getImplData().getJamonContext()");
    }
    writer.println(");");

    writer.println("instance.renderNoFlush(" + ArgNames.WRITER + ");");
    writer.println("reset();");
    writer.closeBlock();
    writer.println();
  }

  private void generateMakeRenderer() {
    writer.print("public " + ClassNames.RENDERER + " makeRenderer");
    writer.openList();
    templateUnit.printRenderArgsDecl(writer);
    writer.closeList();
    writer.println();

    writer.openBlock();
    writer.print("return new " + ClassNames.ABSTRACT_RENDERER + "() ");
    writer.openBlock();
    writer.println("@Override");
    writer.println("public void renderTo(" + ArgNames.WRITER_DECL + ")");
    writer.println("  throws " + ClassNames.IOEXCEPTION);
    writer.openBlock();
    writer.print("render");
    writer.openList();
    writer.printListElement(ArgNames.WRITER);
    templateUnit.printRenderArgs(writer);
    writer.closeList();
    writer.println(";");
    writer.closeBlock();
    writer.closeBlock(";");
    writer.closeBlock();
    writer.println();
  }

  private void generateImplData() throws ParserErrorsImpl {
    writer.println("public static class ImplData"
      + templateUnit.getGenericParams().generateGenericsDeclaration());
    writer.print("  extends ");
    writer.println(implDataAncestor());
    if (templateUnit.isReplacing()) {
      writer.print("  implements ");
      writer.print(ClassNames.IMPL_DATA_COMPATIBLE);
      writer.println("<" + getReplacedImplDataClassName() + ">");
    }
    writer.openBlock();
    if (templateUnit.isReplacing()) {
      generatePopulateFrom();
    }
    if (templateUnit.isOriginatingJamonContext()) {
      writer.println("private " + templateUnit.getJamonContextType() + " m_jamonContext;");
      writer.println("public " + templateUnit.getJamonContextType() + " getJamonContext()");
      writer.openBlock();
      writer.println("return m_jamonContext;");
      writer.closeBlock();
      writer.println("public void setJamonContext(" + templateUnit.getJamonContextType()
        + " p_jamonContext)");
      writer.openBlock();
      writer.println("m_jamonContext = p_jamonContext;");
      writer.closeBlock();
    }
    for (AbstractArgument arg : templateUnit.getDeclaredArgs()) {
      arg.generateImplDataCode(writer);
    }
    writer.closeBlock();

    if (!templateUnit.isParent()) {
      writer.println("@Override");
      writer.println("protected " + ClassNames.TEMPLATE + ".ImplData" + " makeImplData()");
      writer.openBlock();
      writer.println("return new ImplData" + genericParamsList() + "();");
      writer.closeBlock();
    }

    // Only generate the getImplData method if we're actually going to use it.
    if (!templateUnit.isParent() || !templateUnit.getSignatureOptionalArgs().isEmpty()
      || templateUnit.getJamonContextType() != null) {
      generateGetImplData();
    }
  }

  /**
   * Generate a method to cast getImplData() to the ImplData class defined in this Proxy file.
   */
  private void generateGetImplData() {
    if (templateUnit.getGenericParams().getCount() > 0) {
      writer.print("@SuppressWarnings(\"unchecked\") ");
    }
    writer.println("@Override public ImplData" + genericParamsList() + " getImplData()");
    writer.openBlock();
    writer.println("return (ImplData" + genericParamsList() + ") super.getImplData();");
    writer.closeBlock();
  }

  /**
   * Generate the populateFrom method, which is used in replacement templates to populate the
   * template's ImplData instance with an instance of ImplData for the replaced template.
   * @throws ParserErrorsImpl
   */
  private void generatePopulateFrom() throws ParserErrorsImpl {
    for (FragmentArgument farg : templateUnit.getFragmentArgs()) {
      generateFragmentDelegator(farg);
    }
    writer.print(
      "@Override public void populateFrom(" + getReplacedImplDataClassName() + " implData) ");
    writer.openBlock();
    TemplateDescription replacedTemplateDescription = templateUnit.getReplacedTemplateDescription();
    for (RequiredArgument arg : templateUnit.getSignatureRequiredArgs()) {
      writer.println(arg.getSetterName() + "(implData." + arg.getGetterName() + "());");
    }
    Set replacedTemplateOptionalArgNames = getOptionalArgNames(replacedTemplateDescription);
    for (OptionalArgument arg : replacedTemplateDescription.getOptionalArgs()) {
      writer.printLocation(arg.getLocation());
      if (replacedTemplateOptionalArgNames.contains(arg.getName())) {
        writer.println("if(implData." + arg.getIsNotDefaultName() + "()) {");
        writer.println("  " + arg.getSetterName() + "(implData." + arg.getGetterName() + "());");
        writer.println("}");
      }
      else {
        writer.println(arg.getSetterName() + "(implData." + arg.getGetterName() + "());");
      }
    }
    if (templateUnit.getJamonContextType() != null) {
      if (replacedTemplateDescription.getJamonContextType() == null) {
        throw new ParserErrorsImpl(new ParserErrorImpl(
          templateTopLocation(),
          "Replaced component does not have a jamonContext, but replacing component has a " +
          "jamonContext of type " + templateUnit.getJamonContextType()));

      }
      else {
        writer.printLocation(templateTopLocation());
        writer.println("setJamonContext(implData.getJamonContext());");
      }
    }
    for (FragmentArgument farg : templateUnit.getFragmentArgs()) {
      writer.printLocation(farg.getLocation());
      writer.println(
        farg.getSetterName() + "(new " + getFragmentDelegatorName(farg)
        + genericParamsList() + "(implData." + farg.getGetterName() + "()));");
    }
    writer.closeBlock();
  }

  /**
   * Create a class to delegate from a fragment satisfying the interface for the replaced template
   * to a fragment satisfying the corresponding interface in this template.
   *
   * @param farg the fragment argument to create a delegator for.
   */
  private void generateFragmentDelegator(FragmentArgument farg) {
    String fragmentInterfaceName = "Fragment_" + farg.getName() + genericParamsList();
    // FIXME - use farg.getFragmentUnit.getFullyQualifiedType
    String replacedFragmentInterfaceName =
      getReplacedProxyClassName() + "." + fragmentInterfaceName;
    FragmentUnit fragmentUnit = farg.getFragmentUnit();
    // name the fragment being converted "_frag_" to avoid name clashes with the parameters
    // passed to the fragment.
    writer.print(
      "private static class " + getFragmentDelegatorName(farg)
      + templateUnit.getGenericParams().generateGenericsDeclaration() + " implements "
      + fragmentInterfaceName);
    writer.openBlock();
    writer.println("private final " + replacedFragmentInterfaceName + " frag;");
    writer.println();

    writer.print(
      "public " + getFragmentDelegatorName(farg) + "(" + replacedFragmentInterfaceName + " frag)");
    writer.openBlock();
    writer.println("this.frag = frag;");
    writer.closeBlock();
    writer.println();
    writer.print("@Override public void renderNoFlush");
    writer.openList();
    writer.printListElement(ArgNames.WRITER_DECL);
    fragmentUnit.printRenderArgsDecl(writer);
    writer.closeList();
    writer.println();
    writer.println("  throws java.io.IOException");
    writer.openBlock();
    writer.print("this.frag.renderNoFlush");
    writer.openList();
    writer.printListElement(ArgNames.WRITER);
    fragmentUnit.printRenderArgs(writer);
    writer.closeList();
    writer.println(";");
    writer.closeBlock();

    writer.print("@Override public " + ClassNames.RENDERER + " makeRenderer");
    writer.openList();
    fragmentUnit.printRenderArgsDecl(writer);
    writer.closeList();
    writer.openBlock();
    writer.print("return this.frag.makeRenderer");
    writer.openList();
    fragmentUnit.printRenderArgs(writer);
    writer.closeList();
    writer.println(";");
    writer.closeBlock();

    writer.closeBlock();
    writer.println();
  }

  private String getFragmentDelegatorName(FragmentArgument farg) {
    return "Fragment_" + farg.getName() + "_Delegator";
  }

  private String getReplacedImplDataClassName() {
    return getReplacedProxyClassName() + ".ImplData" + genericParamsList();
  }

  private String getReplacedIntfClassName() {
    return getReplacedProxyClassName() + ".Intf" + genericParamsList();
  }

  private String getReplacedProxyClassName() {
    return PathUtils.getFullyQualifiedIntfClassName(templateUnit.getReplacedTemplatePath());
  }

  private static Set getOptionalArgNames(TemplateDescription replacedTemplateDescription) {
    Set replacedTemplateOptionalArgNames = new HashSet();
    for (OptionalArgument arg : replacedTemplateDescription.getOptionalArgs()) {
      replacedTemplateOptionalArgNames.add(arg.getName());
    }
    return replacedTemplateOptionalArgNames;
  }

  private String implDataAncestor() {
    return templateUnit.hasParentPath()
        ? PathUtils.getFullyQualifiedIntfClassName(templateUnit.getParentPath()) + ".ImplData"
        : ClassNames.IMPL_DATA;
  }

  private void generateJamonContextSetter() {
    writer.println();
    if (!templateUnit.isOriginatingJamonContext()) {
      writer.print("@Override ");
    }
    writer.print("public ");
    printFullProxyType();
    writer.println(" setJamonContext(" + templateUnit.getJamonContextType() + " p_jamonContext)");
    writer.openBlock();
    writer.println("getImplData().setJamonContext(p_jamonContext);");
    writer.println("return this;");
    writer.closeBlock();
  }

  private void generateOptionalArgs() {
    for (OptionalArgument arg : templateUnit.getDeclaredOptionalArgs()) {
      writer.println();
      writer.println("protected " + arg.getType() + " " + arg.getName() + ";");
      writer.print("public final ");
      printFullProxyType();
      writer.println(" " + arg.getSetterName() + "(" + arg.getType() + " p_" + arg.getName() + ")");
      writer.openBlock();
      writer.println("(" + "getImplData()" + ")." + arg.getSetterName() + "(p_" + arg.getName()
        + ");");
      writer.println("return this;");
      writer.closeBlock();
    }
  }

  private void printFullProxyType() {
    String pkgName = getPackageName();
    if (pkgName.length() > 0) {
      writer.print(pkgName + ".");
    }
    writer.print(getClassName());
    writer.print(genericParamsList());
  }

  private void generateIntf() {
    writer.println("public interface Intf"
      + templateUnit.getGenericParams().generateGenericsDeclaration());
    writer.print("  extends ");
    writer.openList("", false);
    if (templateUnit.hasParentPath()) {
      writer.printListElement(
        PathUtils.getFullyQualifiedIntfClassName(templateUnit.getParentPath()) + ".Intf");
    }
    if (templateUnit.isReplacing()) {
      writer.printListElement(getReplacedIntfClassName());
    }
    if (!templateUnit.hasParentPath() && !templateUnit.isReplacing()) {
      writer.printListElement(ClassNames.TEMPLATE_INTF);
    }
    writer.closeList("");
    writer.println();
    writer.openBlock();

    generateFragmentInterfaces(true);

    if (!templateUnit.isParent()) {
      if (templateUnit.isReplacing()) {
        writer.print("@Override ");
      }
      writer.println(
        "void renderNoFlush(" + ArgNames.WRITER_DECL + ") throws " + ClassNames.IOEXCEPTION + ";");
      writer.println();
    }
    writer.closeBlock();
  }

  private void generateParentRendererClass() {
    writer.println("public abstract class ParentRenderer");
    writer.openBlock();
    writer.println("protected ParentRenderer() {}");

    for (OptionalArgument arg : templateUnit.getSignatureOptionalArgs()) {
      writer.println();
      String name = arg.getName();
      writer.print("public final ParentRenderer ");
      writer.println(arg.getSetterName() + "(" + arg.getType() + " p_" + name + ")");
      writer.openBlock();
      writer.println(getClassName() + ".this." + arg.getSetterName() + "(" + "p_" + name + ");");
      writer.println("return this;");
      writer.closeBlock();
    }

    if (templateUnit.getJamonContextType() != null) {
      writer.print(
        "public final ParentRenderer setJamonContext("
        + templateUnit.getJamonContextType() + " p_jamonContext)");
      writer.openBlock();
      writer.println(getClassName() + ".this.setJamonContext(p_jamonContext);");
      writer.println("return this;");
      writer.closeBlock();
    }

    if (!templateUnit.hasParentPath()) {
      writer.print("public void render");
      writer.openList();
      writer.printListElement(ArgNames.WRITER_DECL);
      templateUnit.printDeclaredRenderArgsDecl(writer);
      writer.closeList();
      writer.println();
      writer.print("  throws " + ClassNames.IOEXCEPTION);
      writer.openBlock();
      writer.print("renderNoFlush");
      writer.openList();
      writer.printListElement(ArgNames.WRITER);
      templateUnit.printDeclaredRenderArgs(writer);
      writer.closeList();
      writer.println(";");
      writer.println(ArgNames.WRITER + ".flush();");
      writer.closeBlock();

      writer.print("public void renderNoFlush");
      writer.openList();
      writer.printListElement(ArgNames.WRITER_DECL);
      templateUnit.printDeclaredRenderArgsDecl(writer);
      writer.closeList();
      writer.println();
      writer.print("  throws " + ClassNames.IOEXCEPTION);
      writer.openBlock();
      writer.print("renderChild");
      writer.openList();
      writer.printListElement(ArgNames.WRITER);
      templateUnit.printDeclaredRenderArgs(writer);
      writer.closeList();
      writer.println(";");
      writer.closeBlock();

      generateMakeRenderer();
    }
    else {
      generateMakeParentRenderer();
    }

    writer.print("protected abstract void renderChild");
    writer.openList();
    writer.printListElement(ArgNames.WRITER_DECL);
    templateUnit.printRenderArgsDecl(writer);
    writer.closeList();
    writer.println();
    writer.println("  throws " + ClassNames.IOEXCEPTION + ";");

    writer.closeBlock();
  }

  private void generateMakeParentRenderer() {
    String parentRendererClass =
      PathUtils.getFullyQualifiedIntfClassName(templateUnit.getParentPath()) + ".ParentRenderer";
    writer.print("public " + parentRendererClass + " makeParentRenderer");
    writer.openList();
    templateUnit.printDeclaredRenderArgsDecl(writer);
    writer.closeList();
    writer.println();
    writer.openBlock();
    writer.print("return new " + parentRendererClass + "() ");
    writer.openBlock();
    writer.print("@Override protected void renderChild");
    writer.openList();
    writer.printListElement(ArgNames.WRITER_DECL);
    templateUnit.printParentRenderArgsDecl(writer);
    writer.closeList();
    writer.println();
    writer.println("  throws " + ClassNames.IOEXCEPTION);
    writer.openBlock();
    writer.print(PathUtils.getFullyQualifiedIntfClassName(getClassName()));
    if (templateUnit.isParent()) {
      writer.print(".ParentRenderer.this.renderChild");
    }
    else {
      writer.print(".this.renderNoFlush");
    }
    writer.openList();
    writer.printListElement(ArgNames.WRITER);
    templateUnit.printRenderArgs(writer);
    writer.closeList();
    writer.println(";");
    writer.closeBlock();
    writer.closeBlock(";");
    writer.closeBlock();
  }

  private void generateEpilogue() {
    writer.println();
    writer.closeBlock();
  }

  private String genericParamsList() {
    return templateUnit.getGenericParams().generateGenericParamsList();
  }


  /**
   * @return a location representing the top of the template. Useful for constructs which don't
   * relate to any specific point in the template.
   */
  private LocationImpl templateTopLocation() {
    return new LocationImpl(describer.getTemplateLocation(templateUnit.getName()), 1, 1);
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy