blob: c8d98f25c041211413d67626cefd86af099dc9b9 [file] [log] [blame]
/*******************************************************************************
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.ofbiz.ws.rs.util;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.ofbiz.base.util.Debug;
import org.apache.ofbiz.base.util.UtilValidate;
import org.apache.ofbiz.entity.Delegator;
import org.apache.ofbiz.entity.model.ModelEntity;
import org.apache.ofbiz.entity.model.ModelField;
import org.apache.ofbiz.service.ModelParam;
import org.apache.ofbiz.service.ModelService;
import org.apache.ofbiz.webapp.WebAppUtil;
import org.apache.ofbiz.ws.rs.listener.ApiContextListener;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.BooleanSchema;
import io.swagger.v3.oas.models.media.DateSchema;
import io.swagger.v3.oas.models.media.IntegerSchema;
import io.swagger.v3.oas.models.media.MapSchema;
import io.swagger.v3.oas.models.media.NumberSchema;
import io.swagger.v3.oas.models.media.ObjectSchema;
import io.swagger.v3.oas.models.media.Schema;
import io.swagger.v3.oas.models.media.StringSchema;
public final class OpenApiUtil {
private static final String MODULE = OpenApiUtil.class.getName();
private OpenApiUtil() {
}
private static final Map<String, String> CLASS_ALIAS = new HashMap<>();
private static final Map<String, Class<?>> JAVA_OPEN_API_MAP = new HashMap<>();
private static final Map<String, String> FIELD_TYPE_MAP = new HashMap<String, String>();
static {
CLASS_ALIAS.put("String", "String");
CLASS_ALIAS.put("java.lang.String", "String");
CLASS_ALIAS.put("CharSequence", "String");
CLASS_ALIAS.put("java.lang.CharSequence", "String");
CLASS_ALIAS.put("Date", "String");
CLASS_ALIAS.put("java.sql.Date", "String");
CLASS_ALIAS.put("Time", "String");
CLASS_ALIAS.put("java.sql.Time", "String");
CLASS_ALIAS.put("Timestamp", "Timestamp");
CLASS_ALIAS.put("java.sql.Timestamp", "Timestamp");
CLASS_ALIAS.put("Integer", "Integer");
CLASS_ALIAS.put("java.lang.Integer", "Integer");
CLASS_ALIAS.put("Long", "Long");
CLASS_ALIAS.put("java.lang.Long", "Long");
CLASS_ALIAS.put("BigInteger", "BigInteger");
CLASS_ALIAS.put("java.math.BigInteger", "BigInteger");
CLASS_ALIAS.put("Float", "Float");
CLASS_ALIAS.put("java.lang.Float", "Float");
CLASS_ALIAS.put("Double", "Float");
CLASS_ALIAS.put("java.lang.Double", "Float");
CLASS_ALIAS.put("BigDecimal", "BigDecimal");
CLASS_ALIAS.put("java.math.BigDecimal", "BigDecimal");
CLASS_ALIAS.put("Boolean", "Boolean");
CLASS_ALIAS.put("java.lang.Boolean", "Boolean");
CLASS_ALIAS.put("org.apache.ofbiz.entity.GenericValue", "GenericValue");
CLASS_ALIAS.put("GenericValue", "GenericValue");
CLASS_ALIAS.put("GenericPK", "GenericPK");
CLASS_ALIAS.put("org.apache.ofbiz.entity.GenericPK", "GenericPK");
CLASS_ALIAS.put("org.apache.ofbiz.entity.GenericEntity", "GenericEntity");
CLASS_ALIAS.put("GenericEntity", "GenericEntity");
CLASS_ALIAS.put("java.util.List", "List");
CLASS_ALIAS.put("List", "List");
CLASS_ALIAS.put("java.util.Set", "Set");
CLASS_ALIAS.put("Set", "Set");
CLASS_ALIAS.put("java.util.Map", "Map");
CLASS_ALIAS.put("Map", "Map");
CLASS_ALIAS.put("java.util.HashMap", "HashMap");
CLASS_ALIAS.put("HashMap", "HashMap");
JAVA_OPEN_API_MAP.put("String", StringSchema.class);
JAVA_OPEN_API_MAP.put("Integer", IntegerSchema.class);
JAVA_OPEN_API_MAP.put("Long", IntegerSchema.class);
JAVA_OPEN_API_MAP.put("Boolean", BooleanSchema.class);
JAVA_OPEN_API_MAP.put("Map", MapSchema.class);
JAVA_OPEN_API_MAP.put("GenericEntity", MapSchema.class);
JAVA_OPEN_API_MAP.put("GenericPK", MapSchema.class);
JAVA_OPEN_API_MAP.put("GenericValue", MapSchema.class);
JAVA_OPEN_API_MAP.put("HashMap", MapSchema.class);
JAVA_OPEN_API_MAP.put("List", ArraySchema.class);
JAVA_OPEN_API_MAP.put("Set", ArraySchema.class);
JAVA_OPEN_API_MAP.put("Collection", ArraySchema.class);
JAVA_OPEN_API_MAP.put("Float", NumberSchema.class);
JAVA_OPEN_API_MAP.put("Double", NumberSchema.class);
JAVA_OPEN_API_MAP.put("BigDecimal", NumberSchema.class);
JAVA_OPEN_API_MAP.put("BigInteger", IntegerSchema.class);
JAVA_OPEN_API_MAP.put("Timestamp", DateSchema.class);
FIELD_TYPE_MAP.put("id", "String");
FIELD_TYPE_MAP.put("indicator", "String");
FIELD_TYPE_MAP.put("date", "String");
FIELD_TYPE_MAP.put("id-vlong", "String");
FIELD_TYPE_MAP.put("description", "String");
FIELD_TYPE_MAP.put("numeric", "Int"); //
FIELD_TYPE_MAP.put("long-varchar", "String");
FIELD_TYPE_MAP.put("id-long", "String");
FIELD_TYPE_MAP.put("currency-amount", "BigDecimal");
FIELD_TYPE_MAP.put("value", "value");
FIELD_TYPE_MAP.put("email", "String");
FIELD_TYPE_MAP.put("currency-precise", "BigDecimal");
FIELD_TYPE_MAP.put("very-short", "String");
FIELD_TYPE_MAP.put("date-time", "Timestamp");
FIELD_TYPE_MAP.put("credit-card-date", "String");
FIELD_TYPE_MAP.put("url", "String");
FIELD_TYPE_MAP.put("credit-card-number", "String");
FIELD_TYPE_MAP.put("fixed-point", "BigDecimal");
FIELD_TYPE_MAP.put("name", "String");
FIELD_TYPE_MAP.put("short-varchar", "String");
FIELD_TYPE_MAP.put("comment", "String");
FIELD_TYPE_MAP.put("time", "String");
FIELD_TYPE_MAP.put("very-long", "String");
FIELD_TYPE_MAP.put("floating-point", "Float");
FIELD_TYPE_MAP.put("object", "Byte");
FIELD_TYPE_MAP.put("byte-array", "Byte");
FIELD_TYPE_MAP.put("blob", "Byte");
}
public static Class<?> getOpenApiTypeForAttributeType(String attributeType) {
return JAVA_OPEN_API_MAP.get(CLASS_ALIAS.get(attributeType));
}
public static Class<?> getOpenApiTypeForFieldType(String fieldType) {
return JAVA_OPEN_API_MAP.get(FIELD_TYPE_MAP.get(fieldType));
}
public static Schema<Object> getInSchema(ModelService service) {
Schema<Object> parentSchema = new Schema<Object>();
parentSchema.setDescription("In Schema for service: " + service.getName() + " request");
parentSchema.setType("object");
service.getInParamNamesMap().forEach((name, type) -> {
Schema<?> attrSchema = getAttributeSchema(service, service.getParam(name));
if (attrSchema != null) {
parentSchema.addProperties(name, getAttributeSchema(service, service.getParam(name)));
}
});
return parentSchema;
}
private static Schema<?> getAttributeSchema(ModelService service, ModelParam param) {
Schema<?> schema = null;
Class<?> schemaClass = getOpenApiTypeForAttributeType(param.getType());
if (schemaClass == null) {
Debug.logWarning("Attribute '" + param.getName() + "' ignored as it is declared as '" + param.getType()
+ "' and corresponding OpenApi Type Mapping not found.", MODULE);
return null;
}
try {
schema = (Schema<?>) schemaClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
List<ModelParam> children = param.getChildren();
Delegator delegator = WebAppUtil.getDelegator(ApiContextListener.getApplicationCntx());
if (schema instanceof ArraySchema) {
((ArraySchema) schema).setItems(getAttributeSchema(service, children.get(0)));
} else if (schema instanceof MapSchema) {
if (isTypeGenericEntityOrGenericValue(param.getType())) {
if (UtilValidate.isEmpty(param.getEntityName())) {
Debug.logWarning(
"Attribute '" + param.getName() + "' ignored as it is declared as '" + param.getType() + "' but does not have "
+ "entity-name defined.",
MODULE);
return null;
} else {
schema = getSchemaForEntity(delegator.getModelEntity(param.getEntityName()));
}
} else if (UtilValidate.isEmpty(param.getChildren())) {
Debug.logWarning(
"Attribute '" + param.getName() + "' ignored as it is declared as '" + param.getType() + "' but does not have "
+ "any child attributes.",
MODULE);
return null;
} else {
for (ModelParam childParam : children) {
schema.addProperties(childParam.getName(), getAttributeSchema(service, childParam));
}
}
}
return schema;
}
public static Schema<Object> getOutSchema(ModelService service) {
Schema<Object> parentSchema = new Schema<Object>();
parentSchema.setDescription("Out Schema for service: " + service.getName() + " response");
parentSchema.setType("object");
parentSchema.addProperties("statusCode", new IntegerSchema().description("HTTP Status Code"));
parentSchema.addProperties("statusDescription", new StringSchema().description("HTTP Status Code Description"));
parentSchema.addProperties("successMessage", new StringSchema().description("Success Message"));
ObjectSchema dataSchema = new ObjectSchema();
parentSchema.addProperties("data", dataSchema);
service.getOutParamNamesMap().forEach((name, type) -> {
Schema<?> schema = null;
Class<?> schemaClass = getOpenApiTypeForAttributeType(type);
if (schemaClass == null) {
return;
}
try {
schema = (Schema<?>) schemaClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
if (schema instanceof ArraySchema) {
ArraySchema arraySchema = (ArraySchema) schema;
arraySchema.items(new StringSchema());
}
dataSchema.addProperties(name, schema.description(name));
});
return parentSchema;
}
private static boolean isTypeGenericEntityOrGenericValue(String type) {
if (type == null) {
return false;
}
return type.matches("org.apache.ofbiz.entity.GenericValue|GenericValue|org.apache.ofbiz.entity.GenericEntity|GenericEntity");
}
private static Schema<?> getSchemaForEntity(ModelEntity entity) {
Schema<?> dataSchema = new Schema<>();
dataSchema.setType("object");
List<String> fields = entity.getAllFieldNames();
for (String fieldNm : fields) {
ModelField field = entity.getField(fieldNm);
Schema<?> schema = null;
Class<?> schemaClass = getOpenApiTypeForFieldType(field.getType());
if (schemaClass == null) {
continue;
}
try {
schema = (Schema<?>) schemaClass.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
dataSchema.addProperties(fieldNm, schema.description(fieldNm));
}
return dataSchema;
}
}