diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java index 5373b99e934ddf7292f3878889c63e13548b5794..639f8448c3f2d332e2b0dd5245cf1edbee9e59e0 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/DefaultCodegen.java @@ -19,7 +19,11 @@ package org.openapitools.codegen; import com.fasterxml.jackson.core.JsonProcessingException; import com.google.common.base.CaseFormat; +import com.google.common.collect.ImmutableMap; +import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Mustache.Compiler; +import com.samskivert.mustache.Mustache.Lambda; + import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.Operation; @@ -48,6 +52,11 @@ import org.openapitools.codegen.meta.GeneratorMetadata; import org.openapitools.codegen.meta.Stability; import org.openapitools.codegen.serializer.SerializerUtils; import org.openapitools.codegen.templating.MustacheEngineAdapter; +import org.openapitools.codegen.templating.mustache.CamelCaseLambda; +import org.openapitools.codegen.templating.mustache.IndentedLambda; +import org.openapitools.codegen.templating.mustache.LowercaseLambda; +import org.openapitools.codegen.templating.mustache.TitlecaseLambda; +import org.openapitools.codegen.templating.mustache.UppercaseLambda; import org.openapitools.codegen.utils.ModelUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -199,6 +208,47 @@ public class DefaultCodegen implements CodegenConfig { } } + /*** + * Preset map builder with commonly used Mustache lambdas. + * + * To extend the map, override addMustacheLambdas(), call parent method + * first and then add additional lambdas to the returned builder. + * + * If common lambdas are not desired, override addMustacheLambdas() method + * and return empty builder. + * + * @return preinitialized map builder with common lambdas + */ + protected ImmutableMap.Builder<String, Lambda> addMustacheLambdas() { + + return new ImmutableMap.Builder<String, Mustache.Lambda>() + .put("lowercase", new LowercaseLambda().generator(this)) + .put("uppercase", new UppercaseLambda()) + .put("titlecase", new TitlecaseLambda()) + .put("camelcase", new CamelCaseLambda().generator(this)) + .put("indented", new IndentedLambda()) + .put("indented_8", new IndentedLambda(8, " ")) + .put("indented_12", new IndentedLambda(12, " ")) + .put("indented_16", new IndentedLambda(16, " ")); + } + + private void registerMustacheLambdas() { + ImmutableMap<String, Lambda> lambdas = addMustacheLambdas().build(); + + if (lambdas.size() == 0) { + return; + } + + if (additionalProperties.containsKey("lambda")) { + LOGGER.warn("A property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " + + "You'll likely need to use a custom template, " + + "see https://github.com/OpenAPITools/openapi-generator/blob/master/docs/templating.md. "); + additionalProperties.put("_lambda", lambdas); + } else { + additionalProperties.put("lambda", lambdas); + } + } + // override with any special post-processing for all models @SuppressWarnings({"static-method", "unchecked"}) public Map<String, Object> postProcessAllModels(Map<String, Object> objs) { @@ -1060,6 +1110,9 @@ public class DefaultCodegen implements CodegenConfig { // initialize special character mapping initalizeSpecialCharacterMapping(); + + // Register common Mustache lambdas. + registerMustacheLambdas(); } /** @@ -1523,7 +1576,7 @@ public class DefaultCodegen implements CodegenConfig { // If the format matches a typeMapping (supplied with the --typeMappings flag) // then treat the format as a primitive type. // This allows the typeMapping flag to add a new custom type which can then - // be used in the format field. + // be used in the format field. return schema.getFormat(); } return "string"; diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java index 1e7a454007f87c69441332e97267f0097426f8a1..d39c6c07ab47aae6caae6c6b35b51b8781e7ec4d 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCSharpCodegen.java @@ -17,8 +17,9 @@ package org.openapitools.codegen.languages; -import com.google.common.collect.ImmutableMap; -import com.samskivert.mustache.Mustache; +import com.google.common.collect.ImmutableMap.Builder; +import com.samskivert.mustache.Mustache.Lambda; + import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; @@ -359,32 +360,12 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co // This either updates additionalProperties with the above fixes, or sets the default if the option was not specified. additionalProperties.put(CodegenConstants.INTERFACE_PREFIX, interfacePrefix); - - addMustacheLambdas(additionalProperties); } - private void addMustacheLambdas(Map<String, Object> objs) { - - Map<String, Mustache.Lambda> lambdas = new ImmutableMap.Builder<String, Mustache.Lambda>() - .put("lowercase", new LowercaseLambda().generator(this)) - .put("uppercase", new UppercaseLambda()) - .put("titlecase", new TitlecaseLambda()) - .put("camelcase", new CamelCaseLambda().generator(this)) - .put("camelcase_param", new CamelCaseLambda().generator(this).escapeAsParamName(true)) - .put("indented", new IndentedLambda()) - .put("indented_8", new IndentedLambda(8, " ")) - .put("indented_12", new IndentedLambda(12, " ")) - .put("indented_16", new IndentedLambda(16, " ")) - .build(); - - if (objs.containsKey("lambda")) { - LOGGER.warn("A property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " + - "You'll likely need to use a custom template, " + - "see https://github.com/swagger-api/swagger-codegen#modifying-the-client-library-format. "); - objs.put("_lambda", lambdas); - } else { - objs.put("lambda", lambdas); - } + @Override + protected Builder<String, Lambda> addMustacheLambdas() { + return super.addMustacheLambdas() + .put("camelcase_param", new CamelCaseLambda().generator(this).escapeAsParamName(true)); } @Override diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCppCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCppCodegen.java index 65105e467a869c183d83554517d7bbe42a60c43b..afbbae668485837883f5d945336441f6feaf2874 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCppCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractCppCodegen.java @@ -17,8 +17,8 @@ package org.openapitools.codegen.languages; -import com.google.common.collect.ImmutableMap; -import com.samskivert.mustache.Mustache; +import com.google.common.collect.ImmutableMap.Builder; +import com.samskivert.mustache.Mustache.Lambda; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; @@ -35,7 +35,6 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.net.URL; import java.util.Arrays; -import java.util.Map; abstract public class AbstractCppCodegen extends DefaultCodegen implements CodegenConfig { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractCppCodegen.class); @@ -260,22 +259,12 @@ abstract public class AbstractCppCodegen extends DefaultCodegen implements Codeg LOGGER.info("Environment variable CPP_POST_PROCESS_FILE not defined so the C++ code may not be properly formatted. To define it, try 'export CPP_POST_PROCESS_FILE=\"/usr/local/bin/clang-format -i\"' (Linux/Mac)"); LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI)."); } - - addMustacheLambdas(additionalProperties); } - private void addMustacheLambdas(Map<String, Object> objs) { - - Map<String, Mustache.Lambda> lambdas = new ImmutableMap.Builder<String, Mustache.Lambda>() - .put("multiline_comment_4", new IndentedLambda(4, " ", "///")) - .build(); - - if (objs.containsKey("lambda")) { - LOGGER.warn("A property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'."); - objs.put("_lambda", lambdas); - } else { - objs.put("lambda", lambdas); - } + @Override + protected Builder<String, Lambda> addMustacheLambdas() { + return super.addMustacheLambdas() + .put("multiline_comment_4", new IndentedLambda(4, " ", "///")); } @Override @@ -304,17 +293,17 @@ abstract public class AbstractCppCodegen extends DefaultCodegen implements Codeg } } } - + @Override public void preprocessOpenAPI(OpenAPI openAPI) { URL url = URLPathUtils.getServerURL(openAPI); String port = URLPathUtils.getPort(url, ""); String host = url.getHost(); if(!port.isEmpty()) { - this.additionalProperties.put("serverPort", port); + this.additionalProperties.put("serverPort", port); } if(!host.isEmpty()) { - this.additionalProperties.put("serverHost", host); - } + this.additionalProperties.put("serverHost", host); + } } } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractFSharpCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractFSharpCodegen.java index 9d82448ffb3b399850efbbef4c6fff71317c7b5b..04a626eac774a38a925fec9d5dc225dc6dfc5b50 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractFSharpCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractFSharpCodegen.java @@ -16,8 +16,9 @@ package org.openapitools.codegen.languages; -import com.google.common.collect.ImmutableMap; -import com.samskivert.mustache.Mustache; +import com.google.common.collect.ImmutableMap.Builder; +import com.samskivert.mustache.Mustache.Lambda; + import io.swagger.v3.core.util.Json; import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; @@ -67,7 +68,7 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co protected Set<String> collectionTypes; protected Set<String> mapTypes; - // true if nullable types will be supported (as option) + // true if nullable types will be supported (as option) protected boolean supportNullable = Boolean.TRUE; protected Set<String> nullableType = new HashSet<String>(); @@ -329,32 +330,12 @@ public abstract class AbstractFSharpCodegen extends DefaultCodegen implements Co // This either updates additionalProperties with the above fixes, or sets the default if the option was not specified. additionalProperties.put(CodegenConstants.INTERFACE_PREFIX, interfacePrefix); - - addMustacheLambdas(additionalProperties); } - private void addMustacheLambdas(Map<String, Object> objs) { - - Map<String, Mustache.Lambda> lambdas = new ImmutableMap.Builder<String, Mustache.Lambda>() - .put("lowercase", new LowercaseLambda().generator(this)) - .put("uppercase", new UppercaseLambda()) - .put("titlecase", new TitlecaseLambda()) - .put("camelcase", new CamelCaseLambda().generator(this)) - .put("camelcase_param", new CamelCaseLambda().generator(this).escapeAsParamName(true)) - .put("indented", new IndentedLambda()) - .put("indented_8", new IndentedLambda(8, " ")) - .put("indented_12", new IndentedLambda(12, " ")) - .put("indented_16", new IndentedLambda(16, " ")) - .build(); - - if (objs.containsKey("lambda")) { - LOGGER.warn("A property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " + - "You'll likely need to use a custom template, " + - "see https://github.com/swagger-api/swagger-codegen#modifying-the-client-library-format. "); - objs.put("_lambda", lambdas); - } else { - objs.put("lambda", lambdas); - } + @Override + protected Builder<String, Lambda> addMustacheLambdas() { + return super.addMustacheLambdas() + .put("camelcase_param", new CamelCaseLambda().generator(this).escapeAsParamName(true)); } @Override diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinServerCodegen.java index 80e48bf0bc02512da078cce2dd6abd76fd4d633b..4bd48eb2188e7fc27b35a1716e3cad251d25e337 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinServerCodegen.java @@ -18,13 +18,11 @@ package org.openapitools.codegen.languages; import com.google.common.collect.ImmutableMap; -import com.samskivert.mustache.Mustache; import org.apache.commons.lang3.StringUtils; import org.openapitools.codegen.CliOption; import org.openapitools.codegen.CodegenConstants; import org.openapitools.codegen.CodegenType; import org.openapitools.codegen.SupportingFile; -import org.openapitools.codegen.templating.mustache.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -211,31 +209,6 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen { final String infrastructureFolder = (sourceFolder + File.separator + packageName + File.separator + "infrastructure").replace(".", File.separator); supportingFiles.add(new SupportingFile("ApiKeyAuth.kt.mustache", infrastructureFolder, "ApiKeyAuth.kt")); - - addMustacheLambdas(additionalProperties); - } - - private void addMustacheLambdas(Map<String, Object> objs) { - - Map<String, Mustache.Lambda> lambdas = new ImmutableMap.Builder<String, Mustache.Lambda>() - .put("lowercase", new LowercaseLambda().generator(this)) - .put("uppercase", new UppercaseLambda()) - .put("titlecase", new TitlecaseLambda()) - .put("camelcase", new CamelCaseLambda().generator(this)) - .put("indented", new IndentedLambda()) - .put("indented_8", new IndentedLambda(8, " ")) - .put("indented_12", new IndentedLambda(12, " ")) - .put("indented_16", new IndentedLambda(16, " ")) - .build(); - - if (objs.containsKey("lambda")) { - LOGGER.warn("A property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " + - "You'll likely need to use a custom template, " + - "see https://github.com/OpenAPITools/openapi-generator/blob/master/docs/templating.md. "); - objs.put("_lambda", lambdas); - } else { - objs.put("lambda", lambdas); - } } public static class Constants { diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java index 28e45eb7af4d2bdbc5f80b53a90e6682e39732e5..36c99c39a7088d46abd8d47f00e1ff8ddf3962e2 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java @@ -16,9 +16,11 @@ package org.openapitools.codegen.languages; -import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableMap.Builder; import com.samskivert.mustache.Mustache; import com.samskivert.mustache.Template; +import com.samskivert.mustache.Mustache.Lambda; + import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.media.Schema; import org.openapitools.codegen.*; @@ -51,7 +53,6 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen )); public static final String TITLE = "title"; - public static final String LAMBDA = "lambda"; public static final String SERVER_PORT = "serverPort"; public static final String BASE_PACKAGE = "basePackage"; public static final String SPRING_BOOT = "spring-boot"; @@ -370,22 +371,14 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen sanitizeDirectory(sourceFolder + File.separator + basePackage), "Application.kt")); } - addMustacheLambdas(additionalProperties); - // spring uses the jackson lib, and we disallow configuration. additionalProperties.put("jackson", "true"); } - private void addMustacheLambdas(final Map<String, Object> objs) { - Map<String, Mustache.Lambda> lambdas = - new ImmutableMap.Builder<String, Mustache.Lambda>() - .put("escapeDoubleQuote", new EscapeLambda("\"", "\\\"")) - .build(); - - if (objs.containsKey(LAMBDA)) { - LOGGER.warn("The lambda property is a reserved word, and will be overwritten!"); - } - objs.put(LAMBDA, lambdas); + @Override + protected Builder<String, Lambda> addMustacheLambdas() { + return super.addMustacheLambdas() + .put("escapeDoubleQuote", new EscapeLambda("\"", "\\\"")); } @Override diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OpenAPIYamlGenerator.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OpenAPIYamlGenerator.java index 5c46567fd940b631418e116906105c80d4f56029..ca1e91026643f347a767922a59b181e628d17280 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OpenAPIYamlGenerator.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/OpenAPIYamlGenerator.java @@ -18,21 +18,15 @@ package org.openapitools.codegen.languages; import org.openapitools.codegen.*; -import org.openapitools.codegen.templating.mustache.CamelCaseLambda; -import org.openapitools.codegen.templating.mustache.IndentedLambda; -import org.openapitools.codegen.templating.mustache.LowercaseLambda; -import org.openapitools.codegen.templating.mustache.TitlecaseLambda; -import org.openapitools.codegen.templating.mustache.UppercaseLambda; +import org.openapitools.codegen.templating.mustache.OnChangeLambda; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.collect.ImmutableMap; -import com.samskivert.mustache.Mustache; -import com.samskivert.mustache.Template; +import com.google.common.collect.ImmutableMap.Builder; +import com.samskivert.mustache.Mustache.Lambda; + import io.swagger.v3.oas.models.Operation; -import java.io.IOException; -import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -75,32 +69,12 @@ public class OpenAPIYamlGenerator extends DefaultCodegen implements CodegenConfi } LOGGER.info("Output file [outputFile={}]", outputFile); supportingFiles.add(new SupportingFile("openapi.mustache", outputFile)); - - addMustacheLambdas(additionalProperties); } - private void addMustacheLambdas(Map<String, Object> objs) { - - Map<String, Mustache.Lambda> lambdas = new ImmutableMap.Builder<String, Mustache.Lambda>() - .put("lowercase", new LowercaseLambda().generator(this)) - .put("uppercase", new UppercaseLambda()) - .put("titlecase", new TitlecaseLambda()) - .put("camelcase", new CamelCaseLambda().generator(this)) - .put("indented", new IndentedLambda()) - .put("indented_8", new IndentedLambda(8, " ")) - .put("indented_12", new IndentedLambda(12, " ")) - .put("indented_16", new IndentedLambda(16, " ")) - .put("onchange", new OnChangeLambda()) - .build(); - - if (objs.containsKey("lambda")) { - LOGGER.warn("A property named 'lambda' already exists. Mustache lambdas renamed from 'lambda' to '_lambda'. " + - "You'll likely need to use a custom template, " + - "see https://github.com/OpenAPITools/openapi-generator/blob/master/docs/templating.md. "); - objs.put("_lambda", lambdas); - } else { - objs.put("lambda", lambdas); - } + @Override + protected Builder<String, Lambda> addMustacheLambdas() { + return super.addMustacheLambdas() + .put("onchange", new OnChangeLambda()); } /** @@ -133,24 +107,4 @@ public class OpenAPIYamlGenerator extends DefaultCodegen implements CodegenConfi return input; } - /** - * Lambda writes current fragment to the output when it is different than - * previous fragment. - */ - public static class OnChangeLambda implements Mustache.Lambda { - private static final Logger LOGGER = LoggerFactory.getLogger(OnChangeLambda.class); - - private String lastVal = null; - - @Override - public void execute(Template.Fragment frag, Writer out) throws IOException { - String curVal = frag.execute(); - LOGGER.debug("[lastVal={}, curVal={}]", lastVal, curVal); - if (curVal != null && !curVal.equals(lastVal)) { - out.write(curVal); - lastVal = curVal; - } - } - } - } diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java index a30f0bd7972ccef8029ed5dfacccb3b0e64ca319..1f02cc989f4d662d4aba20a96d7e64b77a6ba64f 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/ScalaPlayFrameworkServerCodegen.java @@ -16,8 +16,9 @@ package org.openapitools.codegen.languages; -import com.google.common.collect.ImmutableMap; -import com.samskivert.mustache.Mustache; +import com.google.common.collect.ImmutableMap.Builder; +import com.samskivert.mustache.Mustache.Lambda; + import io.swagger.v3.oas.models.media.ArraySchema; import io.swagger.v3.oas.models.media.Schema; import org.openapitools.codegen.*; @@ -192,15 +193,12 @@ public class ScalaPlayFrameworkServerCodegen extends AbstractScalaCodegen implem supportingFiles.add(new SupportingFile("public/openapi.json.mustache", "public", "openapi.json")); supportingFiles.add(new SupportingFile("app/apiDocController.scala.mustache", String.format(Locale.ROOT, "app/%s", apiPackage.replace(".", File.separator)), "ApiDocController.scala")); } - addMustacheLambdas(additionalProperties); } - private void addMustacheLambdas(Map<String, Object> objs) { - Map<String, Mustache.Lambda> lambdas = new ImmutableMap.Builder<String, Mustache.Lambda>() - .put("indented_4", new IndentedLambda(4, " ")) - .put("indented_8", new IndentedLambda(8, " ")) - .build(); - objs.put("lambda", lambdas); + @Override + protected Builder<String, Lambda> addMustacheLambdas() { + return super.addMustacheLambdas() + .put("indented_4", new IndentedLambda(4, " ")); } @SuppressWarnings("unchecked") diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/templating/mustache/OnChangeLambda.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/templating/mustache/OnChangeLambda.java new file mode 100644 index 0000000000000000000000000000000000000000..11efbfae5bb3192f7b2dbd8f93445953d438c290 --- /dev/null +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/templating/mustache/OnChangeLambda.java @@ -0,0 +1,40 @@ +package org.openapitools.codegen.templating.mustache; + +import java.io.IOException; +import java.io.Writer; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.samskivert.mustache.Mustache; +import com.samskivert.mustache.Template; + +/** + * Lambda writes current fragment to the output when it is different than + * the previous fragment. + * + * Register: + * <pre> + * additionalProperties.put("onchange", new OnChangeLambda()); + * </pre> + * + * Use: + * <pre> + * {{#onchange}}{{name}}{{/onchange}} + * </pre> + */ +public class OnChangeLambda implements Mustache.Lambda { + private static final Logger LOGGER = LoggerFactory.getLogger(OnChangeLambda.class); + + private String lastVal = null; + + @Override + public void execute(Template.Fragment frag, Writer out) throws IOException { + String curVal = frag.execute(); + LOGGER.debug("[lastVal={}, curVal={}]", lastVal, curVal); + if (curVal != null && !curVal.equals(lastVal)) { + out.write(curVal); + lastVal = curVal; + } + } +} \ No newline at end of file