
com.okta.swagger.codegen.OktaJavaClientImplCodegen Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2017 Okta
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.okta.swagger.codegen;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.codegen.v3.CodegenModel;
import io.swagger.codegen.v3.CodegenOperation;
import io.swagger.codegen.v3.CodegenProperty;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.lang3.BooleanUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class OktaJavaClientImplCodegen extends AbstractOktaJavaClientCodegen {
private static final String CREATE_NESTED_KEY = "x-oktaInstantiateNested";
private final String overrideModelPackage;
public OktaJavaClientImplCodegen() {
super("okta_java_impl", "com.okta.sdk.impl.resource");
overrideModelPackage = "com.okta.sdk.resource";
apiPackage = "com.okta.sdk.impl.client";
}
@Override
public String getDefaultTemplateDir() {
return "OktaJavaImpl";
}
@Override
public void preprocessOpenAPI(OpenAPI openAPI) {
super.preprocessOpenAPI(openAPI);
// Enum based definitions are created by OktaJavaClientApiCodegen, so they need to be removed here
enumList.forEach(enumEntry -> openAPI.getComponents().getSchemas().remove(enumEntry));
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
if (!BooleanUtils.toBoolean(model.getIsEnum())) {
String propertyType;
String propertyTypeMethod;
boolean forceCast = false;
if (property.getIsListContainer()) {
if (property.items.baseType.equals("String")) {
propertyType = "ListProperty";
propertyTypeMethod = "getListProperty";
} else if (enumList.contains(property.items.baseType)) {
propertyType = "EnumListProperty";
propertyTypeMethod = "getEnumListProperty";
property.vendorExtensions.put("itemType", property.items.datatypeWithEnum);
property.vendorExtensions.put("constructorTypeExtra", ", " + property.items.datatypeWithEnum + ".class");
property.vendorExtensions.put("typeClassExtra", Boolean.TRUE);
} else {
propertyType = "ResourceListProperty";
propertyTypeMethod = "getResourceListProperty";
property.vendorExtensions.put("itemType", property.items.datatypeWithEnum);
property.vendorExtensions.put("constructorTypeExtra", ", " + property.items.datatypeWithEnum + ".class");
property.vendorExtensions.put("typeClassExtra", Boolean.TRUE);
}
forceCast = true;
} else if (property.getIsEnum() || enumList.contains(property.datatype)) {
propertyType = "EnumProperty";
propertyTypeMethod = "getEnumProperty";
property.vendorExtensions.put("itemType", property.datatypeWithEnum);
property.vendorExtensions.put("constructorTypeExtra", ", " + property.datatypeWithEnum + ".class");
property.vendorExtensions.put("typeClassExtra", Boolean.TRUE);
} else if (property.getIsMapContainer() || "Object".equals(property.datatype)) {
propertyType = "MapProperty";
propertyTypeMethod = "getMap";
}
else {
switch (property.baseType) {
case "String":
if ("password".equals(property.dataFormat)) {
propertyType = "CharacterArrayProperty";
propertyTypeMethod = "getCharArray";
} else {
propertyType = "StringProperty";
propertyTypeMethod = "getString";
}
break;
case "Boolean":
propertyType = "BooleanProperty";
propertyTypeMethod = "getBoolean";
break;
case "Integer":
propertyType = "IntegerProperty";
propertyTypeMethod = "getIntProperty";
break;
case "Date":
propertyType = "DateProperty";
propertyTypeMethod = "getDateProperty";
break;
case "Double":
propertyType = "DoubleProperty";
propertyTypeMethod = "getDoubleProperty";
break;
default:
propertyType = "ResourceReference";
propertyTypeMethod = "getResourceProperty";
property.vendorExtensions.put("itemType", property.datatype);
property.vendorExtensions.put("constructorTypeExtra", buildConstructorTypeExtra(property));
property.vendorExtensions.put("typeClassExtra", Boolean.TRUE);
}
}
property.vendorExtensions.put("forceCast", forceCast);
property.vendorExtensions.put("propertyType", propertyType);
property.vendorExtensions.put("propertyTypeMethod", propertyTypeMethod);
}
}
private String buildConstructorTypeExtra(CodegenProperty property) {
Collection autoCreateParams = Collections.singleton("profile");
boolean createNested = property.vendorExtensions.containsKey(CREATE_NESTED_KEY) || autoCreateParams.contains(property.name);
return ", " + property.datatype + ".class, "+ createNested;
}
@Override
public CodegenModel fromModel(String name, Schema schema, Map allSchemas) {
CodegenModel codegenModel = super.fromModel(name, schema, allSchemas);
Map defaultValuesMap = new LinkedHashMap<>();
if (codegenModel.vendorExtensions.containsKey("x-okta-defined-as")) {
Object rawDefaultValues = codegenModel.vendorExtensions.get("x-okta-defined-as");
if(rawDefaultValues instanceof HashMap) {
((HashMap)rawDefaultValues).forEach((key, value) -> {
defaultValuesMap.put(key.toString(), value.toString());
});
}
}
// if the parent is set, we need to check for discrimination
String parent = (String) codegenModel.vendorExtensions.get("x-okta-parent");
if (parent != null) {
parent = parent.substring(parent.lastIndexOf('/') + 1);
if (discriminatorMap.containsKey(parent)) {
Discriminator discriminator = discriminatorMap.get(parent);
String fieldName = discriminator.getFieldName();
String defaultValue = discriminator.getDefaultFieldValue(name);
defaultValuesMap.put(fieldName, defaultValue);
}
}
List defaultTypeSetter = defaultValuesMap.entrySet().stream()
.map(entry -> new KeyValuePair(entry.getKey(), entry.getValue()))
.collect(Collectors.toList());
codegenModel.vendorExtensions.put("defaultSetter", defaultTypeSetter);
return codegenModel;
}
public CodegenOperation fromOperation(String path,
String httpMethod,
Operation operation,
Map definitions,
OpenAPI openAPI) {
CodegenOperation co = super.fromOperation(path, httpMethod, operation, definitions, openAPI);
co.vendorExtensions.put("resourceReturnType", co.returnType);
if (operation.getOperationId() != null && operation.getOperationId().equals("updateBrandTheme")) {
co.vendorExtensions.put("forceToCreateObject", "true");
}
if ("put".equals(httpMethod) ) {
co.vendorExtensions.put("dsMethod", "create");
co.vendorExtensions.put("isPut", true);
if (co.bodyParam == null) {
co.vendorExtensions.put("resourceReturnType", "VoidResource");
}
else {
co.vendorExtensions.put("dsMethod", "save");
}
if ("updateBrandTheme".equals(operation.getOperationId()) ||
"updateFeatureForApplication".equals(operation.getOperationId())) {
co.vendorExtensions.put("forceToCreateObject", "true");
}
} else if ("post".equals(httpMethod) ) {
co.vendorExtensions.put("dsMethod", "create");
co.vendorExtensions.put("isPost", true);
} else if ("get".equals(httpMethod)) {
co.vendorExtensions.put("dsMethod", "getResource");
co.vendorExtensions.put("isGet", true);
} else if ("delete".equals(httpMethod)) {
co.vendorExtensions.put("dsMethod", "delete");
co.vendorExtensions.put("isDelete", true);
}
// pre interpolate the resource href
co.vendorExtensions.put("hrefFiltered", co.path
.replaceAll("\\{", "\" + ")
.replaceAll("\\}", " + \""));
return co;
}
@Override
protected void addToModelTagMap(String modelName) {
modelTagMap.put(modelName, "");
modelTagMap.put("Default" + modelName, ""); // Also add the 'Default' impl
}
@Override
public String toApiName(String name) {
return "Default" + super.toApiName(name);
}
@Override
public String toModelFilename(String name) {
return super.toModelFilename("Default" + name);
}
@Override
public Map postProcessOperations(Map objs) {
objs.entrySet().stream()
.filter(e -> "operations".equals(e.getKey()) && e.getValue() instanceof Map)
.filter(e -> ((Map) e.getValue()).containsKey("classname"))
.forEach(e -> {
Map ops = (Map) e.getValue();
String interfaceClassname = ops.get("classname").toString().replaceFirst("^Default", "");
ops.put("interfaceClassname", interfaceClassname);
});
return super.postProcessOperations(objs);
}
public String toModelImport(String name) {
if ("".equals(modelPackage())) {
return name;
}
if (modelTagMap.containsKey(name)) {
return overrideModelPackage +"."+ modelTagMap.get(name) +"."+ name;
}
return overrideModelPackage + "." + name;
}
@Override
protected void buildDiscriminationMap(OpenAPI openAPI) {
super.buildDiscriminationMap(openAPI);
Map rootConfigMap = new HashMap<>();
Map destMap = new HashMap<>();
rootConfigMap.put("config", destMap);
discriminatorMap.values().forEach(disc -> {
String fqn = toModelImport(disc.getParentDefName());
String fieldName = disc.getFieldName();
Map valueMap = disc.getValueDefMap().entrySet().stream()
.collect(Collectors.toMap(Map.Entry::getValue, e -> toModelImport(e.getKey())));
Map entries = new HashMap<>();
entries.put("fieldName", fieldName);
entries.put("values", valueMap);
destMap.put(fqn, entries);
});
// now dump this to yaml
// cheat a little here because we are assuming we are using maven, replace the LAST index of /target/ (the
// release process will have two 'target' directories in the path
String mavenTargetDir = outputFolder().substring(0, outputFolder.lastIndexOf("/target/") + 8);
File destDir = new File(mavenTargetDir, "generated-resources/swagger/" + overrideModelPackage.replace('.', '/'));
boolean folderCreated = destDir.mkdirs();
if (!folderCreated && !destDir.exists()) {
throw new RuntimeException("Directory does not exist and could not be created: " + destDir);
}
File destFileJson = new File(destDir, "/discrimination.json");
try (OutputStream outputStream = new FileOutputStream(destFileJson)) {
new ObjectMapper().writerWithDefaultPrettyPrinter().writeValue(outputStream, rootConfigMap);
} catch (IOException e) {
throw new RuntimeException("Failed to write discrimination map to json: "+ destFileJson.getAbsolutePath(), e);
}
}
@Override
protected Map reflectionConfig(String fqcn) {
Map data = new HashMap<>(super.reflectionConfig(fqcn));
data.put("allDeclaredConstructors", true);
return data;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy