You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@olingo.apache.org by ra...@apache.org on 2015/02/11 17:45:49 UTC
[3/4] olingo-odata4 git commit: A new service dispatcher mechanism
for handling server side requests
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
new file mode 100644
index 0000000..2324648
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataParser.java
@@ -0,0 +1,674 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLEventReader;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+import javax.xml.stream.events.EndElement;
+import javax.xml.stream.events.StartElement;
+import javax.xml.stream.events.XMLEvent;
+
+import org.apache.olingo.commons.api.edm.FullQualifiedName;
+import org.apache.olingo.commons.api.edm.constants.EdmOnDelete;
+import org.apache.olingo.server.api.edm.provider.Action;
+import org.apache.olingo.server.api.edm.provider.ActionImport;
+import org.apache.olingo.server.api.edm.provider.ComplexType;
+import org.apache.olingo.server.api.edm.provider.EdmProvider;
+import org.apache.olingo.server.api.edm.provider.EntityContainer;
+import org.apache.olingo.server.api.edm.provider.EntitySet;
+import org.apache.olingo.server.api.edm.provider.EntitySetPath;
+import org.apache.olingo.server.api.edm.provider.EntityType;
+import org.apache.olingo.server.api.edm.provider.EnumMember;
+import org.apache.olingo.server.api.edm.provider.EnumType;
+import org.apache.olingo.server.api.edm.provider.Function;
+import org.apache.olingo.server.api.edm.provider.FunctionImport;
+import org.apache.olingo.server.api.edm.provider.NavigationProperty;
+import org.apache.olingo.server.api.edm.provider.NavigationPropertyBinding;
+import org.apache.olingo.server.api.edm.provider.Operation;
+import org.apache.olingo.server.api.edm.provider.Parameter;
+import org.apache.olingo.server.api.edm.provider.Property;
+import org.apache.olingo.server.api.edm.provider.PropertyRef;
+import org.apache.olingo.server.api.edm.provider.ReferentialConstraint;
+import org.apache.olingo.server.api.edm.provider.ReturnType;
+import org.apache.olingo.server.api.edm.provider.Schema;
+import org.apache.olingo.server.api.edm.provider.Singleton;
+import org.apache.olingo.server.api.edm.provider.Term;
+import org.apache.olingo.server.api.edm.provider.TypeDefinition;
+
+public class MetadataParser {
+
+ public EdmProvider buildEdmProvider(Reader csdl) throws XMLStreamException {
+ XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
+ XMLEventReader reader = xmlInputFactory.createXMLEventReader(csdl);
+
+ SchemaBasedEdmProvider provider = new SchemaBasedEdmProvider();
+ new ElementReader<SchemaBasedEdmProvider>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
+ String name) throws XMLStreamException {
+ String version = attr(element, "Version");
+ if (version.equals("4.0")) {
+ readDataServicesAndReference(reader, element, provider);
+ }
+ }
+ }.read(reader, null, provider, "Edmx");
+
+ return provider;
+ }
+
+ private void readDataServicesAndReference(XMLEventReader reader, StartElement element,
+ SchemaBasedEdmProvider provider) throws XMLStreamException {
+ new ElementReader<SchemaBasedEdmProvider>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider provider,
+ String name) throws XMLStreamException {
+ if (name.equals("DataServices")) {
+ readSchema(reader, element, provider);
+ } else if (name.equals("Reference")) {
+ readReference(reader, element, provider, "Reference");
+ }
+ }
+ }.read(reader, element, provider, "DataServices", "Reference");
+ }
+
+ private void readReference(XMLEventReader reader, StartElement element,
+ SchemaBasedEdmProvider provider, String name) throws XMLStreamException {
+ new ElementReader<SchemaBasedEdmProvider>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, SchemaBasedEdmProvider t, String name)
+ throws XMLStreamException {
+ // TODO:
+ }
+ }.read(reader, element, provider, name);
+ }
+
+ private void readSchema(XMLEventReader reader, StartElement element,
+ SchemaBasedEdmProvider provider) throws XMLStreamException {
+
+ Schema schema = new Schema();
+ schema.setComplexTypes(new ArrayList<ComplexType>());
+ schema.setActions(new ArrayList<Action>());
+ schema.setEntityTypes(new ArrayList<EntityType>());
+ schema.setEnumTypes(new ArrayList<EnumType>());
+ schema.setFunctions(new ArrayList<Function>());
+ schema.setTerms(new ArrayList<Term>());
+ schema.setTypeDefinitions(new ArrayList<TypeDefinition>());
+
+ new ElementReader<Schema>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, Schema schema, String name)
+ throws XMLStreamException {
+ schema.setNamespace(attr(element, "Namespace"));
+ schema.setAlias(attr(element, "Alias"));
+ readSchemaContents(reader, schema);
+ }
+ }.read(reader, element, schema, "Schema");
+ provider.addSchema(schema);
+ }
+
+ private void readSchemaContents(XMLEventReader reader, Schema schema) throws XMLStreamException {
+ new ElementReader<Schema>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, Schema schema, String name)
+ throws XMLStreamException {
+ if (name.equals("Action")) {
+ readAction(reader, element, schema);
+ } else if (name.equals("Annotations")) {
+ // TODO:
+ } else if (name.equals("Annotation")) {
+ // TODO:
+ } else if (name.equals("ComplexType")) {
+ readComplexType(reader, element, schema);
+ } else if (name.equals("EntityContainer")) {
+ readEntityContainer(reader, element, schema);
+ } else if (name.equals("EntityType")) {
+ readEntityType(reader, element, schema);
+ } else if (name.equals("EnumType")) {
+ readEnumType(reader, element, schema);
+ } else if (name.equals("Function")) {
+ readFunction(reader, element, schema);
+ } else if (name.equals("Term")) {
+ schema.getTerms().add(readTerm(element));
+ } else if (name.equals("TypeDefinition")) {
+ schema.getTypeDefinitions().add(readTypeDefinition(element));
+ }
+ }
+ }.read(reader, null, schema, "Action", "Annotations", "Annotation", "ComplexType",
+ "EntityContainer", "EntityType", "EnumType", "Function", "Term", "TypeDefinition");
+ }
+
+ private void readAction(XMLEventReader reader, StartElement element, Schema schema)
+ throws XMLStreamException {
+
+ Action action = new Action();
+ action.setParameters(new ArrayList<Parameter>());
+ action.setName(attr(element, "Name"));
+ action.setBound(Boolean.parseBoolean(attr(element, "IsBound")));
+ String entitySetPath = attr(element, "EntitySetPath");
+ if (entitySetPath != null) {
+ // TODO: need to parse into binding and path.
+ action.setEntitySetPath(new EntitySetPath().setPath(entitySetPath));
+ }
+ readOperationParameters(reader, action);
+ schema.getActions().add(action);
+ }
+
+ private FullQualifiedName readType(StartElement element) {
+ String type = attr(element, "Type");
+ if (type.startsWith("Collection(") && type.endsWith(")")) {
+ return new FullQualifiedName(type.substring(11, type.length() - 1));
+ }
+ return new FullQualifiedName(type);
+ }
+
+ private boolean isCollectionType(StartElement element) {
+ String type = attr(element, "Type");
+ if (type.startsWith("Collection(") && type.endsWith(")")) {
+ return true;
+ }
+ return false;
+ }
+
+ private void readReturnType(StartElement element, Operation operation) {
+ ReturnType returnType = new ReturnType();
+ returnType.setType(readType(element));
+ returnType.setCollection(isCollectionType(element));
+ returnType.setNullable(Boolean.parseBoolean(attr(element, "Nullable")));
+
+ String maxLength = attr(element, "MaxLength");
+ if (maxLength != null) {
+ returnType.setMaxLength(Integer.parseInt(maxLength));
+ }
+ String precision = attr(element, "Precision");
+ if (precision != null) {
+ returnType.setPrecision(Integer.parseInt(precision));
+ }
+ String scale = attr(element, "Scale");
+ if (scale != null) {
+ returnType.setScale(Integer.parseInt(scale));
+ }
+ String srid = attr(element, "SRID");
+ if (srid != null) {
+ // TODO: no olingo support yet.
+ }
+ operation.setReturnType(returnType);
+ }
+
+ private void readParameter(StartElement element, Operation operation) {
+ Parameter parameter = new Parameter();
+ parameter.setName(attr(element, "Name"));
+ parameter.setType(readType(element));
+ parameter.setCollection(isCollectionType(element));
+ parameter.setNullable(Boolean.parseBoolean(attr(element, "Nullable")));
+
+ String maxLength = attr(element, "MaxLength");
+ if (maxLength != null) {
+ parameter.setMaxLength(Integer.parseInt(maxLength));
+ }
+ String precision = attr(element, "Precision");
+ if (precision != null) {
+ parameter.setPrecision(Integer.parseInt(precision));
+ }
+ String scale = attr(element, "Scale");
+ if (scale != null) {
+ parameter.setScale(Integer.parseInt(scale));
+ }
+ String srid = attr(element, "SRID");
+ if (srid != null) {
+ // TODO: no olingo support yet.
+ }
+ operation.getParameters().add(parameter);
+ }
+
+ private TypeDefinition readTypeDefinition(StartElement element) {
+ TypeDefinition td = new TypeDefinition();
+ td.setName(attr(element, "Name"));
+ td.setUnderlyingType(new FullQualifiedName(attr(element, "UnderlyingType")));
+ td.setIsUnicode(Boolean.parseBoolean(attr(element, "Unicode")));
+
+ String maxLength = attr(element, "MaxLength");
+ if (maxLength != null) {
+ td.setMaxLength(Integer.parseInt(maxLength));
+ }
+ String precision = attr(element, "Precision");
+ if (precision != null) {
+ td.setPrecision(Integer.parseInt(precision));
+ }
+ String scale = attr(element, "Scale");
+ if (scale != null) {
+ td.setScale(Integer.parseInt(scale));
+ }
+ String srid = attr(element, "SRID");
+ if (srid != null) {
+ // TODO: no olingo support yet.
+ }
+ return td;
+ }
+
+ private Term readTerm(StartElement element) {
+ Term term = new Term();
+ term.setName(attr(element, "Name"));
+ term.setType(new FullQualifiedName(attr(element, "Type")));
+ if (attr(element, "BaseTerm") != null) {
+ term.setBaseTerm(new FullQualifiedName(attr(element, "BaseTerm")));
+ }
+ if (attr(element, "DefaultValue") != null) {
+ term.setDefaultValue(attr(element, "DefaultValue"));
+ }
+ if (attr(element, "AppliesTo") != null) {
+ term.setAppliesTo(attr(element, "AppliesTo"));
+ }
+ term.setNullable(Boolean.parseBoolean(attr(element, "Nullable")));
+ String maxLength = attr(element, "MaxLength");
+ if (maxLength != null) {
+ term.setMaxLength(Integer.parseInt(maxLength));
+ }
+ String precision = attr(element, "Precision");
+ if (precision != null) {
+ term.setPrecision(Integer.parseInt(precision));
+ }
+ String scale = attr(element, "Scale");
+ if (scale != null) {
+ term.setScale(Integer.parseInt(scale));
+ }
+ String srid = attr(element, "SRID");
+ if (srid != null) {
+ // TODO: no olingo support yet.
+ }
+ return term;
+ }
+
+ private void readFunction(XMLEventReader reader, StartElement element, Schema schema)
+ throws XMLStreamException {
+ Function function = new Function();
+ function.setParameters(new ArrayList<Parameter>());
+ function.setName(attr(element, "Name"));
+ function.setBound(Boolean.parseBoolean(attr(element, "IsBound")));
+ function.setComposable(Boolean.parseBoolean(attr(element, "IsComposable")));
+ String entitySetPath = attr(element, "EntitySetPath");
+ if (entitySetPath != null) {
+ // TODO: need to parse into binding and path.
+ function.setEntitySetPath(new EntitySetPath().setPath(entitySetPath));
+ }
+ readOperationParameters(reader, function);
+ schema.getFunctions().add(function);
+ }
+
+ private void readOperationParameters(XMLEventReader reader, final Operation operation)
+ throws XMLStreamException {
+ new ElementReader<Operation>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, Operation operation, String name)
+ throws XMLStreamException {
+ if (name.equals("Parameter")) {
+ readParameter(element, operation);
+ } else if (name.equals("ReturnType")) {
+ readReturnType(element, operation);
+ }
+ }
+ }.read(reader, null, operation, "Parameter", "ReturnType");
+ }
+
+ private void readEnumType(XMLEventReader reader, StartElement element, Schema schema)
+ throws XMLStreamException {
+ EnumType type = new EnumType();
+ type.setMembers(new ArrayList<EnumMember>());
+ type.setName(attr(element, "Name"));
+ if (attr(element, "UnderlyingType") != null) {
+ type.setUnderlyingType(new FullQualifiedName(attr(element, "UnderlyingType")));
+ }
+ type.setFlags(Boolean.parseBoolean(attr(element, "IsFlags")));
+
+ readEnumMembers(reader, element, type);
+ schema.getEnumTypes().add(type);
+ }
+
+ private void readEnumMembers(XMLEventReader reader, StartElement element, EnumType type)
+ throws XMLStreamException {
+ new ElementReader<EnumType>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, EnumType type, String name)
+ throws XMLStreamException {
+ EnumMember member = new EnumMember();
+ member.setName(attr(element, "Name"));
+ member.setValue(attr(element, "Value"));
+ type.getMembers().add(member);
+ }
+ }.read(reader, element, type, "Member");
+ }
+
+ private void readEntityType(XMLEventReader reader, StartElement element, Schema schema)
+ throws XMLStreamException {
+ EntityType entityType = new EntityType();
+ entityType.setProperties(new ArrayList<Property>());
+ entityType.setNavigationProperties(new ArrayList<NavigationProperty>());
+ entityType.setKey(new ArrayList<PropertyRef>());
+ entityType.setName(attr(element, "Name"));
+ if (attr(element, "BaseType") != null) {
+ entityType.setBaseType(new FullQualifiedName(attr(element, "BaseType")));
+ }
+ entityType.setAbstract(Boolean.parseBoolean(attr(element, "Abstract")));
+ entityType.setOpenType(Boolean.parseBoolean(attr(element, "OpenType")));
+ entityType.setHasStream(Boolean.parseBoolean(attr(element, "HasStream")));
+ readEntityProperties(reader, entityType);
+ schema.getEntityTypes().add(entityType);
+ }
+
+ private void readEntityProperties(XMLEventReader reader, EntityType entityType)
+ throws XMLStreamException {
+ new ElementReader<EntityType>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, EntityType entityType, String name)
+ throws XMLStreamException {
+ if (name.equals("Property")) {
+ entityType.getProperties().add(readProperty(element));
+ } else if (name.equals("NavigationProperty")) {
+ entityType.getNavigationProperties().add(readNavigationProperty(reader, element));
+ } else if (name.equals("Key")) {
+ readKey(reader, element, entityType);
+ }
+ }
+ }.read(reader, null, entityType, "Property", "NavigationProperty", "Key");
+ }
+
+ private void readKey(XMLEventReader reader, StartElement element, EntityType entityType)
+ throws XMLStreamException {
+ new ElementReader<EntityType>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, EntityType entityType, String name)
+ throws XMLStreamException {
+ PropertyRef ref = new PropertyRef();
+ ref.setName(attr(element, "Name"));
+ ref.setAlias(attr(element, "Alias"));
+ entityType.getKey().add(ref);
+ }
+ }.read(reader, element, entityType, "PropertyRef");
+ }
+
+ private NavigationProperty readNavigationProperty(XMLEventReader reader, StartElement element)
+ throws XMLStreamException {
+ NavigationProperty property = new NavigationProperty();
+ property.setReferentialConstraints(new ArrayList<ReferentialConstraint>());
+
+ property.setName(attr(element, "Name"));
+ property.setType(readType(element));
+ property.setCollection(isCollectionType(element));
+ property.setNullable(Boolean.parseBoolean(attr(element, "Nullable")));
+ property.setPartner(attr(element, "Partner"));
+ property.setContainsTarget(Boolean.parseBoolean(attr(element, "ContainsTarget")));
+
+ new ElementReader<NavigationProperty>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, NavigationProperty property,
+ String name) throws XMLStreamException {
+ if (name.equals("ReferentialConstraint")) {
+ ReferentialConstraint constraint = new ReferentialConstraint();
+ constraint.setProperty(attr(element, "Property"));
+ constraint.setReferencedProperty(attr(element, "ReferencedProperty"));
+ property.getReferentialConstraints().add(constraint);
+ } else if (name.equals("OnDelete")) {
+ property.setOnDelete(EdmOnDelete.valueOf(attr(element, "Action")));
+ }
+ }
+ }.read(reader, element, property, "ReferentialConstraint", "OnDelete");
+ return property;
+ }
+
+ private String attr(StartElement element, String name) {
+ Attribute attr = element.getAttributeByName(new QName(name));
+ if (attr != null) {
+ return attr.getValue();
+ }
+ return null;
+ }
+
+ private Property readProperty(StartElement element) {
+ Property property = new Property();
+ property.setName(attr(element, "Name"));
+ property.setType(readType(element));
+ property.setCollection(isCollectionType(element));
+ property.setNullable(Boolean.parseBoolean(attr(element, "Nullable")));
+ property.setUnicode(Boolean.parseBoolean(attr(element, "Unicode")));
+
+ String maxLength = attr(element, "MaxLength");
+ if (maxLength != null) {
+ property.setMaxLength(Integer.parseInt(maxLength));
+ }
+ String precision = attr(element, "Precision");
+ if (precision != null) {
+ property.setPrecision(Integer.parseInt(precision));
+ }
+ String scale = attr(element, "Scale");
+ if (scale != null) {
+ property.setScale(Integer.parseInt(scale));
+ }
+ String srid = attr(element, "SRID");
+ if (srid != null) {
+ // TODO: no olingo support yet.
+ }
+ String defaultValue = attr(element, "DefaultValue");
+ if (defaultValue != null) {
+ property.setDefaultValue(defaultValue);
+ }
+ return property;
+ }
+
+ private void readEntityContainer(XMLEventReader reader, StartElement element, Schema schema)
+ throws XMLStreamException {
+ final EntityContainer container = new EntityContainer();
+ container.setName(attr(element, "Name"));
+ if (attr(element, "Extends") != null) {
+ container.setExtendsContainer(new FullQualifiedName(attr(element, "Extends")));
+ }
+ container.setActionImports(new ArrayList<ActionImport>());
+ container.setFunctionImports(new ArrayList<FunctionImport>());
+ container.setEntitySets(new ArrayList<EntitySet>());
+ container.setSingletons(new ArrayList<Singleton>());
+
+ new ElementReader<Schema>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, Schema schema, String name)
+ throws XMLStreamException {
+ if (name.equals("EntitySet")) {
+ readEntitySet(reader, element, container);
+ } else if (name.equals("Singleton")) {
+ readSingleton(reader, element, container);
+ } else if (name.equals("ActionImport")) {
+ readActionImport(element, container);
+ } else if (name.equals("FunctionImport")) {
+ readFunctionImport(element, container);
+ }
+ }
+
+ private void readFunctionImport(StartElement element, EntityContainer container) {
+ FunctionImport functionImport = new FunctionImport();
+ functionImport.setName(attr(element, "Name"));
+ functionImport.setFunction(new FullQualifiedName(attr(element, "Function")));
+ functionImport.setIncludeInServiceDocument(Boolean.parseBoolean(attr(element,
+ "IncludeInServiceDocument")));
+
+ String entitySet = attr(element, "EntitySet");
+ if (entitySet != null) {
+ functionImport.setEntitySet(new org.apache.olingo.server.core.Target(entitySet));
+ }
+ container.getFunctionImports().add(functionImport);
+ }
+
+ private void readActionImport(StartElement element, EntityContainer container) {
+ ActionImport actionImport = new ActionImport();
+ actionImport.setName(attr(element, "Name"));
+ actionImport.setAction(new FullQualifiedName(attr(element, "Action")));
+
+ String entitySet = attr(element, "EntitySet");
+ if (entitySet != null) {
+ actionImport.setEntitySet(new org.apache.olingo.server.core.Target(entitySet));
+ }
+ container.getActionImports().add(actionImport);
+ }
+
+ private void readSingleton(XMLEventReader reader, StartElement element,
+ EntityContainer container) throws XMLStreamException {
+ Singleton singleton = new Singleton();
+ singleton.setNavigationPropertyBindings(new ArrayList<NavigationPropertyBinding>());
+ singleton.setName(attr(element, "Name"));
+ singleton.setType(new FullQualifiedName(attr(element, "Type")));
+ singleton.setNavigationPropertyBindings(new ArrayList<NavigationPropertyBinding>());
+ readNavigationPropertyBindings(reader, element, singleton.getNavigationPropertyBindings());
+ container.getSingletons().add(singleton);
+ }
+
+ private void readEntitySet(XMLEventReader reader, StartElement element,
+ EntityContainer container) throws XMLStreamException {
+ EntitySet entitySet = new EntitySet();
+ entitySet.setName(attr(element, "Name"));
+ entitySet.setType(new FullQualifiedName(attr(element, "EntityType")));
+ entitySet.setIncludeInServiceDocument(Boolean.parseBoolean(attr(element,
+ "IncludeInServiceDocument")));
+ entitySet.setNavigationPropertyBindings(new ArrayList<NavigationPropertyBinding>());
+ readNavigationPropertyBindings(reader, element, entitySet.getNavigationPropertyBindings());
+ container.getEntitySets().add(entitySet);
+ }
+
+ private void readNavigationPropertyBindings(XMLEventReader reader, StartElement element,
+ List<NavigationPropertyBinding> bindings) throws XMLStreamException {
+ new ElementReader<List<NavigationPropertyBinding>>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element,
+ List<NavigationPropertyBinding> bindings, String name) throws XMLStreamException {
+ NavigationPropertyBinding binding = new NavigationPropertyBinding();
+ binding.setPath(attr(element, "Path"));
+ binding.setTarget(new org.apache.olingo.server.core.Target(attr(element, "Target")));
+ bindings.add(binding);
+ }
+
+ }.read(reader, element, bindings, "NavigationPropertyBinding");
+ ;
+ }
+ }.read(reader, element, schema, "EntitySet", "Singleton", "ActionImport", "FunctionImport");
+ schema.setEntityContainer(container);
+ }
+
+ private void readComplexType(XMLEventReader reader, StartElement element, Schema schema)
+ throws XMLStreamException {
+ ComplexType complexType = new ComplexType();
+ complexType.setProperties(new ArrayList<Property>());
+ complexType.setNavigationProperties(new ArrayList<NavigationProperty>());
+ complexType.setName(attr(element, "Name"));
+ if (attr(element, "BaseType") != null) {
+ complexType.setBaseType(new FullQualifiedName(attr(element, "BaseType")));
+ }
+ complexType.setAbstract(Boolean.parseBoolean(attr(element, "Abstract")));
+ complexType.setOpenType(Boolean.parseBoolean(attr(element, "OpenType")));
+ readProperties(reader, complexType);
+
+ schema.getComplexTypes().add(complexType);
+ }
+
+ private void readProperties(XMLEventReader reader, ComplexType complexType)
+ throws XMLStreamException {
+ new ElementReader<ComplexType>() {
+ @Override
+ void build(XMLEventReader reader, StartElement element, ComplexType complexType, String name)
+ throws XMLStreamException {
+ if (name.equals("Property")) {
+ complexType.getProperties().add(readProperty(element));
+ } else if (name.equals("NavigationProperty")) {
+ complexType.getNavigationProperties().add(readNavigationProperty(reader, element));
+ }
+ }
+ }.read(reader, null, complexType, "Property", "NavigationProperty");
+ }
+
+ abstract class ElementReader<T> {
+ void read(XMLEventReader reader, StartElement element, T t, String... names)
+ throws XMLStreamException {
+ while (reader.hasNext()) {
+ XMLEvent event = reader.peek();
+
+ event = skipAnnotations(reader, event);
+
+ if (!event.isStartElement() && !event.isEndElement()) {
+ reader.nextEvent();
+ continue;
+ }
+
+ boolean hit = false;
+
+ for (int i = 0; i < names.length; i++) {
+ if (event.isStartElement()) {
+ element = event.asStartElement();
+ if (element.getName().getLocalPart().equals(names[i])) {
+ reader.nextEvent(); // advance cursor
+ // System.out.println("reading = "+names[i]);
+ build(reader, element, t, names[i]);
+ hit = true;
+ }
+ }
+ if (event.isEndElement()) {
+ EndElement e = event.asEndElement();
+ if (e.getName().getLocalPart().equals(names[i])) {
+ reader.nextEvent(); // advance cursor
+ // System.out.println("done reading = "+names[i]);
+ hit = true;
+ }
+ }
+ }
+ if (!hit) {
+ break;
+ }
+ }
+ }
+
+ private XMLEvent skipAnnotations(XMLEventReader reader, XMLEvent event)
+ throws XMLStreamException {
+ boolean skip = false;
+
+ while (reader.hasNext()) {
+ if (event.isStartElement()) {
+ StartElement element = event.asStartElement();
+ if (element.getName().getLocalPart().equals("Annotation")) {
+ skip = true;
+ }
+ }
+ if (event.isEndElement()) {
+ EndElement element = event.asEndElement();
+ if (element.getName().getLocalPart().equals("Annotation")) {
+ return reader.peek();
+ }
+ }
+ if (skip) {
+ event = reader.nextEvent();
+ } else {
+ return event;
+ }
+ }
+ return event;
+ }
+
+ abstract void build(XMLEventReader reader, StartElement element, T t, String name)
+ throws XMLStreamException;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataRequest.java
new file mode 100644
index 0000000..49735cb
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataRequest.java
@@ -0,0 +1,57 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ODataTranslatedException;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.RepresentationType;
+import org.apache.olingo.server.api.uri.UriInfoMetadata;
+
+public class MetadataRequest extends ServiceRequest {
+
+ public MetadataRequest(OData odata, ServiceMetadata serviceMetadata) {
+ super(odata, serviceMetadata);
+ }
+
+ @Override
+ public ContentType getResponseContentType() throws ContentNegotiatorException {
+ return ContentNegotiator.doContentNegotiation(this.uriInfo.getFormatOption(), this.request,
+ this.customContentType, RepresentationType.METADATA);
+ }
+
+ public UriInfoMetadata getUriInfoMetadata() {
+ return uriInfo.asUriInfoMetadata();
+ }
+
+ @Override
+ public void execute(ServiceHandler handler, ODataResponse response)
+ throws ODataTranslatedException, ODataApplicationException {
+
+ if (!allowedMethod()) {
+ methodNotAllowed();
+ }
+
+ handler.readMetadata(this, MetadataResponse.getinstance(this, response));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataResponse.java
new file mode 100644
index 0000000..aac7d84
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/MetadataResponse.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ODataTranslatedException;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.ODataSerializer;
+import org.apache.olingo.server.api.serializer.SerializerException;
+
+public class MetadataResponse extends ServiceResponse {
+ private final ODataSerializer serializer;
+ private final ContentType responseContentType;
+
+ public static MetadataResponse getinstance(ServiceRequest request, ODataResponse response)
+ throws ContentNegotiatorException, SerializerException {
+ return new MetadataResponse(response, request.getSerializer(), request.getResponseContentType());
+ }
+
+ private MetadataResponse(ODataResponse response, ODataSerializer serializer, ContentType responseContentType) {
+ super(response);
+ this.serializer = serializer;
+ this.responseContentType = responseContentType;
+ }
+
+ public void writeMetadata(ServiceMetadata metadata)throws ODataTranslatedException {
+ assert (!isClosed());
+ this.response.setContent(this.serializer.metadataDocument(metadata));
+ writeOK(this.responseContentType.toContentTypeString());
+ close();
+ }
+
+ @Override
+ public void accepts(ServiceResponseVisior visitor) throws ODataTranslatedException,
+ ODataApplicationException {
+ visitor.visit(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/NoContentResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/NoContentResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/NoContentResponse.java
new file mode 100644
index 0000000..7bf0c21
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/NoContentResponse.java
@@ -0,0 +1,97 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import org.apache.olingo.commons.api.http.HttpStatusCode;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ODataTranslatedException;
+
+public class NoContentResponse extends ServiceResponse {
+
+ public NoContentResponse(ODataResponse response) {
+ super(response);
+ }
+
+ // 200
+ public void writeOK() {
+ this.response.setStatusCode(HttpStatusCode.OK.getStatusCode());
+ close();
+ }
+
+ // 201
+ public void writeCreated() {
+ this.response.setStatusCode(HttpStatusCode.CREATED.getStatusCode());
+ close();
+ }
+
+ // 202
+ public void writeAccepted() {
+ this.response.setStatusCode(HttpStatusCode.ACCEPTED.getStatusCode());
+ close();
+ }
+
+ // 204
+ public void writeNoContent() {
+ writeNoContent(true);
+ }
+
+ // 304
+ public void writeNotModified() {
+ this.response.setStatusCode(HttpStatusCode.NOT_MODIFIED.getStatusCode());
+ close();
+ }
+
+ // error response codes
+
+ // 404
+ public void writeNotFound() {
+ writeNotFound(true);
+ }
+
+ // 501
+ public void writeNotImplemented() {
+ this.response.setStatusCode(HttpStatusCode.NOT_IMPLEMENTED.getStatusCode());
+ close();
+ }
+
+ // 405
+ public void writeMethodNotAllowed() {
+ this.response.setStatusCode(HttpStatusCode.METHOD_NOT_ALLOWED.getStatusCode());
+ close();
+ }
+
+ // 410
+ public void writeGone() {
+ this.response.setStatusCode(HttpStatusCode.GONE.getStatusCode());
+ close();
+ }
+
+ // 412
+ public void writePreConditionFailed() {
+ this.response.setStatusCode(HttpStatusCode.PRECONDITION_FAILED.getStatusCode());
+ close();
+ }
+
+ @Override
+ public void accepts(ServiceResponseVisior visitor) throws ODataTranslatedException,
+ ODataApplicationException {
+ visitor.visit(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4HttpHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4HttpHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4HttpHandler.java
new file mode 100644
index 0000000..bc93eeb
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4HttpHandler.java
@@ -0,0 +1,111 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
+import org.apache.olingo.commons.api.http.HttpHeader;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataRequest;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ODataTranslatedException;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.processor.Processor;
+import org.apache.olingo.server.api.serializer.CustomContentTypeSupport;
+import org.apache.olingo.server.api.serializer.SerializerException;
+
+public class OData4HttpHandler extends ODataHttpHandlerImpl {
+ private ServiceHandler handler;
+ private final ServiceMetadata serviceMetadata;
+ private final OData odata;
+ private CustomContentTypeSupport customContentTypeSupport;
+
+ public OData4HttpHandler(OData odata, ServiceMetadata serviceMetadata) {
+ super(odata, serviceMetadata);
+ this.odata = odata;
+ this.serviceMetadata = serviceMetadata;
+ }
+
+ @Override
+ public void process(final HttpServletRequest httpRequest, final HttpServletResponse httpResponse) {
+ ODataRequest request = null;
+ ODataResponse response = new ODataResponse();
+
+ try {
+ request = createODataRequest(httpRequest, 0);
+ validateODataVersion(request, response);
+
+ ServiceDispatcher dispatcher = new ServiceDispatcher(this.odata, this.serviceMetadata,
+ handler, this.customContentTypeSupport);
+ dispatcher.execute(request, response);
+
+ } catch (Exception e) {
+ ErrorHandler handler = new ErrorHandler(this.odata, this.serviceMetadata,
+ this.customContentTypeSupport);
+ handler.handleException(e, request, response);
+ }
+ convertToHttp(httpResponse, response);
+ }
+
+
+ ODataRequest createODataRequest(final HttpServletRequest httpRequest, final int split)
+ throws ODataTranslatedException {
+ try {
+ ODataRequest odRequest = new ODataRequest();
+
+ odRequest.setBody(httpRequest.getInputStream());
+ extractHeaders(odRequest, httpRequest);
+ extractMethod(odRequest, httpRequest);
+ extractUri(odRequest, httpRequest, split);
+
+ return odRequest;
+ } catch (final IOException e) {
+ throw new SerializerException(
+ "An I/O exception occurred.", e, SerializerException.MessageKeys.IO_EXCEPTION); //$NON-NLS-1$
+ }
+ }
+
+ void validateODataVersion(final ODataRequest request, final ODataResponse response)
+ throws ODataHandlerException {
+ final String maxVersion = request.getHeader(HttpHeader.ODATA_MAX_VERSION);
+ response.setHeader(HttpHeader.ODATA_VERSION, ODataServiceVersion.V40.toString());
+
+ if (maxVersion != null) {
+ if (ODataServiceVersion.isBiggerThan(ODataServiceVersion.V40.toString(), maxVersion)) {
+ throw new ODataHandlerException("ODataVersion not supported: " + maxVersion, //$NON-NLS-1$
+ ODataHandlerException.MessageKeys.ODATA_VERSION_NOT_SUPPORTED, maxVersion);
+ }
+ }
+ }
+
+ @Override
+ public void register(final Processor processor) {
+ this.handler = (ServiceHandler) processor;
+ this.handler.init(this.odata, this.serviceMetadata);
+ }
+
+ @Override
+ public void register(final CustomContentTypeSupport customContentTypeSupport) {
+ this.customContentTypeSupport = customContentTypeSupport;
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4Impl.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4Impl.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4Impl.java
new file mode 100644
index 0000000..bde9c96
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OData4Impl.java
@@ -0,0 +1,45 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import org.apache.olingo.commons.api.ODataRuntimeException;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ODataHttpHandler;
+import org.apache.olingo.server.api.ServiceMetadata;
+
+public class OData4Impl extends ODataImpl {
+
+ public static OData newInstance() {
+ try {
+ final Class<?> clazz = Class.forName(OData4Impl.class.getName());
+ final Object object = clazz.newInstance();
+ return (OData) object;
+ } catch (final Exception e) {
+ throw new ODataRuntimeException(e);
+ }
+ }
+
+ private OData4Impl() {
+ }
+
+ @Override
+ public ODataHttpHandler createHandler(final ServiceMetadata edm) {
+ return new OData4HttpHandler(this, edm);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ODataServiceHandler.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ODataServiceHandler.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ODataServiceHandler.java
new file mode 100644
index 0000000..1e29f9f
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/ODataServiceHandler.java
@@ -0,0 +1,38 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+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.ODataServerError;
+import org.apache.olingo.server.api.ODataTranslatedException;
+
+public interface ODataServiceHandler {
+
+ void readMetadata(MetadataRequest request, MetadataResponse response)
+ throws ODataTranslatedException, ODataApplicationException;
+
+ void readServiceDocument(ServiceDocumentRequest request,
+ ServiceDocumentResponse response) throws ODataTranslatedException,
+ ODataApplicationException;
+
+ void handleException(ODataRequest request, ODataResponse response,
+ ODataServerError serverError);
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OperationRequest.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OperationRequest.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OperationRequest.java
new file mode 100644
index 0000000..f4252ea
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/OperationRequest.java
@@ -0,0 +1,117 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import org.apache.olingo.commons.api.data.ContextURL;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.server.api.OData;
+import org.apache.olingo.server.api.ServiceMetadata;
+import org.apache.olingo.server.api.serializer.RepresentationType;
+import org.apache.olingo.server.api.serializer.SerializerException;
+import org.apache.olingo.server.api.uri.UriHelper;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
+
+public abstract class OperationRequest extends ServiceRequest {
+ private UriResourceFunction uriResourceFunction;
+
+ public OperationRequest(OData odata, ServiceMetadata serviceMetadata) {
+ super(odata, serviceMetadata);
+ }
+
+ @Override
+ public ContentType getResponseContentType() throws ContentNegotiatorException {
+ if (!hasReturnType()) {
+ // this default content type
+ return ContentType.APPLICATION_OCTET_STREAM;
+ }
+
+ if (isReturnTypePrimitive()) {
+ return ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), this.request,
+ getCustomContentTypeSupport(), isCollection() ? RepresentationType.COLLECTION_PRIMITIVE
+ : RepresentationType.PRIMITIVE);
+ } else if (isReturnTypeComplex()) {
+ return ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), this.request,
+ getCustomContentTypeSupport(), isCollection() ? RepresentationType.COLLECTION_COMPLEX
+ : RepresentationType.COMPLEX);
+ } else {
+ return ContentNegotiator.doContentNegotiation(uriInfo.getFormatOption(), this.request,
+ getCustomContentTypeSupport(), isCollection() ? RepresentationType.COLLECTION_ENTITY
+ : RepresentationType.ENTITY);
+ }
+ }
+
+ public abstract boolean isBound();
+
+ public abstract boolean isCollection();
+
+ public abstract EdmReturnType getReturnType();
+
+ public abstract boolean hasReturnType();
+
+ public ContextURL getContextURL(OData odata) throws SerializerException {
+ if (!hasReturnType()) {
+ return null;
+ }
+
+ final UriHelper helper = odata.createUriHelper();
+
+ if (isReturnTypePrimitive() || isReturnTypeComplex()) {
+ // Part 1 {10.14, 10.14} since the function return properties does not
+ // represent a Entity property
+ ContextURL.Builder builder = ContextURL.with().type(getReturnType().getType());
+ if (isCollection()) {
+ builder.asCollection();
+ }
+ return builder.build();
+ }
+
+ /*
+ // EdmTypeKind.ENTITY;
+ if (isBound()) {
+ // Bound means, we know the EnitySet of the return type. Part 1 {10.2,
+ // 10.3}
+ EdmEntitySet entitySet = this.uriResourceFunction.getFunctionImport().getReturnedEntitySet();
+ ContextURL.Builder builder = DataRequest.buildEntitySetContextURL(helper, entitySet,
+ this.uriInfo, isCollection(), false);
+ return builder.build();
+ }
+ */
+
+ // EdmTypeKind.ENTITY; Not Bound
+ // Here we do not know the EntitySet, then follow directions from
+ // Part-1{10.2. 10.3} to use
+ // {context-url}#{type-name}
+ ContextURL.Builder builder = ContextURL.with().type(getReturnType().getType());
+ if (isCollection()) {
+ builder.asCollection();
+ }
+ return builder.build();
+ }
+
+ protected boolean isReturnTypePrimitive() {
+ return getReturnType().getType().getKind() == EdmTypeKind.PRIMITIVE;
+ }
+
+ protected boolean isReturnTypeComplex() {
+ return getReturnType().getType().getKind() == EdmTypeKind.COMPLEX;
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/PrimitiveValueResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/PrimitiveValueResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/PrimitiveValueResponse.java
new file mode 100644
index 0000000..52801da
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/PrimitiveValueResponse.java
@@ -0,0 +1,99 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.edm.EdmProperty;
+import org.apache.olingo.commons.api.edm.EdmReturnType;
+import org.apache.olingo.commons.api.http.HttpContentType;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ODataTranslatedException;
+import org.apache.olingo.server.api.serializer.FixedFormatSerializer;
+import org.apache.olingo.server.api.serializer.PrimitiveValueSerializerOptions;
+import org.apache.olingo.server.api.serializer.SerializerException;
+
+public class PrimitiveValueResponse extends ServiceResponse {
+ private final boolean returnCollection;
+ private EdmProperty type;
+ private EdmReturnType returnType;
+ private final FixedFormatSerializer serializer;
+
+ public static PrimitiveValueResponse getInstance(ServiceRequest request, ODataResponse response,
+ boolean collection, EdmProperty type) {
+ FixedFormatSerializer serializer = request.getOdata().createFixedFormatSerializer();
+ return new PrimitiveValueResponse(serializer, response, collection, type);
+ }
+
+ public static PrimitiveValueResponse getInstance(ServiceRequest request, ODataResponse response,
+ boolean collection, EdmReturnType type) {
+ FixedFormatSerializer serializer = request.getOdata().createFixedFormatSerializer();
+ return new PrimitiveValueResponse(serializer, response, collection, type);
+ }
+
+ private PrimitiveValueResponse(FixedFormatSerializer serializer, ODataResponse response,
+ boolean collection, EdmProperty type) {
+ super(response);
+ this.returnCollection = collection;
+ this.type = type;
+ this.serializer = serializer;
+ }
+
+ private PrimitiveValueResponse(FixedFormatSerializer serializer, ODataResponse response,
+ boolean collection, EdmReturnType type) {
+ super(response);
+ this.returnCollection = collection;
+ this.returnType = type;
+ this.serializer = serializer;
+ }
+
+ public void write(Object value) throws SerializerException {
+
+ if (value == null) {
+ writeNoContent(true);
+ return;
+ }
+
+ if (this.type != null) {
+ PrimitiveValueSerializerOptions options = PrimitiveValueSerializerOptions.with()
+ .facetsFrom(this.type).build();
+
+ this.response.setContent(this.serializer.primitiveValue((EdmPrimitiveType) this.type.getType(),
+ value, options));
+ } else {
+ PrimitiveValueSerializerOptions options = PrimitiveValueSerializerOptions.with()
+ .nullable(this.returnType.isNullable()).maxLength(this.returnType.getMaxLength())
+ .precision(this.returnType.getPrecision()).scale(this.returnType.getScale()).build();
+ this.response.setContent(this.serializer.primitiveValue(
+ (EdmPrimitiveType) this.returnType.getType(), value, options));
+ }
+
+ writeOK(HttpContentType.TEXT_PLAIN);
+ }
+
+ public boolean isReturnCollection() {
+ return returnCollection;
+ }
+
+ @Override
+ public void accepts(ServiceResponseVisior visitor) throws ODataTranslatedException,
+ ODataApplicationException {
+ visitor.visit(this);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/PropertyResponse.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/PropertyResponse.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/PropertyResponse.java
new file mode 100644
index 0000000..994a5e1
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/PropertyResponse.java
@@ -0,0 +1,133 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import org.apache.olingo.commons.api.data.ContextURL;
+import org.apache.olingo.commons.api.data.Property;
+import org.apache.olingo.commons.api.edm.EdmComplexType;
+import org.apache.olingo.commons.api.edm.EdmPrimitiveType;
+import org.apache.olingo.commons.api.edm.EdmType;
+import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
+import org.apache.olingo.commons.api.format.ContentType;
+import org.apache.olingo.server.api.ODataApplicationException;
+import org.apache.olingo.server.api.ODataResponse;
+import org.apache.olingo.server.api.ODataTranslatedException;
+import org.apache.olingo.server.api.serializer.ComplexSerializerOptions;
+import org.apache.olingo.server.api.serializer.ODataSerializer;
+import org.apache.olingo.server.api.serializer.PrimitiveSerializerOptions;
+import org.apache.olingo.server.api.serializer.SerializerException;
+
+public class PropertyResponse extends ServiceResponse {
+ private PrimitiveSerializerOptions primitiveOptions;
+ private ComplexSerializerOptions complexOptions;
+ private final ContentType responseContentType;
+ private final ODataSerializer serializer;
+ private final boolean collection;
+
+ public static PropertyResponse getInstance(ServiceRequest request, ODataResponse response,
+ EdmType edmType, ContextURL contextURL, boolean collection) throws ContentNegotiatorException,
+ SerializerException {
+ if (edmType.getKind() == EdmTypeKind.PRIMITIVE) {
+ PrimitiveSerializerOptions options = request.getSerializerOptions(
+ PrimitiveSerializerOptions.class, contextURL);
+ ContentType type = request.getResponseContentType();
+ return new PropertyResponse(request.getSerializer(), response, options, type, collection);
+ }
+ ComplexSerializerOptions options = request.getSerializerOptions(ComplexSerializerOptions.class,
+ contextURL);
+ ContentType type = request.getResponseContentType();
+ return new PropertyResponse(request.getSerializer(), response, options, type, collection);
+ }
+
+ private PropertyResponse(ODataSerializer serializer, ODataResponse response,
+ PrimitiveSerializerOptions options, ContentType contentType, boolean collection) {
+ super(response);
+ this.serializer = serializer;
+ this.primitiveOptions = options;
+ this.responseContentType = contentType;
+ this.collection = collection;
+ }
+
+ private PropertyResponse(ODataSerializer serializer, ODataResponse response,
+ ComplexSerializerOptions options, ContentType contentType, boolean collection) {
+ super(response);
+ this.serializer = serializer;
+ this.complexOptions = options;
+ this.responseContentType = contentType;
+ this.collection = collection;
+ }
+
+ public void writeProperty(EdmType edmType, Property property) throws SerializerException {
+ assert (!isClosed());
+
+ if (property == null) {
+ writeNotFound(true);
+ return;
+ }
+
+ if (property.getValue() == null) {
+ writeNoContent(true);
+ return;
+ }
+
+ if (edmType.getKind() == EdmTypeKind.PRIMITIVE) {
+ writePrimitiveProperty((EdmPrimitiveType) edmType, property);
+ } else {
+ writeComplexProperty((EdmComplexType) edmType, property);
+ }
+ }
+
+ private void writeComplexProperty(EdmComplexType type, Property property)
+ throws SerializerException {
+ if (this.collection) {
+ this.response.setContent(this.serializer.complexCollection(type, property, this.complexOptions));
+ } else {
+ this.response.setContent(this.serializer.complex(type, property, this.complexOptions));
+ }
+ writeOK(this.responseContentType.toContentTypeString());
+ close();
+ }
+
+ private void writePrimitiveProperty(EdmPrimitiveType type, Property property)
+ throws SerializerException {
+ if(this.collection) {
+ this.response.setContent(this.serializer.primitiveCollection(type, property, this.primitiveOptions));
+ } else {
+ this.response.setContent(this.serializer.primitive(type, property, this.primitiveOptions));
+ }
+ writeOK(this.responseContentType.toContentTypeString());
+ close();
+ }
+
+ @Override
+ public void accepts(ServiceResponseVisior visitor) throws ODataTranslatedException,
+ ODataApplicationException {
+ visitor.visit(this);
+ }
+
+ public void writePropertyUpdated() {
+ // spec says just success response; so either 200 or 204. 200 typically has
+ // payload
+ writeNoContent(true);
+ }
+
+ public void writePropertyDeleted() {
+ writeNoContent(true);
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLHierarchyVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLHierarchyVisitor.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLHierarchyVisitor.java
new file mode 100644
index 0000000..38c4407
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLHierarchyVisitor.java
@@ -0,0 +1,332 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import java.util.List;
+
+import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.api.uri.UriInfoAll;
+import org.apache.olingo.server.api.uri.UriInfoBatch;
+import org.apache.olingo.server.api.uri.UriInfoCrossjoin;
+import org.apache.olingo.server.api.uri.UriInfoEntityId;
+import org.apache.olingo.server.api.uri.UriInfoKind;
+import org.apache.olingo.server.api.uri.UriInfoMetadata;
+import org.apache.olingo.server.api.uri.UriInfoResource;
+import org.apache.olingo.server.api.uri.UriInfoService;
+import org.apache.olingo.server.api.uri.UriResource;
+import org.apache.olingo.server.api.uri.UriResourceAction;
+import org.apache.olingo.server.api.uri.UriResourceComplexProperty;
+import org.apache.olingo.server.api.uri.UriResourceCount;
+import org.apache.olingo.server.api.uri.UriResourceEntitySet;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
+import org.apache.olingo.server.api.uri.UriResourceIt;
+import org.apache.olingo.server.api.uri.UriResourceLambdaAll;
+import org.apache.olingo.server.api.uri.UriResourceLambdaAny;
+import org.apache.olingo.server.api.uri.UriResourceLambdaVariable;
+import org.apache.olingo.server.api.uri.UriResourceNavigation;
+import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty;
+import org.apache.olingo.server.api.uri.UriResourceRef;
+import org.apache.olingo.server.api.uri.UriResourceRoot;
+import org.apache.olingo.server.api.uri.UriResourceSingleton;
+import org.apache.olingo.server.api.uri.UriResourceValue;
+import org.apache.olingo.server.api.uri.queryoption.CountOption;
+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.FormatOption;
+import org.apache.olingo.server.api.uri.queryoption.IdOption;
+import org.apache.olingo.server.api.uri.queryoption.OrderByOption;
+import org.apache.olingo.server.api.uri.queryoption.SearchOption;
+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.SkipTokenOption;
+import org.apache.olingo.server.api.uri.queryoption.TopOption;
+
+public class RequestURLHierarchyVisitor implements RequestURLVisitor {
+
+ private UriInfo uriInfo;
+
+ public UriInfo getUriInfo() {
+ return this.uriInfo;
+ }
+
+ @Override
+ public void visit(UriInfo info) {
+ this.uriInfo = info;
+
+ UriInfoKind kind = info.getKind();
+ switch (kind) {
+ case all:
+ visit(info.asUriInfoAll());
+ break;
+ case batch:
+ visit(info.asUriInfoBatch());
+ break;
+ case crossjoin:
+ visit(info.asUriInfoCrossjoin());
+ break;
+ case entityId:
+ visit(info.asUriInfoEntityId());
+ break;
+ case metadata:
+ visit(info.asUriInfoMetadata());
+ break;
+ case resource:
+ visit(info.asUriInfoResource());
+ break;
+ case service:
+ visit(info.asUriInfoService());
+ break;
+ }
+ }
+
+ @Override
+ public void visit(UriInfoService info) {
+ }
+
+ @Override
+ public void visit(UriInfoAll info) {
+ }
+
+ @Override
+ public void visit(UriInfoBatch info) {
+ }
+
+ @Override
+ public void visit(UriInfoCrossjoin info) {
+ }
+
+ @Override
+ public void visit(UriInfoEntityId info) {
+ visit(info.getSelectOption());
+
+ if (info.getExpandOption() != null) {
+ visit(info.getExpandOption());
+ }
+ if (info.getFormatOption() != null) {
+ visit(info.getFormatOption());
+ }
+ if (info.getIdOption() != null) {
+ visit(info.getIdOption());
+ }
+ }
+
+ @Override
+ public void visit(UriInfoMetadata info) {
+ }
+
+ @Override
+ public void visit(UriInfoResource info) {
+ List<UriResource> parts = info.getUriResourceParts();
+ for (UriResource resource : parts) {
+ switch (resource.getKind()) {
+ case action:
+ visit((UriResourceAction) resource);
+ break;
+ case complexProperty:
+ visit((UriResourceComplexProperty) resource);
+ break;
+ case count:
+ visit((UriResourceCount) resource);
+ break;
+ case entitySet:
+ visit((UriResourceEntitySet) resource);
+ break;
+ case function:
+ visit((UriResourceFunction) resource);
+ break;
+ case it:
+ visit((UriResourceIt) resource);
+ break;
+ case lambdaAll:
+ visit((UriResourceLambdaAll) resource);
+ break;
+ case lambdaAny:
+ visit((UriResourceLambdaAny) resource);
+ break;
+ case lambdaVariable:
+ visit((UriResourceLambdaVariable) resource);
+ break;
+ case navigationProperty:
+ visit((UriResourceNavigation) resource);
+ break;
+ case ref:
+ visit((UriResourceRef) resource);
+ break;
+ case root:
+ visit((UriResourceRoot) resource);
+ break;
+ case primitiveProperty:
+ visit((UriResourcePrimitiveProperty) resource);
+ break;
+ case singleton:
+ visit((UriResourceSingleton) resource);
+ break;
+ case value:
+ visit((UriResourceValue) resource);
+ break;
+ }
+ }
+
+ // http://docs.oasis-open.org/odata/odata/v4.0/os/part1-protocol/odata-v4.0-os-part1-protocol.html#_Toc372793682
+ if (info.getSearchOption() != null) {
+ visit(info.getSearchOption());
+ }
+
+ if (info.getFilterOption() != null) {
+ visit(info.getFilterOption());
+ }
+
+ if (info.getCountOption() != null) {
+ visit(info.getCountOption());
+ }
+
+ visit(info.getOrderByOption());
+
+ if (info.getSkipOption() != null) {
+ visit(info.getSkipOption());
+ }
+
+ if (info.getTopOption() != null) {
+ visit(info.getTopOption());
+ }
+
+ if (info.getExpandOption() != null) {
+ visit(info.getExpandOption());
+ }
+
+ visit(info.getSelectOption());
+
+ if (info.getFormatOption() != null) {
+ visit(info.getFormatOption());
+ }
+
+ if (info.getIdOption() != null) {
+ visit(info.getIdOption());
+ }
+
+ if (info.getSkipTokenOption() != null) {
+ visit(info.getSkipTokenOption());
+ }
+
+ }
+
+ @Override
+ public void visit(ExpandOption option) {
+ }
+
+ @Override
+ public void visit(FilterOption info) {
+ }
+
+ @Override
+ public void visit(FormatOption info) {
+ }
+
+ @Override
+ public void visit(IdOption info) {
+ }
+
+ @Override
+ public void visit(CountOption info) {
+ }
+
+ @Override
+ public void visit(OrderByOption option) {
+ }
+
+ @Override
+ public void visit(SearchOption option) {
+ }
+
+ @Override
+ public void visit(SelectOption option) {
+ }
+
+ @Override
+ public void visit(SkipOption option) {
+ }
+
+ @Override
+ public void visit(SkipTokenOption option) {
+ }
+
+ @Override
+ public void visit(TopOption option) {
+ }
+
+ @Override
+ public void visit(UriResourceCount option) {
+ }
+
+ @Override
+ public void visit(UriResourceRef info) {
+ }
+
+ @Override
+ public void visit(UriResourceRoot info) {
+ }
+
+ @Override
+ public void visit(UriResourceValue info) {
+ }
+
+ @Override
+ public void visit(UriResourceAction info) {
+ }
+
+ @Override
+ public void visit(UriResourceEntitySet info) {
+ }
+
+ @Override
+ public void visit(UriResourceFunction info) {
+ }
+
+ @Override
+ public void visit(UriResourceIt info) {
+ }
+
+ @Override
+ public void visit(UriResourceLambdaAll info) {
+ }
+
+ @Override
+ public void visit(UriResourceLambdaAny info) {
+ }
+
+ @Override
+ public void visit(UriResourceLambdaVariable info) {
+ }
+
+ @Override
+ public void visit(UriResourceNavigation info) {
+ }
+
+ @Override
+ public void visit(UriResourceSingleton info) {
+ }
+
+ @Override
+ public void visit(UriResourceComplexProperty info) {
+ }
+
+ @Override
+ public void visit(UriResourcePrimitiveProperty info) {
+ }
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLVisitor.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLVisitor.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLVisitor.java
new file mode 100644
index 0000000..21324b1
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/RequestURLVisitor.java
@@ -0,0 +1,126 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+import org.apache.olingo.server.api.uri.UriInfo;
+import org.apache.olingo.server.api.uri.UriInfoAll;
+import org.apache.olingo.server.api.uri.UriInfoBatch;
+import org.apache.olingo.server.api.uri.UriInfoCrossjoin;
+import org.apache.olingo.server.api.uri.UriInfoEntityId;
+import org.apache.olingo.server.api.uri.UriInfoMetadata;
+import org.apache.olingo.server.api.uri.UriInfoResource;
+import org.apache.olingo.server.api.uri.UriInfoService;
+import org.apache.olingo.server.api.uri.UriResourceAction;
+import org.apache.olingo.server.api.uri.UriResourceComplexProperty;
+import org.apache.olingo.server.api.uri.UriResourceCount;
+import org.apache.olingo.server.api.uri.UriResourceEntitySet;
+import org.apache.olingo.server.api.uri.UriResourceFunction;
+import org.apache.olingo.server.api.uri.UriResourceIt;
+import org.apache.olingo.server.api.uri.UriResourceLambdaAll;
+import org.apache.olingo.server.api.uri.UriResourceLambdaAny;
+import org.apache.olingo.server.api.uri.UriResourceLambdaVariable;
+import org.apache.olingo.server.api.uri.UriResourceNavigation;
+import org.apache.olingo.server.api.uri.UriResourcePrimitiveProperty;
+import org.apache.olingo.server.api.uri.UriResourceRef;
+import org.apache.olingo.server.api.uri.UriResourceRoot;
+import org.apache.olingo.server.api.uri.UriResourceSingleton;
+import org.apache.olingo.server.api.uri.UriResourceValue;
+import org.apache.olingo.server.api.uri.queryoption.CountOption;
+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.FormatOption;
+import org.apache.olingo.server.api.uri.queryoption.IdOption;
+import org.apache.olingo.server.api.uri.queryoption.OrderByOption;
+import org.apache.olingo.server.api.uri.queryoption.SearchOption;
+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.SkipTokenOption;
+import org.apache.olingo.server.api.uri.queryoption.TopOption;
+
+public interface RequestURLVisitor {
+
+ void visit(UriInfo info);
+
+ void visit(UriInfoService info);
+
+ void visit(UriInfoAll info);
+
+ void visit(UriInfoBatch info);
+
+ void visit(UriInfoCrossjoin info);
+
+ void visit(UriInfoEntityId info);
+
+ void visit(UriInfoMetadata info);
+
+ void visit(UriInfoResource info);
+
+ // Walk UriInfoResource
+ void visit(ExpandOption option);
+
+ void visit(FilterOption info);
+
+ void visit(FormatOption info);
+
+ void visit(IdOption info);
+
+ void visit(CountOption info);
+
+ void visit(OrderByOption option);
+
+ void visit(SearchOption option);
+
+ void visit(SelectOption option);
+
+ void visit(SkipOption option);
+
+ void visit(SkipTokenOption option);
+
+ void visit(TopOption option);
+
+ void visit(UriResourceCount option);
+
+ void visit(UriResourceRef info);
+
+ void visit(UriResourceRoot info);
+
+ void visit(UriResourceValue info);
+
+ void visit(UriResourceAction info);
+
+ void visit(UriResourceEntitySet info);
+
+ void visit(UriResourceFunction info);
+
+ void visit(UriResourceIt info);
+
+ void visit(UriResourceLambdaAll info);
+
+ void visit(UriResourceLambdaAny info);
+
+ void visit(UriResourceLambdaVariable info);
+
+ void visit(UriResourceNavigation info);
+
+ void visit(UriResourceSingleton info);
+
+ void visit(UriResourceComplexProperty info);
+
+ void visit(UriResourcePrimitiveProperty info);
+}
http://git-wip-us.apache.org/repos/asf/olingo-odata4/blob/b25fc8c2/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
----------------------------------------------------------------------
diff --git a/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
new file mode 100644
index 0000000..b1d3c93
--- /dev/null
+++ b/lib/server-core-ext/src/main/java/org/apache/olingo/server/core/SchemaBasedEdmProvider.java
@@ -0,0 +1,301 @@
+/*
+ * 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 org.apache.olingo.server.core;
+
+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.FullQualifiedName;
+import org.apache.olingo.server.api.edm.provider.Action;
+import org.apache.olingo.server.api.edm.provider.ActionImport;
+import org.apache.olingo.server.api.edm.provider.AliasInfo;
+import org.apache.olingo.server.api.edm.provider.ComplexType;
+import org.apache.olingo.server.api.edm.provider.EdmProvider;
+import org.apache.olingo.server.api.edm.provider.EntityContainer;
+import org.apache.olingo.server.api.edm.provider.EntityContainerInfo;
+import org.apache.olingo.server.api.edm.provider.EntitySet;
+import org.apache.olingo.server.api.edm.provider.EntityType;
+import org.apache.olingo.server.api.edm.provider.EnumType;
+import org.apache.olingo.server.api.edm.provider.Function;
+import org.apache.olingo.server.api.edm.provider.FunctionImport;
+import org.apache.olingo.server.api.edm.provider.Schema;
+import org.apache.olingo.server.api.edm.provider.Singleton;
+import org.apache.olingo.server.api.edm.provider.Term;
+import org.apache.olingo.server.api.edm.provider.TypeDefinition;
+
+public class SchemaBasedEdmProvider extends EdmProvider {
+ private final List<Schema> edmSchemas = new ArrayList<Schema>();
+
+ protected void addSchema(Schema schema) {
+ this.edmSchemas.add(schema);
+ }
+
+ private Schema getSchema(String ns) {
+ for (Schema s : this.edmSchemas) {
+ if (s.getNamespace().equals(ns)) {
+ return s;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public EnumType getEnumType(FullQualifiedName fqn) throws ODataException {
+ Schema schema = getSchema(fqn.getNamespace());
+ if (schema != null) {
+ List<EnumType> types = schema.getEnumTypes();
+ if (types != null) {
+ for (EnumType type : types) {
+ if (type.getName().equals(fqn.getName())) {
+ return type;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public TypeDefinition getTypeDefinition(FullQualifiedName fqn) throws ODataException {
+ Schema schema = getSchema(fqn.getNamespace());
+ if (schema != null) {
+ List<TypeDefinition> types = schema.getTypeDefinitions();
+ if (types != null) {
+ for (TypeDefinition type : types) {
+ if (type.getName().equals(fqn.getName())) {
+ return type;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public List<Function> getFunctions(FullQualifiedName fqn) throws ODataException {
+ ArrayList<Function> foundFuncs = new ArrayList<Function>();
+ Schema schema = getSchema(fqn.getNamespace());
+ if (schema != null) {
+ List<Function> functions = schema.getFunctions();
+ if (functions != null) {
+ for (Function func : functions) {
+ if (func.getName().equals(fqn.getName())) {
+ foundFuncs.add(func);
+ }
+ }
+ }
+ }
+ return foundFuncs;
+ }
+
+ @Override
+ public Term getTerm(FullQualifiedName fqn) throws ODataException {
+ Schema schema = getSchema(fqn.getNamespace());
+ if (schema != null) {
+ List<Term> terms = schema.getTerms();
+ if (terms != null) {
+ for (Term term : terms) {
+ if (term.getName().equals(fqn.getName())) {
+ return term;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public EntitySet getEntitySet(FullQualifiedName fqn, String entitySetName) throws ODataException {
+ Schema schema = getSchema(fqn.getFullQualifiedNameAsString());
+ if (schema != null) {
+ EntityContainer ec = schema.getEntityContainer();
+ if (ec != null && ec.getEntitySets() != null) {
+ for (EntitySet es : ec.getEntitySets()) {
+ if (es.getName().equals(entitySetName)) {
+ return es;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Singleton getSingleton(FullQualifiedName fqn, String singletonName) throws ODataException {
+ Schema schema = getSchema(fqn.getFullQualifiedNameAsString());
+ if (schema != null) {
+ EntityContainer ec = schema.getEntityContainer();
+ if (ec != null && ec.getSingletons() != null) {
+ for (Singleton es : ec.getSingletons()) {
+ if (es.getName().equals(singletonName)) {
+ return es;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public ActionImport getActionImport(FullQualifiedName fqn, String actionImportName)
+ throws ODataException {
+ Schema schema = getSchema(fqn.getFullQualifiedNameAsString());
+ if (schema != null) {
+ EntityContainer ec = schema.getEntityContainer();
+ if (ec != null && ec.getActionImports() != null) {
+ for (ActionImport es : ec.getActionImports()) {
+ if (es.getName().equals(actionImportName)) {
+ return es;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public FunctionImport getFunctionImport(FullQualifiedName fqn, String functionImportName)
+ throws ODataException {
+ Schema schema = getSchema(fqn.getFullQualifiedNameAsString());
+ if (schema != null) {
+ EntityContainer ec = schema.getEntityContainer();
+ if (ec != null && ec.getFunctionImports() != null) {
+ for (FunctionImport es : ec.getFunctionImports()) {
+ if (es.getName().equals(functionImportName)) {
+ return es;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public EntityContainerInfo getEntityContainerInfo(FullQualifiedName fqn) throws ODataException {
+ Schema schema = null;
+
+ if (fqn == null) {
+ for (Schema s : this.edmSchemas) {
+ if (s.getEntityContainer() != null) {
+ schema = s;
+ break;
+ }
+ }
+ } else {
+ schema = getSchema(fqn.getFullQualifiedNameAsString());
+ }
+
+ if (schema != null) {
+ EntityContainer ec = schema.getEntityContainer();
+ if (ec != null) {
+ EntityContainerInfo info = new EntityContainerInfo();
+ info.setContainerName(new FullQualifiedName(schema.getNamespace()));
+ info.setExtendsContainer(schema.getEntityContainer().getExtendsContainer());
+ return info;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public List<AliasInfo> getAliasInfos() throws ODataException {
+ Schema schema = null;
+ for (Schema s : this.edmSchemas) {
+ if (s.getEntityContainer() != null) {
+ schema = s;
+ break;
+ }
+ }
+
+ if (schema == null) {
+ schema = this.edmSchemas.get(0);
+ }
+
+ AliasInfo ai = new AliasInfo();
+ ai.setAlias(schema.getAlias());
+ ai.setNamespace(schema.getNamespace());
+ return Arrays.asList(ai);
+ }
+
+ @Override
+ public EntityContainer getEntityContainer() throws ODataException {
+ // note that there can be many schemas, but only one needs to contain the
+ // entity container in a given metadata document.
+ for (Schema s : this.edmSchemas) {
+ if (s.getEntityContainer() != null) {
+ return s.getEntityContainer();
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public List<Schema> getSchemas() throws ODataException {
+ return new ArrayList<Schema>(this.edmSchemas);
+ }
+
+ @Override
+ public EntityType getEntityType(final FullQualifiedName fqn) throws ODataException {
+ Schema schema = getSchema(fqn.getNamespace());
+ if (schema != null) {
+ if (schema.getEntityTypes() != null) {
+ for (EntityType type : schema.getEntityTypes()) {
+ if (type.getName().equals(fqn.getName())) {
+ return type;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public ComplexType getComplexType(final FullQualifiedName fqn) throws ODataException {
+ Schema schema = getSchema(fqn.getNamespace());
+ if (schema != null) {
+ if (schema.getComplexTypes() != null) {
+ for (ComplexType type : schema.getComplexTypes()) {
+ if (type.getName().equals(fqn.getName())) {
+ return type;
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public List<Action> getActions(final FullQualifiedName fqn) throws ODataException {
+ ArrayList<Action> actions = new ArrayList<Action>();
+ Schema schema = getSchema(fqn.getNamespace());
+ if (schema != null) {
+ List<Action> types = schema.getActions();
+ if (types != null) {
+ for (Action type : types) {
+ if (type.getName().equals(fqn.getName())) {
+ actions.add(type);
+ }
+ }
+ }
+ }
+ return actions;
+ }
+}