From 170d561c0467ab1f24454668d8a16badba0135e5 Mon Sep 17 00:00:00 2001 From: Christian Holzer Date: Thu, 3 Sep 2015 15:31:54 +0200 Subject: [PATCH] [OLINGO-713] Switched tutorials to release snapshot. Started to create a merged version of all tutorials --- samples/tutorials/p0_all/pom.xml | 86 +++++ .../myservice/mynamespace/data/Storage.java | 252 +++++++++++++ .../mynamespace/service/DemoEdmProvider.java | 210 +++++++++++ .../DemoEntityCollectionProcessor.java | 356 ++++++++++++++++++ .../service/DemoEntityProcessor.java | 202 ++++++++++ .../service/DemoPrimitiveProcessor.java | 21 +- .../service/FilterExpressionVisitor.java | 13 +- .../java/myservice/mynamespace/util/Util.java | 149 ++++++++ .../mynamespace/web/DemoServlet.java | 0 .../src/main/webapp/WEB-INF/web.xml | 0 .../src/main/webapp/index.jsp | 0 samples/tutorials/p1_read/pom.xml | 10 +- .../mynamespace/service/DemoEdmProvider.java | 11 +- .../DemoEntityCollectionProcessor.java | 6 +- samples/tutorials/p2_readep/pom.xml | 39 +- .../mynamespace/service/DemoEdmProvider.java | 17 +- .../DemoEntityCollectionProcessor.java | 4 +- .../service/DemoEntityProcessor.java | 4 +- .../service/DemoPrimitiveProcessor.java | 9 +- .../java/myservice/mynamespace/util/Util.java | 4 - samples/tutorials/p3_write/pom.xml | 10 +- .../mynamespace/service/DemoEdmProvider.java | 11 +- .../DemoEntityCollectionProcessor.java | 4 +- .../service/DemoEntityProcessor.java | 13 +- .../service/DemoPrimitiveProcessor.java | 8 +- samples/tutorials/p4_navigation/pom.xml | 11 +- .../mynamespace/service/DemoEdmProvider.java | 11 +- .../DemoEntityCollectionProcessor.java | 3 +- .../service/DemoEntityProcessor.java | 4 +- .../service/DemoPrimitiveProcessor.java | 8 +- samples/tutorials/p5_queryoptions-tcs/pom.xml | 10 +- .../mynamespace/service/DemoEdmProvider.java | 14 +- .../DemoEntityCollectionProcessor.java | 4 +- .../service/DemoEntityProcessor.java | 4 +- .../service/DemoPrimitiveProcessor.java | 9 +- .../java/myservice/mynamespace/util/Util.java | 4 - samples/tutorials/p6_queryoptions-es/pom.xml | 10 +- .../mynamespace/service/DemoEdmProvider.java | 11 +- .../DemoEntityCollectionProcessor.java | 3 +- .../service/DemoEntityProcessor.java | 3 +- .../service/DemoPrimitiveProcessor.java | 9 +- samples/tutorials/p7_queryoptions-o/pom.xml | 85 +++++ .../myservice/mynamespace/data/Storage.java | 0 .../mynamespace/service/DemoEdmProvider.java | 153 ++++++++ .../DemoEntityCollectionProcessor.java | 147 ++++++++ .../service/DemoEntityProcessor.java | 18 +- .../service/DemoPrimitiveProcessor.java | 148 ++++++++ .../java/myservice/mynamespace/util/Util.java | 101 +++++ .../mynamespace/web/DemoServlet.java | 76 ++++ .../src/main/webapp/WEB-INF/web.xml | 40 ++ .../src/main/webapp/index.jsp | 26 ++ .../pom.xml | 10 +- .../myservice/mynamespace/data/Storage.java | 125 ++++++ .../mynamespace/service/DemoEdmProvider.java | 30 +- .../DemoEntityCollectionProcessor.java | 17 +- .../service/DemoEntityProcessor.java | 122 ++++++ .../service/DemoPrimitiveProcessor.java | 150 ++++++++ .../service/FilterExpressionVisitor.java | 303 +++++++++++++++ .../java/myservice/mynamespace/util/Util.java | 0 .../mynamespace/web/DemoServlet.java | 76 ++++ .../src/main/webapp/WEB-INF/web.xml | 40 ++ .../src/main/webapp/index.jsp | 24 ++ samples/tutorials/pom.xml | 4 +- 63 files changed, 3052 insertions(+), 200 deletions(-) create mode 100644 samples/tutorials/p0_all/pom.xml create mode 100644 samples/tutorials/p0_all/src/main/java/myservice/mynamespace/data/Storage.java create mode 100644 samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java create mode 100644 samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java create mode 100644 samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java rename samples/tutorials/{p7_queryoptions-f => p0_all}/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java (89%) rename samples/tutorials/{p7_queryoptions-f => p0_all}/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java (96%) create mode 100644 samples/tutorials/p0_all/src/main/java/myservice/mynamespace/util/Util.java rename samples/tutorials/{p7_queryoptions-f => p0_all}/src/main/java/myservice/mynamespace/web/DemoServlet.java (100%) rename samples/tutorials/{p7_queryoptions-f => p0_all}/src/main/webapp/WEB-INF/web.xml (100%) rename samples/tutorials/{p7_queryoptions-f => p0_all}/src/main/webapp/index.jsp (100%) create mode 100644 samples/tutorials/p7_queryoptions-o/pom.xml rename samples/tutorials/{p7_queryoptions-f => p7_queryoptions-o}/src/main/java/myservice/mynamespace/data/Storage.java (100%) create mode 100644 samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java create mode 100644 samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java rename samples/tutorials/{p7_queryoptions-f => p7_queryoptions-o}/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java (88%) create mode 100644 samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java create mode 100644 samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/util/Util.java create mode 100644 samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/web/DemoServlet.java create mode 100644 samples/tutorials/p7_queryoptions-o/src/main/webapp/WEB-INF/web.xml create mode 100644 samples/tutorials/p7_queryoptions-o/src/main/webapp/index.jsp rename samples/tutorials/{p7_queryoptions-f => p8_queryoptions-f}/pom.xml (91%) create mode 100644 samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/data/Storage.java rename samples/tutorials/{p7_queryoptions-f => p8_queryoptions-f}/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java (87%) rename samples/tutorials/{p7_queryoptions-f => p8_queryoptions-f}/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java (90%) create mode 100644 samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java create mode 100644 samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java create mode 100644 samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java rename samples/tutorials/{p7_queryoptions-f => p8_queryoptions-f}/src/main/java/myservice/mynamespace/util/Util.java (100%) create mode 100644 samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/web/DemoServlet.java create mode 100644 samples/tutorials/p8_queryoptions-f/src/main/webapp/WEB-INF/web.xml create mode 100644 samples/tutorials/p8_queryoptions-f/src/main/webapp/index.jsp diff --git a/samples/tutorials/p0_all/pom.xml b/samples/tutorials/p0_all/pom.xml new file mode 100644 index 000000000..2b388a1ef --- /dev/null +++ b/samples/tutorials/p0_all/pom.xml @@ -0,0 +1,86 @@ + + + + 4.0.0 + my.group.id + DemoService + war + 4.0.0 + + ${project.artifactId} Webapp + + + DemoService + + + + 2.5 + 4.0.0-SNAPSHOT + 1.7.7 + + + + + javax.servlet + servlet-api + ${javax.version} + provided + + + + org.apache.olingo + odata-server-api + ${odata.version} + + + org.apache.olingo + odata-server-core + ${odata.version} + runtime + + + + org.apache.olingo + odata-commons-api + ${odata.version} + + + org.apache.olingo + odata-commons-core + ${odata.version} + + + + org.slf4j + slf4j-simple + ${slf4j.version} + runtime + + + org.slf4j + slf4j-api + 1.7.11 + compile + + + diff --git a/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/data/Storage.java b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/data/Storage.java new file mode 100644 index 000000000..2034fe6fd --- /dev/null +++ b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/data/Storage.java @@ -0,0 +1,252 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.data; + +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.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.data.ValueType; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.FullQualifiedName; +import org.apache.olingo.server.api.uri.UriParameter; + +public class Storage { + + // represent our database + private List productList; + private List categoryList; + + public Storage() { + + productList = new ArrayList(); + categoryList = new ArrayList(); + + // creating some sample data + initProductSampleData(); + initCategorySampleData(); + } + + /* PUBLIC FACADE */ + + public EntityCollection readEntitySetData(EdmEntitySet edmEntitySet) { + EntityCollection entitySet = null; + + if (edmEntitySet.getName().equals(DemoEdmProvider.ES_PRODUCTS_NAME)) { + entitySet = getProducts(); + } else if (edmEntitySet.getName().equals(DemoEdmProvider.ES_CATEGORIES_NAME)) { + entitySet = getCategories(); + } + + return entitySet; + } + + public Entity readEntityData(EdmEntitySet edmEntitySet, List keyParams) { + Entity entity = null; + + EdmEntityType edmEntityType = edmEntitySet.getEntityType(); + + if (edmEntityType.getName().equals(DemoEdmProvider.ET_PRODUCT_NAME)) { + entity = getProduct(edmEntityType, keyParams); + } else if (edmEntityType.getName().equals(DemoEdmProvider.ET_CATEGORY_NAME)) { + entity = getCategory(edmEntityType, keyParams); + } + + return entity; + } + + // Navigation + + public Entity getRelatedEntity(Entity entity, EdmEntityType relatedEntityType) { + EntityCollection collection = getRelatedEntityCollection(entity, relatedEntityType); + if (collection.getEntities().isEmpty()) { + return null; + } + return collection.getEntities().get(0); + } + + public Entity getRelatedEntity(Entity entity, EdmEntityType relatedEntityType, List keyPredicates) { + + EntityCollection relatedEntities = getRelatedEntityCollection(entity, relatedEntityType); + return Util.findEntity(relatedEntityType, relatedEntities, keyPredicates); + } + + public EntityCollection getRelatedEntityCollection(Entity sourceEntity, EdmEntityType targetEntityType) { + EntityCollection navigationTargetEntityCollection = new EntityCollection(); + + FullQualifiedName relatedEntityFqn = targetEntityType.getFullQualifiedName(); + String sourceEntityFqn = sourceEntity.getType(); + + if (sourceEntityFqn.equals(DemoEdmProvider.ET_PRODUCT_FQN.getFullQualifiedNameAsString()) + && relatedEntityFqn.equals(DemoEdmProvider.ET_CATEGORY_FQN)) { + // relation Products->Category (result all categories) + int productID = (Integer) sourceEntity.getProperty("ID").getValue(); + if (productID == 1 || productID == 2) { + navigationTargetEntityCollection.getEntities().add(categoryList.get(0)); + } else if (productID == 3 || productID == 4) { + navigationTargetEntityCollection.getEntities().add(categoryList.get(1)); + } else if (productID == 5 || productID == 6) { + navigationTargetEntityCollection.getEntities().add(categoryList.get(2)); + } + } else if (sourceEntityFqn.equals(DemoEdmProvider.ET_CATEGORY_FQN.getFullQualifiedNameAsString()) + && relatedEntityFqn.equals(DemoEdmProvider.ET_PRODUCT_FQN)) { + // relation Category->Products (result all products) + int categoryID = (Integer) sourceEntity.getProperty("ID").getValue(); + if (categoryID == 1) { + // the first 2 products are notebooks + navigationTargetEntityCollection.getEntities().addAll(productList.subList(0, 2)); + } else if (categoryID == 2) { + // the next 2 products are organizers + navigationTargetEntityCollection.getEntities().addAll(productList.subList(2, 4)); + } else if (categoryID == 3) { + // the first 2 products are monitors + navigationTargetEntityCollection.getEntities().addAll(productList.subList(4, 6)); + } + } + + if (navigationTargetEntityCollection.getEntities().isEmpty()) { + return null; + } + + return navigationTargetEntityCollection; + } + + /* INTERNAL */ + + private EntityCollection getProducts() { + EntityCollection retEntitySet = new EntityCollection(); + + for (Entity productEntity : this.productList) { + retEntitySet.getEntities().add(productEntity); + } + + return retEntitySet; + } + + private Entity getProduct(EdmEntityType edmEntityType, List keyParams) { + + // the list of entities at runtime + EntityCollection entityCollection = getProducts(); + + /* generic approach to find the requested entity */ + return Util.findEntity(edmEntityType, entityCollection, keyParams); + } + + private EntityCollection getCategories() { + EntityCollection entitySet = new EntityCollection(); + + for (Entity categoryEntity : this.categoryList) { + entitySet.getEntities().add(categoryEntity); + } + + return entitySet; + } + + private Entity getCategory(EdmEntityType edmEntityType, List keyParams) { + + // the list of entities at runtime + EntityCollection entitySet = getCategories(); + + /* generic approach to find the requested entity */ + return Util.findEntity(edmEntityType, entitySet, keyParams); + } + + /* HELPER */ + + private void initProductSampleData() { + + Entity entity = new Entity(); + + entity.addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 1)); + entity.addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Notebook Basic 15")); + entity.addProperty(new Property(null, "Description", ValueType.PRIMITIVE, + "Notebook Basic, 1.7GHz - 15 XGA - 1024MB DDR2 SDRAM - 40GB")); + entity.setType(DemoEdmProvider.ET_PRODUCT_FQN.getFullQualifiedNameAsString()); + productList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 2)); + entity.addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Notebook Professional 17")); + entity.addProperty(new Property(null, "Description", ValueType.PRIMITIVE, + "Notebook Professional, 2.8GHz - 15 XGA - 8GB DDR3 RAM - 500GB")); + entity.setType(DemoEdmProvider.ET_PRODUCT_FQN.getFullQualifiedNameAsString()); + productList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 3)); + entity.addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "1UMTS PDA")); + entity.addProperty(new Property(null, "Description", ValueType.PRIMITIVE, + "Ultrafast 3G UMTS/HSDPA Pocket PC, supports GSM network")); + entity.setType(DemoEdmProvider.ET_PRODUCT_FQN.getFullQualifiedNameAsString()); + productList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 4)); + entity.addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Comfort Easy")); + entity.addProperty(new Property(null, "Description", ValueType.PRIMITIVE, + "32 GB Digital Assitant with high-resolution color screen")); + entity.setType(DemoEdmProvider.ET_PRODUCT_FQN.getFullQualifiedNameAsString()); + productList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 5)); + entity.addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Ergo Screen")); + entity.addProperty(new Property(null, "Description", ValueType.PRIMITIVE, + "19 Optimum Resolution 1024 x 768 @ 85Hz, resolution 1280 x 960")); + entity.setType(DemoEdmProvider.ET_PRODUCT_FQN.getFullQualifiedNameAsString()); + productList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 6)); + entity.addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Flat Basic")); + entity.addProperty(new Property(null, "Description", ValueType.PRIMITIVE, + "Optimum Hi-Resolution max. 1600 x 1200 @ 85Hz, Dot Pitch: 0.24mm")); + entity.setType(DemoEdmProvider.ET_PRODUCT_FQN.getFullQualifiedNameAsString()); + productList.add(entity); + } + + private void initCategorySampleData() { + + Entity entity = new Entity(); + + entity.addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 1)); + entity.addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Notebooks")); + entity.setType(DemoEdmProvider.ET_CATEGORY_FQN.getFullQualifiedNameAsString()); + categoryList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 2)); + entity.addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Organizers")); + entity.setType(DemoEdmProvider.ET_CATEGORY_FQN.getFullQualifiedNameAsString()); + categoryList.add(entity); + + entity = new Entity(); + entity.addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 3)); + entity.addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Monitors")); + entity.setType(DemoEdmProvider.ET_CATEGORY_FQN.getFullQualifiedNameAsString()); + categoryList.add(entity); + } + +} diff --git a/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java new file mode 100644 index 000000000..8ce9baced --- /dev/null +++ b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java @@ -0,0 +1,210 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.service; + +import java.util.ArrayList; +import java.util.Arrays; +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.CsdlEntityContainer; +import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainerInfo; +import org.apache.olingo.commons.api.edm.provider.CsdlEntitySet; +import org.apache.olingo.commons.api.edm.provider.CsdlEntityType; +import org.apache.olingo.commons.api.edm.provider.CsdlNavigationProperty; +import org.apache.olingo.commons.api.edm.provider.CsdlNavigationPropertyBinding; +import org.apache.olingo.commons.api.edm.provider.CsdlProperty; +import org.apache.olingo.commons.api.edm.provider.CsdlPropertyRef; +import org.apache.olingo.commons.api.edm.provider.CsdlSchema; + +public class DemoEdmProvider extends CsdlAbstractEdmProvider { + + // Service Namespace + public static final String NAMESPACE = "OData.Demo"; + + // EDM Container + public static final String CONTAINER_NAME = "Container"; + public static final FullQualifiedName CONTAINER = new FullQualifiedName(NAMESPACE, CONTAINER_NAME); + + // Entity Types Names + public static final String ET_PRODUCT_NAME = "Product"; + public static final FullQualifiedName ET_PRODUCT_FQN = new FullQualifiedName(NAMESPACE, ET_PRODUCT_NAME); + + public static final String ET_CATEGORY_NAME = "Category"; + public static final FullQualifiedName ET_CATEGORY_FQN = new FullQualifiedName(NAMESPACE, ET_CATEGORY_NAME); + + // Entity Set Names + public static final String ES_PRODUCTS_NAME = "Products"; + public static final String ES_CATEGORIES_NAME = "Categories"; + + @Override + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { + + // this method is called for each EntityType that are configured in the Schema + CsdlEntityType entityType = null; + + if (entityTypeName.equals(ET_PRODUCT_FQN)) { + // create EntityType properties + CsdlProperty id = new CsdlProperty().setName("ID") + .setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName()); + CsdlProperty name = new CsdlProperty().setName("Name") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); + CsdlProperty description = new CsdlProperty().setName("Description") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); + + // create PropertyRef for Key element + CsdlPropertyRef propertyRef = new CsdlPropertyRef(); + propertyRef.setName("ID"); + + // 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"); + List navPropList = new ArrayList(); + navPropList.add(navProp); + + // configure EntityType + entityType = new CsdlEntityType(); + entityType.setName(ET_PRODUCT_NAME); + entityType.setProperties(Arrays.asList(id, name, description)); + entityType.setKey(Arrays.asList(propertyRef)); + entityType.setNavigationProperties(navPropList); + + } else if (entityTypeName.equals(ET_CATEGORY_FQN)) { + // create EntityType properties + CsdlProperty id = new CsdlProperty().setName("ID") + .setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName()); + CsdlProperty name = new CsdlProperty().setName("Name") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); + + // create PropertyRef for Key element + CsdlPropertyRef propertyRef = new CsdlPropertyRef(); + propertyRef.setName("ID"); + + // navigation property: one-to-many + CsdlNavigationProperty navProp = new CsdlNavigationProperty().setName("Products") + .setType(ET_PRODUCT_FQN).setCollection(true).setPartner("Category"); + List navPropList = new ArrayList(); + navPropList.add(navProp); + + // configure EntityType + entityType = new CsdlEntityType(); + entityType.setName(ET_CATEGORY_NAME); + entityType.setProperties(Arrays.asList(id, name)); + entityType.setKey(Arrays.asList(propertyRef)); + entityType.setNavigationProperties(navPropList); + } + + return entityType; + + } + + @Override + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { + + CsdlEntitySet entitySet = null; + + if (entityContainer.equals(CONTAINER)) { + + if (entitySetName.equals(ES_PRODUCTS_NAME)) { + + entitySet = new CsdlEntitySet(); + entitySet.setName(ES_PRODUCTS_NAME); + entitySet.setType(ET_PRODUCT_FQN); + + // navigation + CsdlNavigationPropertyBinding navPropBinding = new CsdlNavigationPropertyBinding(); + navPropBinding.setTarget("Categories"); // the target entity set, where the navigation property points to + navPropBinding.setPath("Category"); // the path from entity type to navigation property + List navPropBindingList = new ArrayList(); + navPropBindingList.add(navPropBinding); + entitySet.setNavigationPropertyBindings(navPropBindingList); + + } else if (entitySetName.equals(ES_CATEGORIES_NAME)) { + + entitySet = new CsdlEntitySet(); + entitySet.setName(ES_CATEGORIES_NAME); + entitySet.setType(ET_CATEGORY_FQN); + + // navigation + CsdlNavigationPropertyBinding navPropBinding = new CsdlNavigationPropertyBinding(); + navPropBinding.setTarget("Products"); // the target entity set, where the navigation property points to + navPropBinding.setPath("Products"); // the path from entity type to navigation property + List navPropBindingList = new ArrayList(); + navPropBindingList.add(navPropBinding); + entitySet.setNavigationPropertyBindings(navPropBindingList); + } + } + + return entitySet; + } + + @Override + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) { + + // This method is invoked when displaying the service document at + // e.g. http://localhost:8080/DemoService/DemoService.svc + if (entityContainerName == null || entityContainerName.equals(CONTAINER)) { + CsdlEntityContainerInfo entityContainerInfo = new CsdlEntityContainerInfo(); + entityContainerInfo.setContainerName(CONTAINER); + return entityContainerInfo; + } + + return null; + } + + @Override + public List getSchemas() { + // create Schema + CsdlSchema schema = new CsdlSchema(); + schema.setNamespace(NAMESPACE); + + // add EntityTypes + List entityTypes = new ArrayList(); + entityTypes.add(getEntityType(ET_PRODUCT_FQN)); + entityTypes.add(getEntityType(ET_CATEGORY_FQN)); + schema.setEntityTypes(entityTypes); + + // add EntityContainer + schema.setEntityContainer(getEntityContainer()); + + // finally + List schemas = new ArrayList(); + schemas.add(schema); + + return schemas; + } + + @Override + public CsdlEntityContainer getEntityContainer() { + + // create EntitySets + List entitySets = new ArrayList(); + entitySets.add(getEntitySet(CONTAINER, ES_PRODUCTS_NAME)); + entitySets.add(getEntitySet(CONTAINER, ES_CATEGORIES_NAME)); + + // create EntityContainer + CsdlEntityContainer entityContainer = new CsdlEntityContainer(); + entityContainer.setName(CONTAINER_NAME); + entityContainer.setEntitySets(entitySets); + + return entityContainer; + } +} diff --git a/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java new file mode 100644 index 000000000..f3b208544 --- /dev/null +++ b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java @@ -0,0 +1,356 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.service; + +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; + +import myservice.mynamespace.data.Storage; + +import org.apache.olingo.commons.api.Constants; +import org.apache.olingo.commons.api.data.ContextURL; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.data.Link; +import org.apache.olingo.commons.api.edm.EdmElement; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +import org.apache.olingo.commons.api.edm.EdmNavigationPropertyBinding; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.processor.EntityCollectionProcessor; +import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.serializer.SerializerResult; +import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.api.uri.UriInfoResource; +import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.UriResourceNavigation; +import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty; +import org.apache.olingo.server.api.uri.queryoption.CountOption; +import org.apache.olingo.server.api.uri.queryoption.ExpandItem; +import org.apache.olingo.server.api.uri.queryoption.ExpandOption; +import org.apache.olingo.server.api.uri.queryoption.FilterOption; +import org.apache.olingo.server.api.uri.queryoption.OrderByItem; +import org.apache.olingo.server.api.uri.queryoption.OrderByOption; +import org.apache.olingo.server.api.uri.queryoption.SelectOption; +import org.apache.olingo.server.api.uri.queryoption.SkipOption; +import org.apache.olingo.server.api.uri.queryoption.TopOption; +import org.apache.olingo.server.api.uri.queryoption.expression.Expression; +import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException; +import org.apache.olingo.server.api.uri.queryoption.expression.Member; + +public class DemoEntityCollectionProcessor implements EntityCollectionProcessor { + + private OData odata; + private ServiceMetadata serviceMetadata; + private Storage storage; + + public DemoEntityCollectionProcessor(Storage storage) { + this.storage = storage; + } + + public void init(OData odata, ServiceMetadata serviceMetadata) { + this.odata = odata; + this.serviceMetadata = serviceMetadata; + } + + public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType responseFormat) throws ODataApplicationException, SerializerException { + + // 1st: retrieve the requested EntitySet from the uriInfo (representation of the parsed URI) + List resourcePaths = uriInfo.getUriResourceParts(); + // in our example, the first segment is the EntitySet + UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); + EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet(); + + // 2nd: fetch the data from backend for this requested EntitySetName and deliver as EntitySet + EntityCollection entityCollection = storage.readEntitySetData(edmEntitySet); + EntityCollection modifiedEntityCollection = new EntityCollection(); + List modifiedEntityList = new ArrayList(); + modifiedEntityList.addAll(entityCollection.getEntities()); + + // 3rd: Apply system query option + // The system query options have to be applied in a defined order + // 3.1.) $filter + modifiedEntityList = applyFilterQueryOption(modifiedEntityList, uriInfo.getFilterOption()); + // 3.2.) $orderby + modifiedEntityList = applyOrderQueryOption(modifiedEntityList, uriInfo.getOrderByOption()); + // 3.3.) $count + modifiedEntityList = applyCountQueryOption(modifiedEntityCollection, modifiedEntityList, uriInfo.getCountOption()); + // 3.4.) $skip + modifiedEntityList = applySkipQueryOption(modifiedEntityList, uriInfo.getSkipOption()); + // 3.5.) $top + modifiedEntityList = applyTopQueryOption(modifiedEntityList, uriInfo.getTopOption()); + // 3.6.) Server driven paging (not part of this tutorial) + // 3.7.) $expand + modifiedEntityList = applyExpandQueryOption(modifiedEntityCollection, modifiedEntityList, edmEntitySet, + uriInfo.getExpandOption()); + // 3.8.) $select + SelectOption selectOption = uriInfo.getSelectOption(); + + // Set the (may) modified entityList to the new entity collection + modifiedEntityCollection.getEntities().addAll(modifiedEntityList); + + // 4th: create a serializer based on the requested format (json) + ODataSerializer serializer = odata.createSerializer(responseFormat); + + // we need the property names of the $select, in order to build the context URL + EdmEntityType edmEntityType = edmEntitySet.getEntityType(); + String selectList = odata.createUriHelper() + .buildContextURLSelectList(edmEntityType, uriInfo.getExpandOption(), selectOption); + ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).selectList(selectList).build(); + + // adding the selectOption to the serializerOpts will actually tell the lib to do the job + EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with() + .contextURL(contextUrl) + .count(uriInfo.getCountOption()) + .select(selectOption) + .expand(uriInfo.getExpandOption()) + .build(); + + // and serialize the content: transform from the EntitySet object to InputStream + SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, + modifiedEntityCollection, opts); + InputStream serializedContent = serializerResult.getContent(); + + // 5th: configure the response object: set the body, headers and status code + response.setContent(serializedContent); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); + } + + private List applyExpandQueryOption(EntityCollection entityCollection, List modifiedEntityList, + EdmEntitySet edmEntitySet, ExpandOption expandOption) { + + // in our example: http://localhost:8080/DemoService/DemoService.svc/Categories/$expand=Products + // or http://localhost:8080/DemoService/DemoService.svc/Products?$expand=Category + if (expandOption != null) { + // retrieve the EdmNavigationProperty from the expand expression + // Note: in our example, we have only one NavigationProperty, so we can directly access it + EdmNavigationProperty edmNavigationProperty = null; + ExpandItem expandItem = expandOption.getExpandItems().get(0); + if (expandItem.isStar()) { + List bindings = edmEntitySet.getNavigationPropertyBindings(); + // we know that there are navigation bindings + // however normally in this case a check if navigation bindings exists is done + if (!bindings.isEmpty()) { + // can in our case only be 'Category' or 'Products', so we can take the first + EdmNavigationPropertyBinding binding = bindings.get(0); + EdmElement property = edmEntitySet.getEntityType().getProperty(binding.getPath()); + // we don't need to handle error cases, as it is done in the Olingo library + if (property instanceof EdmNavigationProperty) { + edmNavigationProperty = (EdmNavigationProperty) property; + } + } + } else { + // can be 'Category' or 'Products', no path supported + UriResource uriResource = expandItem.getResourcePath().getUriResourceParts().get(0); + // we don't need to handle error cases, as it is done in the Olingo library + if (uriResource instanceof UriResourceNavigation) { + edmNavigationProperty = ((UriResourceNavigation) uriResource).getProperty(); + } + } + + // can be 'Category' or 'Products', no path supported + // we don't need to handle error cases, as it is done in the Olingo library + if (edmNavigationProperty != null) { + String navPropName = edmNavigationProperty.getName(); + EdmEntityType expandEdmEntityType = edmNavigationProperty.getType(); + + for (Entity entity : modifiedEntityList) { + Link link = new Link(); + link.setTitle(navPropName); + link.setType(Constants.ENTITY_NAVIGATION_LINK_TYPE); + + if (edmNavigationProperty.isCollection()) { // in case of Categories/$expand=Products + // fetch the data for the $expand (to-many navigation) from backend + EntityCollection expandEntityCollection = storage.getRelatedEntityCollection(entity, expandEdmEntityType); + link.setInlineEntitySet(expandEntityCollection); + } else { // in case of Products?$expand=Category + // fetch the data for the $expand (to-one navigation) from backend + // here we get the data for the expand + Entity expandEntity = storage.getRelatedEntity(entity, expandEdmEntityType); + link.setInlineEntity(expandEntity); + } + + // set the link - containing the expanded data - to the current entity + entity.getNavigationLinks().add(link); + } + } + } + + return modifiedEntityList; + } + + private List applyTopQueryOption(List entityList, TopOption topOption) + throws ODataApplicationException { + + if (topOption != null) { + int topNumber = topOption.getValue(); + if (topNumber >= 0) { + if(topNumber <= entityList.size()) { + entityList = entityList.subList(0, topNumber); + } // else the client has requested more entities than available => return what we have + } else { + throw new ODataApplicationException("Invalid value for $top", HttpStatusCode.BAD_REQUEST.getStatusCode(), + Locale.ROOT); + } + } + + return entityList; + } + + private List applySkipQueryOption(List entityList, SkipOption skipOption) + throws ODataApplicationException { + + if (skipOption != null) { + int skipNumber = skipOption.getValue(); + if (skipNumber >= 0) { + if(skipNumber <= entityList.size()) { + entityList = entityList.subList(skipNumber, entityList.size()); + } else { + // The client skipped all entities + entityList.clear(); + } + } else { + throw new ODataApplicationException("Invalid value for $skip", HttpStatusCode.BAD_REQUEST.getStatusCode(), + Locale.ROOT); + } + } + + return entityList; + } + + private List applyCountQueryOption(EntityCollection entityCollection, List modifiedEntityList, + CountOption countOption) { + + // handle $count: always return the original number of entities, without considering $top and $skip + if (countOption != null) { + boolean isCount = countOption.getValue(); + if (isCount) { + entityCollection.setCount(modifiedEntityList.size()); + } + } + + return modifiedEntityList; + } + + private List applyOrderQueryOption(List entityList, OrderByOption orderByOption) { + + if (orderByOption != null) { + List orderItemList = orderByOption.getOrders(); + final OrderByItem orderByItem = orderItemList.get(0); // in our example we support only one + Expression expression = orderByItem.getExpression(); + if (expression instanceof Member) { + UriInfoResource resourcePath = ((Member) expression).getResourcePath(); + UriResource uriResource = resourcePath.getUriResourceParts().get(0); + if (uriResource instanceof UriResourcePrimitiveProperty) { + EdmProperty edmProperty = ((UriResourcePrimitiveProperty) uriResource).getProperty(); + final String sortPropertyName = edmProperty.getName(); + + // do the sorting for the list of entities + Collections.sort(entityList, new Comparator() { + + // we delegate the sorting to the native sorter of Integer and String + public int compare(Entity entity1, Entity entity2) { + int compareResult = 0; + + if (sortPropertyName.equals("ID")) { + Integer integer1 = (Integer) entity1.getProperty(sortPropertyName).getValue(); + Integer integer2 = (Integer) entity2.getProperty(sortPropertyName).getValue(); + + compareResult = integer1.compareTo(integer2); + } else { + String propertyValue1 = (String) entity1.getProperty(sortPropertyName).getValue(); + String propertyValue2 = (String) entity2.getProperty(sortPropertyName).getValue(); + + compareResult = propertyValue1.compareTo(propertyValue2); + } + + // if 'desc' is specified in the URI, change the order of the list + if (orderByItem.isDescending()) { + return -compareResult; // just convert the result to negative value to change the order + } + + return compareResult; + } + }); + } + } + } + + return entityList; + } + + private List applyFilterQueryOption(List entityList, FilterOption filterOption) + throws ODataApplicationException { + + if (filterOption != null) { + try { + Iterator entityIterator = entityList.iterator(); + + // Evaluate the expression for each entity + // If the expression is evaluated to "true", keep the entity otherwise remove it from the entityList + while (entityIterator.hasNext()) { + // To evaluate the the expression, create an instance of the Filter Expression Visitor and pass + // the current entity to the constructor + Entity currentEntity = entityIterator.next(); + Expression filterExpression = filterOption.getExpression(); + FilterExpressionVisitor expressionVisitor = new FilterExpressionVisitor(currentEntity); + + // Start evaluating the expression + Object visitorResult = filterExpression.accept(expressionVisitor); + + // The result of the filter expression must be of type Edm.Boolean + if (visitorResult instanceof Boolean) { + if (!Boolean.TRUE.equals(visitorResult)) { + // The expression evaluated to false (or null), so we have to remove the currentEntity from entityList + entityIterator.remove(); + } + } else { + throw new ODataApplicationException("A filter expression must evaulate to type Edm.Boolean", + HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ENGLISH); + } + } + + } catch (ExpressionVisitException e) { + throw new ODataApplicationException("Exception in filter evaluation", + HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ENGLISH); + } + } + + return entityList; + } +} diff --git a/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java new file mode 100644 index 000000000..6b623b08f --- /dev/null +++ b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java @@ -0,0 +1,202 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.service; + +import java.util.List; +import java.util.Locale; + +import myservice.mynamespace.data.Storage; + +import org.apache.olingo.commons.api.Constants; +import org.apache.olingo.commons.api.data.ContextURL; +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.Link; +import org.apache.olingo.commons.api.edm.EdmElement; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +import org.apache.olingo.commons.api.edm.EdmNavigationPropertyBinding; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.processor.EntityProcessor; +import org.apache.olingo.server.api.serializer.EntitySerializerOptions; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.serializer.SerializerResult; +import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.api.uri.UriParameter; +import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.UriResourceNavigation; +import org.apache.olingo.server.api.uri.queryoption.ExpandItem; +import org.apache.olingo.server.api.uri.queryoption.ExpandOption; +import org.apache.olingo.server.api.uri.queryoption.SelectOption; + +public class DemoEntityProcessor implements EntityProcessor { + + private OData odata; + private ServiceMetadata srvMetadata; + private Storage storage; + + public DemoEntityProcessor(Storage storage) { + this.storage = storage; + } + + public void init(OData odata, ServiceMetadata serviceMetadata) { + this.odata = odata; + this.srvMetadata = serviceMetadata; + } + + public void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) + throws ODataApplicationException, SerializerException { + + // 1. retrieve the Entity Type + List resourcePaths = uriInfo.getUriResourceParts(); + // Note: only in our example we can assume that the first segment is the EntitySet + UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); + EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet(); + + // 2. retrieve the data from backend + List keyPredicates = uriResourceEntitySet.getKeyPredicates(); + Entity entity = storage.readEntityData(edmEntitySet, keyPredicates); + + // 3. apply system query options + + // handle $select + SelectOption selectOption = uriInfo.getSelectOption(); + // in our example, we don't have performance issues, so we can rely upon the handling in the Olingo lib + // nothing else to be done + + // handle $expand + ExpandOption expandOption = uriInfo.getExpandOption(); + // in our example: http://localhost:8080/DemoService/DemoService.svc/Categories(1)/$expand=Products + // or http://localhost:8080/DemoService/DemoService.svc/Products(1)?$expand=Category + if(expandOption != null) { + // retrieve the EdmNavigationProperty from the expand expression + // Note: in our example, we have only one NavigationProperty, so we can directly access it + EdmNavigationProperty edmNavigationProperty = null; + ExpandItem expandItem = expandOption.getExpandItems().get(0); + if(expandItem.isStar()) { + List bindings = edmEntitySet.getNavigationPropertyBindings(); + // we know that there are navigation bindings + // however normally in this case a check if navigation bindings exists is done + if(!bindings.isEmpty()) { + // can in our case only be 'Category' or 'Products', so we can take the first + EdmNavigationPropertyBinding binding = bindings.get(0); + EdmElement property = edmEntitySet.getEntityType().getProperty(binding.getPath()); + // we don't need to handle error cases, as it is done in the Olingo library + if(property instanceof EdmNavigationProperty) { + edmNavigationProperty = (EdmNavigationProperty) property; + } + } + } else { + // can be 'Category' or 'Products', no path supported + UriResource uriResource = expandItem.getResourcePath().getUriResourceParts().get(0); + // we don't need to handle error cases, as it is done in the Olingo library + if(uriResource instanceof UriResourceNavigation) { + edmNavigationProperty = ((UriResourceNavigation) uriResource).getProperty(); + } + } + + // can be 'Category' or 'Products', no path supported + // we don't need to handle error cases, as it is done in the Olingo library + if(edmNavigationProperty != null) { + EdmEntityType expandEdmEntityType = edmNavigationProperty.getType(); + String navPropName = edmNavigationProperty.getName(); + + // build the inline data + Link link = new Link(); + link.setTitle(navPropName); + link.setType(Constants.ENTITY_NAVIGATION_LINK_TYPE); + + if(edmNavigationProperty.isCollection()){ // in case of Categories(1)/$expand=Products + // fetch the data for the $expand (to-many navigation) from backend + // here we get the data for the expand + EntityCollection expandEntityCollection = storage.getRelatedEntityCollection(entity, expandEdmEntityType); + link.setInlineEntitySet(expandEntityCollection); + } else { // in case of Products(1)?$expand=Category + // fetch the data for the $expand (to-one navigation) from backend + // here we get the data for the expand + Entity expandEntity = storage.getRelatedEntity(entity, expandEdmEntityType); + link.setInlineEntity(expandEntity); + } + + // set the link - containing the expanded data - to the current entity + entity.getNavigationLinks().add(link); + } + } + + + // 4. serialize + EdmEntityType edmEntityType = edmEntitySet.getEntityType(); + // we need the property names of the $select, in order to build the context URL + String selectList = odata.createUriHelper().buildContextURLSelectList(edmEntityType, expandOption, selectOption); + ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet) + .selectList(selectList) + .suffix(Suffix.ENTITY).build(); + + // make sure that $expand and $select are considered by the serializer + // adding the selectOption to the serializerOpts will actually tell the lib to do the job + EntitySerializerOptions opts = EntitySerializerOptions.with() + .contextURL(contextUrl) + .select(selectOption) + .expand(expandOption) + .build(); + + ODataSerializer serializer = this.odata.createSerializer(responseFormat); + SerializerResult serializerResult = serializer.entity(srvMetadata, edmEntityType, entity, opts); + + // 5. configure the response object + response.setContent(serializerResult.getContent()); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); + } + + + + /* + * These processor methods are not handled in this tutorial + */ + + public void createEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + + public void updateEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType requestFormat, ContentType responseFormat) + throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + + public void deleteEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo) + throws ODataApplicationException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } +} diff --git a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java similarity index 89% rename from samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java rename to samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java index 1ba0c750c..f910838c1 100644 --- a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java +++ b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java @@ -31,7 +31,6 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -55,6 +54,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { private OData odata; private Storage storage; + private ServiceMetadata serviceMetadata; public DemoPrimitiveProcessor(Storage storage) { this.storage = storage; @@ -62,6 +62,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { public void init(OData odata, ServiceMetadata serviceMetadata) { this.odata = odata; + this.serviceMetadata = serviceMetadata; } @@ -87,7 +88,8 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { List keyPredicates = uriEntityset.getKeyPredicates(); // 1.2. retrieve the requested (Edm) property - UriResourceProperty uriProperty = (UriResourceProperty)resourceParts.get(resourceParts.size() -1); // the last segment is the Property + // the last segment is the Property + UriResourceProperty uriProperty = (UriResourceProperty)resourceParts.get(resourceParts.size() -1); EdmProperty edmProperty = uriProperty.getProperty(); String edmPropertyName = edmProperty.getName(); // in our example, we know we have only primitive types in our model @@ -104,20 +106,20 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { // 2.2. retrieve the property data from the entity Property property = entity.getProperty(edmPropertyName); if (property == null) { - throw new ODataApplicationException("Property not found", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ENGLISH); + throw new ODataApplicationException("Property not found", HttpStatusCode.NOT_FOUND.getStatusCode(), + Locale.ENGLISH); } // 3. serialize Object value = property.getValue(); if (value != null) { // 3.1. configure the serializer - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).navOrPropertyPath(edmPropertyName).build(); PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextUrl).build(); // 3.2. serialize - SerializerResult serializerResult = serializer.primitive(edmPropertyType, property, options); + SerializerResult serializerResult = serializer.primitive(serviceMetadata, edmPropertyType, property, options); InputStream propertyStream = serializerResult.getContent(); //4. configure the response object @@ -136,12 +138,13 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { * These processor methods are not handled in this tutorial * */ - public void updatePrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat) - throws ODataApplicationException, DeserializerException, SerializerException { + public void updatePrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } - public void deletePrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException { + public void deletePrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo) + throws ODataApplicationException { throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } } diff --git a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java similarity index 96% rename from samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java rename to samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java index 615c38489..12d6e301a 100644 --- a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java +++ b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java @@ -25,6 +25,7 @@ import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.edm.EdmEnumType; import org.apache.olingo.commons.api.edm.EdmType; import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.commons.core.edm.primitivetype.EdmString; import org.apache.olingo.server.api.ODataApplicationException; import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.UriResource; @@ -33,6 +34,7 @@ import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKin import org.apache.olingo.server.api.uri.queryoption.expression.Expression; import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException; import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor; +import org.apache.olingo.server.api.uri.queryoption.expression.Literal; import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind; import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind; @@ -72,24 +74,25 @@ public class FilterExpressionVisitor implements ExpressionVisitor { } @Override - public Object visitLiteral(String literal) throws ExpressionVisitException, ODataApplicationException { + public Object visitLiteral(Literal literal) throws ExpressionVisitException, ODataApplicationException { // To keep this tutorial simple, our filter expression visitor supports only Edm.Int32 and Edm.String // In real world scenarios it can be difficult to guess the type of an literal. // We can be sure, that the literal is a valid OData literal because the URI Parser checks // the lexicographical structure // String literals start and end with an single quotation mark - if(literal.startsWith("'") && literal.endsWith("'")) { + String literalAsString = literal.getText(); + if(literal.getType() instanceof EdmString) { String stringLiteral = ""; - if(literal.length() > 2) { - stringLiteral = literal.substring(1, literal.length() - 1); + if(literal.getText().length() > 2) { + stringLiteral = literalAsString.substring(1, literalAsString.length() - 1); } return stringLiteral; } else { // Try to convert the literal into an Java Integer try { - return Integer.parseInt(literal); + return Integer.parseInt(literalAsString); } catch(NumberFormatException e) { throw new ODataApplicationException("Only Edm.Int32 and Edm.String literals are implemented", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); diff --git a/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/util/Util.java b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/util/Util.java new file mode 100644 index 000000000..f16360fc6 --- /dev/null +++ b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/util/Util.java @@ -0,0 +1,149 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.util; + +import java.util.List; +import java.util.Locale; + +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.edm.EdmBindingTarget; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmNavigationProperty; +import org.apache.olingo.commons.api.edm.EdmPrimitiveType; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.edm.EdmType; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.uri.UriParameter; + +public class Util { + + public static Entity findEntity(EdmEntityType edmEntityType, EntityCollection entitySet, + List keyParams) { + + List entityList = entitySet.getEntities(); + + // loop over all entities in order to find that one that matches + // all keys in request e.g. contacts(ContactID=1, CompanyID=1) + for (Entity entity : entityList) { + boolean foundEntity = entityMatchesAllKeys(edmEntityType, entity, keyParams); + if (foundEntity) { + return entity; + } + } + + return null; + } + + public static boolean entityMatchesAllKeys(EdmEntityType edmEntityType, Entity rt_entity, + List keyParams) { + + // loop over all keys + for (final UriParameter key : keyParams) { + // key + String keyName = key.getName(); + String keyText = key.getText(); + + // note: below line doesn't consider: keyProp can be part of a complexType in V4 + // in such case, it would be required to access it via getKeyPropertyRef() + // but since this isn't the case in our model, we ignore it in our implementation + EdmProperty edmKeyProperty = (EdmProperty) edmEntityType.getProperty(keyName); + // Edm: we need this info for the comparison below + Boolean isNullable = edmKeyProperty.isNullable(); + Integer maxLength = edmKeyProperty.getMaxLength(); + Integer precision = edmKeyProperty.getPrecision(); + Boolean isUnicode = edmKeyProperty.isUnicode(); + Integer scale = edmKeyProperty.getScale(); + // get the EdmType in order to compare + EdmType edmType = edmKeyProperty.getType(); + // if(EdmType instanceof EdmPrimitiveType) // do we need this? + EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) edmType; + + // Runtime data: the value of the current entity + // don't need to check for null, this is done in FWK + Object valueObject = rt_entity.getProperty(keyName).getValue(); + // TODO if the property is a complex type + + // now need to compare the valueObject with the keyText String + // this is done using the type.valueToString + String valueAsString = null; + try { + valueAsString = edmPrimitiveType.valueToString(valueObject, isNullable, + maxLength, precision, scale, isUnicode); + } catch (EdmPrimitiveTypeException e) { + return false; // TODO proper Exception handling + } + + if (valueAsString == null) { + return false; + } + + boolean matches = valueAsString.equals(keyText); + // if any of the key properties is not found in the entity, we don't need to search further + if (!matches) { + return false; + } + // if the given key value is found in the current entity, continue with the next key + } + + return true; + } + + /** + * Example: + * For the following navigation: DemoService.svc/Categories(1)/Products + * we need the EdmEntitySet for the navigation property "Products" + * + * This is defined as follows in the metadata: + * + * + * + * + * + * + * The "Target" attribute specifies the target EntitySet + * Therefore we need the startEntitySet "Categories" in order to retrieve the target EntitySet "Products" + */ + public static EdmEntitySet getNavigationTargetEntitySet(EdmEntitySet startEntitySet, + EdmNavigationProperty edmNavigationProperty) + throws ODataApplicationException { + + EdmEntitySet navigationTargetEntitySet = null; + + String navPropName = edmNavigationProperty.getName(); + EdmBindingTarget edmBindingTarget = startEntitySet.getRelatedBindingTarget(navPropName); + if (edmBindingTarget == null) { + throw new ODataApplicationException("Not supported.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + + if (edmBindingTarget instanceof EdmEntitySet) { + navigationTargetEntitySet = (EdmEntitySet) edmBindingTarget; + } else { + throw new ODataApplicationException("Not supported.", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + + return navigationTargetEntitySet; + } + +} diff --git a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/web/DemoServlet.java b/samples/tutorials/p0_all/src/main/java/myservice/mynamespace/web/DemoServlet.java similarity index 100% rename from samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/web/DemoServlet.java rename to samples/tutorials/p0_all/src/main/java/myservice/mynamespace/web/DemoServlet.java diff --git a/samples/tutorials/p7_queryoptions-f/src/main/webapp/WEB-INF/web.xml b/samples/tutorials/p0_all/src/main/webapp/WEB-INF/web.xml similarity index 100% rename from samples/tutorials/p7_queryoptions-f/src/main/webapp/WEB-INF/web.xml rename to samples/tutorials/p0_all/src/main/webapp/WEB-INF/web.xml diff --git a/samples/tutorials/p7_queryoptions-f/src/main/webapp/index.jsp b/samples/tutorials/p0_all/src/main/webapp/index.jsp similarity index 100% rename from samples/tutorials/p7_queryoptions-f/src/main/webapp/index.jsp rename to samples/tutorials/p0_all/src/main/webapp/index.jsp diff --git a/samples/tutorials/p1_read/pom.xml b/samples/tutorials/p1_read/pom.xml index 7f212c5f7..cad1b0cee 100755 --- a/samples/tutorials/p1_read/pom.xml +++ b/samples/tutorials/p1_read/pom.xml @@ -25,7 +25,7 @@ my.group.id DemoService-Read war - 0.0.1 + 4.0.0 ${project.artifactId}-Webapp @@ -35,7 +35,7 @@ 2.5 - 4.0.0-beta-03 + 4.0.0-SNAPSHOT 1.7.7 @@ -75,5 +75,11 @@ ${slf4j.version} runtime + + org.slf4j + slf4j-api + 1.7.11 + compile + diff --git a/samples/tutorials/p1_read/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java b/samples/tutorials/p1_read/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java index dd46e864e..614738ae7 100755 --- a/samples/tutorials/p1_read/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java +++ b/samples/tutorials/p1_read/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.apache.olingo.commons.api.ODataException; 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; @@ -58,7 +57,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { @Override - public List getSchemas() throws ODataException { + public List getSchemas() { // create Schema CsdlSchema schema = new CsdlSchema(); @@ -81,7 +80,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { @Override - public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException { + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { // this method is called for one of the EntityTypes that are configured in the Schema if(entityTypeName.equals(ET_PRODUCT_FQN)){ @@ -108,7 +107,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) throws ODataException { + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { if(entityContainer.equals(CONTAINER)){ if(entitySetName.equals(ES_PRODUCTS_NAME)){ @@ -124,7 +123,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainer getEntityContainer() throws ODataException { + public CsdlEntityContainer getEntityContainer() { // create EntitySets List entitySets = new ArrayList(); @@ -139,7 +138,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) throws ODataException { + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) { // This method is invoked when displaying the service document at e.g. http://localhost:8080/DemoService/DemoService.svc if(entityContainerName == null || entityContainerName.equals(CONTAINER)){ diff --git a/samples/tutorials/p1_read/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java b/samples/tutorials/p1_read/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java index e82a3caa6..4e4567beb 100755 --- a/samples/tutorials/p1_read/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java +++ b/samples/tutorials/p1_read/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java @@ -28,7 +28,6 @@ import org.apache.olingo.commons.api.data.ValueType; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -78,9 +77,8 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor EntityCollection entitySet = getData(edmEntitySet); // 3rd: create a serializer based on the requested format (json) - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); - + ODataSerializer serializer = odata.createSerializer(responseFormat); + // 4th: Now serialize the content: transform from the EntitySet object to InputStream EdmEntityType edmEntityType = edmEntitySet.getEntityType(); ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).build(); diff --git a/samples/tutorials/p2_readep/pom.xml b/samples/tutorials/p2_readep/pom.xml index 9a47d1c95..a6beac065 100755 --- a/samples/tutorials/p2_readep/pom.xml +++ b/samples/tutorials/p2_readep/pom.xml @@ -1,31 +1,15 @@ - - + + 4.0.0 my.group.id DemoService-ReadEp war - 0.0.1 + 4.0.0 ${project.artifactId}-Webapp @@ -35,7 +19,7 @@ 2.5 - 4.0.0-beta-03 + 4.0.0-SNAPSHOT 1.7.7 @@ -75,5 +59,12 @@ ${slf4j.version} runtime + + + org.slf4j + slf4j-api + 1.7.11 + compile + diff --git a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java index 15140e19a..14e3db6f0 100755 --- a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java +++ b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.apache.olingo.commons.api.ODataException; 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; @@ -53,8 +52,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { @Override - public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) - throws ODataException { + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { // this method is called for one of the EntityTypes that are configured in the Schema if(ET_PRODUCT_FQN.equals(entityTypeName)){ @@ -81,8 +79,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, - String entitySetName) throws ODataException { + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { if(entityContainer.equals(CONTAINER)){ if(entitySetName.equals(ES_PRODUCTS_NAME)){ CsdlEntitySet entitySet = new CsdlEntitySet(); @@ -98,9 +95,9 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainerInfo getEntityContainerInfo( - FullQualifiedName entityContainerName) throws ODataException { - // This method is invoked when displaying the service document at e.g. http://localhost:8080/DemoService/DemoService.svc + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) { + // This method is invoked when displaying the service document + // at e.g. http://localhost:8080/DemoService/DemoService.svc if(entityContainerName == null || entityContainerName.equals(CONTAINER)){ CsdlEntityContainerInfo entityContainerInfo = new CsdlEntityContainerInfo(); entityContainerInfo.setContainerName(CONTAINER); @@ -112,7 +109,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public List getSchemas() throws ODataException { + public List getSchemas() { // create Schema CsdlSchema schema = new CsdlSchema(); schema.setNamespace(NAMESPACE); @@ -134,7 +131,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainer getEntityContainer() throws ODataException { + public CsdlEntityContainer getEntityContainer() { // create EntitySets List entitySets = new ArrayList(); entitySets.add(getEntitySet(CONTAINER, ES_PRODUCTS_NAME)); diff --git a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java index d69d5291f..9b6e25abd 100755 --- a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java +++ b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java @@ -28,7 +28,6 @@ import org.apache.olingo.commons.api.data.EntityCollection; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -71,8 +70,7 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor EntityCollection entityCollection = storage.readEntitySetData(edmEntitySet); // 3rd: create a serializer based on the requested format (json) - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); // and serialize the content: transform from the EntitySet object to InputStream EdmEntityType edmEntityType = edmEntitySet.getEntityType(); diff --git a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java index e3c876787..82163f494 100755 --- a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java +++ b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java @@ -29,7 +29,6 @@ import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -88,8 +87,7 @@ public class DemoEntityProcessor implements EntityProcessor { // expand and select currently not supported EntitySerializerOptions options = EntitySerializerOptions.with().contextURL(contextUrl).build(); - ODataFormat oDataFormat = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = this.odata.createSerializer(oDataFormat); + ODataSerializer serializer = this.odata.createSerializer(responseFormat); SerializerResult serializerResult = serializer.entity(serviceMetadata, entityType, entity, options); InputStream entityStream = serializerResult.getContent(); diff --git a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java index 1ba0c750c..40ae7ca87 100755 --- a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java +++ b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java @@ -31,7 +31,6 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -55,6 +54,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { private OData odata; private Storage storage; + private ServiceMetadata serviceMetadata; public DemoPrimitiveProcessor(Storage storage) { this.storage = storage; @@ -62,7 +62,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { public void init(OData odata, ServiceMetadata serviceMetadata) { this.odata = odata; - + this.serviceMetadata = serviceMetadata; } /* @@ -111,13 +111,12 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { Object value = property.getValue(); if (value != null) { // 3.1. configure the serializer - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).navOrPropertyPath(edmPropertyName).build(); PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextUrl).build(); // 3.2. serialize - SerializerResult serializerResult = serializer.primitive(edmPropertyType, property, options); + SerializerResult serializerResult = serializer.primitive(serviceMetadata, edmPropertyType, property, options); InputStream propertyStream = serializerResult.getContent(); //4. configure the response object diff --git a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/util/Util.java b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/util/Util.java index c21d352c3..a645d462c 100755 --- a/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/util/Util.java +++ b/samples/tutorials/p2_readep/src/main/java/myservice/mynamespace/util/Util.java @@ -23,7 +23,6 @@ import java.util.Locale; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityCollection; -import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; @@ -31,10 +30,7 @@ import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.EdmType; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.ODataApplicationException; -import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.UriParameter; -import org.apache.olingo.server.api.uri.UriResource; -import org.apache.olingo.server.api.uri.UriResourceEntitySet; public class Util { diff --git a/samples/tutorials/p3_write/pom.xml b/samples/tutorials/p3_write/pom.xml index dc9ba693c..7ff4f22fd 100755 --- a/samples/tutorials/p3_write/pom.xml +++ b/samples/tutorials/p3_write/pom.xml @@ -25,7 +25,7 @@ my.group.id DemoService-Write war - 0.0.1 + 4.0.0 ${project.artifactId}-Webapp @@ -35,7 +35,7 @@ 2.5 - 4.0.0-beta-03 + 4.0.0-SNAPSHOT 1.7.7 @@ -75,5 +75,11 @@ ${slf4j.version} runtime + + org.slf4j + slf4j-api + 1.7.11 + compile + diff --git a/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java b/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java index f842af8ad..b19d7fd7d 100755 --- a/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java +++ b/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.apache.olingo.commons.api.ODataException; 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; @@ -58,7 +57,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { @Override - public List getSchemas() throws ODataException { + public List getSchemas() { // create Schema CsdlSchema schema = new CsdlSchema(); @@ -81,7 +80,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { @Override - public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException { + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { // this method is called for one of the EntityTypes that are configured in the Schema if(entityTypeName.equals(ET_PRODUCT_FQN)){ @@ -111,7 +110,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) throws ODataException { + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { if(entityContainer.equals(CONTAINER)){ if(entitySetName.equals(ES_PRODUCTS_NAME)){ @@ -128,7 +127,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } - public CsdlEntityContainer getEntityContainer() throws ODataException { + public CsdlEntityContainer getEntityContainer() { // create EntitySets List entitySets = new ArrayList(); entitySets.add(getEntitySet(CONTAINER, ES_PRODUCTS_NAME)); @@ -143,7 +142,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) throws ODataException { + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) { // This method is invoked when displaying the service document at // e.g. http://localhost:8080/DemoService/DemoService.svc diff --git a/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java b/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java index 53470cb8b..bae1ec584 100755 --- a/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java +++ b/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java @@ -27,7 +27,6 @@ import org.apache.olingo.commons.api.data.EntityCollection; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -75,8 +74,7 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor EntityCollection entitySet = storage.readEntitySetData(edmEntitySet); // 3rd: create a serializer based on the requested format (json) - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); // and serialize the content: transform from the EntitySet object to InputStream EdmEntityType edmEntityType = edmEntitySet.getEntityType(); diff --git a/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java b/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java index 35d42033e..499f5f616 100755 --- a/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java +++ b/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java @@ -29,7 +29,6 @@ import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpMethod; import org.apache.olingo.commons.api.http.HttpStatusCode; @@ -87,8 +86,7 @@ public class DemoEntityProcessor implements EntityProcessor { // expand and select currently not supported EntitySerializerOptions options = EntitySerializerOptions.with().contextURL(contextUrl).build(); - ODataFormat oDataFormat = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = this.odata.createSerializer(oDataFormat); + ODataSerializer serializer = this.odata.createSerializer(responseFormat); SerializerResult result = serializer.entity(serviceMetadata, entityType, entity, options); //4. configure the response object @@ -120,8 +118,7 @@ public class DemoEntityProcessor implements EntityProcessor { // 2. create the data in backend // 2.1. retrieve the payload from the POST request for the entity to create and deserialize it InputStream requestInputStream = request.getBody(); - ODataFormat requestODataFormat = ODataFormat.fromContentType(requestFormat); - ODataDeserializer deserializer = this.odata.createDeserializer(requestODataFormat); + ODataDeserializer deserializer = this.odata.createDeserializer(requestFormat); DeserializerResult result = deserializer.entity(requestInputStream, edmEntityType); Entity requestEntity = result.getEntity(); // 2.2 do the creation in backend, which returns the newly created entity @@ -131,8 +128,7 @@ public class DemoEntityProcessor implements EntityProcessor { ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).build(); EntitySerializerOptions options = EntitySerializerOptions.with().contextURL(contextUrl).build(); // expand and select currently not supported - ODataFormat oDataFormat = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = this.odata.createSerializer(oDataFormat); + ODataSerializer serializer = this.odata.createSerializer(responseFormat); SerializerResult serializedResponse = serializer.entity(serviceMetadata, edmEntityType, createdEntity, options); //4. configure the response object @@ -156,8 +152,7 @@ public class DemoEntityProcessor implements EntityProcessor { // 2. update the data in backend // 2.1. retrieve the payload from the PUT request for the entity to be updated InputStream requestInputStream = request.getBody(); - ODataFormat requestODataFormat = ODataFormat.fromContentType(requestFormat); - ODataDeserializer deserializer = this.odata.createDeserializer(requestODataFormat); + ODataDeserializer deserializer = this.odata.createDeserializer(requestFormat); DeserializerResult result = deserializer.entity(requestInputStream, edmEntityType); Entity requestEntity = result.getEntity(); // 2.2 do the modification in backend diff --git a/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java b/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java index ccf6d2b85..8766b8d71 100755 --- a/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java +++ b/samples/tutorials/p3_write/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java @@ -30,7 +30,6 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -54,6 +53,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { private OData odata; private Storage storage; + private ServiceMetadata serviceMetadata; public DemoPrimitiveProcessor(Storage storage) { this.storage = storage; @@ -61,6 +61,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { public void init(OData odata, ServiceMetadata serviceMetadata) { this.odata = odata; + this.serviceMetadata = serviceMetadata; } /* @@ -111,13 +112,12 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { Object value = property.getValue(); if (value != null) { // 3.1. configure the serializer - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).navOrPropertyPath(edmPropertyName).build(); PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextUrl).build(); // 3.2. serialize - SerializerResult result = serializer.primitive(edmPropertyType, property, options); + SerializerResult result = serializer.primitive(serviceMetadata, edmPropertyType, property, options); //4. configure the response object response.setContent(result.getContent()); diff --git a/samples/tutorials/p4_navigation/pom.xml b/samples/tutorials/p4_navigation/pom.xml index e24efea5b..2f226792c 100755 --- a/samples/tutorials/p4_navigation/pom.xml +++ b/samples/tutorials/p4_navigation/pom.xml @@ -25,7 +25,7 @@ my.group.id DemoService-Navigation war - 0.0.1 + 4.0.0 ${project.artifactId}-Webapp @@ -35,7 +35,7 @@ 2.5 - 4.0.0-beta-03 + 4.0.0-SNAPSHOT 1.7.7 @@ -76,5 +76,12 @@ ${slf4j.version} runtime + + + org.slf4j + slf4j-api + 1.7.11 + compile + 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 7b1fef806..8ce9baced 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 @@ -22,7 +22,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.apache.olingo.commons.api.ODataException; 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; @@ -57,7 +56,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { public static final String ES_CATEGORIES_NAME = "Categories"; @Override - public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException { + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { // this method is called for each EntityType that are configured in the Schema CsdlEntityType entityType = null; @@ -118,7 +117,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) throws ODataException { + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { CsdlEntitySet entitySet = null; @@ -158,7 +157,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) throws ODataException { + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) { // This method is invoked when displaying the service document at // e.g. http://localhost:8080/DemoService/DemoService.svc @@ -172,7 +171,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public List getSchemas() throws ODataException { + public List getSchemas() { // create Schema CsdlSchema schema = new CsdlSchema(); schema.setNamespace(NAMESPACE); @@ -194,7 +193,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainer getEntityContainer() throws ODataException { + public CsdlEntityContainer getEntityContainer() { // create EntitySets List entitySets = new ArrayList(); 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 9f281bbf5..5a87c0d1e 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 @@ -31,7 +31,6 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmNavigationProperty; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -136,7 +135,7 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with().contextURL(contextUrl).build(); EdmEntityType edmEntityType = responseEdmEntitySet.getEntityType(); - ODataSerializer serializer = odata.createSerializer(ODataFormat.fromContentType(responseFormat)); + ODataSerializer serializer = odata.createSerializer(responseFormat); SerializerResult serializerResult = serializer.entityCollection(this.srvMetadata, edmEntityType, responseEntityCollection, opts); 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 a2cf344b1..fba514a32 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 @@ -31,7 +31,6 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmNavigationProperty; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -145,8 +144,7 @@ public class DemoEntityProcessor implements EntityProcessor { ContextURL contextUrl = ContextURL.with().entitySet(responseEdmEntitySet).suffix(Suffix.ENTITY).build(); EntitySerializerOptions opts = EntitySerializerOptions.with().contextURL(contextUrl).build(); - ODataFormat oDataFormat = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = this.odata.createSerializer(oDataFormat); + ODataSerializer serializer = this.odata.createSerializer(responseFormat); SerializerResult serializerResult = serializer.entity(this.srvMetadata, responseEdmEntityType, responseEntity, opts); diff --git a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java index c32c5c24a..9246bf163 100755 --- a/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java +++ b/samples/tutorials/p4_navigation/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java @@ -31,7 +31,6 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -55,6 +54,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { private OData odata; private Storage storage; + private ServiceMetadata serviceMetadata; public DemoPrimitiveProcessor(Storage storage) { this.storage = storage; @@ -62,6 +62,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { public void init(OData odata, ServiceMetadata serviceMetadata) { this.odata = odata; + this.serviceMetadata = serviceMetadata; } @@ -114,13 +115,12 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { Object value = property.getValue(); if (value != null) { // 3.1. configure the serializer - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).navOrPropertyPath(edmPropertyName).build(); PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextUrl).build(); // 3.2. serialize - SerializerResult serializerResult = serializer.primitive(edmPropertyType, property, options); + SerializerResult serializerResult = serializer.primitive(serviceMetadata, edmPropertyType, property, options); InputStream propertyStream = serializerResult.getContent(); // 4. configure the response object diff --git a/samples/tutorials/p5_queryoptions-tcs/pom.xml b/samples/tutorials/p5_queryoptions-tcs/pom.xml index d9b463e5b..db68f42f0 100755 --- a/samples/tutorials/p5_queryoptions-tcs/pom.xml +++ b/samples/tutorials/p5_queryoptions-tcs/pom.xml @@ -25,7 +25,7 @@ my.group.id DemoService-QueryOptions-TCS war - 0.0.1 + 4.0.0 ${project.artifactId}-Webapp @@ -35,7 +35,7 @@ 2.5 - 4.0.0-beta-03 + 4.0.0-SNAPSHOT 1.7.7 @@ -75,5 +75,11 @@ ${slf4j.version} runtime + + org.slf4j + slf4j-api + 1.7.11 + compile + diff --git a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java index 3c28a21c4..6ff041bb4 100755 --- a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java +++ b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.apache.olingo.commons.api.ODataException; 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; @@ -52,8 +51,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { public static final String ES_PRODUCTS_NAME = "Products"; @Override - public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) - throws ODataException { + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { // this method is called for one of the EntityTypes that are configured in the Schema if (ET_PRODUCT_FQN.equals(entityTypeName)) { @@ -83,8 +81,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, - String entitySetName) throws ODataException { + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { if (entityContainer.equals(CONTAINER)) { if (entitySetName.equals(ES_PRODUCTS_NAME)) { CsdlEntitySet entitySet = new CsdlEntitySet(); @@ -100,8 +97,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainerInfo getEntityContainerInfo( - FullQualifiedName entityContainerName) throws ODataException { + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) { // This method is invoked when displaying the service document at // e.g. http://localhost:8080/DemoService/DemoService.svc if (entityContainerName == null || entityContainerName.equals(CONTAINER)) { @@ -115,7 +111,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public List getSchemas() throws ODataException { + public List getSchemas() { // create Schema CsdlSchema schema = new CsdlSchema(); schema.setNamespace(NAMESPACE); @@ -137,7 +133,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainer getEntityContainer() throws ODataException { + public CsdlEntityContainer getEntityContainer() { // create EntitySets List entitySets = new ArrayList(); entitySets.add(getEntitySet(CONTAINER, ES_PRODUCTS_NAME)); diff --git a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java index fc58c2309..737c6b08e 100755 --- a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java +++ b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java @@ -30,7 +30,6 @@ import org.apache.olingo.commons.api.data.EntityCollection; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -121,8 +120,7 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor } // 4th: create a serializer based on the requested format (json) - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); // and serialize the content: transform from the EntitySet object to InputStream EdmEntityType edmEntityType = edmEntitySet.getEntityType(); diff --git a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java index 81453a06b..a2ec93718 100755 --- a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java +++ b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java @@ -29,7 +29,6 @@ import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -83,8 +82,7 @@ public class DemoEntityProcessor implements EntityProcessor { // expand and select currently not supported EntitySerializerOptions options = EntitySerializerOptions.with().contextURL(contextUrl).build(); - ODataFormat oDataFormat = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = this.odata.createSerializer(oDataFormat); + ODataSerializer serializer = this.odata.createSerializer(responseFormat); SerializerResult serializerResult = serializer.entity(serviceMetadata, entityType, entity, options); InputStream entityStream = serializerResult.getContent(); diff --git a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java index 64f794960..b6c42a266 100755 --- a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java +++ b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java @@ -31,7 +31,6 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -55,6 +54,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { private OData odata; private Storage storage; + private ServiceMetadata serviceMetadata; public DemoPrimitiveProcessor(Storage storage) { this.storage = storage; @@ -62,7 +62,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { public void init(OData odata, ServiceMetadata serviceMetadata) { this.odata = odata; - + this.serviceMetadata = serviceMetadata; } /* @@ -112,13 +112,12 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { Object value = property.getValue(); if (value != null) { // 3.1. configure the serializer - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).navOrPropertyPath(edmPropertyName).build(); PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextUrl).build(); // 3.2. serialize - SerializerResult serializerResult = serializer.primitive(edmPropertyType, property, options); + SerializerResult serializerResult = serializer.primitive(serviceMetadata, edmPropertyType, property, options); InputStream propertyStream = serializerResult.getContent(); //4. configure the response object diff --git a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/util/Util.java b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/util/Util.java index c21d352c3..a645d462c 100755 --- a/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/util/Util.java +++ b/samples/tutorials/p5_queryoptions-tcs/src/main/java/myservice/mynamespace/util/Util.java @@ -23,7 +23,6 @@ import java.util.Locale; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntityCollection; -import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; @@ -31,10 +30,7 @@ import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.edm.EdmType; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.ODataApplicationException; -import org.apache.olingo.server.api.uri.UriInfoResource; import org.apache.olingo.server.api.uri.UriParameter; -import org.apache.olingo.server.api.uri.UriResource; -import org.apache.olingo.server.api.uri.UriResourceEntitySet; public class Util { diff --git a/samples/tutorials/p6_queryoptions-es/pom.xml b/samples/tutorials/p6_queryoptions-es/pom.xml index bb095adc7..da69b3a6b 100755 --- a/samples/tutorials/p6_queryoptions-es/pom.xml +++ b/samples/tutorials/p6_queryoptions-es/pom.xml @@ -25,7 +25,7 @@ my.group.id DemoService-QueryOptions-ES war - 0.0.1 + 4.0.0 ${project.artifactId}-Webapp @@ -35,7 +35,7 @@ 2.5 - 4.0.0-beta-03 + 4.0.0-SNAPSHOT 1.7.7 @@ -76,5 +76,11 @@ ${slf4j.version} runtime + + org.slf4j + slf4j-api + 1.7.11 + compile + diff --git a/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java b/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java index 7b1fef806..8ce9baced 100755 --- a/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java +++ b/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java @@ -22,7 +22,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.apache.olingo.commons.api.ODataException; 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; @@ -57,7 +56,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { public static final String ES_CATEGORIES_NAME = "Categories"; @Override - public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) throws ODataException { + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { // this method is called for each EntityType that are configured in the Schema CsdlEntityType entityType = null; @@ -118,7 +117,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) throws ODataException { + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { CsdlEntitySet entitySet = null; @@ -158,7 +157,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) throws ODataException { + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) { // This method is invoked when displaying the service document at // e.g. http://localhost:8080/DemoService/DemoService.svc @@ -172,7 +171,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public List getSchemas() throws ODataException { + public List getSchemas() { // create Schema CsdlSchema schema = new CsdlSchema(); schema.setNamespace(NAMESPACE); @@ -194,7 +193,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainer getEntityContainer() throws ODataException { + public CsdlEntityContainer getEntityContainer() { // create EntitySets List entitySets = new ArrayList(); diff --git a/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java b/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java index 83dd676a7..14ac8cbce 100755 --- a/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java +++ b/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java @@ -33,7 +33,6 @@ import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmNavigationProperty; import org.apache.olingo.commons.api.edm.EdmNavigationPropertyBinding; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -170,7 +169,7 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor .expand(expandOption) .build(); - ODataSerializer serializer = odata.createSerializer(ODataFormat.fromContentType(responseFormat)); + ODataSerializer serializer = odata.createSerializer(responseFormat); SerializerResult serializerResult = serializer.entityCollection(srvMetadata, edmEntityType, entityCollection, opts); // 5th: configure the response object: set the body, headers and status code diff --git a/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java b/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java index 281fdbe33..6b623b08f 100755 --- a/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java +++ b/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java @@ -35,7 +35,6 @@ import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmNavigationProperty; import org.apache.olingo.commons.api.edm.EdmNavigationPropertyBinding; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -169,7 +168,7 @@ public class DemoEntityProcessor implements EntityProcessor { .expand(expandOption) .build(); - ODataSerializer serializer = this.odata.createSerializer(ODataFormat.fromContentType(responseFormat)); + ODataSerializer serializer = this.odata.createSerializer(responseFormat); SerializerResult serializerResult = serializer.entity(srvMetadata, edmEntityType, entity, opts); // 5. configure the response object diff --git a/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java b/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java index c32c5c24a..bf0527960 100755 --- a/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java +++ b/samples/tutorials/p6_queryoptions-es/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java @@ -31,7 +31,6 @@ import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmProperty; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -55,6 +54,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { private OData odata; private Storage storage; + private ServiceMetadata serviceMetadata; public DemoPrimitiveProcessor(Storage storage) { this.storage = storage; @@ -62,7 +62,7 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { public void init(OData odata, ServiceMetadata serviceMetadata) { this.odata = odata; - + this.serviceMetadata = serviceMetadata; } /* @@ -114,13 +114,12 @@ public class DemoPrimitiveProcessor implements PrimitiveProcessor { Object value = property.getValue(); if (value != null) { // 3.1. configure the serializer - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).navOrPropertyPath(edmPropertyName).build(); PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextUrl).build(); // 3.2. serialize - SerializerResult serializerResult = serializer.primitive(edmPropertyType, property, options); + SerializerResult serializerResult = serializer.primitive(serviceMetadata, edmPropertyType, property, options); InputStream propertyStream = serializerResult.getContent(); // 4. configure the response object diff --git a/samples/tutorials/p7_queryoptions-o/pom.xml b/samples/tutorials/p7_queryoptions-o/pom.xml new file mode 100644 index 000000000..108b0deb3 --- /dev/null +++ b/samples/tutorials/p7_queryoptions-o/pom.xml @@ -0,0 +1,85 @@ + + + + 4.0.0 + my.group.id + DemoService-QueryOptions-O + war + 4.0.0 + + ${project.artifactId}-Webapp + + + DemoService + + + + 2.5 + 4.0.0-SNAPSHOT + 1.7.7 + + + + + javax.servlet + servlet-api + ${javax.version} + provided + + + + org.apache.olingo + odata-server-api + ${odata.version} + + + org.apache.olingo + odata-server-core + ${odata.version} + + + + org.apache.olingo + odata-commons-api + ${odata.version} + + + org.apache.olingo + odata-commons-core + ${odata.version} + + + + org.slf4j + slf4j-simple + ${slf4j.version} + runtime + + + org.slf4j + slf4j-api + 1.7.11 + compile + + + diff --git a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/data/Storage.java b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/data/Storage.java similarity index 100% rename from samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/data/Storage.java rename to samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/data/Storage.java diff --git a/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java new file mode 100644 index 000000000..0d0fbb265 --- /dev/null +++ b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java @@ -0,0 +1,153 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.service; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +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.CsdlEntityContainer; +import org.apache.olingo.commons.api.edm.provider.CsdlEntityContainerInfo; +import org.apache.olingo.commons.api.edm.provider.CsdlEntitySet; +import org.apache.olingo.commons.api.edm.provider.CsdlEntityType; +import org.apache.olingo.commons.api.edm.provider.CsdlProperty; +import org.apache.olingo.commons.api.edm.provider.CsdlPropertyRef; +import org.apache.olingo.commons.api.edm.provider.CsdlSchema; + +public class DemoEdmProvider extends CsdlAbstractEdmProvider { + + // Service Namespace + public static final String NAMESPACE = "OData.Demo"; + + // EDM Container + public static final String CONTAINER_NAME = "Container"; + public static final FullQualifiedName CONTAINER = new FullQualifiedName(NAMESPACE, CONTAINER_NAME); + + // Entity Types Names + public static final String ET_PRODUCT_NAME = "Product"; + public static final FullQualifiedName ET_PRODUCT_FQN = new FullQualifiedName(NAMESPACE, ET_PRODUCT_NAME); + + // Entity Set Names + public static final String ES_PRODUCTS_NAME = "Products"; + + + @Override + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { + // this method is called for one of the EntityTypes that are configured in the Schema + if(ET_PRODUCT_FQN.equals(entityTypeName)){ + + //create EntityType properties + CsdlProperty id = new CsdlProperty().setName("ID") + .setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName()); + CsdlProperty name = new CsdlProperty().setName("Name") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); + CsdlProperty description = new CsdlProperty().setName("Description") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); + + // create PropertyRef for Key element + CsdlPropertyRef propertyRef = new CsdlPropertyRef(); + propertyRef.setName("ID"); + + // configure EntityType + CsdlEntityType entityType = new CsdlEntityType(); + entityType.setName(ET_PRODUCT_NAME); + entityType.setProperties(Arrays.asList(id, name, description)); + entityType.setKey(Collections.singletonList(propertyRef)); + + return entityType; + } + + return null; + + } + + @Override + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { + if(entityContainer.equals(CONTAINER)){ + if(entitySetName.equals(ES_PRODUCTS_NAME)){ + CsdlEntitySet entitySet = new CsdlEntitySet(); + entitySet.setName(ES_PRODUCTS_NAME); + entitySet.setType(ET_PRODUCT_FQN); + + return entitySet; + } + } + + return null; + + } + + @Override + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) { + // This method is invoked when displaying the service document at + // e.g. http://localhost:8080/DemoService/DemoService.svc + if(entityContainerName == null || entityContainerName.equals(CONTAINER)){ + CsdlEntityContainerInfo entityContainerInfo = new CsdlEntityContainerInfo(); + entityContainerInfo.setContainerName(CONTAINER); + return entityContainerInfo; + } + + return null; + + } + + @Override + public List getSchemas() { + // create Schema + CsdlSchema schema = new CsdlSchema(); + schema.setNamespace(NAMESPACE); + + // add EntityTypes + List entityTypes = new ArrayList(); + entityTypes.add(getEntityType(ET_PRODUCT_FQN)); + schema.setEntityTypes(entityTypes); + + // add EntityContainer + schema.setEntityContainer(getEntityContainer()); + + // finally + List schemas = new ArrayList(); + schemas.add(schema); + + return schemas; + + } + + @Override + public CsdlEntityContainer getEntityContainer() { + // create EntitySets + List entitySets = new ArrayList(); + entitySets.add(getEntitySet(CONTAINER, ES_PRODUCTS_NAME)); + + // create EntityContainer + CsdlEntityContainer entityContainer = new CsdlEntityContainer(); + entityContainer.setName(CONTAINER_NAME); + entityContainer.setEntitySets(entitySets); + + return entityContainer; + + } + + + +} diff --git a/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java new file mode 100644 index 000000000..5b5a5eb59 --- /dev/null +++ b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java @@ -0,0 +1,147 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.service; + +import java.io.InputStream; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import myservice.mynamespace.data.Storage; + +import org.apache.olingo.commons.api.data.ContextURL; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.processor.EntityCollectionProcessor; +import org.apache.olingo.server.api.serializer.EntityCollectionSerializerOptions; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.serializer.SerializerResult; +import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.api.uri.UriInfoResource; +import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty; +import org.apache.olingo.server.api.uri.queryoption.OrderByItem; +import org.apache.olingo.server.api.uri.queryoption.OrderByOption; +import org.apache.olingo.server.api.uri.queryoption.expression.Expression; +import org.apache.olingo.server.api.uri.queryoption.expression.Member; + +public class DemoEntityCollectionProcessor implements EntityCollectionProcessor { + + private OData odata; + private ServiceMetadata serviceMetadata; + private Storage storage; + + public DemoEntityCollectionProcessor(Storage storage) { + this.storage = storage; + } + + public void init(OData odata, ServiceMetadata serviceMetadata) { + this.odata = odata; + this.serviceMetadata = serviceMetadata; + } + + public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType responseFormat) throws ODataApplicationException, SerializerException { + + // 1st retrieve the requested EntitySet from the uriInfo (representation of the parsed URI) + List resourcePaths = uriInfo.getUriResourceParts(); + // in our example, the first segment is the EntitySet + UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); + EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet(); + + // 2nd: fetch the data from backend for this requested EntitySetName and deliver as EntitySet + EntityCollection entityCollection = storage.readEntitySetData(edmEntitySet); + List entityList = entityCollection.getEntities(); + + // 3rd apply $orderby + OrderByOption orderByOption = uriInfo.getOrderByOption(); + if (orderByOption != null) { + List orderItemList = orderByOption.getOrders(); + final OrderByItem orderByItem = orderItemList.get(0); // in our example we support only one + Expression expression = orderByItem.getExpression(); + if(expression instanceof Member){ + UriInfoResource resourcePath = ((Member)expression).getResourcePath(); + UriResource uriResource = resourcePath.getUriResourceParts().get(0); + if (uriResource instanceof UriResourcePrimitiveProperty) { + EdmProperty edmProperty = ((UriResourcePrimitiveProperty)uriResource).getProperty(); + final String sortPropertyName = edmProperty.getName(); + + // do the sorting for the list of entities + Collections.sort(entityList, new Comparator() { + + // we delegate the sorting to the native sorter of Integer and String + public int compare(Entity entity1, Entity entity2) { + int compareResult = 0; + + if(sortPropertyName.equals("ID")){ + Integer integer1 = (Integer) entity1.getProperty(sortPropertyName).getValue(); + Integer integer2 = (Integer) entity2.getProperty(sortPropertyName).getValue(); + + compareResult = integer1.compareTo(integer2); + }else{ + String propertyValue1 = (String) entity1.getProperty(sortPropertyName).getValue(); + String propertyValue2 = (String) entity2.getProperty(sortPropertyName).getValue(); + + compareResult = propertyValue1.compareTo(propertyValue2); + } + + // if 'desc' is specified in the URI, change the order of the list + if(orderByItem.isDescending()){ + return - compareResult; // just convert the result to negative value to change the order + } + + return compareResult; + } + }); + } + } + } + + + // 4th: create a serializer based on the requested format (json) + ODataSerializer serializer = odata.createSerializer(responseFormat); + + // and serialize the content: transform from the EntitySet object to InputStream + EdmEntityType edmEntityType = edmEntitySet.getEntityType(); + ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).build(); + + EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with().contextURL(contextUrl).build(); + SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, + entityCollection, opts); + InputStream serializedContent = serializerResult.getContent(); + + // 5th: configure the response object: set the body, headers and status code + response.setContent(serializedContent); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); + } +} diff --git a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java similarity index 88% rename from samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java rename to samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java index e3c876787..addfef099 100644 --- a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java +++ b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java @@ -29,7 +29,6 @@ import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -88,8 +87,7 @@ public class DemoEntityProcessor implements EntityProcessor { // expand and select currently not supported EntitySerializerOptions options = EntitySerializerOptions.with().contextURL(contextUrl).build(); - ODataFormat oDataFormat = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = this.odata.createSerializer(oDataFormat); + ODataSerializer serializer = this.odata.createSerializer(responseFormat); SerializerResult serializerResult = serializer.entity(serviceMetadata, entityType, entity, options); InputStream entityStream = serializerResult.getContent(); @@ -105,22 +103,20 @@ public class DemoEntityProcessor implements EntityProcessor { /* * These processor methods are not handled in this tutorial * */ - - - public void createEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat) - throws ODataApplicationException, DeserializerException, SerializerException { + public void createEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } - public void updateEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, ContentType responseFormat) - throws ODataApplicationException, DeserializerException, SerializerException { + public void updateEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } - public void deleteEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo) throws ODataApplicationException { + public void deleteEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo) + throws ODataApplicationException { throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); } - } diff --git a/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java new file mode 100644 index 000000000..3ca2a16dc --- /dev/null +++ b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java @@ -0,0 +1,148 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.service; + +import java.io.InputStream; +import java.util.List; +import java.util.Locale; + +import myservice.mynamespace.data.Storage; + +import org.apache.olingo.commons.api.data.ContextURL; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmPrimitiveType; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.processor.PrimitiveProcessor; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.serializer.SerializerResult; +import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.api.uri.UriParameter; +import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.UriResourceProperty; + +public class DemoPrimitiveProcessor implements PrimitiveProcessor { + + private OData odata; + private Storage storage; + private ServiceMetadata serviceMetadata; + + public DemoPrimitiveProcessor(Storage storage) { + this.storage = storage; + } + + public void init(OData odata, ServiceMetadata serviceMetadata) { + this.odata = odata; + this.serviceMetadata = serviceMetadata; + } + + /* + * In our example, the URL would be: http://localhost:8080/DemoService/DemoService.svc/Products(1)/Name + * and the response: + * { + * @odata.context: "$metadata#Products/Name", + * value: "Notebook Basic 15" + * } + * */ + public void readPrimitive(ODataRequest request, ODataResponse response,UriInfo uriInfo, ContentType responseFormat) + throws ODataApplicationException, SerializerException { + + // 1. Retrieve info from URI + // 1.1. retrieve the info about the requested entity set + List resourceParts = uriInfo.getUriResourceParts(); + // Note: only in our example we can rely that the first segment is the EntitySet + UriResourceEntitySet uriEntityset = (UriResourceEntitySet) resourceParts.get(0); + EdmEntitySet edmEntitySet = uriEntityset.getEntitySet(); + // the key for the entity + List keyPredicates = uriEntityset.getKeyPredicates(); + + // 1.2. retrieve the requested (Edm) property + // the last segment is the Property + UriResourceProperty uriProperty = (UriResourceProperty)resourceParts.get(resourceParts.size() -1); + EdmProperty edmProperty = uriProperty.getProperty(); + String edmPropertyName = edmProperty.getName(); + // in our example, we know we have only primitive types in our model + EdmPrimitiveType edmPropertyType = (EdmPrimitiveType) edmProperty.getType(); + + + // 2. retrieve data from backend + // 2.1. retrieve the entity data, for which the property has to be read + Entity entity = storage.readEntityData(edmEntitySet, keyPredicates); + if (entity == null) { // Bad request + throw new ODataApplicationException("Entity not found", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ENGLISH); + } + + // 2.2. retrieve the property data from the entity + Property property = entity.getProperty(edmPropertyName); + if (property == null) { + throw new ODataApplicationException("Property not found", HttpStatusCode.NOT_FOUND.getStatusCode(), + Locale.ENGLISH); + } + + // 3. serialize + Object value = property.getValue(); + if (value != null) { + // 3.1. configure the serializer + ODataSerializer serializer = odata.createSerializer(responseFormat); + + ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).navOrPropertyPath(edmPropertyName).build(); + PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextUrl).build(); + // 3.2. serialize + SerializerResult serializerResult = serializer.primitive(serviceMetadata, edmPropertyType, property, options); + InputStream propertyStream = serializerResult.getContent(); + + //4. configure the response object + response.setContent(propertyStream); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); + } else { + // in case there's no value for the property, we can skip the serialization + response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode()); + } + } + + + + /* + * These processor methods are not handled in this tutorial + * */ + + public void updatePrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + + public void deletePrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo) + throws ODataApplicationException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } +} diff --git a/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/util/Util.java b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/util/Util.java new file mode 100644 index 000000000..a645d462c --- /dev/null +++ b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/util/Util.java @@ -0,0 +1,101 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.util; + +import java.util.List; +import java.util.Locale; + +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.edm.EdmPrimitiveType; +import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.edm.EdmType; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.uri.UriParameter; + +public class Util { + + public static Entity findEntity(EdmEntityType edmEntityType, EntityCollection entitySet, + List keyParams) throws ODataApplicationException { + + List entityList = entitySet.getEntities(); + + // loop over all entities in order to find that one that matches all keys in request + // e.g. contacts(ContactID=1, CompanyID=1) + for (Entity entity: entityList) { + boolean foundEntity = entityMatchesAllKeys(edmEntityType, entity, keyParams); + if (foundEntity) { + return entity; + } + } + + return null; + } + + public static boolean entityMatchesAllKeys(EdmEntityType edmEntityType, Entity entity, List keyParams) + throws ODataApplicationException { + + // loop over all keys + for (final UriParameter key : keyParams) { + // key + String keyName = key.getName(); + String keyText = key.getText(); + + // Edm: we need this info for the comparison below + EdmProperty edmKeyProperty = (EdmProperty) edmEntityType.getProperty(keyName); + Boolean isNullable = edmKeyProperty.isNullable(); + Integer maxLength = edmKeyProperty.getMaxLength(); + Integer precision = edmKeyProperty.getPrecision(); + Boolean isUnicode = edmKeyProperty.isUnicode(); + Integer scale = edmKeyProperty.getScale(); + // get the EdmType in order to compare + EdmType edmType = edmKeyProperty.getType(); + EdmPrimitiveType edmPrimitiveType = (EdmPrimitiveType) edmType; + + // Runtime data: the value of the current entity + // don't need to check for null, this is done in olingo library + Object valueObject = entity.getProperty(keyName).getValue(); + + // now need to compare the valueObject with the keyText String + // this is done using the type.valueToString + String valueAsString; + try { + valueAsString = edmPrimitiveType.valueToString(valueObject, isNullable, maxLength, precision, scale, isUnicode); + } catch (EdmPrimitiveTypeException e) { + throw new ODataApplicationException("Failed to retrieve String value", HttpStatusCode.INTERNAL_SERVER_ERROR + .getStatusCode(), Locale.ENGLISH, e); + } + + if (valueAsString == null) { + return false; + } + + boolean matches = valueAsString.equals(keyText); + if (!matches) { + // if any of the key properties is not found in the entity, we don't need to search further + return false; + } + } + + return true; + } +} diff --git a/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/web/DemoServlet.java b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/web/DemoServlet.java new file mode 100644 index 000000000..fe5cdbb38 --- /dev/null +++ b/samples/tutorials/p7_queryoptions-o/src/main/java/myservice/mynamespace/web/DemoServlet.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.web; + +import java.io.IOException; +import java.lang.Override;import java.lang.RuntimeException;import java.util.ArrayList; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import myservice.mynamespace.data.Storage; +import myservice.mynamespace.service.DemoEdmProvider; +import myservice.mynamespace.service.DemoEntityCollectionProcessor; +import myservice.mynamespace.service.DemoEntityProcessor; +import myservice.mynamespace.service.DemoPrimitiveProcessor; + +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataHttpHandler; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.edmx.EdmxReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DemoServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + private static final Logger LOG = LoggerFactory.getLogger(DemoServlet.class); + + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + try { + HttpSession session = req.getSession(true); + Storage storage = (Storage) session.getAttribute(Storage.class.getName()); + if (storage == null) { + storage = new Storage(); + session.setAttribute(Storage.class.getName(), storage); + } + + // create odata handler and configure it with EdmProvider and Processor + OData odata = OData.newInstance(); + ServiceMetadata edm = odata.createServiceMetadata(new DemoEdmProvider(), new ArrayList()); + ODataHttpHandler handler = odata.createHandler(edm); + handler.register(new DemoEntityCollectionProcessor(storage)); + handler.register(new DemoEntityProcessor(storage)); + handler.register(new DemoPrimitiveProcessor(storage)); + + // let the handler do the work + handler.process(req, resp); + } catch (RuntimeException e) { + LOG.error("Server Error occurred in ExampleServlet", e); + throw new ServletException(e); + } + + } + +} diff --git a/samples/tutorials/p7_queryoptions-o/src/main/webapp/WEB-INF/web.xml b/samples/tutorials/p7_queryoptions-o/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..21de52a8f --- /dev/null +++ b/samples/tutorials/p7_queryoptions-o/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,40 @@ + + + + + + + DemoServlet + myservice.mynamespace.web.DemoServlet + 1 + + + + + DemoServlet + /DemoService.svc/* + + \ No newline at end of file diff --git a/samples/tutorials/p7_queryoptions-o/src/main/webapp/index.jsp b/samples/tutorials/p7_queryoptions-o/src/main/webapp/index.jsp new file mode 100644 index 000000000..7ffb4ba6f --- /dev/null +++ b/samples/tutorials/p7_queryoptions-o/src/main/webapp/index.jsp @@ -0,0 +1,26 @@ + + + +

Hello World!

+OData Olingo V4 Demo Service + + diff --git a/samples/tutorials/p7_queryoptions-f/pom.xml b/samples/tutorials/p8_queryoptions-f/pom.xml similarity index 91% rename from samples/tutorials/p7_queryoptions-f/pom.xml rename to samples/tutorials/p8_queryoptions-f/pom.xml index 439a37c46..c2c305a0f 100644 --- a/samples/tutorials/p7_queryoptions-f/pom.xml +++ b/samples/tutorials/p8_queryoptions-f/pom.xml @@ -25,7 +25,7 @@ my.group.id DemoService-QueryOptions-F war - 0.0.1 + 4.0.0 ${project.artifactId} Webapp @@ -35,7 +35,7 @@ 2.5 - 4.0.0-beta-03 + 4.0.0-SNAPSHOT 1.7.7 @@ -76,5 +76,11 @@ ${slf4j.version} runtime + + org.slf4j + slf4j-api + 1.7.11 + compile + diff --git a/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/data/Storage.java b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/data/Storage.java new file mode 100644 index 000000000..d5d16c299 --- /dev/null +++ b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/data/Storage.java @@ -0,0 +1,125 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.data; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import myservice.mynamespace.service.DemoEdmProvider; +import myservice.mynamespace.util.Util; + +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.EntityCollection; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.data.ValueType; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.uri.UriParameter; + +public class Storage { + + private List productList; + + public Storage() { + productList = new ArrayList(); + initSampleData(); + } + + /* PUBLIC FACADE */ + + public EntityCollection readEntitySetData(EdmEntitySet edmEntitySet)throws ODataApplicationException{ + + // actually, this is only required if we have more than one Entity Sets + if(edmEntitySet.getName().equals(DemoEdmProvider.ES_PRODUCTS_NAME)){ + return getProducts(); + } + + return null; + } + + public Entity readEntityData(EdmEntitySet edmEntitySet, List keyParams) throws ODataApplicationException{ + + EdmEntityType edmEntityType = edmEntitySet.getEntityType(); + + // actually, this is only required if we have more than one Entity Type + if(edmEntityType.getName().equals(DemoEdmProvider.ET_PRODUCT_NAME)){ + return getProduct(edmEntityType, keyParams); + } + + return null; + } + + + + /* INTERNAL */ + + private EntityCollection getProducts(){ + EntityCollection retEntitySet = new EntityCollection(); + + for(Entity productEntity : this.productList){ + retEntitySet.getEntities().add(productEntity); + } + + return retEntitySet; + } + + + private Entity getProduct(EdmEntityType edmEntityType, List keyParams) throws ODataApplicationException{ + + // the list of entities at runtime + EntityCollection entitySet = getProducts(); + + /* generic approach to find the requested entity */ + Entity requestedEntity = Util.findEntity(edmEntityType, entitySet, keyParams); + + if(requestedEntity == null){ + // this variable is null if our data doesn't contain an entity for the requested key + // Throw suitable exception + throw new ODataApplicationException("Entity for requested key doesn't exist", + HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ENGLISH); + } + + return requestedEntity; + } + + /* HELPER */ + + private void initSampleData(){ + + // add some sample product entities + productList.add(new Entity() + .addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 1)) + .addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Notebook Basic 15")) + .addProperty(new Property(null, "Description", ValueType.PRIMITIVE, "Notebook Basic, 1.7GHz - 15 XGA - 1024MB DDR2 SDRAM - 40GB"))); + + productList.add(new Entity() + .addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 2)) + .addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "1UMTS PDA")) + .addProperty(new Property(null, "Description", ValueType.PRIMITIVE, "Ultrafast 3G UMTS/HSDPA Pocket PC, supports GSM network"))); + + productList.add(new Entity() + .addProperty(new Property(null, "ID", ValueType.PRIMITIVE, 3)) + .addProperty(new Property(null, "Name", ValueType.PRIMITIVE, "Ergo Screen")) + .addProperty(new Property(null, "Description", ValueType.PRIMITIVE, "19 Optimum Resolution 1024 x 768 @ 85Hz, resolution 1280 x 960"))); + + } +} diff --git a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java similarity index 87% rename from samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java rename to samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java index 15140e19a..a0ac68aaf 100644 --- a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java +++ b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEdmProvider.java @@ -23,7 +23,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.apache.olingo.commons.api.ODataException; 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; @@ -53,15 +52,16 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { @Override - public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) - throws ODataException { + public CsdlEntityType getEntityType(FullQualifiedName entityTypeName) { // this method is called for one of the EntityTypes that are configured in the Schema if(ET_PRODUCT_FQN.equals(entityTypeName)){ //create EntityType properties CsdlProperty id = new CsdlProperty().setName("ID").setType(EdmPrimitiveTypeKind.Int32.getFullQualifiedName()); - CsdlProperty name = new CsdlProperty().setName("Name").setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); - CsdlProperty description = new CsdlProperty().setName("Description").setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); + CsdlProperty name = new CsdlProperty().setName("Name") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); + CsdlProperty description = new CsdlProperty().setName("Description") + .setType(EdmPrimitiveTypeKind.String.getFullQualifiedName()); // create PropertyRef for Key element CsdlPropertyRef propertyRef = new CsdlPropertyRef(); @@ -77,12 +77,10 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } return null; - } @Override - public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, - String entitySetName) throws ODataException { + public CsdlEntitySet getEntitySet(FullQualifiedName entityContainer, String entitySetName) { if(entityContainer.equals(CONTAINER)){ if(entitySetName.equals(ES_PRODUCTS_NAME)){ CsdlEntitySet entitySet = new CsdlEntitySet(); @@ -94,13 +92,12 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } return null; - } @Override - public CsdlEntityContainerInfo getEntityContainerInfo( - FullQualifiedName entityContainerName) throws ODataException { - // This method is invoked when displaying the service document at e.g. http://localhost:8080/DemoService/DemoService.svc + public CsdlEntityContainerInfo getEntityContainerInfo(FullQualifiedName entityContainerName) { + // This method is invoked when displaying the service document at + // e.g. http://localhost:8080/DemoService/DemoService.svc if(entityContainerName == null || entityContainerName.equals(CONTAINER)){ CsdlEntityContainerInfo entityContainerInfo = new CsdlEntityContainerInfo(); entityContainerInfo.setContainerName(CONTAINER); @@ -108,11 +105,10 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } return null; - } @Override - public List getSchemas() throws ODataException { + public List getSchemas() { // create Schema CsdlSchema schema = new CsdlSchema(); schema.setNamespace(NAMESPACE); @@ -134,7 +130,7 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { } @Override - public CsdlEntityContainer getEntityContainer() throws ODataException { + public CsdlEntityContainer getEntityContainer() { // create EntitySets List entitySets = new ArrayList(); entitySets.add(getEntitySet(CONTAINER, ES_PRODUCTS_NAME)); @@ -145,9 +141,5 @@ public class DemoEdmProvider extends CsdlAbstractEdmProvider { entityContainer.setEntitySets(entitySets); return entityContainer; - } - - - } diff --git a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java similarity index 90% rename from samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java rename to samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java index 292a0c4ba..861b78658 100644 --- a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java +++ b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityCollectionProcessor.java @@ -31,7 +31,6 @@ import org.apache.olingo.commons.api.data.EntityCollection; import org.apache.olingo.commons.api.edm.EdmEntitySet; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.format.ContentType; -import org.apache.olingo.commons.api.format.ODataFormat; import org.apache.olingo.commons.api.http.HttpHeader; import org.apache.olingo.commons.api.http.HttpStatusCode; import org.apache.olingo.server.api.OData; @@ -66,11 +65,13 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor this.serviceMetadata = serviceMetadata; } - public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) throws ODataApplicationException, SerializerException { + public void readEntityCollection(ODataRequest request, ODataResponse response, UriInfo uriInfo, + ContentType responseFormat) throws ODataApplicationException, SerializerException { // 1st: retrieve the requested EntitySet from the uriInfo (representation of the parsed URI) List resourcePaths = uriInfo.getUriResourceParts(); - UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); // in our example, the first segment is the EntitySet + // in our example, the first segment is the EntitySet + UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet(); // 2nd: fetch the data from backend for this requested EntitySetName and deliver as EntitySet @@ -98,8 +99,8 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor // The result of the filter expression must be of type Edm.Boolean if(visitorResult instanceof Boolean) { - if(visitorResult != null && Boolean.FALSE.equals(visitorResult)) { - // The expression evaluated to false, so we have to remove the currentEntity from entityList + if(!Boolean.TRUE.equals(visitorResult)) { + // The expression evaluated to false (or null), so we have to remove the currentEntity from entityList entityIterator.remove(); } } else { @@ -115,15 +116,15 @@ public class DemoEntityCollectionProcessor implements EntityCollectionProcessor } // 4th: create a serializer based on the requested format (json) - ODataFormat format = ODataFormat.fromContentType(responseFormat); - ODataSerializer serializer = odata.createSerializer(format); + ODataSerializer serializer = odata.createSerializer(responseFormat); // and serialize the content: transform from the EntitySet object to InputStream EdmEntityType edmEntityType = edmEntitySet.getEntityType(); ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).build(); EntityCollectionSerializerOptions opts = EntityCollectionSerializerOptions.with().contextURL(contextUrl).build(); - SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, entityCollection, opts); + SerializerResult serializerResult = serializer.entityCollection(serviceMetadata, edmEntityType, + entityCollection, opts); InputStream serializedContent = serializerResult.getContent(); // 5th: configure the response object: set the body, headers and status code diff --git a/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java new file mode 100644 index 000000000..addfef099 --- /dev/null +++ b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoEntityProcessor.java @@ -0,0 +1,122 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.service; + +import java.io.InputStream; +import java.util.List; +import java.util.Locale; + +import myservice.mynamespace.data.Storage; + +import org.apache.olingo.commons.api.data.ContextURL; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmEntityType; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.processor.EntityProcessor; +import org.apache.olingo.server.api.serializer.EntitySerializerOptions; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.serializer.SerializerResult; +import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.api.uri.UriParameter; +import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceEntitySet; + +public class DemoEntityProcessor implements EntityProcessor { + + + private OData odata; + private ServiceMetadata serviceMetadata; + private Storage storage; + + + + public DemoEntityProcessor(Storage storage) { + this.storage = storage; + } + + + public void init(OData odata, ServiceMetadata serviceMetadata) { + this.odata = odata; + this.serviceMetadata = serviceMetadata; + } + + + public void readEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType responseFormat) + throws ODataApplicationException, SerializerException { + + // 1. retrieve the Entity Type + List resourcePaths = uriInfo.getUriResourceParts(); + // Note: only in our example we can assume that the first segment is the EntitySet + UriResourceEntitySet uriResourceEntitySet = (UriResourceEntitySet) resourcePaths.get(0); + EdmEntitySet edmEntitySet = uriResourceEntitySet.getEntitySet(); + + // 2. retrieve the data from backend + List keyPredicates = uriResourceEntitySet.getKeyPredicates(); + Entity entity = storage.readEntityData(edmEntitySet, keyPredicates); + + // 3. serialize + EdmEntityType entityType = edmEntitySet.getEntityType(); + + ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).suffix(ContextURL.Suffix.ENTITY).build(); + // expand and select currently not supported + EntitySerializerOptions options = EntitySerializerOptions.with().contextURL(contextUrl).build(); + + ODataSerializer serializer = this.odata.createSerializer(responseFormat); + SerializerResult serializerResult = serializer.entity(serviceMetadata, entityType, entity, options); + InputStream entityStream = serializerResult.getContent(); + + //4. configure the response object + response.setContent(entityStream); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); + } + + + + + /* + * These processor methods are not handled in this tutorial + * */ + public void createEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + + + public void updateEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + + + public void deleteEntity(ODataRequest request, ODataResponse response, UriInfo uriInfo) + throws ODataApplicationException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } +} diff --git a/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java new file mode 100644 index 000000000..f910838c1 --- /dev/null +++ b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/DemoPrimitiveProcessor.java @@ -0,0 +1,150 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.service; + +import java.io.InputStream; +import java.util.List; +import java.util.Locale; + +import myservice.mynamespace.data.Storage; + +import org.apache.olingo.commons.api.data.ContextURL; +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.data.Property; +import org.apache.olingo.commons.api.edm.EdmEntitySet; +import org.apache.olingo.commons.api.edm.EdmPrimitiveType; +import org.apache.olingo.commons.api.edm.EdmProperty; +import org.apache.olingo.commons.api.format.ContentType; +import org.apache.olingo.commons.api.http.HttpHeader; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.ODataRequest; +import org.apache.olingo.server.api.ODataResponse; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.deserializer.DeserializerException; +import org.apache.olingo.server.api.processor.PrimitiveProcessor; +import org.apache.olingo.server.api.serializer.ODataSerializer; +import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions; +import org.apache.olingo.server.api.serializer.SerializerException; +import org.apache.olingo.server.api.serializer.SerializerResult; +import org.apache.olingo.server.api.uri.UriInfo; +import org.apache.olingo.server.api.uri.UriParameter; +import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourceEntitySet; +import org.apache.olingo.server.api.uri.UriResourceProperty; + +public class DemoPrimitiveProcessor implements PrimitiveProcessor { + + private OData odata; + private Storage storage; + private ServiceMetadata serviceMetadata; + + public DemoPrimitiveProcessor(Storage storage) { + this.storage = storage; + } + + public void init(OData odata, ServiceMetadata serviceMetadata) { + this.odata = odata; + this.serviceMetadata = serviceMetadata; + + } + + /* + * In our example, the URL would be: http://localhost:8080/DemoService/DemoService.svc/Products(1)/Name + * and the response: + * { + * @odata.context: "$metadata#Products/Name", + * value: "Notebook Basic 15" + * } + * */ + public void readPrimitive(ODataRequest request, ODataResponse response, + UriInfo uriInfo, ContentType responseFormat) + throws ODataApplicationException, SerializerException { + + // 1. Retrieve info from URI + // 1.1. retrieve the info about the requested entity set + List resourceParts = uriInfo.getUriResourceParts(); + // Note: only in our example we can rely that the first segment is the EntitySet + UriResourceEntitySet uriEntityset = (UriResourceEntitySet) resourceParts.get(0); + EdmEntitySet edmEntitySet = uriEntityset.getEntitySet(); + // the key for the entity + List keyPredicates = uriEntityset.getKeyPredicates(); + + // 1.2. retrieve the requested (Edm) property + // the last segment is the Property + UriResourceProperty uriProperty = (UriResourceProperty)resourceParts.get(resourceParts.size() -1); + EdmProperty edmProperty = uriProperty.getProperty(); + String edmPropertyName = edmProperty.getName(); + // in our example, we know we have only primitive types in our model + EdmPrimitiveType edmPropertyType = (EdmPrimitiveType) edmProperty.getType(); + + + // 2. retrieve data from backend + // 2.1. retrieve the entity data, for which the property has to be read + Entity entity = storage.readEntityData(edmEntitySet, keyPredicates); + if (entity == null) { // Bad request + throw new ODataApplicationException("Entity not found", HttpStatusCode.NOT_FOUND.getStatusCode(), Locale.ENGLISH); + } + + // 2.2. retrieve the property data from the entity + Property property = entity.getProperty(edmPropertyName); + if (property == null) { + throw new ODataApplicationException("Property not found", HttpStatusCode.NOT_FOUND.getStatusCode(), + Locale.ENGLISH); + } + + // 3. serialize + Object value = property.getValue(); + if (value != null) { + // 3.1. configure the serializer + ODataSerializer serializer = odata.createSerializer(responseFormat); + + ContextURL contextUrl = ContextURL.with().entitySet(edmEntitySet).navOrPropertyPath(edmPropertyName).build(); + PrimitiveSerializerOptions options = PrimitiveSerializerOptions.with().contextURL(contextUrl).build(); + // 3.2. serialize + SerializerResult serializerResult = serializer.primitive(serviceMetadata, edmPropertyType, property, options); + InputStream propertyStream = serializerResult.getContent(); + + //4. configure the response object + response.setContent(propertyStream); + response.setStatusCode(HttpStatusCode.OK.getStatusCode()); + response.setHeader(HttpHeader.CONTENT_TYPE, responseFormat.toContentTypeString()); + } else { + // in case there's no value for the property, we can skip the serialization + response.setStatusCode(HttpStatusCode.NO_CONTENT.getStatusCode()); + } + } + + + + /* + * These processor methods are not handled in this tutorial + * */ + + public void updatePrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo, ContentType requestFormat, + ContentType responseFormat) throws ODataApplicationException, DeserializerException, SerializerException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } + + public void deletePrimitive(ODataRequest request, ODataResponse response, UriInfo uriInfo) + throws ODataApplicationException { + throw new ODataApplicationException("Not supported.", HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ROOT); + } +} diff --git a/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java new file mode 100644 index 000000000..12d6e301a --- /dev/null +++ b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/service/FilterExpressionVisitor.java @@ -0,0 +1,303 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.service; + +import java.util.List; +import java.util.Locale; + +import org.apache.olingo.commons.api.data.Entity; +import org.apache.olingo.commons.api.edm.EdmEnumType; +import org.apache.olingo.commons.api.edm.EdmType; +import org.apache.olingo.commons.api.http.HttpStatusCode; +import org.apache.olingo.commons.core.edm.primitivetype.EdmString; +import org.apache.olingo.server.api.ODataApplicationException; +import org.apache.olingo.server.api.uri.UriInfoResource; +import org.apache.olingo.server.api.uri.UriResource; +import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty; +import org.apache.olingo.server.api.uri.queryoption.expression.BinaryOperatorKind; +import org.apache.olingo.server.api.uri.queryoption.expression.Expression; +import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitException; +import org.apache.olingo.server.api.uri.queryoption.expression.ExpressionVisitor; +import org.apache.olingo.server.api.uri.queryoption.expression.Literal; +import org.apache.olingo.server.api.uri.queryoption.expression.MethodKind; +import org.apache.olingo.server.api.uri.queryoption.expression.UnaryOperatorKind; + +public class FilterExpressionVisitor implements ExpressionVisitor { + + private Entity currentEntity; + + public FilterExpressionVisitor(Entity currentEntity) { + this.currentEntity = currentEntity; + } + + @Override + public Object visitMember(UriInfoResource member) throws ExpressionVisitException, ODataApplicationException { + // To keeps things simple, this tutorial allows only primitive properties. + // We have faith that the java type of Edm.Int32 is Integer + + final List uriResourceParts = member.getUriResourceParts(); + + // Make sure that the resource path of the property contains only a single segment and a primitive property + // has been addressed. We can be sure, that the property exists because the UriParser checks if the + // property has been defined in service metadata document. + + if(uriResourceParts.size() == 1 && uriResourceParts.get(0) instanceof UriResourcePrimitiveProperty) { + UriResourcePrimitiveProperty uriResourceProperty = (UriResourcePrimitiveProperty) uriResourceParts.get(0); + return currentEntity.getProperty(uriResourceProperty.getProperty().getName()).getValue(); + } else { + // The OData specification allows in addition complex properties and navigation properties + // with a target cardinality 0..1 or 1. + // This means any combination can occur e.g. Supplier/Address/City + // -> Navigation properties Supplier + // -> Complex Property Address + // -> Primitive Property City + // For such cases the resource path returns a list of UriResourceParts + throw new ODataApplicationException("Only primitive properties are implemented in filter expressions", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); + } + } + + @Override + public Object visitLiteral(Literal literal) throws ExpressionVisitException, ODataApplicationException { + // To keep this tutorial simple, our filter expression visitor supports only Edm.Int32 and Edm.String + // In real world scenarios it can be difficult to guess the type of an literal. + // We can be sure, that the literal is a valid OData literal because the URI Parser checks + // the lexicographical structure + + // String literals start and end with an single quotation mark + String literalAsString = literal.getText(); + if(literal.getType() instanceof EdmString) { + String stringLiteral = ""; + if(literal.getText().length() > 2) { + stringLiteral = literalAsString.substring(1, literalAsString.length() - 1); + } + + return stringLiteral; + } else { + // Try to convert the literal into an Java Integer + try { + return Integer.parseInt(literalAsString); + } catch(NumberFormatException e) { + throw new ODataApplicationException("Only Edm.Int32 and Edm.String literals are implemented", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); + } + } + } + + @Override + public Object visitUnaryOperator(UnaryOperatorKind operator, Object operand) + throws ExpressionVisitException, ODataApplicationException { + // OData allows two different unary operators. We have to take care, that the type of the operand fits to + // operand + + if(operator == UnaryOperatorKind.NOT && operand instanceof Boolean) { + // 1.) boolean negation + return !(Boolean) operand; + } else if(operator == UnaryOperatorKind.MINUS && operand instanceof Integer){ + // 2.) arithmetic minus + return -(Integer) operand; + } + + // Operation not processed, throw an exception + throw new ODataApplicationException("Invalid type for unary operator", + HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ENGLISH); + } + + @Override + public Object visitBinaryOperator(BinaryOperatorKind operator, Object left, Object right) + throws ExpressionVisitException, ODataApplicationException { + + // Binary Operators are split up in three different kinds. Up to the kind of the operator it can be applied + // to different types + // - Arithmetic operations like add, minus, modulo, etc. are allowed on numeric types like Edm.Int32 + // - Logical operations are allowed on numeric types and also Edm.String + // - Boolean operations like and, or are allowed on Edm.Boolean + // A detailed explanation can be found in OData Version 4.0 Part 2: URL Conventions + + if (operator == BinaryOperatorKind.ADD + || operator == BinaryOperatorKind.MOD + || operator == BinaryOperatorKind.MUL + || operator == BinaryOperatorKind.DIV + || operator == BinaryOperatorKind.SUB) { + return evaluateArithmeticOperation(operator, left, right); + } else if (operator == BinaryOperatorKind.EQ + || operator == BinaryOperatorKind.NE + || operator == BinaryOperatorKind.GE + || operator == BinaryOperatorKind.GT + || operator == BinaryOperatorKind.LE + || operator == BinaryOperatorKind.LT) { + return evaluateComparisonOperation(operator, left, right); + } else if (operator == BinaryOperatorKind.AND + || operator == BinaryOperatorKind.OR) { + return evaluateBooleanOperation(operator, left, right); + } else { + throw new ODataApplicationException("Binary operation " + operator.name() + " is not implemented", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); + } + } + + private Object evaluateBooleanOperation(BinaryOperatorKind operator, Object left, Object right) + throws ODataApplicationException { + + // First check that both operands are of type Boolean + if(left instanceof Boolean && right instanceof Boolean) { + Boolean valueLeft = (Boolean) left; + Boolean valueRight = (Boolean) right; + + // Than calculate the result value + if(operator == BinaryOperatorKind.AND) { + return valueLeft && valueRight; + } else { + // OR + return valueLeft || valueRight; + } + } else { + throw new ODataApplicationException("Boolean operations needs two numeric operands", + HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ENGLISH); + } + } + + private Object evaluateComparisonOperation(BinaryOperatorKind operator, Object left, Object right) + throws ODataApplicationException { + + // All types in our tutorial supports all logical operations, but we have to make sure that the types are equals + if(left.getClass().equals(right.getClass()) && left instanceof Comparable) { + // Luckily all used types String, Boolean and also Integer support the interface Comparable + int result; + if(left instanceof Integer) { + result = ((Comparable) (Integer)left).compareTo((Integer) right); + } else if(left instanceof String) { + result = ((Comparable) (String)left).compareTo((String) right); + } else if(left instanceof Boolean) { + result = ((Comparable) (Boolean)left).compareTo((Boolean) right); + } else { + throw new ODataApplicationException("Class " + left.getClass().getCanonicalName() + " not expected", + HttpStatusCode.INTERNAL_SERVER_ERROR.getStatusCode(), Locale.ENGLISH); + } + + if (operator == BinaryOperatorKind.EQ) { + return result == 0; + } else if (operator == BinaryOperatorKind.NE) { + return result != 0; + } else if (operator == BinaryOperatorKind.GE) { + return result >= 0; + } else if (operator == BinaryOperatorKind.GT) { + return result > 0; + } else if (operator == BinaryOperatorKind.LE) { + return result <= 0; + } else { + // BinaryOperatorKind.LT + return result < 0; + } + + } else { + throw new ODataApplicationException("Comparision needs two equal types", + HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ENGLISH); + } + } + + private Object evaluateArithmeticOperation(BinaryOperatorKind operator, Object left, + Object right) throws ODataApplicationException { + + // First check if the type of both operands is numerical + if(left instanceof Integer && right instanceof Integer) { + Integer valueLeft = (Integer) left; + Integer valueRight = (Integer) right; + + // Than calculate the result value + if(operator == BinaryOperatorKind.ADD) { + return valueLeft + valueRight; + } else if(operator == BinaryOperatorKind.SUB) { + return valueLeft - valueRight; + } else if(operator == BinaryOperatorKind.MUL) { + return valueLeft * valueRight; + } else if(operator == BinaryOperatorKind.DIV) { + return valueLeft / valueRight; + } else { + // BinaryOperatorKind,MOD + return valueLeft % valueRight; + } + } else { + throw new ODataApplicationException("Arithmetic operations needs two numeric operands", + HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ENGLISH); + } + } + + @Override + public Object visitMethodCall(MethodKind methodCall, List parameters) + throws ExpressionVisitException, ODataApplicationException { + + // To keep this tutorial small and simple, we implement only one method call + if(methodCall == MethodKind.CONTAINS) { + // "Contains" gets two parameters, both have to be of type String + // e.g. /Products?$filter=contains(Description, '1024 MB') + // + // First the method visistMember is called, which returns the current String value of the property. + // After that the method visitLiteral is called with the string literal '1024 MB', + // which returns a String + // + // Both String values are passed to visitMethodCall. + if(parameters.get(0) instanceof String && parameters.get(1) instanceof String) { + String valueParam1 = (String) parameters.get(0); + String valueParam2 = (String) parameters.get(1); + + return valueParam1.contains(valueParam2); + } else { + throw new ODataApplicationException("Contains needs two parametes of type Edm.String", + HttpStatusCode.BAD_REQUEST.getStatusCode(), Locale.ENGLISH); + } + } else { + throw new ODataApplicationException("Method call " + methodCall + " not implemented", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); + } + } + + @Override + public Object visitTypeLiteral(EdmType type) throws ExpressionVisitException, ODataApplicationException { + throw new ODataApplicationException("Type literals are not implemented", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); + } + + @Override + public Object visitAlias(String aliasName) throws ExpressionVisitException, ODataApplicationException { + throw new ODataApplicationException("Aliases are not implemented", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); + } + + @Override + public Object visitEnum(EdmEnumType type, List enumValues) + throws ExpressionVisitException, ODataApplicationException { + throw new ODataApplicationException("Enums are not implemented", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); + } + + @Override + public Object visitLambdaExpression(String lambdaFunction, String lambdaVariable, Expression expression) + throws ExpressionVisitException, ODataApplicationException { + throw new ODataApplicationException("Lamdba expressions are not implemented", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); + } + + @Override + public Object visitLambdaReference(String variableName) + throws ExpressionVisitException, ODataApplicationException { + throw new ODataApplicationException("Lamdba references are not implemented", + HttpStatusCode.NOT_IMPLEMENTED.getStatusCode(), Locale.ENGLISH); + } +} diff --git a/samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/util/Util.java b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/util/Util.java similarity index 100% rename from samples/tutorials/p7_queryoptions-f/src/main/java/myservice/mynamespace/util/Util.java rename to samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/util/Util.java diff --git a/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/web/DemoServlet.java b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/web/DemoServlet.java new file mode 100644 index 000000000..fe5cdbb38 --- /dev/null +++ b/samples/tutorials/p8_queryoptions-f/src/main/java/myservice/mynamespace/web/DemoServlet.java @@ -0,0 +1,76 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package myservice.mynamespace.web; + +import java.io.IOException; +import java.lang.Override;import java.lang.RuntimeException;import java.util.ArrayList; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import myservice.mynamespace.data.Storage; +import myservice.mynamespace.service.DemoEdmProvider; +import myservice.mynamespace.service.DemoEntityCollectionProcessor; +import myservice.mynamespace.service.DemoEntityProcessor; +import myservice.mynamespace.service.DemoPrimitiveProcessor; + +import org.apache.olingo.server.api.OData; +import org.apache.olingo.server.api.ODataHttpHandler; +import org.apache.olingo.server.api.ServiceMetadata; +import org.apache.olingo.server.api.edmx.EdmxReference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class DemoServlet extends HttpServlet { + + private static final long serialVersionUID = 1L; + private static final Logger LOG = LoggerFactory.getLogger(DemoServlet.class); + + + @Override + protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + try { + HttpSession session = req.getSession(true); + Storage storage = (Storage) session.getAttribute(Storage.class.getName()); + if (storage == null) { + storage = new Storage(); + session.setAttribute(Storage.class.getName(), storage); + } + + // create odata handler and configure it with EdmProvider and Processor + OData odata = OData.newInstance(); + ServiceMetadata edm = odata.createServiceMetadata(new DemoEdmProvider(), new ArrayList()); + ODataHttpHandler handler = odata.createHandler(edm); + handler.register(new DemoEntityCollectionProcessor(storage)); + handler.register(new DemoEntityProcessor(storage)); + handler.register(new DemoPrimitiveProcessor(storage)); + + // let the handler do the work + handler.process(req, resp); + } catch (RuntimeException e) { + LOG.error("Server Error occurred in ExampleServlet", e); + throw new ServletException(e); + } + + } + +} diff --git a/samples/tutorials/p8_queryoptions-f/src/main/webapp/WEB-INF/web.xml b/samples/tutorials/p8_queryoptions-f/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 000000000..21de52a8f --- /dev/null +++ b/samples/tutorials/p8_queryoptions-f/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,40 @@ + + + + + + + DemoServlet + myservice.mynamespace.web.DemoServlet + 1 + + + + + DemoServlet + /DemoService.svc/* + + \ No newline at end of file diff --git a/samples/tutorials/p8_queryoptions-f/src/main/webapp/index.jsp b/samples/tutorials/p8_queryoptions-f/src/main/webapp/index.jsp new file mode 100644 index 000000000..c0fe23e9c --- /dev/null +++ b/samples/tutorials/p8_queryoptions-f/src/main/webapp/index.jsp @@ -0,0 +1,24 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + + +

Hello World!

+OData Olingo V4 Demo Service + + diff --git a/samples/tutorials/pom.xml b/samples/tutorials/pom.xml index c4244ddb4..454c0b670 100644 --- a/samples/tutorials/pom.xml +++ b/samples/tutorials/pom.xml @@ -35,13 +35,15 @@ + p0_all p1_read p2_readep p3_write p4_navigation p5_queryoptions-tcs p6_queryoptions-es - p7_queryoptions-f + p7_queryoptions-o + p8_queryoptions-f