package org.odata4j.test.integration.expressions; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import junit.framework.Assert; import org.core4j.Enumerable; import org.core4j.Func; import org.core4j.Funcs; import org.joda.time.DateTime; import org.joda.time.LocalDateTime; import org.joda.time.LocalTime; import org.junit.Test; import org.odata4j.consumer.ODataConsumer; import org.odata4j.core.Guid; import org.odata4j.core.OCollection; import org.odata4j.core.OComplexObject; import org.odata4j.core.OEntity; import org.odata4j.core.OProperty; import org.odata4j.core.ORelatedEntitiesLinkInline; import org.odata4j.core.ORelatedEntityLinkInline; import org.odata4j.core.OSimpleObject; import org.odata4j.core.OStructuralObject; import org.odata4j.core.UnsignedByte; import org.odata4j.format.FormatType; import org.odata4j.producer.inmemory.InMemoryProducer; import org.odata4j.producer.resources.DefaultODataProducerProvider; import org.odata4j.producer.server.ODataServer; import org.odata4j.test.integration.AbstractRuntimeTest; import org.odata4j.test.integration.expressions.PojoWithAllTypesComplex.Complex1; import org.odata4j.test.integration.expressions.PojoWithAllTypesComplex.Complex2; import org.odata4j.test.integration.expressions.PojoWithAllTypesComplex.Entity1; public class JsonTest extends AbstractRuntimeTest { public static final String uri = "http://localhost:18890/TestService.svc/"; public JsonTest(RuntimeFacadeType type) { super(type); } @Test public void testJsonEntity() throws Exception { try { setup(); // did the properties round trip ok? OEntity e = consumer.getEntity("Pojo", (int) 1).expand("FavoriteEntity,OnNoticeEntities").execute(); assertPojoEqualsOEntity(pojo, e, e.getProperties()); PojoWithAllTypesComplex rpojo = producer.toPojo(e, PojoWithAllTypesComplex.class); assertPojoEqualsOEntity(rpojo, e, e.getProperties()); Assert.assertTrue(rpojo.beforeUnmarshalCalled); Assert.assertTrue(rpojo.afterUnmarshalCalled); } finally { server.stop(); } } @Test public void testGetNavProps() throws Exception { try { setup(); // a to-1 nav prop OEntity e = consumer.getEntity("Pojo", (int) 1).nav("FavoriteEntity").execute(); assertNDGT(e); // a to-many nav prop Enumerable<OEntity> es = consumer.getEntities("Pojo").nav((int) 1, "OnNoticeEntities").execute(); assertOnNoticeEntities(es.toList()); } finally { server.stop(); } } @Test public void testSelect() throws Exception { // $select now supported in InMemoryProducer. try { setup(); String output = this.rtFacade.getWebResource(uri + "Pojo(1)?$format=jsonverbose&$select=ComplexType,StringList,FavoriteEntity,FavoriteEntity/Prop2&$expand=FavoriteEntity").getEntity(); System.out.println(output); // did the properties round trip ok? OEntity e = consumer.getEntity("Pojo", (int) 1).expand("FavoriteEntity").select("ComplexType,StringList,FavoriteEntity,FavoriteEntity/Prop2").execute(); Assert.assertTrue(e.getProperties().size() == 2); Assert.assertNotNull(getPropertyValue("ComplexType", e.getProperties())); Assert.assertNotNull(getPropertyValue("StringList", e.getProperties())); OEntity ndgt = ((OEntity) e).getLink("FavoriteEntity", ORelatedEntityLinkInline.class).getRelatedEntity(); Assert.assertTrue(ndgt.getProperties().size() == 1); Assert.assertEquals(getPropertyValue("Prop2", ndgt.getProperties()), 1); } finally { server.stop(); } } private PojoWithAllTypesComplex pojo; private InMemoryProducer producer; private ODataServer server; private ODataConsumer consumer; private static List<Entity1> getOnNoticeEntities() { List<Entity1> l = new ArrayList<Entity1>(); l.add(new Entity1("Bears", 2)); l.add(new Entity1("Irony", 33)); return l; } private static Entity1 getNDGT() { return new Entity1("Neil DeGrasse-Tyson", 1); } private void setup() throws Exception { producer = new InMemoryProducer("JsonTest"); DefaultODataProducerProvider.setInstance(producer); server = this.rtFacade.startODataServer(uri); consumer = this.rtFacade.createODataConsumer(uri, FormatType.JSONVERBOSE); Assert.assertEquals(0, consumer.getEntitySets().count()); // register a complex type: producer.registerComplexType(PojoWithAllTypes.class, "PojoWithAllTypes"); producer.registerComplexType(PojoWithAllTypesComplex.Complex2.class, "Complex2"); producer.registerComplexType(PojoWithAllTypesComplex.Complex1.class, "Complex1"); producer.register(PojoWithAllTypesComplex.Entity1.class, "Relations", new Func<Iterable<Entity1>>() { @Override public Iterable<Entity1> apply() { List<Entity1> l = getOnNoticeEntities(); l.add(getNDGT()); return l; } }, "Prop1"); List<PojoWithAllTypesComplex> pojos = new ArrayList<PojoWithAllTypesComplex>(); producer.register(PojoWithAllTypesComplex.class, "Pojo", Funcs.constant((Iterable<PojoWithAllTypesComplex>) pojos), "Int32"); List<String> stringList = new ArrayList<String>(); stringList.add("tag1"); stringList.add("tag2"); stringList.add("tag3"); PojoWithAllTypes embeddedPojo = new PojoWithAllTypes(new byte[] { 0x04, 0x05, 0x06 }, false, UnsignedByte.valueOf(0xEE), (byte) -0x04, new LocalDateTime(), new BigDecimal("223.456"), 223.456, Guid.randomGuid(), (short) 124, 2, Long.MAX_VALUE - 1, 124.456F, "JohnEmbedded", new LocalTime(), new DateTime()); pojo = new PojoWithAllTypesComplex(new byte[] { 0x01, 0x02, 0x03 }, true, UnsignedByte.valueOf(0xFF), (byte) -0x05, new LocalDateTime(), new BigDecimal("123.456"), 123.456, Guid.randomGuid(), (short) 123, 1, Long.MAX_VALUE, 123.456F, "John", new LocalTime(), new DateTime(), stringList, embeddedPojo); pojo.addComplex1(new Complex1("c1a", "c1b", new Complex2("c2a", "c2b"), null, null)).addComplex1(new Complex1("c2a", "c2b", null, Arrays.asList(new Complex2[] { new Complex2("cc2a", "cc2b") }), Arrays.asList(new String[] { "es1", "es2" }))); pojo.setFavoriteEntity(getNDGT()); pojo.setOnNoticeEntities(getOnNoticeEntities()); pojos.add(pojo); { //String output = this.rtFacade.getWebResource(uri + "$metadata"); //System.out.println(output); } //String output = this.rtFacade.getWebResource(uri + "Pojo?$format=json&$expand=FavoriteEntity,OnNoticeEntities"); //System.out.println(output); } private static Object getPropertyValue(String name, List<OProperty<?>> props) { for (OProperty<?> p : props) { if (p.getName().equals(name)) { return p.getValue(); } } return null; } private static void assertPojoEqualsOEntity(PojoWithAllTypes pojo, OStructuralObject sobject, List<OProperty<?>> props) { Assert.assertEquals(pojo.getBoolean(), getPropertyValue("Boolean", props)); // TODO when Edm.Binary supported by InMemoryProducer // assertArrayEquals(pojo.getBinary(), (byte[])getPropertyValue("Binary", props)); Assert.assertEquals(pojo.getByte(), getPropertyValue("Byte", props)); Assert.assertEquals(pojo.getDateTime(), getPropertyValue("DateTime", props)); Assert.assertTrue(pojo.getDecimal().compareTo((BigDecimal) getPropertyValue("Decimal", props)) == 0); Assert.assertEquals(pojo.getDouble(), getPropertyValue("Double", props)); Assert.assertEquals(pojo.getGuid(), getPropertyValue("Guid", props)); Assert.assertEquals(pojo.getInt16(), getPropertyValue("Int16", props)); Assert.assertEquals(pojo.getInt32(), getPropertyValue("Int32", props)); Assert.assertEquals(pojo.getInt64(), getPropertyValue("Int64", props)); Assert.assertEquals(pojo.getSingle(), getPropertyValue("Single", props)); Assert.assertEquals(pojo.getString(), getPropertyValue("String", props)); Assert.assertEquals(pojo.getTime(), getPropertyValue("Time", props)); Assert.assertTrue(pojo.getDateTimeOffset().isEqual((DateTime) getPropertyValue("DateTimeOffset", props))); if (pojo instanceof PojoWithAllTypesComplex) { // embedded EdmComplexType PojoWithAllTypesComplex pojoC = (PojoWithAllTypesComplex) pojo; assertPojoEqualsOEntity(pojoC.getComplexType(), null, (List<OProperty<?>>) getPropertyValue("ComplexType", props)); // embedded collection(Edm.String) OCollection<OSimpleObject<String>> scollection = (OCollection<OSimpleObject<String>>) getPropertyValue("StringList", props); Assert.assertEquals(scollection.size(), pojoC.getStringList().size()); for (String sl : pojoC.getStringList()) { boolean found = false; for (OSimpleObject<String> so : scollection) { if (((String) so.getValue()).equals(sl)) { found = true; break; } } Assert.assertTrue(found); } // embedded collection(Edm.ComplexType) assertComplexes((OCollection<OComplexObject>) getPropertyValue("Complexes", props), pojoC); // TODO need a generalized differ here... // inlined entity OEntity ndgt = ((OEntity) sobject).getLink("FavoriteEntity", ORelatedEntityLinkInline.class).getRelatedEntity(); assertNDGT(ndgt); List<OEntity> one = ((OEntity) sobject).getLink("OnNoticeEntities", ORelatedEntitiesLinkInline.class).getRelatedEntities(); assertOnNoticeEntities(one); } } private static void assertNDGT(OEntity ndgt) { Assert.assertEquals(getNDGT().getProp1(), getPropertyValue("Prop1", ndgt.getProperties())); } private static void assertOnNoticeEntities(List<OEntity> one) { Assert.assertEquals(2, one.size()); for (OEntity onNotice : one) { boolean found = false; for (Entity1 e1 : getOnNoticeEntities()) { if (e1.getProp1().equals(getPropertyValue("Prop1", onNotice.getProperties())) && getPropertyValue("Prop2", onNotice.getProperties()).equals(e1.getProp2())) { found = true; break; } } Assert.assertTrue(found); } } private static void assertComplexes(OCollection<OComplexObject> ccollection, PojoWithAllTypesComplex pojoC) { Assert.assertEquals(ccollection.size(), pojoC.getComplexes().size()); for (Complex1 c1 : pojoC.getComplexes()) { boolean found = false; for (OComplexObject co : ccollection) { if (((String) getPropertyValue("S1", co.getProperties())).equals(c1.getS1()) && ((String) getPropertyValue("S2", co.getProperties())).equals(c1.getS2())) { found = true; break; } } Assert.assertTrue(found); } } private static void assertArrayEquals(byte[] a, byte[] b) { Assert.assertEquals(a.length, b.length); for (int i = 0; i < a.length; i++) { Assert.assertEquals(a[i], b[i]); } } }