Skip to content
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
28 changes: 27 additions & 1 deletion template/libraries/jersey3/api.mustache
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,42 @@ public class {{classname}} {
{{^required}}
/**
* getter for {{paramName}} - {{{description}}}
{{#vendorExtensions.x-aliased-parameter-name}}
*
* @see {@link #get{{#lambda.pascalcase}}{{vendorExtensions.x-aliased-parameter-name}}{{/lambda.pascalcase}}}
{{/vendorExtensions.x-aliased-parameter-name}}
{{#vendorExtensions.x-parameter-alias}}
*
* @see {@link #get{{#lambda.pascalcase}}{{vendorExtensions.x-parameter-alias}}{{/lambda.pascalcase}}}
{{/vendorExtensions.x-parameter-alias}}
*/
public {{{dataType}}} get{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}() {
return {{paramName}};
}

/**
* setter for {{paramName}} - {{{description}}}
{{#vendorExtensions.x-aliased-parameter-name}}
*
* {{paramName}} is an alias for {{#lambda.camelcase}}{{vendorExtensions.x-aliased-parameter-name}}{{/lambda.camelcase}}. Invoking {@link #set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}} will also set `{{#lambda.camelcase}}{{vendorExtensions.x-aliased-parameter-name}}{{/lambda.camelcase}}` to `null` to clear an existing `{{#lambda.camelcase}}{{vendorExtensions.x-aliased-parameter-name}}{{/lambda.camelcase}}` parameter value.
*
* @see {@link #set{{#lambda.pascalcase}}{{vendorExtensions.x-aliased-parameter-name}}{{/lambda.pascalcase}}}
{{/vendorExtensions.x-aliased-parameter-name}}
{{#vendorExtensions.x-parameter-alias}}
*
* {{paramName}} is an alias for {{#lambda.camelcase}}{{vendorExtensions.x-parameter-alias}}{{/lambda.camelcase}}. Invoking {@link #set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}} will also set `{{#lambda.camelcase}}{{vendorExtensions.x-parameter-alias}}{{/lambda.camelcase}}` to `null` to clear an existing `{{#lambda.camelcase}}{{vendorExtensions.x-parameter-alias}}{{/lambda.camelcase}}` parameter value.
*
* @see {@link #set{{#lambda.pascalcase}}{{vendorExtensions.x-parameter-alias}}{{/lambda.pascalcase}}}
{{/vendorExtensions.x-parameter-alias}}
Comment thread
mcnulty-fp marked this conversation as resolved.
*/
public {{operationIdCamelCase}}OptionalParams set{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}({{{dataType}}} {{paramName}}) {
this.{{paramName}} = {{paramName}};
{{#vendorExtensions.x-aliased-parameter-name}}
this.{{#lambda.camelcase}}{{vendorExtensions.x-aliased-parameter-name}}{{/lambda.camelcase}} = null;
{{/vendorExtensions.x-aliased-parameter-name}}
{{#vendorExtensions.x-parameter-alias}}
this.{{#lambda.camelcase}}{{vendorExtensions.x-parameter-alias}}{{/lambda.camelcase}} = null;
{{/vendorExtensions.x-parameter-alias}}
return this;
}

Expand Down Expand Up @@ -228,7 +254,7 @@ public class {{classname}} {
if ({{operationId}}OptionalParams != null) {
{{#queryParams}}
{{^required}}
localVarQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", "{{baseName}}", {{operationId}}OptionalParams.get{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}()));
localVarQueryParams.addAll(apiClient.parameterToPairs("{{{collectionFormat}}}", "{{#vendorExtensions.x-aliased-parameter-name}}{{vendorExtensions.x-aliased-parameter-name}}{{/vendorExtensions.x-aliased-parameter-name}}{{^vendorExtensions.x-aliased-parameter-name}}{{baseName}}{{/vendorExtensions.x-aliased-parameter-name}}", {{operationId}}OptionalParams.get{{#lambda.titlecase}}{{paramName}}{{/lambda.titlecase}}()));
{{/required}}
Comment thread
mcnulty-fp marked this conversation as resolved.
{{/queryParams}}
}
Expand Down
226 changes: 224 additions & 2 deletions template/libraries/jersey3/oneof_model.mustache
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}}
{{#discriminator}}
{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}}
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
Expand Down Expand Up @@ -297,5 +297,227 @@ public interface {{classname}}{{#vendorExtensions.x-implements}} extends {{{.}}}
}
{{/discriminator}}
{{^discriminator}}
// No model generated. The oneof_model template requires the schema to use the discriminator construct.
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
import java.time.OffsetDateTime;
import java.util.Locale;
Comment thread
mcnulty-fp marked this conversation as resolved.
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;

{{>additionalModelTypeAnnotations}}{{>generatedAnnotation}}{{>xmlAnnotation}}
@JsonDeserialize(using = {{classname}}.{{classname}}Deserializer.class)
@JsonSerialize(using = {{classname}}.{{classname}}Serializer.class)
public final class {{classname}} {
private static final Logger log = Logger.getLogger({{classname}}.class.getName());

{{#isNullable}}
@{{javaxPackage}}.annotation.Nullable
{{/isNullable}}
{{^isNullable}}
@{{javaxPackage}}.annotation.Nonnull
{{/isNullable}}
private final Object value;

private {{classname}}(Object o) {
{{#isNullable}}
this.value = o;
{{/isNullable}}
{{^isNullable}}
this.value = Objects.requireNonNull(o);
{{/isNullable}}
}

{{#composedSchemas}}
{{#oneOf}}
public {{classname}}({{{baseType}}} o) {
{{#isNullable}}
this.value = o;
{{/isNullable}}
{{^isNullable}}
this.value = Objects.requireNonNull(o);
{{/isNullable}}
Comment thread
mcnulty-fp marked this conversation as resolved.
}
{{/oneOf}}
{{/composedSchemas}}

{{#composedSchemas}}
{{#oneOf}}
/**
* Get the value of `{{{classname}}}` as an instance of `{{{dataType}}}`. If the value is not `{{{dataType}}}`, a ClassCastException will be thrown.
*
* @return The value of `{{{classname}}}`
* @throws ClassCastException if the instance is not `{{{dataType}}}`
*/
public {{{dataType}}} get{{#sanitizeDataType}}{{{dataType}}}{{/sanitizeDataType}}() throws ClassCastException {
return ({{{dataType}}})value;
}

{{/oneOf}}
{{/composedSchemas}}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
{{classname}} {{classVarName}} = ({{classname}}) o;
return Objects.equals(this.value, {{classVarName}}.value);
}

@Override
public int hashCode() {
return Objects.hash(this.value);
}

@Override
public String toString() {
return String.valueOf(value);
}

public static class {{classname}}Serializer extends StdSerializer<{{classname}}> {
public {{classname}}Serializer(Class<{{classname}}> t) {
super(t);
}

public {{classname}}Serializer() {
this(null);
}

@Override
public void serialize({{classname}} value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
if (value == null || value.value == null) {
jgen.writeNull();
} else {
provider.defaultSerializeValue(value.value, jgen);
}
}
}

public static class {{classname}}Deserializer extends StdDeserializer<{{classname}}> {
public {{classname}}Deserializer() {
this({{classname}}.class);
}

public {{classname}}Deserializer(Class<?> vc) {
super(vc);
}

@Override
public {{classname}} deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
JsonNode tree = jp.readValueAsTree();
Object deserialized = null;
boolean typeCoercion = ctxt.isEnabled(MapperFeature.ALLOW_COERCION_OF_SCALARS);
int match = 0;
JsonToken token = tree.traverse(jp.getCodec()).nextToken();
{{#composedSchemas}}
{{#oneOf}}
// deserialize {{{dataType}}}{{#isNullable}} (nullable){{/isNullable}}
try {
{{^isArray}}
boolean attemptParsing = true;
{{#isPrimitiveType}}
attemptParsing = typeCoercion; //respect type coercion setting
if (!attemptParsing) {
{{#isString}}
attemptParsing |= (token == JsonToken.VALUE_STRING);
{{/isString}}
{{#isInteger}}
attemptParsing |= (token == JsonToken.VALUE_NUMBER_INT);
{{/isInteger}}
{{#isLong}}
attemptParsing |= (token == JsonToken.VALUE_NUMBER_INT);
{{/isLong}}
{{#isShort}}
attemptParsing |= (token == JsonToken.VALUE_NUMBER_INT);
{{/isShort}}
{{#isFloat}}
attemptParsing |= (token == JsonToken.VALUE_NUMBER_FLOAT);
{{/isFloat}}
{{#isDouble}}
attemptParsing |= (token == JsonToken.VALUE_NUMBER_FLOAT);
{{/isDouble}}
{{#isNumber}}
attemptParsing |= (token == JsonToken.VALUE_NUMBER_FLOAT);
{{/isNumber}}
{{#isDecimal}}
attemptParsing |= (token == JsonToken.VALUE_NUMBER_FLOAT);
{{/isDecimal}}
{{#isBoolean}}
attemptParsing |= (token == JsonToken.VALUE_FALSE || token == JsonToken.VALUE_TRUE);
{{/isBoolean}}
{{#isNullable}}
attemptParsing |= (token == JsonToken.VALUE_NULL);
{{/isNullable}}
}
{{/isPrimitiveType}}
if (attemptParsing) {
{{#isMap}}
final TypeReference<{{{dataType}}}> ref = new TypeReference<{{{dataType}}}>(){};
deserialized = tree.traverse(jp.getCodec()).readValueAs(ref);
{{/isMap}}
{{^isMap}}
deserialized = tree.traverse(jp.getCodec()).readValueAs({{{dataType}}}.class);
{{/isMap}}
// TODO: there is no validation against JSON schema constraints
// (min, max, enum, pattern...), this does not perform a strict JSON
// validation, which means the 'match' count may be higher than it should be.
match++;
log.log(Level.FINER, "Input data matches schema '{{{dataType}}}'");
}
{{/isArray}}
{{#isArray}}
if (token == JsonToken.START_ARRAY) {
final TypeReference<{{{dataType}}}> ref = new TypeReference<{{{dataType}}}>(){};
deserialized = tree.traverse(jp.getCodec()).readValueAs(ref);
// TODO: there is no validation against JSON schema constraints
Comment thread
mcnulty-fp marked this conversation as resolved.
// (min, max, enum, pattern...), this does not perform a strict JSON
// validation, which means the 'match' count may be higher than it should be.
match++;
log.log(Level.FINER, "Input data matches schema '{{{dataType}}}'");
}
{{/isArray}}
} catch (Exception e) {
// deserialization failed, continue
log.log(Level.FINER, "Input data does not match schema '{{{dataType}}}'", e);
}

{{/oneOf}}
{{/composedSchemas}}
if (match == 1) {
return new {{classname}}(deserialized);
}
throw new IOException(String.format(Locale.ROOT, "Failed deserialization for {{classname}}: %d classes match result, expected 1", match));
}

/**
* Handle deserialization of the 'null' value.
*/
@Override
public {{classname}} getNullValue(DeserializationContext ctxt) throws JsonMappingException {
{{#isNullable}}
return null;
{{/isNullable}}
{{^isNullable}}
throw new JsonMappingException(ctxt.getParser(), "{{classname}} cannot be null");
{{/isNullable}}
}
}
}
{{/discriminator}}
Loading