diff --git a/omod-1.9/src/test/java/org/openmrs/module/webservices/rest/web/ConversionUtil1_9Test.java b/omod-1.9/src/test/java/org/openmrs/module/webservices/rest/web/ConversionUtil1_9Test.java index 2f3eac5fe..f6cbb8fd1 100644 --- a/omod-1.9/src/test/java/org/openmrs/module/webservices/rest/web/ConversionUtil1_9Test.java +++ b/omod-1.9/src/test/java/org/openmrs/module/webservices/rest/web/ConversionUtil1_9Test.java @@ -15,21 +15,30 @@ import org.openmrs.Drug; import org.openmrs.Encounter; import org.openmrs.Obs; +import org.openmrs.api.ConceptService; import org.openmrs.module.webservices.rest.SimpleObject; import org.openmrs.module.webservices.rest.web.representation.CustomRepresentation; +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.v1_0.resource.openmrs1_8.EncounterResource1_8; import org.openmrs.web.test.BaseModuleWebContextSensitiveTest; +import org.springframework.beans.factory.annotation.Autowired; import java.util.List; import static org.hamcrest.core.Is.is; import static org.hibernate.validator.util.Contracts.assertNotNull; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; +import static org.openmrs.module.webservices.rest.web.representation.Representation.DEFAULT; +import static org.openmrs.module.webservices.rest.web.representation.Representation.REF; public class ConversionUtil1_9Test extends BaseModuleWebContextSensitiveTest { + @Autowired + ConceptService conceptService; @Test public void convertToRepresentation_shouldConvertObsDrugValueAsNull() { @@ -82,4 +91,50 @@ public void convertToRepresentation_shouldConvertObsDrugValueAsNull() { } } + + @Test + public void convert_shouldConvertObjectWithNestedCustomRepresentations() { + String customRep = "(concepts:(creator:(person:(uuid),username),datatype:ref,uuid))"; + DelegatingResourceDescription fullDesc = ConversionUtil.getCustomRepresentationDescription(new CustomRepresentation(customRep)); + assertThat(fullDesc.getProperties().size(), is(1)); + DelegatingResourceDescription.Property conceptsProperty = fullDesc.getProperties().get("concepts"); + assertNotNull(conceptsProperty); + assertCustomRepresentation(conceptsProperty.getRep(), "(creator:(person:(uuid),username),datatype:ref,uuid)"); + + DelegatingResourceDescription conceptDesc = ConversionUtil.getCustomRepresentationDescription((CustomRepresentation) conceptsProperty.getRep()); + assertThat(conceptDesc.getProperties().size(), is(3)); + DelegatingResourceDescription.Property creatorProperty = conceptDesc.getProperties().get("creator"); + assertNotNull(creatorProperty); + assertCustomRepresentation(creatorProperty.getRep(), "(person:(uuid),username)"); + + DelegatingResourceDescription creatorDesc = ConversionUtil.getCustomRepresentationDescription((CustomRepresentation) creatorProperty.getRep()); + assertThat(creatorDesc.getProperties().size(), is(2)); + DelegatingResourceDescription.Property personProperty = creatorDesc.getProperties().get("person"); + assertNotNull(personProperty); + + DelegatingResourceDescription.Property usernameProperty = creatorDesc.getProperties().get("username"); + assertNotNull(usernameProperty); + assertEquals(DEFAULT, usernameProperty.getRep()); + + DelegatingResourceDescription personDesc = ConversionUtil.getCustomRepresentationDescription((CustomRepresentation) personProperty.getRep()); + assertThat(personDesc.getProperties().size(), is(1)); + DelegatingResourceDescription.Property personUuidProperty = personDesc.getProperties().get("uuid"); + assertNotNull(personUuidProperty); + assertEquals(DEFAULT, personUuidProperty.getRep()); + + DelegatingResourceDescription.Property datatypeProperty = conceptDesc.getProperties().get("datatype"); + assertNotNull(datatypeProperty); + assertEquals(REF, datatypeProperty.getRep()); + + DelegatingResourceDescription.Property uuidProperty = conceptDesc.getProperties().get("uuid"); + assertNotNull(uuidProperty); + assertEquals(DEFAULT, uuidProperty.getRep()); + } + + public void assertCustomRepresentation(Representation representation, String rep) { + assertNotNull(representation); + assertTrue(representation instanceof CustomRepresentation); + CustomRepresentation customRepresentation = (CustomRepresentation) representation; + assertEquals(rep, customRepresentation.getRepresentation()); + } } diff --git a/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/ConversionUtil.java b/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/ConversionUtil.java index 044d8c341..1d2b69be1 100644 --- a/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/ConversionUtil.java +++ b/omod-common/src/main/java/org/openmrs/module/webservices/rest/web/ConversionUtil.java @@ -9,26 +9,6 @@ */ package org.openmrs.module.webservices.rest.web; -import java.lang.reflect.Array; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - import org.apache.commons.beanutils.PropertyUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -53,6 +33,30 @@ import org.openmrs.util.HandlerUtil; import org.openmrs.util.LocaleUtility; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.TypeVariable; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.SortedSet; +import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +import static org.openmrs.module.webservices.rest.web.representation.Representation.DEFAULT; +import static org.openmrs.module.webservices.rest.web.representation.Representation.FULL; +import static org.openmrs.module.webservices.rest.web.representation.Representation.REF; + public class ConversionUtil { static final Log log = LogFactory.getLog(ConversionUtil.class); @@ -539,56 +543,46 @@ public static DelegatingResourceDescription getCustomRepresentationDescription(C String def = representation.getRepresentation(); def = def.startsWith("(") ? def.substring(1) : def; def = def.endsWith(")") ? def.substring(0, def.length() - 1) : def; - String[] fragments = def.split(","); - for (int i = 0; i < fragments.length; i++) { - String[] field = fragments[i].split(":"); //split into field and representation - if (field.length == 1) { - if (!field[0].equals("links")) - desc.addProperty(field[0]); - if (field[0].equals("links")) { + + int startIndex = 0; + List properties = new ArrayList(); + int nestingLevel = 0; + for (int i=0; i < def.length(); i++) { + char c = def.charAt(i); + if (c == '(') { + nestingLevel++; + } + else if (c == ')') { + nestingLevel--; + } + else if (c == ',' && nestingLevel == 0) { + properties.add(def.substring(startIndex, i)); + startIndex = i + 1; + } + } + properties.add(def.substring(startIndex)); + + for (String propertyDefinition : properties) { + if (propertyDefinition.contains(":")) { + String[] propertyAndRepresentation = propertyDefinition.split(":", 2); + String property = propertyAndRepresentation[0]; + String rep = propertyAndRepresentation[1]; + Representation r; + if (rep.startsWith("(")) { + r = new CustomRepresentation(rep); + } + else { + r = rep.equalsIgnoreCase("REF") ? REF : rep.equalsIgnoreCase("FULL") ? FULL : DEFAULT; + } + desc.addProperty(property, r); + } + else { + if (propertyDefinition.equals("links")) { desc.addSelfLink(); desc.addLink("default", ".?v=" + RestConstants.REPRESENTATION_DEFAULT); } - } else { - String property = field[0]; - String rep = field[1]; - - // if custom representation - if (rep.startsWith("(")) { - StringBuilder customRep = new StringBuilder(); - customRep.append(rep); - if (!rep.endsWith(")")) { - for (int j = 2; j < field.length; j++) { - customRep.append(":").append(field[j]); - } - int open = 1; - for (i = i + 1; i < fragments.length; i++) { - for (char fragment : fragments[i].toCharArray()) { - if (fragment == '(') { - open++; - } else if (fragment == ')') { - open--; - } - } - - customRep.append(","); - customRep.append(fragments[i]); - - if (open == 0) { - break; - } - } - } - desc.addProperty(property, new CustomRepresentation(customRep.toString())); - } else { - rep = rep.toUpperCase(); //normalize - if (rep.equals("REF")) { - desc.addProperty(property, Representation.REF); - } else if (rep.equals("FULL")) { - desc.addProperty(property, Representation.FULL); - } else if (rep.equals("DEFAULT")) { - desc.addProperty(property, Representation.DEFAULT); - } + else { + desc.addProperty(propertyDefinition); } } }