Skip to content

Kotlin model name camelize #2430

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Mar 24, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -597,10 +597,7 @@ private String getArrayTypeDeclaration(ArraySchema arr) {
private String sanitizeKotlinSpecificNames(final String name) {
String word = name;
for (Map.Entry<String, String> specialCharacters : specialCharReplacements.entrySet()) {
// Underscore is the only special character we'll allow
if (!specialCharacters.getKey().equals("_")) {
word = word.replaceAll("\\Q" + specialCharacters.getKey() + "\\E", specialCharacters.getValue());
}
word = replaceSpecialCharacters(word, specialCharacters);
}

// Fallback, replace unknowns with underscore.
Expand All @@ -617,6 +614,38 @@ private String sanitizeKotlinSpecificNames(final String name) {
return word;
}

private String replaceSpecialCharacters(String word, Map.Entry<String, String> specialCharacters) {
String specialChar = specialCharacters.getKey();
String replacementChar = specialCharacters.getValue();
// Underscore is the only special character we'll allow
if (!specialChar.equals("_") && word.contains(specialChar)) {
return replaceCharacters(word, specialChar, replacementChar);
}
return word;
}

private String replaceCharacters(String word, String oldValue, String newValue) {
if (!word.contains(oldValue)) {
return word;
}
if ( word.equals(oldValue)) {
return newValue;
}
int i = word.indexOf(oldValue);
String start = word.substring(0, i);
String end = recurseOnEndOfWord(word, oldValue, newValue, i);
return start + newValue + end;
}

private String recurseOnEndOfWord(String word, String oldValue, String newValue, int lastReplacedValue) {
String end = word.substring(lastReplacedValue + 1);
if (!end.isEmpty()) {
end = titleCase(end);
end = replaceCharacters(end, oldValue, newValue);
}
return end;
}

private String titleCase(final String input) {
return input.substring(0, 1).toUpperCase(Locale.ROOT) + input.substring(1);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ public class StringUtils {
* @param word The word
* @return The underscored version of the word
*/
public static String underscore(String word) {
public static String underscore(final String word) {
String firstPattern = "([A-Z]+)([A-Z][a-z])";
String secondPattern = "([a-z\\d])([A-Z])";
String replacementPattern = "$1_$2";
// Replace package separator with slash.
word = word.replaceAll("\\.", "/"); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
String result = word.replaceAll("\\.", "/");
// Replace $ with two underscores for inner classes.
word = word.replaceAll("\\$", "__");
result = result.replaceAll("\\$", "__");
// Replace capital letter with _ plus lowercase letter.
word = word.replaceAll(firstPattern, replacementPattern);
word = word.replaceAll(secondPattern, replacementPattern);
word = word.replace('-', '_');
result = result.replaceAll(firstPattern, replacementPattern);
result = result.replaceAll(secondPattern, replacementPattern);
result = result.replace('-', '_');
// replace space with underscore
word = word.replace(' ', '_');
word = word.toLowerCase(Locale.ROOT);
return word;
result = result.replace(' ', '_');
result = result.toLowerCase(Locale.ROOT);
return result;
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,17 +85,24 @@ public void isDataTypeString(){
}

@Test
public void toModelNameShouldUseProvidedMapping() throws Exception {
public void toModelNameShouldUseProvidedMapping() {
codegen.importMapping().put("json_myclass", "com.test.MyClass");
assertEquals("com.test.MyClass", codegen.toModelName("json_myclass"));
}

@Test
public void convertModelName() throws Exception {
public void convertModelNameTitleCase() {
assertEquals(codegen.toModelName("name"), "Name");
assertEquals(codegen.toModelName("$name"), "Dollarname");
assertEquals(codegen.toModelName("nam#e"), "NamHashe");
assertEquals(codegen.toModelName("$another-fake?"), "DollaranotherMinusfakeQuestionMark");
}

@Test
public void escapeSpecialCharactersCamelize() {
assertEquals(codegen.toModelName("$"), "Dollar");
assertEquals(codegen.toModelName("$$"), "DollarDollar");
assertEquals(codegen.toModelName("Pony?"), "PonyQuestionMark");
assertEquals(codegen.toModelName("$name"), "DollarName");
assertEquals(codegen.toModelName("nam#e"), "NamHashE");
assertEquals(codegen.toModelName("$another-fake?"), "DollarAnotherMinusFakeQuestionMark");
assertEquals(codegen.toModelName("Pony>=>="), "PonyGreaterThanEqualGreaterThanEqual");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,15 @@

import static org.openapitools.codegen.utils.StringUtils.camelize;
import static org.openapitools.codegen.utils.StringUtils.dashize;
import static org.openapitools.codegen.utils.StringUtils.underscore;

public class StringUtilsTest {
// we'll assume that <i>underscore</i> (Twitter elephant bird) works fine
@Test
public void testUnderscore() {
Assert.assertEquals(underscore("abcd"), "abcd");
Assert.assertEquals(underscore("abCd"), "ab_cd");
}

@Test
public void testCamelize() throws Exception {
Expand Down
10 changes: 10 additions & 0 deletions samples/openapi3/client/petstore/kotlin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ Class | Method | HTTP request | Description
------------ | ------------- | ------------- | -------------
*AnotherFakeApi* | [**call123testSpecialTags**](docs/AnotherFakeApi.md#call123testspecialtags) | **PATCH** /another-fake/dummy | To test special tags
*DefaultApi* | [**fooGet**](docs/DefaultApi.md#fooget) | **GET** /foo |
*FakeApi* | [**fakeHealthGet**](docs/FakeApi.md#fakehealthget) | **GET** /fake/health | Health check endpoint
*FakeApi* | [**fakeOuterBooleanSerialize**](docs/FakeApi.md#fakeouterbooleanserialize) | **POST** /fake/outer/boolean |
*FakeApi* | [**fakeOuterCompositeSerialize**](docs/FakeApi.md#fakeoutercompositeserialize) | **POST** /fake/outer/composite |
*FakeApi* | [**fakeOuterNumberSerialize**](docs/FakeApi.md#fakeouternumberserialize) | **POST** /fake/outer/number |
Expand Down Expand Up @@ -95,6 +96,7 @@ Class | Method | HTTP request | Description
- [org.openapitools.client.models.Foo](docs/Foo.md)
- [org.openapitools.client.models.FormatTest](docs/FormatTest.md)
- [org.openapitools.client.models.HasOnlyReadOnly](docs/HasOnlyReadOnly.md)
- [org.openapitools.client.models.HealthCheckResult](docs/HealthCheckResult.md)
- [org.openapitools.client.models.InlineObject](docs/InlineObject.md)
- [org.openapitools.client.models.InlineObject1](docs/InlineObject1.md)
- [org.openapitools.client.models.InlineObject2](docs/InlineObject2.md)
Expand All @@ -111,6 +113,9 @@ Class | Method | HTTP request | Description
- [org.openapitools.client.models.Order](docs/Order.md)
- [org.openapitools.client.models.OuterComposite](docs/OuterComposite.md)
- [org.openapitools.client.models.OuterEnum](docs/OuterEnum.md)
- [org.openapitools.client.models.OuterEnumDefaultValue](docs/OuterEnumDefaultValue.md)
- [org.openapitools.client.models.OuterEnumInteger](docs/OuterEnumInteger.md)
- [org.openapitools.client.models.OuterEnumIntegerDefaultValue](docs/OuterEnumIntegerDefaultValue.md)
- [org.openapitools.client.models.Pet](docs/Pet.md)
- [org.openapitools.client.models.ReadOnlyFirst](docs/ReadOnlyFirst.md)
- [org.openapitools.client.models.Return](docs/Return.md)
Expand All @@ -136,6 +141,11 @@ Class | Method | HTTP request | Description
- **API key parameter name**: api_key_query
- **Location**: URL query string

<a name="bearer_test"></a>
### bearer_test

- **Type**: HTTP basic authentication

<a name="http_basic_test"></a>
### http_basic_test

Expand Down
4 changes: 2 additions & 2 deletions samples/openapi3/client/petstore/kotlin/docs/EnumClass.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@

* `abc` (value: `"_abc"`)

* `minusefg` (value: `"-efg"`)
* `minusEfg` (value: `"-efg"`)

* `leftParenthesisxyzRightParenthesis` (value: `"(xyz)"`)
* `leftParenthesisXyzRightParenthesis` (value: `"(xyz)"`)



Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ Name | Type | Description | Notes
**enumInteger** | [**inline**](#EnumIntegerEnum) | | [optional]
**enumNumber** | [**inline**](#EnumNumberEnum) | | [optional]
**outerEnum** | [**OuterEnum**](OuterEnum.md) | | [optional]
**outerEnumInteger** | [**OuterEnumInteger**](OuterEnumInteger.md) | | [optional]
**outerEnumDefaultValue** | [**OuterEnumDefaultValue**](OuterEnumDefaultValue.md) | | [optional]
**outerEnumIntegerDefaultValue** | [**OuterEnumIntegerDefaultValue**](OuterEnumIntegerDefaultValue.md) | | [optional]


<a name="EnumStringEnum"></a>
Expand Down
48 changes: 45 additions & 3 deletions samples/openapi3/client/petstore/kotlin/docs/FakeApi.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ All URIs are relative to *http://petstore.swagger.io:80/v2*

Method | HTTP request | Description
------------- | ------------- | -------------
[**fakeHealthGet**](FakeApi.md#fakeHealthGet) | **GET** /fake/health | Health check endpoint
[**fakeOuterBooleanSerialize**](FakeApi.md#fakeOuterBooleanSerialize) | **POST** /fake/outer/boolean |
[**fakeOuterCompositeSerialize**](FakeApi.md#fakeOuterCompositeSerialize) | **POST** /fake/outer/composite |
[**fakeOuterNumberSerialize**](FakeApi.md#fakeOuterNumberSerialize) | **POST** /fake/outer/number |
Expand All @@ -18,6 +19,47 @@ Method | HTTP request | Description
[**testJsonFormData**](FakeApi.md#testJsonFormData) | **GET** /fake/jsonFormData | test json serialization of form data


<a name="fakeHealthGet"></a>
# **fakeHealthGet**
> HealthCheckResult fakeHealthGet()

Health check endpoint

### Example
```kotlin
// Import classes:
//import org.openapitools.client.infrastructure.*
//import org.openapitools.client.models.*

val apiInstance = FakeApi()
try {
val result : HealthCheckResult = apiInstance.fakeHealthGet()
println(result)
} catch (e: ClientException) {
println("4xx response calling FakeApi#fakeHealthGet")
e.printStackTrace()
} catch (e: ServerException) {
println("5xx response calling FakeApi#fakeHealthGet")
e.printStackTrace()
}
```

### Parameters
This endpoint does not need any parameter.

### Return type

[**HealthCheckResult**](HealthCheckResult.md)

### Authorization

No authorization required

### HTTP request headers

- **Content-Type**: Not defined
- **Accept**: application/json

<a name="fakeOuterBooleanSerialize"></a>
# **fakeOuterBooleanSerialize**
> kotlin.Boolean fakeOuterBooleanSerialize(body)
Expand Down Expand Up @@ -127,7 +169,7 @@ Test serialization of outer number types
//import org.openapitools.client.models.*

val apiInstance = FakeApi()
val body : java.math.BigDecimal = 1.2 // java.math.BigDecimal | Input number as post body
val body : java.math.BigDecimal = 8.14 // java.math.BigDecimal | Input number as post body
try {
val result : java.math.BigDecimal = apiInstance.fakeOuterNumberSerialize(body)
println(result)
Expand Down Expand Up @@ -360,7 +402,7 @@ Fake endpoint for testing various parameters 假端點 偽のエンドポイン
//import org.openapitools.client.models.*

val apiInstance = FakeApi()
val number : java.math.BigDecimal = 1.2 // java.math.BigDecimal | None
val number : java.math.BigDecimal = 8.14 // java.math.BigDecimal | None
val double : kotlin.Double = 1.2 // kotlin.Double | None
val patternWithoutDelimiter : kotlin.String = patternWithoutDelimiter_example // kotlin.String | None
val byte : kotlin.ByteArray = BYTE_ARRAY_DATA_HERE // kotlin.ByteArray | None
Expand Down Expand Up @@ -526,7 +568,7 @@ null (empty response body)

### Authorization

No authorization required
[bearer_test](../README.md#bearer_test)

### HTTP request headers

Expand Down
10 changes: 10 additions & 0 deletions samples/openapi3/client/petstore/kotlin/docs/HealthCheckResult.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

# HealthCheckResult

## Properties
Name | Type | Description | Notes
------------ | ------------- | ------------- | -------------
**nullableMessage** | **kotlin.String** | | [optional]



Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

# OuterEnumDefaultValue

## Enum


* `placed` (value: `"placed"`)

* `approved` (value: `"approved"`)

* `delivered` (value: `"delivered"`)



14 changes: 14 additions & 0 deletions samples/openapi3/client/petstore/kotlin/docs/OuterEnumInteger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

# OuterEnumInteger

## Enum


* `_0` (value: `0`)

* `_1` (value: `1`)

* `_2` (value: `2`)



Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

# OuterEnumIntegerDefaultValue

## Enum


* `_0` (value: `0`)

* `_1` (value: `1`)

* `_2` (value: `2`)



Binary file not shown.

This file was deleted.

Loading