From 37be47fc5664a9710d4d9d48608bd29679fc4acd Mon Sep 17 00:00:00 2001 From: Marvin Date: Tue, 24 Jul 2018 12:41:18 +0200 Subject: [PATCH] [Java] Escaping properties for java (#628) --- .../openapitools/codegen/DefaultCodegen.java | 30 +++++++++++++++++++ .../languages/AbstractJavaCodegen.java | 8 +++++ .../codegen/java/JavaModelTest.java | 25 ++++++++++++++++ 3 files changed, 63 insertions(+) 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 d7a04d25312..ae2d2a6fc3d 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 @@ -761,6 +761,8 @@ public class DefaultCodegen implements CodegenConfig { public String toVarName(String name) { if (reservedWords.contains(name)) { return escapeReservedWord(name); + } else if (((CharSequence) name).chars().anyMatch(character -> specialCharReplacements.keySet().contains( "" + ((char) character)))) { + return escapeSpecialCharacters(name, null, null); } else { return name; } @@ -777,6 +779,8 @@ public class DefaultCodegen implements CodegenConfig { name = removeNonNameElementToCamelCase(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. if (reservedWords.contains(name)) { return escapeReservedWord(name); + } else if (((CharSequence) name).chars().anyMatch(character -> specialCharReplacements.keySet().contains( "" + ((char) character)))) { + return escapeSpecialCharacters(name, null, null); } return name; } @@ -815,6 +819,32 @@ public class DefaultCodegen implements CodegenConfig { throw new RuntimeException("reserved word " + name + " not allowed"); } + /** + * Return the name with escaped characters. + * + * @param name the name to be escaped + * @param charactersToAllow characters that are not escaped + * @param appdendixToReplacement String to append to replaced characters. + * @return the escaped word + *

+ * throws Runtime exception as word is not escaped properly. + */ + public String escapeSpecialCharacters(String name, List charactersToAllow, String appdendixToReplacement) { + String result = (String) ((CharSequence) name).chars().mapToObj(c -> { + String character = "" + (char) c; + if (charactersToAllow != null && charactersToAllow.contains(character)) { + return character; + } else if (specialCharReplacements.containsKey(character)) { + return specialCharReplacements.get(character) + (appdendixToReplacement != null ? appdendixToReplacement: ""); + } else { + return character; + } + }).reduce( (c1, c2) -> "" + c1 + c2).orElse(null); + + if (result != null) return result; + throw new RuntimeException("Word '" + name + "' could not be escaped."); + } + /** * Return the fully-qualified "Model" name for import * diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java index 85feab0ca1c..3f7d014a3ca 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractJavaCodegen.java @@ -574,6 +574,14 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code name = name.substring(0, 2).toLowerCase() + name.substring(2); } + // If name contains special chars -> replace them. + if ((((CharSequence) name).chars().anyMatch(character -> specialCharReplacements.keySet().contains( "" + ((char) character))))) { + List allowedCharacters = new ArrayList<>(); + allowedCharacters.add("_"); + allowedCharacters.add("$"); + name = escapeSpecialCharacters(name, allowedCharacters, "_"); + } + // camelize (lower first character) the variable name // pet_id => petId name = camelize(name, true); diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaModelTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaModelTest.java index b54a8bf2ebb..54dc3b0cd63 100644 --- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaModelTest.java +++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/java/JavaModelTest.java @@ -242,6 +242,31 @@ public class JavaModelTest { Assert.assertTrue(property.isContainer); } + @Test(description = "convert a model with restriced characters") + public void restrictedCharactersPropertiesTest() { + final Schema schema = new Schema() + .description("a sample model") + .addProperties("@Some:restricted%characters#to!handle+", new BooleanSchema()); + final DefaultCodegen codegen = new JavaClientCodegen(); + final CodegenModel cm = codegen.fromModel("sample", schema, Collections.singletonMap("sample", schema)); + + Assert.assertEquals(cm.name, "sample"); + Assert.assertEquals(cm.classname, "Sample"); + Assert.assertEquals(cm.description, "a sample model"); + Assert.assertEquals(cm.vars.size(), 1); + + final CodegenProperty property = cm.vars.get(0); + Assert.assertEquals(property.baseName, "@Some:restricted%characters#to!handle+"); + Assert.assertEquals(property.getter, "getAtSomeColonRestrictedPercentCharactersHashToExclamationHandlePlus"); + Assert.assertEquals(property.setter, "setAtSomeColonRestrictedPercentCharactersHashToExclamationHandlePlus"); + Assert.assertEquals(property.dataType, "Boolean"); + Assert.assertEquals(property.name, "atSomeColonRestrictedPercentCharactersHashToExclamationHandlePlus"); + Assert.assertEquals(property.defaultValue, "null"); + Assert.assertEquals(property.baseType, "Boolean"); + Assert.assertFalse(property.required); + Assert.assertTrue(property.isNotContainer); + } + @Test(description = "convert a model with complex properties") public void complexPropertiesTest() { final Schema schema = new Schema()