package org.odata4j.test.integration.producer.custom; import static org.junit.Assert.assertTrue; import java.util.ArrayList; import java.util.List; import org.junit.Test; import org.odata4j.consumer.ODataConsumer; import org.odata4j.core.OCollection; import org.odata4j.core.OEntity; import org.odata4j.core.OObject; import org.odata4j.core.OProperty; import org.odata4j.core.OSimpleObject; import org.odata4j.edm.EdmCollectionType; import org.odata4j.edm.EdmComplexType; import org.odata4j.edm.EdmDataServices; import org.odata4j.edm.EdmEntityContainer; import org.odata4j.edm.EdmFunctionImport; import org.odata4j.edm.EdmFunctionParameter; import org.odata4j.edm.EdmProperty; import org.odata4j.edm.EdmProperty.CollectionKind; import org.odata4j.edm.EdmSchema; import org.odata4j.edm.EdmSimpleType; import org.odata4j.edm.EdmStructuralType; import org.odata4j.edm.EdmType; import org.odata4j.format.FormatType; public class CustomTest extends CustomBaseTest { public CustomTest(RuntimeFacadeType type) { super(type); } @Test public void testPropertiesJSON() throws Exception { dumpResourceJSON("Type1s"); testProperties(FormatType.JSONVERBOSE); } @Test public void testPropertiesJSONMinimalMetadata() throws Exception { dumpResourceJSON("Type1s"); testProperties(FormatType.JSON); } @Test public void testPropertiesJSONNometadata() throws Exception { dumpResourceJSON("Type1s"); testProperties(FormatType.JSONLITENOMETADATA); } @Test public void testPropertiesJSONFullMetadata() throws Exception { dumpResourceJSON("Type1s"); testProperties(FormatType.JSONLITEFULLMETADATA); } @Test public void testPropertiesAtom() { // TODO when the xml parsers/writers support Bag properties // testProperties(FormatType.ATOM); } // TODO this probably belongs in a more comprehensize metadata test class... @Test public void testEdmxCreationTypeResolution() { // when producers create EdmDataServices, there should not be multiple // instances of an EdmType object representing the same type. checkForDups(producer.getMetadata()); checkForDups(producer.getMetadataProducer().getMetadata()); } private void checkForDups(EdmDataServices md) { for (EdmStructuralType st : md.getStructuralTypes()) { for (EdmProperty p : st.getDeclaredProperties()) { assertTrue(p.getDeclaringType() == st); checkType(p.getType(), md); } } for (EdmSchema s : md.getSchemas()) { for (EdmEntityContainer c : s.getEntityContainers()) { for (EdmFunctionImport f : c.getFunctionImports()) { checkType(f.getReturnType(), md); for (EdmFunctionParameter p : f.getParameters()) { checkType(p.getType(), md); } } } } } private void checkType(EdmType type, EdmDataServices md) { EdmType checkType = null; if (type.isSimple()) { assertTrue(type instanceof EdmSimpleType); checkType = EdmType.getSimple(type.getFullyQualifiedTypeName()); } else if (type instanceof EdmComplexType) { checkType = md.findEdmComplexType(type.getFullyQualifiedTypeName()); } else { // hmmh...EdmCollectionType is still a little weird...can't make this assertion } if (checkType != null) { assertTrue("two instances of type: " + checkType.getFullyQualifiedTypeName(), type == checkType); } } @Test public void testEdmxFormatParserTypeResolution() throws Exception { // when consumers parse an edm, they should only create one type object // for each unique type. ODataConsumer c = createConsumer(FormatType.JSONVERBOSE); checkForDups(c.getMetadata()); } @Test public void testEdmxFormatParserTypeResolutionMinimalMetadata() throws Exception { ODataConsumer c = createConsumer(FormatType.JSON); checkForDups(c.getMetadata()); } @Test public void testEdmxFormatParserTypeResolutionFullMetadata() throws Exception { ODataConsumer c = createConsumer(FormatType.JSONLITEFULLMETADATA); checkForDups(c.getMetadata()); } @Test public void testEdmxFormatParserTypeResolutionNoMetadata() throws Exception { ODataConsumer c = createConsumer(FormatType.JSONLITENOMETADATA); checkForDups(c.getMetadata()); } @Test public void testEdmxBuilderContext() { dumpResource("$metadata", FormatType.JSONVERBOSE); // add some functions to the edm EdmDataServices.Builder ds = EdmDataServices.newBuilder(producer.getMetadata()); EdmSchema.Builder schema = ds.findSchema("myns"); EdmEntityContainer.Builder container = schema.findEntityContainer("Container1"); EdmComplexType.Builder ct = ds.findEdmComplexType("myns.ComplexType1"); List<EdmFunctionParameter.Builder> params = new ArrayList<EdmFunctionParameter.Builder>(15); params.add(EdmFunctionParameter.newBuilder().input("PBoolean", EdmSimpleType.BOOLEAN)); params.add(EdmFunctionParameter.newBuilder().input("PByte", EdmSimpleType.BYTE)); params.add(EdmFunctionParameter.newBuilder().input("PSByte", EdmSimpleType.SBYTE)); params.add(EdmFunctionParameter.newBuilder().input("PDateTime", EdmSimpleType.DATETIME)); params.add(EdmFunctionParameter.newBuilder().input("PDateTimeOffset", EdmSimpleType.DATETIMEOFFSET)); params.add(EdmFunctionParameter.newBuilder().input("PDecimal", EdmSimpleType.DECIMAL)); params.add(EdmFunctionParameter.newBuilder().input("PDouble", EdmSimpleType.DOUBLE)); params.add(EdmFunctionParameter.newBuilder().input("PGuid", EdmSimpleType.GUID)); params.add(EdmFunctionParameter.newBuilder().input("PInt16", EdmSimpleType.INT16)); params.add(EdmFunctionParameter.newBuilder().input("PInt32", EdmSimpleType.INT32)); params.add(EdmFunctionParameter.newBuilder().input("PInt64", EdmSimpleType.INT64)); params.add(EdmFunctionParameter.newBuilder().input("PSingle", EdmSimpleType.SINGLE)); params.add(EdmFunctionParameter.newBuilder().input("PString", EdmSimpleType.STRING)); params.add(EdmFunctionParameter.newBuilder().input("PTime", EdmSimpleType.TIME)); EdmFunctionImport.Builder f = EdmFunctionImport.newBuilder() .setName("TestFunction1") .setReturnType(ct.build()) .setHttpMethod("GET") .addParameters(params); container.addFunctionImports(f); params = new ArrayList<EdmFunctionParameter.Builder>(1); params.add(EdmFunctionParameter.newBuilder().input("NResults", EdmSimpleType.INT16)); f = EdmFunctionImport.newBuilder() .setName("TestFunction2") .setReturnType(new EdmCollectionType(CollectionKind.Collection, ct.build())) .setHttpMethod("GET") .addParameters(params); container.addFunctionImports(f); checkForDups(ds.build()); } @SuppressWarnings("unchecked") private void testProperties(FormatType format) throws Exception { ODataConsumer c = createConsumer(format); OEntity e = c.getEntity("Type1s", "0").execute(); checkCollection(e.getProperty("EmptyStrings"), EdmSimpleType.STRING, new ValueGenerator() { @Override public Object getValue(int idx) { return null; } @Override public int getNExpected() { return 0; } }); checkCollection(e.getProperty("BagOStrings"), EdmSimpleType.STRING, new ValueGenerator() { @Override public Object getValue(int idx) { return "bagstring-" + idx; } @Override public int getNExpected() { return 3; } }); checkCollection(e.getProperty("ListOStrings"), EdmSimpleType.STRING, new ValueGenerator() { @Override public Object getValue(int idx) { return "liststring-" + idx; } @Override public int getNExpected() { return 5; } }); checkCollection(e.getProperty("BagOInts"), EdmSimpleType.INT32, new ValueGenerator() { @Override public Object getValue(int idx) { return idx; } @Override public int getNExpected() { return 5; } }); OProperty<?> cx = e.getProperty("Complex1"); assertTrue(cx.getType().getFullyQualifiedTypeName().equals("myns.ComplexType1")); List<OProperty<?>> props = (List<OProperty<?>>) cx.getValue(); // uggh...why isn't this an OComplexObject? assertTrue(props.size() == 2); OProperty<?> prop = findProp("Prop1", props); assertTrue(prop != null); assertTrue(prop.getValue() instanceof String); assertTrue(((String) prop.getValue()).equals("Val1")); prop = findProp("Prop2", props); assertTrue(prop != null); assertTrue(prop.getValue() instanceof String); assertTrue(((String) prop.getValue()).equals("Val2")); OProperty<?> ccx = e.getProperty("ListOComplex"); assertTrue(ccx.getType() instanceof EdmCollectionType); EdmCollectionType ct = (EdmCollectionType) ccx.getType(); assertTrue(ct.getItemType().getFullyQualifiedTypeName().equals("myns.ComplexType1")); assertTrue(((OCollection<?>) ccx.getValue()).size() == 2); } private OProperty<?> findProp(String name, List<OProperty<?>> props) { for (OProperty<?> p : props) { if (name.equals(p.getName())) { return p; } } return null; } private static interface ValueGenerator { int getNExpected(); Object getValue(int idx); } @SuppressWarnings("unchecked") private void checkCollection(OProperty<?> prop, EdmType itemType, ValueGenerator vg) { //OProperty<?> prop = e.getProperty("BagOStrings"); assertTrue(prop != null); assertTrue(prop.getType() instanceof EdmCollectionType); EdmCollectionType ct = (EdmCollectionType) prop.getType(); assertTrue(ct.getItemType().equals(itemType)); OCollection<? extends OObject> coll = (OCollection<? extends OObject>) prop.getValue(); assertTrue(coll.size() == vg.getNExpected()); int idx = 0; for (OObject obj : coll) { assertTrue(obj.getType().equals(itemType)); assertTrue(((OSimpleObject<?>) obj).getValue().equals(vg.getValue(idx))); idx += 1; } } }