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]);
}
}
}