Skip to content
Closed
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
1 change: 1 addition & 0 deletions bin/elm-petstore-all.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@

./bin/elm-0.18-petstore.sh
./bin/elm-petstore.sh
./bin/openapi3/elm-petstore.sh

4 changes: 2 additions & 2 deletions bin/openapi3/elm-petstore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"

if [ ! -f "$executable" ]
then
mvn clean package
mvn -B clean package
fi

# if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -i modules/openapi-generator/src/test/resources/3_0/petstore.yaml -g elm -o samples/client/petstore/elm $@"
ags="generate -i modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml -g elm -t modules/openapi-generator/src/main/resources/elm -o samples/openapi3/client/petstore/elm --additional-properties prefixCustomTypeVariants=true $@"

java $JAVA_OPTS -jar $executable $ags
Original file line number Diff line number Diff line change
Expand Up @@ -58,16 +58,19 @@
public class ElmClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(ElmClientCodegen.class);
private Set<String> customPrimitives = new HashSet<String>();
private Map<String, String> reservedCharacters = new HashMap<>();
private ElmVersion elmVersion = ElmVersion.ELM_019;

private static final String ELM_VERSION = "elmVersion";
private static final String PREFIX_CUSTOM_TYPE_VARIANTS = "prefixCustomTypeVariants";
private static final String ENCODER = "elmEncoder";
private static final String DECODER = "elmDecoder";
private static final String DISCRIMINATOR_NAME = "discriminatorName";
private static final String UNION_TYPE = "elmUnionType";

protected String packageName = "openapi";
protected String packageVersion = "1.0.0";
protected Boolean prefixCustomTypeVariants = false;

public CodegenType getTag() {
return CodegenType.CLIENT;
Expand Down Expand Up @@ -146,11 +149,36 @@ public ElmClientCodegen() {
typeMapping.put("date", "DateOnly");
typeMapping.put("DateTime", "DateTime");
typeMapping.put("password", "String");
typeMapping.put("UUID", "String");
typeMapping.put("file", "String");
typeMapping.put("ByteArray", "Byte");
typeMapping.put("binary", "String");

reservedCharacters.clear();
reservedCharacters.put(";", "Semicolon");
reservedCharacters.put("/", "Slash");
reservedCharacters.put("?", "QuestionMark");
reservedCharacters.put(":", "Colon");
reservedCharacters.put("@", "At");
reservedCharacters.put("&", "Ampersand");
reservedCharacters.put("=;", "Equal");
reservedCharacters.put("+", "Plus");
reservedCharacters.put("$", "Dollar");
reservedCharacters.put(",", "Comma");
reservedCharacters.put("_", "_");
reservedCharacters.put(".", "Dot");
reservedCharacters.put("!", "ExclamationMark");
reservedCharacters.put("~", "Tilde");
reservedCharacters.put("*", "Asterisk");
reservedCharacters.put("(", "");
reservedCharacters.put(")", "");
reservedCharacters.put("[", "");
reservedCharacters.put("]", "");
reservedCharacters.put("<", "LessThan");
reservedCharacters.put(">", "GreaterThan");

importMapping.clear();
// TODO DateTime, DateOnly, Byte ???

cliOptions.clear();

Expand All @@ -160,13 +188,14 @@ public ElmClientCodegen() {
supportedVersions.put("0.19", "Elm 0.19");
elmVersion.setEnum(supportedVersions);
cliOptions.add(elmVersion);
final CliOption prefixCustomTypeVariants = CliOption.newBoolean(PREFIX_CUSTOM_TYPE_VARIANTS, "Prefix custom type variants");
cliOptions.add(prefixCustomTypeVariants);
}

@Override
public void processOpts() {
super.processOpts();


if (additionalProperties.containsKey(ELM_VERSION)) {
final String version = (String) additionalProperties.get(ELM_VERSION);
if ("0.18".equals(version)) {
Expand All @@ -176,6 +205,10 @@ public void processOpts() {
}
}

if (additionalProperties.containsKey(PREFIX_CUSTOM_TYPE_VARIANTS)) {
prefixCustomTypeVariants = "true".equals(additionalProperties.get(PREFIX_CUSTOM_TYPE_VARIANTS));
}

if (StringUtils.isEmpty(System.getenv("ELM_POST_PROCESS_FILE"))) {
if (elmVersion.equals(ElmVersion.ELM_018)) { // 0.18
LOGGER.info("Environment variable ELM_POST_PROCESS_FILE not defined so the Elm code may not be properly formatted. To define it, try `export ELM_POST_PROCESS_FILE=\"/usr/local/bin/elm-format --elm-version={} --yes\"` (Linux/Mac)", "0.18");
Expand Down Expand Up @@ -220,6 +253,20 @@ public String escapeQuotationMark(String input) {
return input.replace("\"", "");
}

@Override
public String removeNonNameElementToCamelCase(final String name) {
if (StringUtils.isEmpty(name)) {
return "";
}
String prefixed;
if (Character.isLetter(name.charAt(0))) {
prefixed = name;
} else {
prefixed = "N" + name;
}
return removeNonNameElementToCamelCase(prefixed.replace('.', '_').replace('-', '_').replace('[', '_').replace(']', '_'), "[:;&#$@%(){}<>=-]");
}

@Override
public String toApiName(String name) {
if (name.length() == 0) {
Expand All @@ -231,6 +278,9 @@ public String toApiName(String name) {
@Override
public String toModelName(String name) {
final String modelName = org.openapitools.codegen.utils.StringUtils.camelize(name);
if (!Character.isUpperCase(modelName.charAt(0))) {
return "N" + modelName;
}
return defaultIncludes.contains(modelName) ? modelName + "_" : modelName;
}

Expand All @@ -246,17 +296,25 @@ public String toEnumName(CodegenProperty property) {

@Override
public String toVarName(String name) {
final String varName = org.openapitools.codegen.utils.StringUtils.camelize(name, true);
return isReservedWord(varName) ? escapeReservedWord(name) : varName;
final String escaped = name == null ? "" : removeNonNameElementToCamelCase(name);
if ("".equals(escaped)) {
return "";
}
final String varName = escaped.substring(0, 1).toLowerCase(Locale.ROOT) + (escaped.length() > 1 ? escaped.substring(1) : "");
return isReservedWord(varName) ? escapeReservedWord(varName) : varName;
}

@Override
public String toEnumVarName(String value, String datatype) {
final String camelized = org.openapitools.codegen.utils.StringUtils.camelize(value.replace(" ", "_").replace("(", "_").replace(")", "")); // TODO FIXME escape properly
if (!Character.isUpperCase(camelized.charAt(0))) {
return "N" + camelized;
String name = value;
for (Map.Entry<String, String> entry : reservedCharacters.entrySet()) {
name = name.replace(entry.getKey(), entry.getValue());
}
final String varName = toVarName(name);
if ("".equals(varName)) {
return "Empty";
}
return camelized;
return varName.substring(0, 1).toUpperCase(Locale.ROOT) + (varName.length() > 1 ? varName.substring(1) : "");
}

@Override
Expand Down Expand Up @@ -337,6 +395,9 @@ public int compare(CodegenModel cm1, CodegenModel cm2) {
if (cm.isEnum) {
addEncoderAndDecoder(cm.vendorExtensions, cm.classname, DataTypeExposure.EXPOSED);
cm.vendorExtensions.put(UNION_TYPE, cm.classname);
if (prefixCustomTypeVariants) {
addCustomTypeVariantsPrefix(cm.classname, cm.allowableValues);
}
} else if (cm.isAlias) {
addEncoderAndDecoder(cm.vendorExtensions, cm.dataType, DataTypeExposure.EXPOSED);
}
Expand Down Expand Up @@ -539,6 +600,9 @@ public CodegenProperty fromProperty(String name, Schema p) {
if (property.isEnum) {
addEncoderAndDecoder(property.vendorExtensions, property.baseName, DataTypeExposure.INTERNAL);
property.vendorExtensions.put(UNION_TYPE, property.datatypeWithEnum);
if (prefixCustomTypeVariants) {
addCustomTypeVariantsPrefix(property.datatypeWithEnum, property.allowableValues);
}
} else {
final boolean isPrimitiveType = property.isMapContainer ? isPrimitiveDataType(property.dataType) : property.isPrimitiveType;
addEncoderAndDecoder(property.vendorExtensions, property.dataType, isPrimitiveType ? DataTypeExposure.PRIMITIVE : DataTypeExposure.EXTERNAL);
Expand All @@ -563,6 +627,16 @@ public void postProcessParameter(CodegenParameter parameter) {
addEncoderAndDecoder(parameter.vendorExtensions, parameter.dataType, isPrimitiveType ? DataTypeExposure.PRIMITIVE : DataTypeExposure.EXTERNAL);
}

private void addCustomTypeVariantsPrefix(final String prefix, final Map<String, Object> allowableValues) {
List<Map<String, Object>> enumVars = (ArrayList<Map<String, Object>>) allowableValues.get("enumVars");
if (enumVars == null) {
return;
}
for (Map<String, Object> enumVar : enumVars) {
enumVar.put("name", prefix + enumVar.get("name"));
}
}

private boolean isPrimitiveDataType(String dataType) {
return languageSpecificPrimitives.contains(dataType);
}
Expand Down
10 changes: 5 additions & 5 deletions modules/openapi-generator/src/main/resources/elm/Byte.mustache
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
module Byte exposing (Byte, byteDecoder, byteEncoder)
module Byte exposing (Byte, decoder, encoder)

import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode
Expand All @@ -8,11 +8,11 @@ type alias Byte =
String


byteDecoder : Decoder Byte
byteDecoder =
decoder : Decoder Byte
decoder =
Decode.string


byteEncoder : Byte -> Encode.Value
byteEncoder model =
encoder : Byte -> Encode.Value
encoder model =
Encode.string model
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ module Request.{{classname}} exposing ({{#operations}}{{#operation}}{{^-first}},
{{>imports}}import Dict
import Http
import Json.Decode as Decode
import Json.Encode as Encode


basePath : String
Expand Down
1 change: 1 addition & 0 deletions samples/openapi3/client/petstore/elm/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/elm-stuff
23 changes: 23 additions & 0 deletions samples/openapi3/client/petstore/elm/.openapi-generator-ignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator

# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.

# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs

# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux

# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux

# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.3.0-SNAPSHOT
10 changes: 10 additions & 0 deletions samples/openapi3/client/petstore/elm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# Elm API client

This spec is mainly for testing Petstore server and contains fake endpoints, models. Please do not use this for any other purpose. Special characters: \" \\

## Overview
This API client was generated by the [OpenAPI Generator](https://openapi-generator.tech) project. By using the [openapi-spec](https://github.com/OAI/OpenAPI-Specification) from a remote server, you can easily generate an API client.

- API version: 1.0.0
- Package version:
- Build package: org.openapitools.codegen.languages.ElmClientCodegen
14 changes: 14 additions & 0 deletions samples/openapi3/client/petstore/elm/elm-compile-test
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash -e
# elm make all elm files under src

for ELM in `find src -name "*.elm"`
do
echo "Compiling $ELM"
elm make $ELM --output /dev/null
rc=$?
if [[ $rc != 0 ]]
then
echo "ERROR!! FAILED TO COMPILE $ELM"
exit $rc;
fi
done
28 changes: 28 additions & 0 deletions samples/openapi3/client/petstore/elm/elm.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"type": "application",
"source-directories": [
"src"
],
"elm-version": "0.19.0",
"dependencies": {
"direct": {
"NoRedInk/elm-json-decode-pipeline": "1.0.0",
"elm/browser": "1.0.0",
"elm/core": "1.0.0",
"elm/html": "1.0.0",
"elm/http": "1.0.0",
"elm/json": "1.0.0",
"elm/time": "1.0.0",
"rtfeldman/elm-iso8601-date-strings": "1.0.0"
},
"indirect": {
"elm/parser": "1.0.0",
"elm/url": "1.0.0",
"elm/virtual-dom": "1.0.0"
}
},
"test-dependencies": {
"direct": {},
"indirect": {}
}
}
43 changes: 43 additions & 0 deletions samples/openapi3/client/petstore/elm/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>org.openapitools</groupId>
<artifactId>ElmClientTests</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<name>Elm AllOf Client</name>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>bundle-test</id>
<phase>integration-test</phase>
<goals>
<goal>exec</goal>
</goals>
<configuration>
<executable>./elm-compile-test</executable>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
18 changes: 18 additions & 0 deletions samples/openapi3/client/petstore/elm/src/Byte.elm
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Byte exposing (Byte, decoder, encoder)

import Json.Decode as Decode exposing (Decoder)
import Json.Encode as Encode


type alias Byte =
String


decoder : Decoder Byte
decoder =
Decode.string


encoder : Byte -> Encode.Value
encoder model =
Encode.string model
Loading