Repository: olingo-odata4 Updated Branches: refs/heads/master 73d1e2e07 -> b86aa5d97
[OLINGO-1207] Sample project supporting containment navigation Project: http://git-wip-us.apache.org/repos/asf/olingo-odata4/repo Commit: http://git-wip-us.apache.org/repos/asf/olingo-odata4/commit/b86aa5d9 Tree: http://git-wip-us.apache.org/repos/asf/olingo-odata4/tree/b86aa5d9 Diff: http://git-wip-us.apache.org/repos/asf/olingo-odata4/diff/b86aa5d9 Branch: refs/heads/master Commit: b86aa5d9777854db77d8d29663d79dd58d904c89 Parents: 73d1e2e Author: ramya vasanth <[email protected]> Authored: Fri Dec 1 09:56:36 2017 +0530 Committer: ramya vasanth <[email protected]> Committed: Fri Dec 1 09:56:36 2017 +0530 ---------------------------------------------------------------------- .../olingo/server/tecsvc/data/DataCreator.java | 296 ++++++++++++++++++- .../olingo/server/tecsvc/data/DataProvider.java | 106 +++++++ .../processor/TechnicalEntityProcessor.java | 100 +++++-- .../tecsvc/processor/TechnicalProcessor.java | 20 +- .../tecsvc/provider/ComplexTypeProvider.java | 4 +- .../tecsvc/provider/EntityTypeProvider.java | 52 +++- .../tecsvc/provider/PropertyProvider.java | 66 +++++ .../server/tecsvc/provider/SchemaProvider.java | 3 + .../json/ODataJsonSerializerTest.java | 78 +++++ .../myservice/mynamespace/data/Storage.java | 182 +++++++++++- .../mynamespace/service/DemoEdmProvider.java | 53 ++++ .../service/DemoEntityCollectionProcessor.java | 36 ++- .../service/DemoEntityProcessor.java | 31 +- 13 files changed, 983 insertions(+), 44 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java index 2bed5a2..10e951c 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataCreator.java @@ -94,7 +94,11 @@ public class DataCreator { data.put("ESCompCollDerived", createESCompCollDerived(edm, odata)); data.put("ESTwoPrimDerived", createESTwoPrimDerived(edm, odata)); data.put("ESAllPrimDerived", createESAllPrimDerived(edm, odata)); - data.put("ESDelta", createESDelta(edm, odata)); + data.put("ESDelta", createESDelta(edm, odata)); + data.put("ESKeyNavCont", createESKeyNavCont(edm, odata)); + data.put("ETCont", createETCont(edm, odata)); + data.put("ETBaseCont", createETBaseCont(edm, odata)); + data.put("ETTwoCont", createETTwoCont(edm, odata)); linkSINav(data); linkESTwoPrim(data); @@ -104,6 +108,8 @@ public class DataCreator { linkESTwoKeyNav(data); linkESPeople(data); linkESDelta(data); + linkESKeyNavCont(data); + linkETBaseCont(data); } @@ -1696,6 +1702,35 @@ public class DataCreator { setLinks(entityCollection.getEntities().get(0), "NavPropertyETTwoKeyNavMany", esTwoKeyNavTargets.get(0), esTwoKeyNavTargets.get(1)); } + + private void linkESKeyNavCont(final Map<String, EntityCollection> data) { + final EntityCollection entityCollection = data.get("ESKeyNavCont"); + final List<Entity> targetEntities = data.get("ETCont").getEntities(); + final List<Entity> etBaseContEntities = data.get("ETBaseCont").getEntities(); + + setLinks(entityCollection.getEntities().get(1), "NavPropertyETContMany", targetEntities.get(1), + targetEntities.get(2)); + + setLinkForContNav(entityCollection.getEntities().get(3), "NavPropertyETContOne", targetEntities.get(0)); + + setLinks(entityCollection.getEntities().get(2), "NavPropertyETBaseContMany", etBaseContEntities.get(1), + etBaseContEntities.get(2)); + } + + protected static void setLinkForContNav(final Entity entity, + final String navigationPropertyName, final Entity target) { + Link link = entity.getNavigationLink(navigationPropertyName); + if (link == null) { + link = new Link(); + link.setRel(Constants.NS_NAVIGATION_LINK_REL + navigationPropertyName); + link.setType(Constants.ENTITY_NAVIGATION_LINK_TYPE); + link.setTitle(navigationPropertyName); + link.setHref(entity.getId().toASCIIString() + + (navigationPropertyName != null && navigationPropertyName.length() > 0 ? "/" + navigationPropertyName: "")); + entity.getNavigationLinks().add(link); + } + link.setInlineEntity(target); + } protected static Property createPrimitive(final String name, final Object value) { return new Property(null, name, ValueType.PRIMITIVE, value); @@ -1848,4 +1883,263 @@ public class DataCreator { } } } + + private EntityCollection createESKeyNavCont(final Edm edm, final OData odata) { + EntityCollection entityCollection = new EntityCollection(); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", (short) 32766)) + .addProperty(createPrimitive("PropertyString", "Test String1")) + .addProperty(createComplex("PropertyCompNavCont", + ComplexTypeProvider.nameCTNavCont.getFullQualifiedNameAsString()))); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", (short) -365)) + .addProperty(createPrimitive("PropertyString", "Test String2")) + .addProperty(createComplex("PropertyCompNavCont", + ComplexTypeProvider.nameCTNavCont.getFullQualifiedNameAsString()))); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", (short) -32766)) + .addProperty(createPrimitive("PropertyString", "Test String3")) + .addProperty(createComplex("PropertyCompNavCont", + ComplexTypeProvider.nameCTNavCont.getFullQualifiedNameAsString()))); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE)) + .addProperty(createPrimitive("PropertyString", "Test String4")) + .addProperty(createComplex("PropertyCompNavCont", + ComplexTypeProvider.nameCTNavCont.getFullQualifiedNameAsString()))); + + setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETKeyNavCont)); + createEntityId(edm, odata, "ESKeyNavCont", entityCollection); + createOperations("ESKeyNavCont", entityCollection, EntityTypeProvider.nameETKeyNavCont); + return entityCollection; + } + + private EntityCollection createETCont(final Edm edm, final OData odata) { + EntityCollection entityCollection = new EntityCollection(); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE)) + .addProperty(createPrimitive("PropertyString", "First Resource - positive values")) + .addProperty(createPrimitive("PropertyBoolean", true)) + .addProperty(createPrimitive("PropertyByte", (short) 255)) + .addProperty(createPrimitive("PropertySByte", Byte.MAX_VALUE)) + .addProperty(createPrimitive("PropertyInt32", Integer.MAX_VALUE)) + .addProperty(createPrimitive("PropertyInt64", Long.MAX_VALUE)) + .addProperty(createPrimitive("PropertySingle", (float) 1.79000000E+20)) + .addProperty(createPrimitive("PropertyDouble", -1.7900000000000000E+19)) + .addProperty(createPrimitive("PropertyDecimal", BigDecimal.valueOf(34))) + .addProperty(createPrimitive("PropertyBinary", + new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF })) + .addProperty(createPrimitive("PropertyDate", getDate(2012, 12, 3))) + .addProperty(createPrimitive("PropertyDateTimeOffset", getDateTime(2012, 12, 3, 7, 16, 23))) + .addProperty(createPrimitive("PropertyDuration", BigDecimal.valueOf(6))) + .addProperty(createPrimitive("PropertyGuid", GUID)) + .addProperty(createPrimitive("PropertyTimeOfDay", getTime(3, 26, 5)))); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", Short.MIN_VALUE)) + .addProperty(createPrimitive("PropertyString", "Second Resource - negative values")) + .addProperty(createPrimitive("PropertyBoolean", false)) + .addProperty(createPrimitive("PropertyByte", (short) 0)) + .addProperty(createPrimitive("PropertySByte", Byte.MIN_VALUE)) + .addProperty(createPrimitive("PropertyInt32", Integer.MIN_VALUE)) + .addProperty(createPrimitive("PropertyInt64", Long.MIN_VALUE)) + .addProperty(createPrimitive("PropertySingle", (float) -1.79000000E+08)) + .addProperty(createPrimitive("PropertyDouble", -1.7900000000000000E+05)) + .addProperty(createPrimitive("PropertyDecimal", BigDecimal.valueOf(-34))) + .addProperty(createPrimitive("PropertyBinary", + new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF })) + .addProperty(createPrimitive("PropertyDate", getDate(2015, 11, 5))) + .addProperty(createPrimitive("PropertyDateTimeOffset", getDateTime(2005, 12, 3, 7, 17, 8))) + .addProperty(createPrimitive("PropertyDuration", BigDecimal.valueOf(9))) + .addProperty(createPrimitive("PropertyGuid", UUID.fromString("76543201-23ab-cdef-0123-456789dddfff"))) + .addProperty(createPrimitive("PropertyTimeOfDay", getTime(23, 49, 14)))); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", (short) 0)) + .addProperty(createPrimitive("PropertyString", "")) + .addProperty(createPrimitive("PropertyBoolean", false)) + .addProperty(createPrimitive("PropertyByte", (short) 0)) + .addProperty(createPrimitive("PropertySByte", 0)) + .addProperty(createPrimitive("PropertyInt32", 0)) + .addProperty(createPrimitive("PropertyInt64", 0L)) + .addProperty(createPrimitive("PropertySingle", (float) 0)) + .addProperty(createPrimitive("PropertyDouble", 0D)) + .addProperty(createPrimitive("PropertyDecimal", BigDecimal.valueOf(0))) + .addProperty(createPrimitive("PropertyBinary", new byte[] {})) + .addProperty(createPrimitive("PropertyDate", getDate(1970, 1, 1))) + .addProperty(createPrimitive("PropertyDateTimeOffset", getDateTime(2005, 12, 3, 0, 0, 0))) + .addProperty(createPrimitive("PropertyDuration", BigDecimal.valueOf(0))) + .addProperty(createPrimitive("PropertyGuid", UUID.fromString("76543201-23ab-cdef-0123-456789cccddd"))) + .addProperty(createPrimitive("PropertyTimeOfDay", getTime(0, 1, 1)))); + + setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETCont)); + createEntityId(edm, odata, "ESKeyNavCont", entityCollection); + String id = "ESKeyNavCont(-365)"; + id = id + "/NavPropertyETContMany(" + + entityCollection.getEntities().get(1).getProperty("PropertyInt16").getValue() + ")"; + entityCollection.getEntities().get(1).setId(URI.create(id)); + id = "ESKeyNavCont(-365)"; + id = id + "/NavPropertyETContMany(" + + entityCollection.getEntities().get(2).getProperty("PropertyInt16").getValue() + ")"; + entityCollection.getEntities().get(2).setId(URI.create(id)); + id = "ESKeyNavCont(32766)"; + id = id + "/NavPropertyETContOne(" + + entityCollection.getEntities().get(0).getProperty("PropertyInt16").getValue() + ")"; + entityCollection.getEntities().get(0).setId(URI.create(id)); + return entityCollection; + } + + private EntityCollection createETBaseCont(final Edm edm, final OData odata) { + EntityCollection entityCollection = new EntityCollection(); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE)) + .addProperty(createPrimitive("PropertyString", "First Resource - positive values")) + .addProperty(createPrimitive("PropertyInt32", Integer.MAX_VALUE)) + .addProperty(createPrimitive("PropertyInt64", Long.MAX_VALUE)) + .addProperty(createPrimitive("PropertySingle", (float) 1.79000000E+20)) + .addProperty(createPrimitive("PropertyDouble", -1.7900000000000000E+19)) + .addProperty(createPrimitive("PropertyDecimal", BigDecimal.valueOf(34))) + .addProperty(createPrimitive("PropertyBinary", + new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF })) + .addProperty(createPrimitive("PropertyDate", getDate(2012, 12, 3))) + .addProperty(createPrimitive("PropertyDateTimeOffset", getDateTime(2012, 12, 3, 7, 16, 23))) + .addProperty(createPrimitive("PropertyDuration", BigDecimal.valueOf(6))) + .addProperty(createPrimitive("PropertyGuid", GUID)) + .addProperty(createPrimitive("PropertyTimeOfDay", getTime(3, 26, 5)))); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", Short.MIN_VALUE)) + .addProperty(createPrimitive("PropertyString", "Second Resource - negative values")) + .addProperty(createPrimitive("PropertyInt32", Integer.MIN_VALUE)) + .addProperty(createPrimitive("PropertyInt64", Long.MIN_VALUE)) + .addProperty(createPrimitive("PropertySingle", (float) -1.79000000E+08)) + .addProperty(createPrimitive("PropertyDouble", -1.7900000000000000E+05)) + .addProperty(createPrimitive("PropertyDecimal", BigDecimal.valueOf(-34))) + .addProperty(createPrimitive("PropertyBinary", + new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF })) + .addProperty(createPrimitive("PropertyDate", getDate(2015, 11, 5))) + .addProperty(createPrimitive("PropertyDateTimeOffset", getDateTime(2005, 12, 3, 7, 17, 8))) + .addProperty(createPrimitive("PropertyDuration", BigDecimal.valueOf(9))) + .addProperty(createPrimitive("PropertyGuid", UUID.fromString("76543201-23ab-cdef-0123-456789dddfff"))) + .addProperty(createPrimitive("PropertyTimeOfDay", getTime(23, 49, 14)))); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", (short) 0)) + .addProperty(createPrimitive("PropertyString", "")) + .addProperty(createPrimitive("PropertyInt32", 0)) + .addProperty(createPrimitive("PropertyInt64", 0L)) + .addProperty(createPrimitive("PropertySingle", (float) 0)) + .addProperty(createPrimitive("PropertyDouble", 0D)) + .addProperty(createPrimitive("PropertyDecimal", BigDecimal.valueOf(0))) + .addProperty(createPrimitive("PropertyBinary", new byte[] {})) + .addProperty(createPrimitive("PropertyDate", getDate(1970, 1, 1))) + .addProperty(createPrimitive("PropertyDateTimeOffset", getDateTime(2005, 12, 3, 0, 0, 0))) + .addProperty(createPrimitive("PropertyDuration", BigDecimal.valueOf(0))) + .addProperty(createPrimitive("PropertyGuid", UUID.fromString("76543201-23ab-cdef-0123-456789cccddd"))) + .addProperty(createPrimitive("PropertyTimeOfDay", getTime(0, 1, 1)))); + + setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETBaseCont)); + createEntityId(edm, odata, "ESKeyNavCont", entityCollection); + String id = "ESKeyNavCont(-32766)"; + id = id + "/NavPropertyETBaseContMany(" + + entityCollection.getEntities().get(1).getProperty("PropertyInt16").getValue() + ")"; + entityCollection.getEntities().get(1).setId(URI.create(id)); + id = "ESKeyNavCont(-32766)"; + id = id + "/NavPropertyETBaseContMany(" + + entityCollection.getEntities().get(2).getProperty("PropertyInt16").getValue() + ")"; + entityCollection.getEntities().get(2).setId(URI.create(id)); + return entityCollection; + } + + private void linkETBaseCont(final Map<String, EntityCollection> data) { + final EntityCollection entityCollection = data.get("ETBaseCont"); + final List<Entity> etTwoContEntities = data.get("ETTwoCont").getEntities(); + + setLinkForContNav(entityCollection.getEntities().get(1), + "NavPropertyETBaseContTwoContOne", etTwoContEntities.get(0)); + + setLinks(entityCollection.getEntities().get(2), "NavPropertyETBaseContTwoContMany", etTwoContEntities.get(1), + etTwoContEntities.get(2)); + } + + private EntityCollection createETTwoCont(final Edm edm, final OData odata) { + EntityCollection entityCollection = new EntityCollection(); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", Short.MAX_VALUE)) + .addProperty(createPrimitive("PropertyString", "First Resource - positive values")) + .addProperty(createPrimitive("PropertyBoolean", true)) + .addProperty(createPrimitive("PropertyByte", (short) 255)) + .addProperty(createPrimitive("PropertySByte", Byte.MAX_VALUE)) + .addProperty(createPrimitive("PropertyInt32", Integer.MAX_VALUE)) + .addProperty(createPrimitive("PropertyInt64", Long.MAX_VALUE)) + .addProperty(createPrimitive("PropertySingle", (float) 1.79000000E+20)) + .addProperty(createPrimitive("PropertyDouble", -1.7900000000000000E+19)) + .addProperty(createPrimitive("PropertyDecimal", BigDecimal.valueOf(34))) + .addProperty(createPrimitive("PropertyBinary", + new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF })) + .addProperty(createPrimitive("PropertyDate", getDate(2012, 12, 3))) + .addProperty(createPrimitive("PropertyDateTimeOffset", getDateTime(2012, 12, 3, 7, 16, 23))) + .addProperty(createPrimitive("PropertyDuration", BigDecimal.valueOf(6))) + .addProperty(createPrimitive("PropertyGuid", GUID)) + .addProperty(createPrimitive("PropertyTimeOfDay", getTime(3, 26, 5)))); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", Short.MIN_VALUE)) + .addProperty(createPrimitive("PropertyString", "Second Resource - negative values")) + .addProperty(createPrimitive("PropertyBoolean", false)) + .addProperty(createPrimitive("PropertyByte", (short) 0)) + .addProperty(createPrimitive("PropertySByte", Byte.MIN_VALUE)) + .addProperty(createPrimitive("PropertyInt32", Integer.MIN_VALUE)) + .addProperty(createPrimitive("PropertyInt64", Long.MIN_VALUE)) + .addProperty(createPrimitive("PropertySingle", (float) -1.79000000E+08)) + .addProperty(createPrimitive("PropertyDouble", -1.7900000000000000E+05)) + .addProperty(createPrimitive("PropertyDecimal", BigDecimal.valueOf(-34))) + .addProperty(createPrimitive("PropertyBinary", + new byte[] { 0x01, 0x23, 0x45, 0x67, (byte) 0x89, (byte) 0xAB, (byte) 0xCD, (byte) 0xEF })) + .addProperty(createPrimitive("PropertyDate", getDate(2015, 11, 5))) + .addProperty(createPrimitive("PropertyDateTimeOffset", getDateTime(2005, 12, 3, 7, 17, 8))) + .addProperty(createPrimitive("PropertyDuration", BigDecimal.valueOf(9))) + .addProperty(createPrimitive("PropertyGuid", UUID.fromString("76543201-23ab-cdef-0123-456789dddfff"))) + .addProperty(createPrimitive("PropertyTimeOfDay", getTime(23, 49, 14)))); + + entityCollection.getEntities().add(new Entity() + .addProperty(createPrimitive("PropertyInt16", (short) 0)) + .addProperty(createPrimitive("PropertyString", "")) + .addProperty(createPrimitive("PropertyBoolean", false)) + .addProperty(createPrimitive("PropertyByte", (short) 0)) + .addProperty(createPrimitive("PropertySByte", 0)) + .addProperty(createPrimitive("PropertyInt32", 0)) + .addProperty(createPrimitive("PropertyInt64", 0L)) + .addProperty(createPrimitive("PropertySingle", (float) 0)) + .addProperty(createPrimitive("PropertyDouble", 0D)) + .addProperty(createPrimitive("PropertyDecimal", BigDecimal.valueOf(0))) + .addProperty(createPrimitive("PropertyBinary", new byte[] {})) + .addProperty(createPrimitive("PropertyDate", getDate(1970, 1, 1))) + .addProperty(createPrimitive("PropertyDateTimeOffset", getDateTime(2005, 12, 3, 0, 0, 0))) + .addProperty(createPrimitive("PropertyDuration", BigDecimal.valueOf(0))) + .addProperty(createPrimitive("PropertyGuid", UUID.fromString("76543201-23ab-cdef-0123-456789cccddd"))) + .addProperty(createPrimitive("PropertyTimeOfDay", getTime(0, 1, 1)))); + + setEntityType(entityCollection, edm.getEntityType(EntityTypeProvider.nameETTwoCont)); + createEntityId(edm, odata, "ESKeyNavCont", entityCollection); + String id = "ESKeyNavCont(-32766)/NavPropertyETBaseContMany(-32768)"; + id = id + "/NavPropertyETBaseContTwoContOne(" + + entityCollection.getEntities().get(0).getProperty("PropertyInt16").getValue() + ")"; + entityCollection.getEntities().get(0).setId(URI.create(id)); + id = "ESKeyNavCont(-32766)/NavPropertyETBaseContMany(0)"; + id = id + "/NavPropertyETBaseContTwoContMany(" + + entityCollection.getEntities().get(1).getProperty("PropertyInt16").getValue() + ")"; + entityCollection.getEntities().get(1).setId(URI.create(id)); + id = "ESKeyNavCont(-32766)/NavPropertyETBaseContMany(0)"; + id = id + "/NavPropertyETBaseContTwoContMany(" + + entityCollection.getEntities().get(2).getProperty("PropertyInt16").getValue() + ")"; + entityCollection.getEntities().get(2).setId(URI.create(id)); + return entityCollection; + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java index c76f04b..0682c15 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/data/DataProvider.java @@ -31,6 +31,7 @@ import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; +import org.apache.olingo.commons.api.Constants; import org.apache.olingo.commons.api.data.ComplexValue; import org.apache.olingo.commons.api.data.DeletedEntity; import org.apache.olingo.commons.api.data.DeletedEntity.Reason; @@ -870,4 +871,109 @@ public class DataProvider { } return null; } + + public Entity createContNav(final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, + final Entity newEntity, List<UriParameter> keys, String navPropertyName) throws DataProviderException { + List<Entity> rootEntity = data.get(edmEntitySet.getName()).getEntities(); + EntityCollection entitySet = data.get(edmEntityType.getName()); + entitySet.getEntities().add(newEntity); + + + + for (Entity entity : rootEntity) { + if (isRootEntity(entity, keys)){ + String id = entity.getId().toASCIIString() + "/" + navPropertyName + + appendKeys(newEntity.getProperties(), edmEntityType.getKeyPredicateNames()); + newEntity.setId(URI.create(id)); + + Link link = entity.getNavigationLink(navPropertyName); + if (link == null) { + link = new Link(); + link.setRel(Constants.NS_NAVIGATION_LINK_REL + navPropertyName); + link.setType(Constants.ENTITY_NAVIGATION_LINK_TYPE); + link.setTitle(navPropertyName); + link.setHref(entity.getId().toASCIIString() + + (navPropertyName != null && navPropertyName.length() > 0 ? "/" + navPropertyName: "")); + entity.getNavigationLinks().add(link); + } + if (link.getInlineEntitySet() != null) { + link.getInlineEntitySet().getEntities().add(newEntity); + } else { + EntityCollection collection = new EntityCollection(); + collection.getEntities().add(newEntity); + link.setInlineEntitySet(collection); + } + } + } + + return newEntity; + } + + private String appendKeys(List<Property> properties, List<String> keyNames) { + StringBuilder keyValue = new StringBuilder(); + keyValue.append("("); + for (int i = 0; i < keyNames.size(); i++) { + for (Property property : properties) { + if (property.getName().equals(keyNames.get(i))) { + keyValue.append(property.getName()).append("="); + keyValue.append(property.getValue()); + } + if (i < keyNames.size() - 1) { + keyValue.append(","); + } + } + } + keyValue.append(")"); + return keyValue.toString(); + } + + private boolean isRootEntity(Entity entity, List<UriParameter> keys) { + boolean found = false; + for (UriParameter key : keys) { + if (entity.getProperty(key.getName()).getValue().toString().equals(key.getText())) { + found = true; + } else { + found = false; + } + } + return found; + } + + public Entity readDataFromEntity(final EdmEntityType edmEntityType, + final List<UriParameter> keys) throws DataProviderException { + EntityCollection coll = data.get(edmEntityType.getName()); + List<Entity> entities = coll.getEntities(); + try { + for (final Entity entity : entities) { + boolean found = true; + for (final UriParameter key : keys) { + EdmKeyPropertyRef refType = edmEntityType.getKeyPropertyRef(key.getName()); + Object value = findPropertyRefValue(entity, refType); + + final EdmProperty property = refType.getProperty(); + final EdmPrimitiveType type = (EdmPrimitiveType) property.getType(); + + if (key.getExpression() != null && !(key.getExpression() instanceof Literal)) { + throw new DataProviderException("Expression in key value is not supported yet!", + HttpStatusCode.NOT_IMPLEMENTED); + } + final String text = key.getAlias() == null ? key.getText() : ((Literal) key.getExpression()).getText(); + final Object keyValue = type.valueOfString(type.fromUriLiteral(text), + property.isNullable(), property.getMaxLength(), property.getPrecision(), property.getScale(), + property.isUnicode(), + Calendar.class.isAssignableFrom(value.getClass()) ? Calendar.class : value.getClass()); + if (!value.equals(keyValue)) { + found = false; + break; + } + } + if (found) { + return entity; + } + } + return null; + } catch (final EdmPrimitiveTypeException e) { + throw new DataProviderException("Wrong key!", HttpStatusCode.BAD_REQUEST, e); + } + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java index 207a0f2..f7bf618 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalEntityProcessor.java @@ -175,7 +175,9 @@ public class TechnicalEntityProcessor extends TechnicalProcessor public void createEntity(final ODataRequest request, final ODataResponse response, final UriInfo uriInfo, final ContentType requestFormat, final ContentType responseFormat) throws ODataApplicationException, ODataLibraryException { - if (uriInfo.asUriInfoResource().getUriResourceParts().size() > 1) { + final boolean isContNav = checkIfContNavigation(uriInfo); + if (uriInfo.asUriInfoResource().getUriResourceParts().size() > 1 && !isContNav || + isContNav && uriInfo.asUriInfoResource().getUriResourceParts().size() > 2) { throw new ODataApplicationException("Invalid resource type.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } @@ -194,7 +196,11 @@ public class TechnicalEntityProcessor extends TechnicalProcessor final UriResourceEntitySet resourceEntitySet = (UriResourceEntitySet) uriInfo.getUriResourceParts().get(0); final EdmEntitySet edmEntitySet = resourceEntitySet.getEntitySet(); - final EdmEntityType edmEntityType = edmEntitySet.getEntityType(); + EdmEntityType edmEntityType = null; + edmEntityType = getEdmTypeForContNavProperty(uriInfo); + if (edmEntityType == null) { + edmEntityType = edmEntitySet.getEntityType(); + } final Entity entity; ExpandOption expand = null; @@ -208,8 +214,14 @@ public class TechnicalEntityProcessor extends TechnicalProcessor new RequestValidator(dataProvider, request.getRawBaseUri()) .validate(edmEntitySet, deserializerResult.getEntity()); - entity = dataProvider.create(edmEntitySet); - dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, deserializerResult.getEntity(), false, true); + if (isContNav) { + entity = dataProvider.createContNav(edmEntitySet, edmEntityType, deserializerResult.getEntity(), + ((UriResourceEntitySet)uriInfo.getUriResourceParts().get(0)).getKeyPredicates(), + ((UriResourceNavigation)uriInfo.getUriResourceParts().get(1)).getSegmentValue()); + } else { + entity = dataProvider.create(edmEntitySet); + dataProvider.update(request.getRawBaseUri(), edmEntitySet, entity, deserializerResult.getEntity(), false, true); + } expand = deserializerResult.getExpandTree(); } @@ -217,8 +229,8 @@ public class TechnicalEntityProcessor extends TechnicalProcessor + odata.createUriHelper().buildCanonicalURL(edmEntitySet, entity); final Return returnPreference = odata.createPreferences(request.getHeaders(HttpHeader.PREFER)).getReturn(); if (returnPreference == null || returnPreference == Return.REPRESENTATION) { - response.setContent(serializeEntity(request, entity, edmEntitySet, edmEntityType, responseFormat, expand, null) - .getContent()); + response.setContent(serializeEntity(request, entity, edmEntitySet, edmEntityType, responseFormat, + expand, null, isContNav).getContent()); response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); response.setStatusCode(HttpStatusCode.CREATED.getStatusCode()); } else { @@ -450,7 +462,12 @@ public class TechnicalEntityProcessor extends TechnicalProcessor //for Singleton/$ref edmEntityset will be null throw error validateSingletonRef(isReference,edmEntitySet); - final EdmEntityType edmEntityType = getEdmType(uriInfo, edmEntitySet); + EdmEntityType edmEntityType = null; + edmEntityType = getEdmTypeForContNavProperty(uriInfo); + final boolean iscontNav = checkIfContNavigation(uriInfo); + if (edmEntityType == null) { + edmEntityType = getEdmType(uriInfo, edmEntitySet); + } final Entity entity = readEntity(uriInfo); @@ -472,7 +489,8 @@ public class TechnicalEntityProcessor extends TechnicalProcessor final SerializerResult serializerResult = isReference ? serializeReference(entity, edmEntitySet, requestedFormat) : - serializeEntity(request, entitySerialization, edmEntitySet, edmEntityType, requestedFormat, expand, select); + serializeEntity(request, entitySerialization, edmEntitySet, edmEntityType, + requestedFormat, expand, select, iscontNav); if (entity.getETag() != null) { response.setHeader(HttpHeader.ETAG, entity.getETag()); @@ -481,6 +499,39 @@ public class TechnicalEntityProcessor extends TechnicalProcessor response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, requestedFormat.toContentTypeString()); } + + private boolean checkIfContNavigation(UriInfo uriInfo) { + List<UriResource> pathSegments = uriInfo.getUriResourceParts(); + for(UriResource resource : pathSegments) { + if (resource instanceof UriResourceNavigation) { + UriResourceNavigation navResource = (UriResourceNavigation) resource; + if (navResource.getProperty().containsTarget()) { + return true; + } + } + } + return false; + } + + private EdmEntityType getEdmTypeForContNavProperty(UriInfo uriInfo) { + List<UriResource> pathSegments = uriInfo.getUriResourceParts(); + EdmEntityType type = null; + for(UriResource resource : pathSegments) { + if (resource instanceof UriResourceNavigation) { + UriResourceNavigation navResource = (UriResourceNavigation) resource; + if (navResource.getProperty().containsTarget()) { + if (navResource.getTypeFilterOnCollection() != null) { + type = ((EdmEntityType) navResource.getTypeFilterOnCollection()); + } else if (navResource.getTypeFilterOnEntry() != null) { + type = ((EdmEntityType) navResource.getTypeFilterOnEntry()); + } else { + type = ((EdmEntityType) navResource.getType()); + } + } + } + } + return type; + } /*This method validates if the $ref is called directly on Singleton * Error is thrown when $ref is called on a Singleton as it is not implemented*/ @@ -530,10 +581,15 @@ public class TechnicalEntityProcessor extends TechnicalProcessor // final EdmEntitySet edmEntitySet = getEdmEntitySet(uriInfo.asUriInfoResource()); - final EdmEntityType edmEntityType = edmEntitySet == null ? - (EdmEntityType) ((UriResourcePartTyped) uriInfo.getUriResourceParts() - .get(uriInfo.getUriResourceParts().size() - 1)).getType() : - edmEntitySet.getEntityType(); + final boolean isContNav = checkIfContNavigation(uriInfo); + EdmEntityType edmEntityType = null; + edmEntityType = getEdmTypeForContNavProperty(uriInfo); + if (edmEntityType == null) { + edmEntityType = edmEntitySet == null ? + (EdmEntityType) ((UriResourcePartTyped) uriInfo.getUriResourceParts() + .get(uriInfo.getUriResourceParts().size() - 1)).getType() : + edmEntitySet.getEntityType(); + } EntityCollection entitySetInitial = readEntityCollection(uriInfo); Delta delta = null; @@ -640,7 +696,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor final SerializerResult serializerResult = serializeEntityCollection(request, entitySetSerialization, edmEntitySet, edmEntityType, requestedContentType, - expand, select, countOption, id); + expand, select, countOption, id, isContNav); response.setContent(serializerResult.getContent()); } @@ -681,7 +737,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor edmEntityType, delta, EntityCollectionSerializerOptions.with() .contextURL(isODataMetadataNone(requestedFormat) ? null : - getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select)) + getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select, false)) .count(countOption) .expand(expand).select(select) .id(id) @@ -707,7 +763,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor private SerializerResult serializeEntityCollection(final ODataRequest request, final EntityCollection entityCollection, final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, final ContentType requestedFormat, final ExpandOption expand, final SelectOption select, - final CountOption countOption, String id) throws ODataLibraryException { + final CountOption countOption, String id, final boolean isContNav) throws ODataLibraryException { return odata.createSerializer(requestedFormat, request.getHeaders(HttpHeader.ODATA_VERSION)) .entityCollection( @@ -716,7 +772,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor entityCollection, EntityCollectionSerializerOptions.with() .contextURL(isODataMetadataNone(requestedFormat) ? null : - getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select)) + getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select, isContNav)) .count(countOption) .expand(expand).select(select) .id(id) @@ -797,7 +853,7 @@ public class TechnicalEntityProcessor extends TechnicalProcessor streamCollection, EntityCollectionSerializerOptions.with() .contextURL(isODataMetadataNone(requestedFormat) ? null : - getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select)) + getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, false, expand, select, false)) .count(countOption) .expand(expand).select(select) .id(id) @@ -826,17 +882,17 @@ public class TechnicalEntityProcessor extends TechnicalProcessor private SerializerResult serializeEntity(final ODataRequest request, final Entity entity, final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, final ContentType requestedFormat) throws ODataLibraryException { - return serializeEntity(request, entity, edmEntitySet, edmEntityType, requestedFormat, null, null); + return serializeEntity(request, entity, edmEntitySet, edmEntityType, requestedFormat, null, null, false); } private SerializerResult serializeEntity(final ODataRequest request, final Entity entity, final EdmEntitySet edmEntitySet, final EdmEntityType edmEntityType, final ContentType requestedFormat, - final ExpandOption expand, final SelectOption select) + final ExpandOption expand, final SelectOption select, final boolean isContNav) throws ODataLibraryException { ContextURL contextUrl = isODataMetadataNone(requestedFormat) ? null : - getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, true, expand, null); + getContextUrl(request.getRawODataPath(), edmEntitySet, edmEntityType, true, expand, null,isContNav); return odata.createSerializer(requestedFormat, request.getHeaders(HttpHeader.ODATA_VERSION)).entity( serviceMetadata, edmEntityType, @@ -848,12 +904,12 @@ public class TechnicalEntityProcessor extends TechnicalProcessor } private ContextURL getContextUrl(String rawODataPath, final EdmEntitySet entitySet, final EdmEntityType entityType, - final boolean isSingleEntity, final ExpandOption expand, final SelectOption select) + final boolean isSingleEntity, final ExpandOption expand, final SelectOption select, final boolean isContNav) throws ODataLibraryException { Builder builder = ContextURL.with().oDataPath(rawODataPath); builder = entitySet == null ? isSingleEntity ? builder.type(entityType) : builder.asCollection().type(entityType) : - builder.entitySet(entitySet); + !isContNav ? builder.entitySet(entitySet) : builder.entitySetOrSingletonOrType(rawODataPath.substring(1)); builder = builder .selectList(odata.createUriHelper().buildContextURLSelectList(entityType, expand, select)) .suffix(isSingleEntity && entitySet != null ? Suffix.ENTITY : null); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java index 31afcfa..42627eb 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/processor/TechnicalProcessor.java @@ -111,8 +111,7 @@ public abstract class TechnicalProcessor implements Processor { (UriResourceNavigation) resourcePaths.get(navigationCount); blockTypeFilters(uriResourceNavigation); if (uriResourceNavigation.getProperty().containsTarget()) { - throw new ODataApplicationException("Containment navigation is not supported.", - HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + return entitySet; } EdmBindingTarget target = null ; if(entitySet!=null){ @@ -203,6 +202,8 @@ public abstract class TechnicalProcessor implements Processor { key.isEmpty() ? link.getInlineEntity() : dataProvider.read(navigationProperty.getType(), link.getInlineEntitySet(), key); + EdmEntityType edmEntityType = getEntityTypeBasedOnNavPropertyTypeCast(uriNavigationResource); + entity = edmEntityType != null ? dataProvider.readDataFromEntity(edmEntityType, key) : entity; if (entity == null) { throw new ODataApplicationException("Nothing found.", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ROOT); } @@ -210,6 +211,16 @@ public abstract class TechnicalProcessor implements Processor { return entity; } + + private EdmEntityType getEntityTypeBasedOnNavPropertyTypeCast(UriResourceNavigation uriNavigationResource) { + if (uriNavigationResource.getTypeFilterOnCollection() != null) { + return (EdmEntityType) uriNavigationResource.getTypeFilterOnCollection(); + } else if (uriNavigationResource.getTypeFilterOnEntry() != null) { + return (EdmEntityType) uriNavigationResource.getTypeFilterOnEntry(); + } + return null; + + } protected EdmEntitySet getEntitySetBasedOnTypeCast(UriResourceEntitySet uriResource) { EdmEntitySet entitySet = null; @@ -301,10 +312,7 @@ public abstract class TechnicalProcessor implements Processor { private void blockTypeFilters(final UriResource uriResource) throws ODataApplicationException { if (uriResource instanceof UriResourceFunction && (((UriResourceFunction) uriResource).getTypeFilterOnCollection() != null - || ((UriResourceFunction) uriResource).getTypeFilterOnEntry() != null) - || uriResource instanceof UriResourceNavigation - && (((UriResourceNavigation) uriResource).getTypeFilterOnCollection() != null - || ((UriResourceNavigation) uriResource).getTypeFilterOnEntry() != null)) { + || ((UriResourceFunction) uriResource).getTypeFilterOnEntry() != null)) { throw new ODataApplicationException("Type filters are not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java index 114acef..0b4d726 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/ComplexTypeProvider.java @@ -182,7 +182,9 @@ public class ComplexTypeProvider { PropertyProvider.navPropertyETKeyNavOne_CT_ETeyNav, PropertyProvider.collectionNavPropertyETKeyNavMany_CT_ETKeyNav, PropertyProvider.navPropertyETTwoKeyNavOne_CT_ETTwoKeyNav, - PropertyProvider.collectionNavPropertyETTwoKeyNavMany_CT_ETTwoKeyNav + PropertyProvider.collectionNavPropertyETTwoKeyNavMany_CT_ETTwoKeyNav, + PropertyProvider.navPropertyETTwoKeyNavMany_CT_ETCont, + PropertyProvider.collectionNavPropertyETTwoKeyNavMany_CT_ETBaseCont )); } else if (complexTypeName.equals(nameCTBasePrimCompNav)) { http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java index 6178c48..079a1f8 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/EntityTypeProvider.java @@ -91,7 +91,13 @@ public class EntityTypeProvider { new FullQualifiedName(SchemaProvider.NAMESPACE, "ETDelta"); public static final FullQualifiedName nameETPeople = new FullQualifiedName(SchemaProvider.NAMESPACE, "ETPeople"); - + + public static final FullQualifiedName nameETCont = new FullQualifiedName(SchemaProvider.NAMESPACE, "ETCont"); + + public static final FullQualifiedName nameETBaseCont = new FullQualifiedName(SchemaProvider.NAMESPACE, "ETBaseCont"); + + public static final FullQualifiedName nameETTwoCont = new FullQualifiedName(SchemaProvider.NAMESPACE, "ETTwoCont"); + public CsdlEntityType getEntityType(final FullQualifiedName entityTypeName) throws ODataException { if(entityTypeName.equals(nameETAllPrimDefaultValues)){ return new CsdlEntityType() @@ -382,7 +388,10 @@ public class EntityTypeProvider { PropertyProvider.navPropertyETTwoKeyNavOneCT_ETTwoKeyNav, PropertyProvider.collectionNavPropertyETTwoKeyNavMany_CT_ETTwoKeyNav, PropertyProvider.navPropertyETTwoKeyNavContOne_ETTwoKeyNav, - PropertyProvider.collectionNavPropertyETTwoKeyNavContMany_ETTwoKeyNav + PropertyProvider.collectionNavPropertyETTwoKeyNavContMany_ETTwoKeyNav, + PropertyProvider.navPropertyETTwoKeyNavContOne_ETCont, + PropertyProvider.collectionNavPropertyETTwoKeyNavContMany_ETCont, + PropertyProvider.collectionNavPropertyETTwoKeyNavContMany_ETBaseCont )); } else if (entityTypeName.equals(nameETTwoKeyNavCont)) { @@ -514,7 +523,44 @@ public class EntityTypeProvider { .setNavigationProperties( Arrays.asList(PropertyProvider.navPropertyETAllPrimOne_ETAllPrim, PropertyProvider.collectionNavPropertyETAllPrimMany_ETAllPrim)); - } + } else if (entityTypeName.equals(nameETCont)) { + return new CsdlEntityType() + .setName("ETCont").setBaseType(nameETBaseCont) + .setProperties(Arrays.asList( + PropertyProvider.propertyBoolean, PropertyProvider.propertyByte, PropertyProvider.propertySByte + )) + .setNavigationProperties(Arrays.asList(PropertyProvider.navPropertyETCont_ETTwoPrim, + PropertyProvider.collectionNavPropertyETContMany_ETTwoPrim)); + } else if (entityTypeName.equals(nameETBaseCont)) { + return new CsdlEntityType() + .setName("ETBaseCont") + .setKey(Arrays.asList( + new CsdlPropertyRef().setName("PropertyInt16"))) + .setProperties(Arrays.asList( + PropertyProvider.propertyInt16_NotNullable, PropertyProvider.propertyString, + PropertyProvider.propertyInt32, PropertyProvider.propertyInt64, + PropertyProvider.propertySingle, PropertyProvider.propertyDouble, PropertyProvider.propertyDecimal_Scale, + PropertyProvider.propertyBinary, PropertyProvider.propertyDate, PropertyProvider.propertyDateTimeOffset, + PropertyProvider.propertyDuration, PropertyProvider.propertyGuid, PropertyProvider.propertyTimeOfDay + )) + .setNavigationProperties(Arrays.asList(PropertyProvider.navPropertyETBaseCont_ETTwoPrim, + PropertyProvider.collectionNavPropertyETBaseContMany_ETTwoPrim, + PropertyProvider.collectionNavPropertyETBaseContMany_ETTwoCont, + PropertyProvider.navPropertyETBaseCont_ETTwoCont)); + } else if (entityTypeName.equals(nameETTwoCont)) { + return new CsdlEntityType() + .setName("ETTwoCont") + .setKey(Arrays.asList( + new CsdlPropertyRef().setName("PropertyInt16"), + new CsdlPropertyRef().setName("PropertyString"))) + .setProperties(Arrays.asList( + PropertyProvider.propertyInt16_NotNullable, PropertyProvider.propertyString_NotNullable, + PropertyProvider.propertyInt32, PropertyProvider.propertyInt64, + PropertyProvider.propertySingle, PropertyProvider.propertyDouble, PropertyProvider.propertyDecimal_Scale, + PropertyProvider.propertyBinary, PropertyProvider.propertyDate, PropertyProvider.propertyDateTimeOffset, + PropertyProvider.propertyDuration, PropertyProvider.propertyGuid, PropertyProvider.propertyTimeOfDay + )); + } return null; } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java index f991d7f..e74fd6d 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/PropertyProvider.java @@ -952,4 +952,70 @@ public class PropertyProvider { .setType(EntityTypeProvider.nameETPeople) .setNullable(true) .setCollection(true); + + public static final CsdlNavigationProperty navPropertyETCont_ETTwoPrim = new CsdlNavigationProperty() + .setName("NavPropertyETContOne") + .setType(EntityTypeProvider.nameETTwoPrim) + .setNullable(false); + + public static final CsdlNavigationProperty collectionNavPropertyETContMany_ETTwoPrim = + new CsdlNavigationProperty() + .setName("NavPropertyETContMany") + .setType(EntityTypeProvider.nameETTwoPrim) + .setCollection(true); + + public static final CsdlNavigationProperty navPropertyETBaseCont_ETTwoPrim = new CsdlNavigationProperty() + .setName("NavPropertyETBaseContOne") + .setType(EntityTypeProvider.nameETTwoBase) + .setNullable(false); + + public static final CsdlNavigationProperty collectionNavPropertyETBaseContMany_ETTwoPrim = + new CsdlNavigationProperty() + .setName("NavPropertyETBaseContMany") + .setType(EntityTypeProvider.nameETTwoBase) + .setCollection(true); + + public static final CsdlNavigationProperty navPropertyETBaseCont_ETTwoCont = new CsdlNavigationProperty() + .setName("NavPropertyETBaseContTwoContOne") + .setType(EntityTypeProvider.nameETTwoCont).setContainsTarget(true) + .setNullable(false); + + public static final CsdlNavigationProperty collectionNavPropertyETBaseContMany_ETTwoCont = + new CsdlNavigationProperty() + .setName("NavPropertyETBaseContTwoContMany") + .setType(EntityTypeProvider.nameETTwoCont).setContainsTarget(true) + .setCollection(true); + + public static final CsdlNavigationProperty navPropertyETTwoKeyNavContOne_ETCont = new CsdlNavigationProperty() + .setName("NavPropertyETContOne") + .setContainsTarget(true) + .setType(EntityTypeProvider.nameETCont); + + public static final CsdlNavigationProperty collectionNavPropertyETTwoKeyNavContMany_ETCont = + new CsdlNavigationProperty() + .setName("NavPropertyETContMany") + .setContainsTarget(true) + .setType(EntityTypeProvider.nameETCont) + .setCollection(true); + + public static final CsdlNavigationProperty collectionNavPropertyETTwoKeyNavContMany_ETBaseCont = + new CsdlNavigationProperty() + .setName("NavPropertyETBaseContMany") + .setContainsTarget(true) + .setType(EntityTypeProvider.nameETBaseCont) + .setCollection(true); + + public static final CsdlNavigationProperty navPropertyETTwoKeyNavMany_CT_ETCont = + new CsdlNavigationProperty() + .setName("NavPropertyETTwoKeyNavETContOne") + .setContainsTarget(true) + .setType(EntityTypeProvider.nameETCont); + + public static final CsdlNavigationProperty collectionNavPropertyETTwoKeyNavMany_CT_ETBaseCont = + new CsdlNavigationProperty() + .setName("NavPropertyETTwoKeyNavETContMany") + .setContainsTarget(true) + .setCollection(true) + .setType(EntityTypeProvider.nameETBaseCont); + } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java ---------------------------------------------------------------------- diff --git a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java index 074870e..72c4f27 100644 --- a/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java +++ b/lib/server-tecsvc/src/main/java/org/apache/olingo/server/tecsvc/provider/SchemaProvider.java @@ -87,6 +87,9 @@ public class SchemaProvider { entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETKeyPrimNav)); entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETStream)); entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETDelta)); + entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETCont)); + entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETBaseCont)); + entityTypes.add(prov.getEntityType(EntityTypeProvider.nameETTwoCont)); // ComplexTypes List<CsdlComplexType> complexTypes = new ArrayList<CsdlComplexType>(); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java ---------------------------------------------------------------------- diff --git a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java index f092246..80b00fd 100644 --- a/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java +++ b/lib/server-test/src/test/java/org/apache/olingo/server/core/serializer/json/ODataJsonSerializerTest.java @@ -39,6 +39,7 @@ import org.apache.olingo.commons.api.data.ContextURL.Suffix; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityCollection; import org.apache.olingo.commons.api.data.EntityIterator; +import org.apache.olingo.commons.api.data.Link; import org.apache.olingo.commons.api.data.Operation; import org.apache.olingo.commons.api.data.Property; import org.apache.olingo.commons.api.data.ValueType; @@ -2514,4 +2515,81 @@ public class ODataJsonSerializerTest { Mockito.when(complexType.getNamespace()).thenReturn("olingo.odata.test1"); return complexType; } + + @Test + public void entityESKeyNavContFullMetadata() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESKeyNavCont"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(0); + InputStream result = serializerFullMetadata.entity(metadata, edmEntitySet.getEntityType(), entity, + EntitySerializerOptions.with() + .contextURL(ContextURL.with().entitySet(edmEntitySet).suffix(Suffix.ENTITY).build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expected = "{\"@odata.context\":\"$metadata#ESKeyNavCont/$entity\"," + + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\",\"@odata.type\":" + + "\"#olingo.odata.test1.ETKeyNavCont\",\"@odata.id\":\"ESKeyNavCont(32766)\"," + + "\"[email protected]\":\"#Int16\",\"PropertyInt16\":32766," + + "\"PropertyString\":\"Test String1\",\"PropertyCompNavCont\":" + + "{\"@odata.type\":\"#olingo.odata.test1.CTNavCont\"}}"; + + Assert.assertEquals(expected, resultString); + } + + @Test + public void entityESKeyNavContFullMetadataWithContNav() throws Exception { + final EdmEntitySet edmEntitySet = entityContainer.getEntitySet("ESKeyNavCont"); + final Entity entity = data.readAll(edmEntitySet).getEntities().get(1); + Link link = entity.getNavigationLink("NavPropertyETContMany"); + InputStream result = serializerFullMetadata.entityCollection(metadata, + edmEntitySet.getEntityType().getNavigationProperty("NavPropertyETContMany").getType(), + link.getInlineEntitySet(), + EntityCollectionSerializerOptions.with() + .contextURL(ContextURL.with(). + type(edmEntitySet.getEntityType().getNavigationProperty("NavPropertyETContMany").getType()) + .entitySetOrSingletonOrType("ESKeyNavCont(-365)/NavPropertyETContMany").build()) + .build()).getContent(); + final String resultString = IOUtils.toString(result); + final String expected = "{\"@odata.context\":\"$metadata#ESKeyNavCont%28-365%29%2FNavPropertyETContMany\"," + + "\"@odata.metadataEtag\":\"W/\\\"metadataETag\\\"\",\"value\":[{" + + "\"@odata.type\":\"#olingo.odata.test1.ETCont\",\"@odata.id\":" + + "\"ESKeyNavCont(-365)/NavPropertyETContMany(-32768)\"," + + "\"[email protected]\":\"#Int16\",\"PropertyInt16\":-32768," + + "\"PropertyString\":\"Second Resource - negative values\",\"[email protected]\":" + + "\"#Int32\",\"PropertyInt32\":-2147483648,\"[email protected]\":\"#Int64\"," + + "\"PropertyInt64\":-9223372036854775808,\"[email protected]\":\"#Single\"," + + "\"PropertySingle\":-1.79E8,\"PropertyDouble\":-179000.0," + + "\"[email protected]\":\"#Decimal\",\"PropertyDecimal\":-34," + + "\"[email protected]\":\"#Binary\",\"PropertyBinary\":\"ASNFZ4mrze8=\"," + + "\"[email protected]\":\"#Date\",\"PropertyDate\":\"2015-11-05\"," + + "\"[email protected]\":\"#DateTimeOffset\"," + + "\"PropertyDateTimeOffset\":\"2005-12-03T07:17:08Z\"," + + "\"[email protected]\":\"#Duration\"," + + "\"PropertyDuration\":\"PT9S\",\"[email protected]\":" + + "\"#Guid\",\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789dddfff\"," + + "\"[email protected]\":\"#TimeOfDay\"," + + "\"PropertyTimeOfDay\":\"23:49:14\",\"PropertyBoolean\":false," + + "\"[email protected]\":\"#Byte\",\"PropertyByte\":0," + + "\"[email protected]\":\"#SByte\",\"PropertySByte\":-128}," + + "{\"@odata.type\":\"#olingo.odata.test1.ETCont\"," + + "\"@odata.id\":\"ESKeyNavCont(-365)/NavPropertyETContMany(0)\"," + + "\"[email protected]\":\"#Int16\",\"PropertyInt16\":0," + + "\"PropertyString\":\"\",\"[email protected]\":\"#Int32\"," + + "\"PropertyInt32\":0,\"[email protected]\":\"#Int64\"," + + "\"PropertyInt64\":0,\"[email protected]\":\"#Single\"," + + "\"PropertySingle\":0.0,\"PropertyDouble\":0.0," + + "\"[email protected]\":\"#Decimal\",\"PropertyDecimal\":0," + + "\"[email protected]\":\"#Binary\",\"PropertyBinary\":\"\"," + + "\"[email protected]\":\"#Date\",\"PropertyDate\":\"1970-01-01\"," + + "\"[email protected]\":\"#DateTimeOffset\"," + + "\"PropertyDateTimeOffset\":\"2005-12-03T00:00:00Z\"," + + "\"[email protected]\":\"#Duration\",\"PropertyDuration\":\"PT0S\"," + + "\"[email protected]\":\"#Guid\"," + + "\"PropertyGuid\":\"76543201-23ab-cdef-0123-456789cccddd\"," + + "\"[email protected]\":\"#TimeOfDay\"," + + "\"PropertyTimeOfDay\":\"00:01:01\",\"PropertyBoolean\":false," + + "\"[email protected]\":\"#Byte\",\"PropertyByte\":0," + + "\"[email protected]\":\"#SByte\",\"PropertySByte\":0}]}"; + + Assert.assertEquals(expected, resultString); + } } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/data/Storage.java ---------------------------------------------------------------------- diff --git a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/data/Storage.java b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/data/Storage.java index 9b2d342..6b8d673 100755 --- a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/data/Storage.java +++ b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/data/Storage.java @@ -23,9 +23,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; -import myservice.mynamespace.service.DemoEdmProvider; -import myservice.mynamespace.util.Util; - +import org.apache.olingo.commons.api.data.ComplexValue; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityCollection; import org.apache.olingo.commons.api.data.Property; @@ -36,20 +34,26 @@ import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.ex.ODataRuntimeException; import org.apache.olingo.server.api.uri.UriParameter; +import myservice.mynamespace.service.DemoEdmProvider; +import myservice.mynamespace.util.Util; + public class Storage { // represent our database private List<Entity> productList; private List<Entity> categoryList; + private List<Entity> supplierList; public Storage() { productList = new ArrayList<Entity>(); categoryList = new ArrayList<Entity>(); + supplierList = new ArrayList<Entity>(); // creating some sample data initProductSampleData(); initCategorySampleData(); + initSupplierSampleData(); } /* PUBLIC FACADE */ @@ -75,6 +79,8 @@ public class Storage { entity = getProduct(edmEntityType, keyParams); } else if (edmEntityType.getName().equals(DemoEdmProvider.ET_CATEGORY_NAME)) { entity = getCategory(edmEntityType, keyParams); + } else if (edmEntityType.getName().equals(DemoEdmProvider.ET_SUPPLIER_NAME)) { + entity = getSupplier(edmEntityType, keyParams); } return entity; @@ -127,6 +133,23 @@ public class Storage { // the first 2 products are monitors navigationTargetEntityCollection.getEntities().addAll(productList.subList(4, 6)); } + } else if (sourceEntityFqn.equals(DemoEdmProvider.ET_PRODUCT_FQN.getFullQualifiedNameAsString()) + && relatedEntityFqn.equals(DemoEdmProvider.ET_SUPPLIER_FQN)) { + int productID = (Integer) sourceEntity.getProperty("ID").getValue(); + if (productID == 1) { + navigationTargetEntityCollection.getEntities().add(supplierList.get(0)); + navigationTargetEntityCollection.getEntities().add(supplierList.get(1)); + } else if (productID == 2) { + navigationTargetEntityCollection.getEntities().add(supplierList.get(2)); + } else if (productID == 3) { + navigationTargetEntityCollection.getEntities().add(supplierList.get(3)); + } else if (productID == 4) { + navigationTargetEntityCollection.getEntities().add(supplierList.get(4)); + } else if (productID == 5) { + navigationTargetEntityCollection.getEntities().add(supplierList.get(5)); + } else if (productID == 6) { + navigationTargetEntityCollection.getEntities().add(supplierList.get(6)); + } } if (navigationTargetEntityCollection.getEntities().isEmpty()) { @@ -147,6 +170,16 @@ public class Storage { return retEntitySet; } + + private EntityCollection getSuppliers() { + EntityCollection retEntitySet = new EntityCollection(); + + for (Entity supplierEntity : this.supplierList) { + retEntitySet.getEntities().add(supplierEntity); + } + + return retEntitySet; + } private Entity getProduct(EdmEntityType edmEntityType, List<UriParameter> keyParams) { @@ -156,6 +189,15 @@ public class Storage { /* generic approach to find the requested entity */ return Util.findEntity(edmEntityType, entityCollection, keyParams); } + + private Entity getSupplier(EdmEntityType edmEntityType, List<UriParameter> keyParams) { + + // the list of entities at runtime + EntityCollection entityCollection = getSuppliers(); + + /* generic approach to find the requested entity */ + return Util.findEntity(edmEntityType, entityCollection, keyParams); + } private EntityCollection getCategories() { EntityCollection entitySet = new EntityCollection(); @@ -260,6 +302,123 @@ public class Storage { entity.setId(createId(entity, "ID")); categoryList.add(entity); } + + private void initSupplierSampleData() { + + Entity entity = new Entity(); + + entity.addProperty(new Property(null, "SupplierID", ValueType.PRIMITIVE, 1)); + entity.addProperty(new Property(null, "CompanyName", ValueType.PRIMITIVE, "DESIGN INDEX INDIA")); + entity.addProperty(new Property(null, "Fax", ValueType.PRIMITIVE, + "null")); + + Property p1 = new Property(null, "City", ValueType.PRIMITIVE, "Delhi"); + Property p2 = new Property(null, "Country", ValueType.PRIMITIVE, "India"); + ComplexValue complexValue = new ComplexValue(); + complexValue.getValue().add(p1); + complexValue.getValue().add(p2); + + entity.addProperty(new Property(null, "Address", ValueType.COMPLEX, complexValue)); + entity.setType(DemoEdmProvider.ET_SUPPLIER_FQN.getFullQualifiedNameAsString()); + entity.setId(createId(entity, "SupplierID", "Suppliers", "1")); + supplierList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "SupplierID", ValueType.PRIMITIVE, 2)); + entity.addProperty(new Property(null, "CompanyName", ValueType.PRIMITIVE, "Advance Label Ltd")); + entity.addProperty(new Property(null, "Fax", ValueType.PRIMITIVE, + "(617) 555-3389")); + p1 = new Property(null, "City", ValueType.PRIMITIVE, "Tsuen Wan"); + p2 = new Property(null, "Country", ValueType.PRIMITIVE, "Hong Kong"); + complexValue = new ComplexValue(); + complexValue.getValue().add(p1); + complexValue.getValue().add(p2); + + entity.addProperty(new Property(null, "Address", ValueType.COMPLEX, complexValue)); + entity.setType(DemoEdmProvider.ET_SUPPLIER_FQN.getFullQualifiedNameAsString()); + entity.setId(createId(entity, "SupplierID", "Suppliers", "1")); + supplierList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "SupplierID", ValueType.PRIMITIVE, 3)); + entity.addProperty(new Property(null, "CompanyName", ValueType.PRIMITIVE, "TECH GROUP INTERNATIONAL LIMITED ")); + entity.addProperty(new Property(null, "Fax", ValueType.PRIMITIVE, + "null")); + p1 = new Property(null, "City", ValueType.PRIMITIVE, "Bangalore"); + p2 = new Property(null, "Country", ValueType.PRIMITIVE, "India"); + complexValue = new ComplexValue(); + complexValue.getValue().add(p1); + complexValue.getValue().add(p2); + + entity.addProperty(new Property(null, "Address", ValueType.COMPLEX, complexValue)); + entity.setType(DemoEdmProvider.ET_SUPPLIER_FQN.getFullQualifiedNameAsString()); + entity.setId(createId(entity, "SupplierID", "Suppliers", "2")); + supplierList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "SupplierID", ValueType.PRIMITIVE, 4)); + entity.addProperty(new Property(null, "CompanyName", ValueType.PRIMITIVE, "BenQ India Pvt Ltd")); + entity.addProperty(new Property(null, "Fax", ValueType.PRIMITIVE, + "43844115")); + p1 = new Property(null, "City", ValueType.PRIMITIVE, "Gurgaon"); + p2 = new Property(null, "Country", ValueType.PRIMITIVE, "India"); + complexValue = new ComplexValue(); + complexValue.getValue().add(p1); + complexValue.getValue().add(p2); + + entity.addProperty(new Property(null, "Address", ValueType.COMPLEX, complexValue)); + entity.setType(DemoEdmProvider.ET_SUPPLIER_FQN.getFullQualifiedNameAsString()); + entity.setId(createId(entity, "SupplierID", "Suppliers", "3")); + supplierList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "SupplierID", ValueType.PRIMITIVE, 5)); + entity.addProperty(new Property(null, "CompanyName", ValueType.PRIMITIVE, "Sharp")); + entity.addProperty(new Property(null, "Fax", ValueType.PRIMITIVE, + "(12345) 1210")); + p1 = new Property(null, "City", ValueType.PRIMITIVE, "Osaka"); + p2 = new Property(null, "Country", ValueType.PRIMITIVE, "Japan"); + complexValue = new ComplexValue(); + complexValue.getValue().add(p1); + complexValue.getValue().add(p2); + + entity.addProperty(new Property(null, "Address", ValueType.COMPLEX, complexValue)); + entity.setType(DemoEdmProvider.ET_SUPPLIER_FQN.getFullQualifiedNameAsString()); + entity.setId(createId(entity, "SupplierID", "Suppliers", "4")); + supplierList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "SupplierID", ValueType.PRIMITIVE, 6)); + entity.addProperty(new Property(null, "CompanyName", ValueType.PRIMITIVE, "Wonder World")); + entity.addProperty(new Property(null, "Fax", ValueType.PRIMITIVE, + "43844115")); + p1 = new Property(null, "City", ValueType.PRIMITIVE, "Zürich"); + p2 = new Property(null, "Country", ValueType.PRIMITIVE, "Switzerland"); + complexValue = new ComplexValue(); + complexValue.getValue().add(p1); + complexValue.getValue().add(p2); + + entity.addProperty(new Property(null, "Address", ValueType.COMPLEX, complexValue)); + entity.setType(DemoEdmProvider.ET_SUPPLIER_FQN.getFullQualifiedNameAsString()); + entity.setId(createId(entity, "SupplierID", "Suppliers", "5")); + supplierList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "SupplierID", ValueType.PRIMITIVE, 7)); + entity.addProperty(new Property(null, "CompanyName", ValueType.PRIMITIVE, "Touch International")); + entity.addProperty(new Property(null, "Fax", ValueType.PRIMITIVE, + "43847115")); + p1 = new Property(null, "City", ValueType.PRIMITIVE, "Austin"); + p2 = new Property(null, "Country", ValueType.PRIMITIVE, "USA"); + complexValue = new ComplexValue(); + complexValue.getValue().add(p1); + complexValue.getValue().add(p2); + + entity.addProperty(new Property(null, "Address", ValueType.COMPLEX, complexValue)); + entity.setType(DemoEdmProvider.ET_SUPPLIER_FQN.getFullQualifiedNameAsString()); + entity.setId(createId(entity, "SupplierID", "Suppliers", "6")); + supplierList.add(entity); + } private URI createId(Entity entity, String idPropertyName) { return createId(entity, idPropertyName, null); @@ -278,12 +437,29 @@ public class Storage { throw new ODataRuntimeException("Unable to create (Atom) id for entity: " + entity, e); } } + + private URI createId(Entity entity, String idPropertyName, String navigationName, String sourceId) { + try { + StringBuilder sb = new StringBuilder(getEntitySetName(entity)).append("("); + final Property property = entity.getProperty(idPropertyName); + sb.append(sourceId).append(")"); + if(navigationName != null) { + sb.append("/").append(navigationName); + sb.append("(").append(property.asPrimitive()).append(")"); + } + return new URI(sb.toString()); + } catch (URISyntaxException e) { + throw new ODataRuntimeException("Unable to create (Atom) id for entity: " + entity, e); + } + } private String getEntitySetName(Entity entity) { if(DemoEdmProvider.ET_CATEGORY_FQN.getFullQualifiedNameAsString().equals(entity.getType())) { return DemoEdmProvider.ES_CATEGORIES_NAME; } else if(DemoEdmProvider.ET_PRODUCT_FQN.getFullQualifiedNameAsString().equals(entity.getType())) { return DemoEdmProvider.ES_PRODUCTS_NAME; + } else if(DemoEdmProvider.ET_SUPPLIER_FQN.getFullQualifiedNameAsString().equals(entity.getType())) { + return DemoEdmProvider.ES_PRODUCTS_NAME; } return entity.getType(); } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java ---------------------------------------------------------------------- diff --git a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java index 8ce9bac..5599ecb 100755 --- a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java +++ b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java @@ -25,6 +25,7 @@ import java.util.List; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.edm.provider.CsdlAbstractEdmProvider; +import org.apache.olingo.commons.api.edm.provider.CsdlComplexType; import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainer; import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainerInfo; import org.apache.olingo.commons.api.edm.provider.CsdlEntitySet; @@ -50,10 +51,17 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { public static final String ET_CATEGORY_NAME = "Category"; public static final FullQualifiedName ET_CATEGORY_FQN = new FullQualifiedName(NAMESPACE, ET_CATEGORY_NAME); + + public static final String ET_SUPPLIER_NAME = "Supplier"; + public static final FullQualifiedName ET_SUPPLIER_FQN = new FullQualifiedName(NAMESPACE, ET_SUPPLIER_NAME); + + public static final String CT_ADDRESS_NAME = "Address"; + public static final FullQualifiedName CT_ADDRESS_FQN = new FullQualifiedName(NAMESPACE, CT_ADDRESS_NAME); // Entity Set Names public static final String ES_PRODUCTS_NAME = "Products"; public static final String ES_CATEGORIES_NAME = "Categories"; + public static final String ES_SUPPLIERS_NAME = "Suppliers"; @Override public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { @@ -77,8 +85,11 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { // navigation property: many-to-one, null not allowed (product must have a category) CsdlNavigationProperty navProp = new CsdlNavigationProperty().setName("Category") .setType(ET_CATEGORY_FQN).setNullable(false).setPartner("Products"); + CsdlNavigationProperty contNavProp = new CsdlNavigationProperty().setName("Suppliers") + .setType(ET_SUPPLIER_FQN).setContainsTarget(true).setCollection(true); List<CsdlNavigationProperty> navPropList = new ArrayList<CsdlNavigationProperty>(); navPropList.add(navProp); + navPropList.add(contNavProp); // configure EntityType entityType = new CsdlEntityType(); @@ -110,11 +121,47 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { entityType.setProperties(Arrays.asList(id, name)); entityType.setKey(Arrays.asList(propertyRef)); entityType.setNavigationProperties(navPropList); + } else if (entityTypeName.equals(ET_SUPPLIER_FQN)) { + // create EntityType properties + CsdlProperty supplierId = new CsdlProperty().setName("SupplierID") + .setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName()); + CsdlProperty companyName = new CsdlProperty().setName("CompanyName") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); + CsdlProperty fax = new CsdlProperty().setName("Fax") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); + CsdlProperty address = new CsdlProperty().setName(CT_ADDRESS_NAME) + .setType(CT_ADDRESS_FQN); + + // create PropertyRef for Key element + CsdlPropertyRef propertyRef = new CsdlPropertyRef(); + propertyRef.setName("SupplierID"); + + // configure EntityType + entityType = new CsdlEntityType(); + entityType.setName(ET_SUPPLIER_NAME); + entityType.setProperties(Arrays.asList(supplierId, companyName, fax, address)); + entityType.setKey(Arrays.asList(propertyRef)); } return entityType; } + + @Override + public CsdlComplexType getComplexType(final FullQualifiedName complexTypeName) { + CsdlComplexType complexType = null; + if (complexTypeName.equals(CT_ADDRESS_FQN)) { + complexType = new CsdlComplexType().setName(CT_ADDRESS_NAME) + .setProperties(Arrays.asList( + new CsdlProperty() + .setName("City") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()), + new CsdlProperty() + .setName("Country") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()))); + } + return complexType; + } @Override public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { @@ -180,8 +227,14 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { List<CsdlEntityType> entityTypes = new ArrayList<CsdlEntityType>(); entityTypes.add(getEntityType(ET_PRODUCT_FQN)); entityTypes.add(getEntityType(ET_CATEGORY_FQN)); + entityTypes.add(getEntityType(ET_SUPPLIER_FQN)); schema.setEntityTypes(entityTypes); + // add Complex Types + List<CsdlComplexType> complexTypes = new ArrayList<CsdlComplexType>(); + complexTypes.add(getComplexType(CT_ADDRESS_FQN)); + schema.setComplexTypes(complexTypes); + // add EntityContainer schema.setEntityContainer(getEntityContainer()); http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java ---------------------------------------------------------------------- diff --git a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java index 058dd83..018931f 100755 --- a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java +++ b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java @@ -81,6 +81,7 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor EdmEntitySet responseEdmEntitySet = null; // we'll need this to build the ContextURL EntityCollection responseEntityCollection = null; // we'll need this to set the response body + EdmEntityType responseEdmEntityType = null; // 1st retrieve the requested EntitySet from the uriInfo (representation of the parsed URI) List<UriResource> resourceParts = uriInfo.getUriResourceParts(); @@ -107,8 +108,13 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor UriResourceNavigation uriResourceNavigation = (UriResourceNavigation) lastSegment; EdmNavigationProperty edmNavigationProperty = uriResourceNavigation.getProperty(); EdmEntityType targetEntityType = edmNavigationProperty.getType(); - // from Categories(1) to Products - responseEdmEntitySet = Util.getNavigationTargetEntitySet(startEdmEntitySet, edmNavigationProperty); + if (!edmNavigationProperty.containsTarget()) { + // from Categories(1) to Products + responseEdmEntitySet = Util.getNavigationTargetEntitySet(startEdmEntitySet, edmNavigationProperty); + } else { + responseEdmEntitySet = startEdmEntitySet; + responseEdmEntityType = targetEntityType; + } // 2nd: fetch the data from backend // first fetch the entity where the first segment of the URI points to @@ -130,13 +136,20 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } + ContextURL contextUrl = null; + EdmEntityType edmEntityType = null; // 3rd: create and configure a serializer - ContextURL contextUrl = ContextURL.with().entitySet(responseEdmEntitySet).build(); + if (isContNav(uriInfo)) { + contextUrl = ContextURL.with().entitySetOrSingletonOrType(request.getRawODataPath()).build(); + edmEntityType = responseEdmEntityType; + } else { + contextUrl = ContextURL.with().entitySet(responseEdmEntitySet).build(); + edmEntityType = responseEdmEntitySet.getEntityType(); + } final String id = request.getRawBaseUri() + "/" + responseEdmEntitySet.getName(); EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with() .contextURL(contextUrl).id(id).build(); - EdmEntityType edmEntityType = responseEdmEntitySet.getEntityType(); - + ODataSerializer serializer = odata.createSerializer(responseFormat); SerializerResult serializerResult = serializer.entityCollection(this.srvMetadata, edmEntityType, responseEntityCollection, opts); @@ -147,4 +160,17 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); } + private boolean isContNav(UriInfo uriInfo) { + List<UriResource> resourceParts = uriInfo.getUriResourceParts(); + for (UriResource resourcePart : resourceParts) { + if (resourcePart instanceof UriResourceNavigation) { + UriResourceNavigation navResource = (UriResourceNavigation) resourcePart; + if (navResource.getProperty().containsTarget()) { + return true; + } + } + } + return false; + } + } http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b86aa5d9/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java ---------------------------------------------------------------------- diff --git a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java index fba514a..1cf75c1 100755 --- a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java +++ b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java @@ -109,8 +109,13 @@ public class DemoEntityProcessor implements EntityProcessor { UriResourceNavigation uriResourceNavigation = (UriResourceNavigation) navSegment; EdmNavigationProperty edmNavigationProperty = uriResourceNavigation.getProperty(); responseEdmEntityType = edmNavigationProperty.getType(); - // contextURL displays the last segment - responseEdmEntitySet = Util.getNavigationTargetEntitySet(startEdmEntitySet, edmNavigationProperty); + if (!edmNavigationProperty.containsTarget()) { + // contextURL displays the last segment + responseEdmEntitySet = Util.getNavigationTargetEntitySet(startEdmEntitySet, edmNavigationProperty); + } else { + responseEdmEntitySet = startEdmEntitySet; + } + // 2nd: fetch the data from backend. // e.g. for the URI: Products(1)/Category we have to find the correct Category entity @@ -141,7 +146,14 @@ public class DemoEntityProcessor implements EntityProcessor { } // 3. serialize - ContextURL contextUrl = ContextURL.with().entitySet(responseEdmEntitySet).suffix(Suffix.ENTITY).build(); + ContextURL contextUrl = null; + if (isContNav(uriInfo)) { + contextUrl = ContextURL.with().entitySetOrSingletonOrType(request.getRawODataPath()). + suffix(Suffix.ENTITY).build(); + } else { + contextUrl = ContextURL.with().entitySet(responseEdmEntitySet).suffix(Suffix.ENTITY).build(); + } + EntitySerializerOptions opts = EntitySerializerOptions.with().contextURL(contextUrl).build(); ODataSerializer serializer = this.odata.createSerializer(responseFormat); @@ -153,6 +165,19 @@ public class DemoEntityProcessor implements EntityProcessor { response.setStatusCode(HttpStatusCode.OK.getStatusCode()); response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); } + + private boolean isContNav(UriInfo uriInfo) { + List<UriResource> resourceParts = uriInfo.getUriResourceParts(); + for (UriResource resourcePart : resourceParts) { + if (resourcePart instanceof UriResourceNavigation) { + UriResourceNavigation navResource = (UriResourceNavigation) resourcePart; + if (navResource.getProperty().containsTarget()) { + return true; + } + } + } + return false; + } /* * These processor methods are not handled in this tutorial
