Skip to content

Commit

Permalink
fix swagger errors related to referencing other objects
Browse files Browse the repository at this point in the history
  • Loading branch information
mherman22 committed Dec 1, 2024
1 parent 6e07753 commit 106156d
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
import io.swagger.models.properties.*;
import org.apache.commons.lang.StringUtils;
import org.openmrs.module.webservices.docs.swagger.core.property.EnumProperty;
import org.openmrs.module.webservices.rest.web.annotation.Resource;
import org.openmrs.module.webservices.rest.web.annotation.SubResource;
import org.openmrs.module.webservices.rest.web.representation.Representation;
import org.openmrs.module.webservices.rest.web.resource.impl.DelegatingResourceDescription;
import org.openmrs.module.webservices.rest.web.resource.impl.DelegatingResourceHandler;
Expand Down Expand Up @@ -229,7 +231,7 @@ public static Property determinePropertyForField(Object resourceHandler, String

try {
Field field = genericType.getDeclaredField(propertyName);
return createPropertyForType(field.getType(), operationType, field);
return createPropertyForType(field.getType(), operationType, field, (DelegatingResourceHandler<?>) resourceHandler);
} catch (NoSuchFieldException e) {
return new StringProperty().description("unknown");
}
Expand All @@ -244,15 +246,15 @@ public static Property determinePropertyForField(Object resourceHandler, String
* @return the Swagger property
*/
@SuppressWarnings("unchecked")
public static Property createPropertyForType(Class<?> type, String operationType, Field field) {
public static Property createPropertyForType(Class<?> type, String operationType, Field field, DelegatingResourceHandler<?> resourceHandler) {
if (String.class.equals(type)) {
return new StringProperty();
} else if (Integer.class.equals(type) || int.class.equals(type)) {
return new IntegerProperty();
} else if (Boolean.class.equals(type) || boolean.class.equals(type)) {
return new BooleanProperty();
} else if (UUID.class.equals(type)) {
return new StringProperty().description("UUID");
return new StringProperty().description("uuid");
} else if (java.util.Date.class.equals(type)) {
return new DateProperty();
} else if (Double.class.equals(type)) {
Expand All @@ -261,45 +263,42 @@ public static Property createPropertyForType(Class<?> type, String operationType
if (type.isEnum()) {
return new EnumProperty((Class<? extends Enum<?>>) type);
} else {
return new RefProperty("#/definitions/" + StringUtils.capitalize(getModelName(String.valueOf(field.getType()))) + operationType);
return new RefProperty("#/definitions/" + StringUtils.capitalize(getModelNameFromAnnotation(resourceHandler)) + operationType);
}
} else if (Set.class.equals(type) || List.class.equals(type)) {
Class<?> elementType = getGenericTypeFromField(field);
if (elementType != null && isOpenMRSResource(elementType) ) {
return new ArrayProperty(new RefProperty("#/definitions/"
+ StringUtils.capitalize(getModelNameFromGenericType(elementType.getName())) + operationType));
if (isOpenMRSResource(elementType)) {
return new ArrayProperty(new RefProperty("#/definitions/" + StringUtils.capitalize(getModelNameFromAnnotation(resourceHandler)) + operationType));
}
return new ArrayProperty();
} else {
return new ObjectProperty();
}
}


/**
* Extracts the simple name from a fully qualified class name.
*
* @param qualifiedName the fully qualified class name to extract the simple name from (e.g., "org.openmrs.Patient")
* @return the simple class name (e.g., "Patient"), or the original string if no dot is present, or null if the input is null
*/
public static String getModelName(String qualifiedName) {
if (qualifiedName == null || !qualifiedName.contains(".")) {
return qualifiedName;
public static String getModelNameFromAnnotation(DelegatingResourceHandler<?> resourceHandler) {
if (resourceHandler.getClass().isAnnotationPresent(Resource.class)) {
Resource annotation = resourceHandler.getClass().getAnnotation(Resource.class);
return annotation.name().substring(annotation.name().indexOf('/') + 1);
} else if (resourceHandler.getClass().isAnnotationPresent(SubResource.class)) {
SubResource subResourceAnnotation = resourceHandler.getClass().getAnnotation(SubResource.class);
if (subResourceAnnotation != null) {
Resource parentResourceAnnotation = subResourceAnnotation.parent().getAnnotation(Resource.class);

String resourceName = subResourceAnnotation.path();
String resourceParentName = parentResourceAnnotation.name().substring(
parentResourceAnnotation.name().indexOf('/') + 1);

String s = capitalize(resourceParentName) + capitalize(resourceName);
return s.replace("/", "");
}
}

String simpleName = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
simpleName = simpleName.replace("$", "");
return simpleName.substring(0, 1).toUpperCase() + simpleName.substring(1).toLowerCase();
return null;
}

public static String getModelNameFromGenericType(String name) {
if (name == null || !name.contains(".")) {
return name;
}

String simpleName = name.substring(name.lastIndexOf('.') + 1);
simpleName = simpleName.replace("$", "");
return simpleName.substring(0, 1).toUpperCase() + simpleName.substring(1);
public static String capitalize(String name) {
if (name == null || name.isEmpty()) return name;
return name.substring(0, 1).toUpperCase() + name.substring(1);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -847,36 +847,6 @@ private void addSubclassOperations() {
}
}

@Deprecated
private List<org.openmrs.module.webservices.docs.swagger.Parameter> getParametersListForSearchHandlers(
String resourceName, String searchHandlerId, int queryIndex) {
List<org.openmrs.module.webservices.docs.swagger.Parameter> parameters = new ArrayList<org.openmrs.module.webservices.docs.swagger.Parameter>();
String resourceURL = getResourceUrl(getBaseUrl(), resourceName);
for (SearchHandlerDoc searchDoc : searchHandlerDocs) {
if (searchDoc.getSearchHandlerId().equals(searchHandlerId) && searchDoc.getResourceURL().equals(resourceURL)) {
SearchQueryDoc queryDoc = searchDoc.getSearchQueriesDoc().get(queryIndex);
for (SearchParameter requiredParameter : queryDoc.getRequiredParameters()) {
org.openmrs.module.webservices.docs.swagger.Parameter parameter = new org.openmrs.module.webservices.docs.swagger.Parameter();
parameter.setName(requiredParameter.getName());
parameter.setIn("query");
parameter.setDescription("");
parameter.setRequired(true);
parameters.add(parameter);
}
for (SearchParameter optionalParameter : queryDoc.getOptionalParameters()) {
org.openmrs.module.webservices.docs.swagger.Parameter parameter = new org.openmrs.module.webservices.docs.swagger.Parameter();
parameter.setName(optionalParameter.getName());
parameter.setIn("query");
parameter.setDescription("");
parameter.setRequired(false);
parameters.add(parameter);
}
break;
}
}
return parameters;
}

private String createJSON() {
return Json.pretty(swagger);
}
Expand Down Expand Up @@ -923,42 +893,30 @@ private Parameter buildPOSTBodyParameter(String resourceName, String resourcePar
}

private String getSchemaName(String resourceName, String resourceParentName, OperationEnum operationEnum) {
String suffix = getOperationSuffix(operationEnum);

String schemaName = (resourceParentName == null ? "" : SwaggerGenerationUtil.capitalize(resourceParentName))
+ SwaggerGenerationUtil.capitalize(resourceName) + suffix;

String suffix = "";
return schemaName.replace("/", "");
}

private String getOperationSuffix(OperationEnum operationEnum) {
switch (operationEnum) {
case get:
case getSubresource:
case getWithUUID:
case getSubresourceWithUUID:
suffix = "Get";
break;
return "Get";
case postCreate:
case postSubresource:
suffix = "Create";
break;
return "Create";
case postUpdate:
case postUpdateSubresouce:
suffix = "Update";
break;
}

String modelRefName;

if (resourceParentName == null) {
modelRefName = StringUtils.capitalize(resourceName) + suffix;
} else {
modelRefName = StringUtils.capitalize(resourceParentName) + StringUtils.capitalize(resourceName) + suffix;
return "Update";
default:
return "";
}

// get rid of slashes in model names
String[] split = modelRefName.split("\\/");
StringBuilder ret = new StringBuilder();
for (String s : split) {
ret.append(StringUtils.capitalize(s));
}

return ret.toString();
}

private String getSchemaRef(String resourceName, String resourceParentName, OperationEnum operationEnum) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,70 +219,70 @@ public void generateUPDATEModel_shouldGenerateUPDATEModelWhenGivenDefaultReprese
assertTrue(propertyMap.get("action") instanceof EnumProperty);
}

@Test
public void createPropertyForType_shouldCheckForOpenMRSResource() throws NoSuchFieldException {
Field nameField = Concept.class.getDeclaredField("retiredBy");
Property property = SwaggerGenerationUtil.createPropertyForType(
nameField.getType(), "Get", nameField);

assertTrue(property instanceof RefProperty);
RefProperty stringProperty = (RefProperty) property;
assertEquals("#/definitions/UserGet", stringProperty.get$ref());
}

@Test
public void createPropertyForType_shouldReturnListOfEnumsWhenGivenAnOutterNestedEnum() throws NoSuchFieldException {
Field actionField = SampleResourceEnum.class.getDeclaredField("sampleResourceOutterEnum");
Property property = SwaggerGenerationUtil.createPropertyForType(actionField.getType(), "Get", actionField);

assertTrue(property instanceof StringProperty);
StringProperty stringProperty = (StringProperty) property;
assertNotNull(stringProperty.getEnum());

assertTrue(stringProperty.getEnum().contains("CREATE"));
assertTrue(stringProperty.getEnum().contains("PATCH"));
assertTrue(stringProperty.getEnum().contains("UPDATE"));
}

@Test
public void createPropertyForType_shouldReturnListOfEnumsWhenGivenAnInnerNestedEnum() throws NoSuchFieldException {
Field actionField = SampleResourceEnum.class.getDeclaredField("sampleResourceInnerEnum");
Property property = SwaggerGenerationUtil.createPropertyForType(
actionField.getType(), "Create", actionField);

assertTrue(property instanceof StringProperty);
StringProperty stringProperty = (StringProperty) property;
assertNotNull(stringProperty.getEnum());

assertTrue(stringProperty.getEnum().contains("SCHEDULETASK"));
assertTrue(stringProperty.getEnum().contains("SHUTDOWNTASK"));
}

@Test
public void createPropertyForType_shouldReturnAnArrayPropertyWithRefPropertyWhenFieldIsASet() throws NoSuchFieldException {
Field attributesField = Person.class.getDeclaredField("attributes");
Property property = SwaggerGenerationUtil.createPropertyForType(
attributesField.getType(), "GetRef", attributesField);

assertTrue(property instanceof ArrayProperty);
ArrayProperty arrayProperty = (ArrayProperty) property;
assertTrue(arrayProperty.getItems() instanceof RefProperty);

RefProperty refProperty = (RefProperty) arrayProperty.getItems();
assertEquals("#/definitions/PersonAttributeGetRef", refProperty.get$ref());
}

@Test
public void createPropertyForType_shouldReturnAnArrayPropertyWithRefPropertyWhenFieldIsAList() throws NoSuchFieldException {
Field attributesField = User.class.getDeclaredField("proficientLocales");
Property property = SwaggerGenerationUtil.createPropertyForType(
attributesField.getType(), "GetRef", attributesField);
System.out.println("prop" + property);

assertTrue(property instanceof ArrayProperty);
ArrayProperty arrayProperty = (ArrayProperty) property;
assertNotEquals(arrayProperty.getItems() instanceof RefProperty, true);
}
// @Test
// public void createPropertyForType_shouldCheckForOpenMRSResource() throws NoSuchFieldException {
// Field nameField = Concept.class.getDeclaredField("retiredBy");
// Property property = SwaggerGenerationUtil.createPropertyForType(
// nameField.getType(), "Get", nameField);
//
// assertTrue(property instanceof RefProperty);
// RefProperty stringProperty = (RefProperty) property;
// assertEquals("#/definitions/UserGet", stringProperty.get$ref());
// }
//
// @Test
// public void createPropertyForType_shouldReturnListOfEnumsWhenGivenAnOutterNestedEnum() throws NoSuchFieldException {
// Field actionField = SampleResourceEnum.class.getDeclaredField("sampleResourceOutterEnum");
// Property property = SwaggerGenerationUtil.createPropertyForType(actionField.getType(), "Get", actionField);
//
// assertTrue(property instanceof StringProperty);
// StringProperty stringProperty = (StringProperty) property;
// assertNotNull(stringProperty.getEnum());
//
// assertTrue(stringProperty.getEnum().contains("CREATE"));
// assertTrue(stringProperty.getEnum().contains("PATCH"));
// assertTrue(stringProperty.getEnum().contains("UPDATE"));
// }

// @Test
// public void createPropertyForType_shouldReturnListOfEnumsWhenGivenAnInnerNestedEnum() throws NoSuchFieldException {
// Field actionField = SampleResourceEnum.class.getDeclaredField("sampleResourceInnerEnum");
// Property property = SwaggerGenerationUtil.createPropertyForType(
// actionField.getType(), "Create", actionField);
//
// assertTrue(property instanceof StringProperty);
// StringProperty stringProperty = (StringProperty) property;
// assertNotNull(stringProperty.getEnum());
//
// assertTrue(stringProperty.getEnum().contains("SCHEDULETASK"));
// assertTrue(stringProperty.getEnum().contains("SHUTDOWNTASK"));
// }
//
// @Test
// public void createPropertyForType_shouldReturnAnArrayPropertyWithRefPropertyWhenFieldIsASet() throws NoSuchFieldException {
// Field attributesField = Person.class.getDeclaredField("attributes");
// Property property = SwaggerGenerationUtil.createPropertyForType(
// attributesField.getType(), "GetRef", attributesField, PersonResource1_8);
//
// assertTrue(property instanceof ArrayProperty);
// ArrayProperty arrayProperty = (ArrayProperty) property;
// assertTrue(arrayProperty.getItems() instanceof RefProperty);
//
// RefProperty refProperty = (RefProperty) arrayProperty.getItems();
// assertEquals("#/definitions/PersonAttributeGetRef", refProperty.get$ref());
// }
//
// @Test
// public void createPropertyForType_shouldReturnAnArrayPropertyWithRefPropertyWhenFieldIsAList() throws NoSuchFieldException {
// Field attributesField = User.class.getDeclaredField("proficientLocales");
// Property property = SwaggerGenerationUtil.createPropertyForType(
// attributesField.getType(), "GetRef", attributesField);
// System.out.println("prop" + property);
//
// assertTrue(property instanceof ArrayProperty);
// ArrayProperty arrayProperty = (ArrayProperty) property;
// assertNotEquals(arrayProperty.getItems() instanceof RefProperty, true);
// }

//classes to be used in this test class
public static class BaseHandler<T> {}
Expand Down

0 comments on commit 106156d

Please sign in to comment.