From 9aefb95905edee86a6747c26afa40d6f57451008 Mon Sep 17 00:00:00 2001 From: fmartelli Date: Mon, 24 Mar 2014 09:50:23 +0100 Subject: [PATCH] [OLINGO-205, OLINGO-200] provided atom v4 deserialization for entity type/set + entity set request --- .../apache/olingo/fit/AbstractServices.java | 28 +- ...lities.java => AbstractJSONUtilities.java} | 4 +- .../olingo/fit/utils/AbstractUtilities.java | 3 +- ...ilities.java => AbstractXMLUtilities.java} | 92 +- .../org/apache/olingo/fit/utils/Accept.java | 50 +- .../org/apache/olingo/fit/utils/Commons.java | 6 +- .../olingo/fit/utils/v3/JSONUtilities.java | 28 + .../olingo/fit/utils/v3/XMLUtilities.java | 191 +++++ .../olingo/fit/utils/v4/JSONUtilities.java | 28 + .../olingo/fit/utils/v4/XMLUtilities.java | 142 ++++ .../main/resources/v4/People/feed.full.json | 332 ++++++++ fit/src/main/resources/v4/People/feed.xml | 218 +++++ fit/src/main/resources/v4/metadata.xml | 791 ++++++++---------- .../request/ODataBasicRequest.java | 3 +- .../retrieve/ODataRetrieveRequest.java | 3 +- .../client/api/domain/ODataLinkType.java | 8 +- .../olingo/client/api/format/Format.java | 26 + .../olingo/client/api/format/ODataFormat.java | 8 +- .../client/api/format/ODataMediaFormat.java | 8 +- .../client/api/format/ODataPubFormat.java | 47 +- .../client/api/format/ODataValueFormat.java | 8 +- .../request/AbstractODataBasicRequest.java | 154 ++-- .../request/ODataRequestImpl.java | 12 +- .../invoke/ODataInvokeRequestImpl.java | 4 +- .../AbstractODataRetrieveRequest.java | 3 +- .../request/retrieve/ODataRawRequestImpl.java | 2 +- .../AbstractODataStreamedEntityRequest.java | 4 +- .../core/data/AbstractJsonDeserializer.java | 5 +- .../client/core/data/AtomDeserializer.java | 2 - .../core/data/AtomPropertyDeserializer.java | 16 +- .../core/data/JSONGeoValueDeserializer.java | 11 +- .../client/core/edm/EdmActionImportImpl.java | 1 - .../client/core/edm/EdmOperationImpl.java | 8 +- .../olingo/client/core/edm/EdmTypeInfo.java | 26 +- .../core/op/impl/AbstractODataBinder.java | 8 +- .../op/impl/AbstractODataDeserializer.java | 1 - .../core/it/v3/EntityRetrieveTestITCase.java | 2 +- .../core/it/v3/EntitySetTestITCase.java | 2 +- .../core/it/v3/QueryOptionsTestITCase.java | 3 +- .../client/core/it/v4/AbstractTestITCase.java | 4 +- .../core/it/v4/EntitySetTestITCase.java | 152 ++++ .../apache/olingo/commons/api/edm/Edm.java | 161 ++-- .../commons/api/edm/EdmActionImport.java | 2 +- .../edm/constants/ODataServiceVersion.java | 7 +- .../core/edm/AbstractEdmComplexType.java | 41 +- .../core/edm/AbstractEdmEntityContainer.java | 178 ++-- .../core/edm/AbstractEdmOperation.java | 129 +-- .../core/edm/AbstractEdmOperationImport.java | 57 +- .../core/edm/AbstractEdmStructuredType.java | 175 ++-- .../olingo/commons/core/edm/EdmNamedImpl.java | 21 +- .../olingo/commons/core/edm/EdmTypeImpl.java | 31 +- 51 files changed, 2151 insertions(+), 1095 deletions(-) rename fit/src/main/java/org/apache/olingo/fit/utils/{JSONUtilities.java => AbstractJSONUtilities.java} (99%) rename fit/src/main/java/org/apache/olingo/fit/utils/{XMLUtilities.java => AbstractXMLUtilities.java} (92%) create mode 100644 fit/src/main/java/org/apache/olingo/fit/utils/v3/JSONUtilities.java create mode 100644 fit/src/main/java/org/apache/olingo/fit/utils/v3/XMLUtilities.java create mode 100644 fit/src/main/java/org/apache/olingo/fit/utils/v4/JSONUtilities.java create mode 100644 fit/src/main/java/org/apache/olingo/fit/utils/v4/XMLUtilities.java create mode 100644 fit/src/main/resources/v4/People/feed.full.json create mode 100644 fit/src/main/resources/v4/People/feed.xml create mode 100644 lib/client-api/src/main/java/org/apache/olingo/client/api/format/Format.java create mode 100644 lib/client-core/src/test/java/org/apache/olingo/client/core/it/v4/EntitySetTestITCase.java diff --git a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java index 12032c583..025e4fed4 100644 --- a/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java +++ b/fit/src/main/java/org/apache/olingo/fit/AbstractServices.java @@ -19,8 +19,8 @@ package org.apache.olingo.fit; import org.apache.olingo.fit.utils.Accept; -import org.apache.olingo.fit.utils.XMLUtilities; -import org.apache.olingo.fit.utils.JSONUtilities; +import org.apache.olingo.fit.utils.AbstractXMLUtilities; +import org.apache.olingo.fit.utils.AbstractJSONUtilities; import org.apache.olingo.fit.utils.ODataVersion; import org.apache.olingo.fit.utils.FSManager; @@ -70,13 +70,18 @@ public abstract class AbstractServices { private static Set initialized = EnumSet.noneOf(ODataVersion.class); protected abstract ODataVersion getVersion(); - protected final XMLUtilities xml; + protected final AbstractXMLUtilities xml; - protected final JSONUtilities json; + protected final AbstractJSONUtilities json; public AbstractServices() throws Exception { - this.xml = new XMLUtilities(getVersion()); - this.json = new JSONUtilities(getVersion()); + if (ODataVersion.v3 == getVersion()) { + this.xml = new org.apache.olingo.fit.utils.v3.XMLUtilities(); + this.json = new org.apache.olingo.fit.utils.v3.JSONUtilities(); + } else { + this.xml = new org.apache.olingo.fit.utils.v4.XMLUtilities(); + this.json = new org.apache.olingo.fit.utils.v4.JSONUtilities(); + } if (!initialized.contains(getVersion())) { xml.retrieveLinkInfoFromMetadata(); @@ -135,7 +140,7 @@ public abstract class AbstractServices { return xml. createResponse(FSManager.instance(getVersion()).readFile(filename, Accept.XML), null, Accept.XML); } catch (Exception e) { - return xml.createFaultResponse(Accept.XML.toString(), e); + return xml.createFaultResponse(Accept.XML.toString(getVersion()), e); } } @@ -547,7 +552,7 @@ public abstract class AbstractServices { return xml.createResponse(null, null, null, Response.Status.NO_CONTENT); } catch (Exception e) { - return xml.createFaultResponse(Accept.XML.toString(), e); + return xml.createFaultResponse(Accept.XML.toString(getVersion()), e); } } @@ -749,7 +754,7 @@ public abstract class AbstractServices { } catch (Exception e) { LOG.error("Error retrieving entity", e); - return xml.createFaultResponse(Accept.JSON.toString(), e); + return xml.createFaultResponse(Accept.JSON.toString(getVersion()), e); } } @@ -775,7 +780,7 @@ public abstract class AbstractServices { @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format, final String changes) { if (xml.isMediaContent(entitySetName + "/" + path)) { - return replaceMediaProperty(prefer, entitySetName, entityId, path, format, changes); + return replaceMediaProperty(prefer, entitySetName, entityId, path, changes); } else { return replaceProperty(accept, prefer, entitySetName, entityId, path, format, changes, false); } @@ -786,7 +791,6 @@ public abstract class AbstractServices { final String entitySetName, final String entityId, final String path, - final String format, final String value) { try { final AbstractUtilities utils = getUtilities(null); @@ -809,7 +813,7 @@ public abstract class AbstractServices { } catch (Exception e) { LOG.error("Error retrieving entity", e); - return xml.createFaultResponse(Accept.JSON.toString(), e); + return xml.createFaultResponse(Accept.JSON.toString(getVersion()), e); } } diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractJSONUtilities.java similarity index 99% rename from fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java rename to fit/src/main/java/org/apache/olingo/fit/utils/AbstractJSONUtilities.java index 79d2d8fe0..c62d3419a 100644 --- a/fit/src/main/java/org/apache/olingo/fit/utils/JSONUtilities.java +++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractJSONUtilities.java @@ -41,9 +41,9 @@ import javax.ws.rs.NotFoundException; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; -public class JSONUtilities extends AbstractUtilities { +public abstract class AbstractJSONUtilities extends AbstractUtilities { - public JSONUtilities(final ODataVersion version) throws Exception { + public AbstractJSONUtilities(final ODataVersion version) throws Exception { super(version); } diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java index 74653a1de..7b74b6213 100644 --- a/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java +++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractUtilities.java @@ -384,7 +384,7 @@ public abstract class AbstractUtilities { } if (accept != null) { - builder.header("Content-Type", accept.toString()); + builder.header("Content-Type", accept.toString(version)); } else { builder.header("Content-Type", "*/*"); } @@ -423,7 +423,6 @@ public abstract class AbstractUtilities { public Response createFaultResponse(final String accept, final Exception e) { LOG.debug("Create fault response about .... ", e); - e.printStackTrace(); final Response.ResponseBuilder builder = Response.serverError(); if (version == ODataVersion.v3) { diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractXMLUtilities.java similarity index 92% rename from fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java rename to fit/src/main/java/org/apache/olingo/fit/utils/AbstractXMLUtilities.java index 0009eea7d..d02e8289a 100644 --- a/fit/src/main/java/org/apache/olingo/fit/utils/XMLUtilities.java +++ b/fit/src/main/java/org/apache/olingo/fit/utils/AbstractXMLUtilities.java @@ -55,103 +55,17 @@ import org.apache.commons.lang3.StringUtils; import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileSystemException; -public class XMLUtilities extends AbstractUtilities { +public abstract class AbstractXMLUtilities extends AbstractUtilities { protected static XMLInputFactory ifactory = null; protected static XMLOutputFactory ofactory = null; - public XMLUtilities(final ODataVersion version) throws Exception { + public AbstractXMLUtilities(final ODataVersion version) throws Exception { super(version); } - public void retrieveLinkInfoFromMetadata() throws Exception { - - final MetadataLinkInfo metadataLinkInfo = new MetadataLinkInfo(); - Commons.linkInfo.put(version, metadataLinkInfo); - - final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML); - final XMLEventReader reader = getEventReader(metadata); - - int initialDepth = 0; - try { - while (true) { - Map.Entry entityType = - extractElement(reader, null, Collections.singletonList("EntityType"), - null, false, initialDepth, 4, 4); - initialDepth = entityType.getKey(); - - final String entitySetName = - entityType.getValue().getStart().getAttributeByName(new QName("Name")).getValue(); - - final XMLEventReader entityReader = getEventReader(entityType.getValue().toStream()); - int size = 0; - - try { - while (true) { - final XmlElement navProperty = - extractElement(entityReader, null, Collections.singletonList("NavigationProperty"), - null, false, 0, -1, -1).getValue(); - - final String linkName = navProperty.getStart().getAttributeByName(new QName("Name")).getValue(); - final Map.Entry target = getTargetInfo(navProperty.getStart(), linkName); - - metadataLinkInfo.addLink( - entitySetName, - linkName, - target.getKey(), - target.getValue()); - - size++; - } - } catch (Exception e) { - } finally { - entityReader.close(); - } - - if (size == 0) { - metadataLinkInfo.addEntitySet(entitySetName); - } - } - } catch (Exception e) { - } finally { - reader.close(); - } - } - - private Map.Entry getTargetInfo(final StartElement element, final String linkName) - throws Exception { - final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML); - XMLEventReader reader = getEventReader(metadata); - - final String associationName = element.getAttributeByName(new QName("Relationship")).getValue(); - - final Map.Entry association = extractElement( - reader, null, Collections.singletonList("Association"), - Collections.>singleton(new SimpleEntry( - "Name", associationName.substring(associationName.lastIndexOf(".") + 1))), false, - 0, 4, 4); - - reader.close(); - IOUtils.closeQuietly(metadata); - - final InputStream associationContent = association.getValue().toStream(); - reader = getEventReader(associationContent); - - final Map.Entry associationEnd = extractElement( - reader, null, Collections.singletonList("End"), - Collections.>singleton(new SimpleEntry("Role", linkName)), - false, 0, -1, -1); - - reader.close(); - IOUtils.closeQuietly(associationContent); - - final String target = associationEnd.getValue().getStart().getAttributeByName(new QName("Type")).getValue(); - final boolean feed = associationEnd.getValue().getStart().getAttributeByName( - new QName("Multiplicity")).getValue().equals("*"); - - return new SimpleEntry(target, feed); - } + public abstract void retrieveLinkInfoFromMetadata() throws Exception; @Override protected Accept getDefaultFormat() { diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java b/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java index 9fdf1dacf..237184320 100644 --- a/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java +++ b/fit/src/main/java/org/apache/olingo/fit/utils/Accept.java @@ -28,24 +28,35 @@ public enum Accept { TEXT(ContentType.TEXT_PLAIN.getMimeType(), ".txt"), XML(ContentType.APPLICATION_XML.getMimeType(), ".xml"), ATOM(ContentType.APPLICATION_ATOM_XML.getMimeType(), ".xml"), - JSON(ContentType.APPLICATION_JSON.getMimeType() + ";odata=minimalmetadata", ".full.json"), - JSON_NOMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=nometadata", ".full.json"), - JSON_FULLMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=fullmetadata", ".full.json"); + JSON(ContentType.APPLICATION_JSON.getMimeType() + ";odata=minimalmetadata", + ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=minimal", ".full.json"), + JSON_NOMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=nometadata", + ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=none", ".full.json"), + JSON_FULLMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=fullmetadata", + ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=full", ".full.json"); - private final String contentType; + private final String contentTypeV3; + + private final String contentTypeV4; private final String fileExtension; private static Pattern allTypesPattern = Pattern.compile("(.*,)?\\*/\\*([,;].*)?"); - Accept(final String contentType, final String fileExtension) { - this.contentType = contentType; + Accept(final String contentTypeV3, final String fileExtension) { + this.contentTypeV3 = contentTypeV3; + this.contentTypeV4 = contentTypeV3; this.fileExtension = fileExtension; } - @Override - public String toString() { - return contentType; + Accept(final String contentTypeV3, final String contentTypeV4, final String fileExtension) { + this.contentTypeV3 = contentTypeV3; + this.contentTypeV4 = contentTypeV4; + this.fileExtension = fileExtension; + } + + public String toString(final ODataVersion version) { + return ODataVersion.v3 == version ? contentTypeV3 : contentTypeV4; } public String getExtension() { @@ -53,23 +64,30 @@ public enum Accept { } public static Accept parse(final String contentType, final ODataVersion version) { - return parse(contentType, version, ODataVersion.v3 == version ? ATOM : JSON_NOMETA); + final Accept def; + if (ODataVersion.v3 == version) { + def = ATOM; + } else { + def = JSON_NOMETA; + } + + return parse(contentType, version, def); } public static Accept parse(final String contentType, final ODataVersion version, final Accept def) { if (StringUtils.isBlank(contentType) || allTypesPattern.matcher(contentType).matches()) { return def; - } else if (JSON_NOMETA.toString().equals(contentType)) { + } else if (JSON_NOMETA.toString(version).equals(contentType)) { return JSON_NOMETA; - } else if (JSON.toString().equals(contentType) || "application/json".equals(contentType)) { + } else if (JSON.toString(version).equals(contentType) || "application/json".equals(contentType)) { return JSON; - } else if (JSON_FULLMETA.toString().equals(contentType)) { + } else if (JSON_FULLMETA.toString(version).equals(contentType)) { return JSON_FULLMETA; - } else if (XML.toString().equals(contentType)) { + } else if (XML.toString(version).equals(contentType)) { return XML; - } else if (ATOM.toString().equals(contentType)) { + } else if (ATOM.toString(version).equals(contentType)) { return ATOM; - } else if (TEXT.toString().equals(contentType)) { + } else if (TEXT.toString(version).equals(contentType)) { return TEXT; } else { throw new UnsupportedMediaTypeException("Unsupported media type"); diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java b/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java index 233e03d9b..dcc48074b 100644 --- a/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java +++ b/fit/src/main/java/org/apache/olingo/fit/utils/Commons.java @@ -74,6 +74,10 @@ public abstract class Commons { mediaContent.put("Car/Photo", null); } + public static Map getLinkInfo() { + return linkInfo; + } + public static String getEntityURI(final String entitySetName, final String entityKey) { return entitySetName + "(" + entityKey + ")"; } @@ -230,7 +234,7 @@ public abstract class Commons { break; default: - throw new UnsupportedOperationException(target.toString()); + throw new UnsupportedOperationException(target.name()); } for (String field : toBeRemoved) { diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/v3/JSONUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/v3/JSONUtilities.java new file mode 100644 index 000000000..0f2a3f242 --- /dev/null +++ b/fit/src/main/java/org/apache/olingo/fit/utils/v3/JSONUtilities.java @@ -0,0 +1,28 @@ +/* + * 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.fit.utils.v3; + +import org.apache.olingo.fit.utils.ODataVersion; + +public class JSONUtilities extends org.apache.olingo.fit.utils.AbstractJSONUtilities { + + public JSONUtilities() throws Exception { + super(ODataVersion.v3); + } +} diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/v3/XMLUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/v3/XMLUtilities.java new file mode 100644 index 000000000..c1a58bf95 --- /dev/null +++ b/fit/src/main/java/org/apache/olingo/fit/utils/v3/XMLUtilities.java @@ -0,0 +1,191 @@ +/* + * 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.fit.utils.v3; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.AbstractMap.SimpleEntry; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.events.StartElement; +import org.apache.commons.io.IOUtils; +import org.apache.olingo.fit.utils.Accept; +import org.apache.olingo.fit.utils.Commons; +import org.apache.olingo.fit.utils.Constants; +import org.apache.olingo.fit.utils.MetadataLinkInfo; +import org.apache.olingo.fit.utils.ODataVersion; +import org.apache.olingo.fit.utils.XmlElement; + +public class XMLUtilities extends org.apache.olingo.fit.utils.AbstractXMLUtilities { + + public XMLUtilities() throws Exception { + super(ODataVersion.v3); + } + + @Override + public void retrieveLinkInfoFromMetadata() throws Exception { + + final MetadataLinkInfo metadataLinkInfo = new MetadataLinkInfo(); + Commons.getLinkInfo().put(version, metadataLinkInfo); + + final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML); + final XMLEventReader reader = getEventReader(metadata); + + try { + while (true) { + final Map.Entry entitySetElement = + extractElement(reader, null, Collections.singletonList("EntitySet"), + null, false, 0, -1, -1); + + retrieveLinks(entitySetElement.getValue(), metadataLinkInfo); + } + } catch (Exception e) { + } finally { + reader.close(); + } + } + + private void retrieveLinks(final XmlElement entitySetElement, final MetadataLinkInfo metadataLinkInfo) + throws Exception { + + final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML); + + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + IOUtils.copy(metadata, bos); + IOUtils.closeQuietly(metadata); + + final String entitySetName = entitySetElement.getStart().getAttributeByName(new QName("Name")).getValue().trim(); + final String entityType = entitySetElement.getStart().getAttributeByName(new QName("EntityType")).getValue().trim(); + + final Collection> filter = new HashSet>(); + filter.add(new SimpleEntry( + "Name", entityType.substring(entityType.lastIndexOf(".") + 1, entityType.length()))); + filter.add(new SimpleEntry("BaseType", entityType)); + + final XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray())); + + final Map.Entry entityTypeElement = extractElement( + reader, null, Collections.singletonList("EntityType"), filter, true, 0, -1, -1); + + final XMLEventReader entityReader = entityTypeElement.getValue().getContentReader(); + int size = 0; + + try { + while (true) { + final XmlElement navProperty = + extractElement(entityReader, null, Collections.singletonList("NavigationProperty"), + null, false, 0, -1, -1).getValue(); + + final String linkName = navProperty.getStart().getAttributeByName(new QName("Name")).getValue(); + final Map.Entry target = getTargetInfo(navProperty.getStart(), linkName); + + metadataLinkInfo.addLink( + entitySetName, + linkName, + target.getKey(), + target.getValue()); + + size++; + } + } catch (Exception e) { + } finally { + entityReader.close(); + } + + if (size == 0) { + metadataLinkInfo.addEntitySet(entitySetName); + } + } + + private Map.Entry getTargetInfo(final StartElement element, final String linkName) + throws Exception { + final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML); + + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + IOUtils.copy(metadata, bos); + IOUtils.closeQuietly(metadata); + + // ------------------------------------ + // Retrieve association + // ------------------------------------ + XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray())); + + final String associationName = element.getAttributeByName(new QName("Relationship")).getValue(); + + final Map.Entry association = extractElement( + reader, null, Collections.singletonList("Association"), + Collections.>singleton(new SimpleEntry( + "Name", associationName.substring(associationName.lastIndexOf(".") + 1))), false, + 0, 4, 4); + + reader.close(); + // ------------------------------------ + + // ------------------------------------ + // check for feed or not from Association role + // ------------------------------------ + InputStream associationContent = association.getValue().toStream(); + reader = getEventReader(associationContent); + + Map.Entry associationEnd = extractElement( + reader, null, Collections.singletonList("End"), + Collections.>singleton(new SimpleEntry("Role", linkName)), + false, 0, -1, -1); + + reader.close(); + IOUtils.closeQuietly(associationContent); + + final boolean feed = associationEnd.getValue().getStart().getAttributeByName( + new QName("Multiplicity")).getValue().equals("*"); + // ------------------------------------ + + // ------------------------------------ + // Retrieve target association set name + // ------------------------------------ + reader = getEventReader(new ByteArrayInputStream(bos.toByteArray())); + + final Map.Entry associationSet = extractElement( + reader, null, Collections.singletonList("AssociationSet"), + Collections.>singleton(new SimpleEntry( + "Association", associationName)), false, 0, -1, -1); + + reader.close(); + + associationContent = associationSet.getValue().toStream(); + reader = getEventReader(associationContent); + + associationEnd = extractElement( + reader, null, Collections.singletonList("End"), + Collections.>singleton(new SimpleEntry("Role", linkName)), + false, 0, -1, -1); + + reader.close(); + IOUtils.closeQuietly(associationContent); + + final String target = associationEnd.getValue().getStart().getAttributeByName(new QName("EntitySet")).getValue(); + // ------------------------------------ + + return new SimpleEntry(target, feed); + } +} diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/v4/JSONUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/v4/JSONUtilities.java new file mode 100644 index 000000000..daf75f4e2 --- /dev/null +++ b/fit/src/main/java/org/apache/olingo/fit/utils/v4/JSONUtilities.java @@ -0,0 +1,28 @@ +/* + * 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.fit.utils.v4; + +import org.apache.olingo.fit.utils.ODataVersion; + +public class JSONUtilities extends org.apache.olingo.fit.utils.AbstractJSONUtilities { + + public JSONUtilities() throws Exception { + super(ODataVersion.v4); + } +} diff --git a/fit/src/main/java/org/apache/olingo/fit/utils/v4/XMLUtilities.java b/fit/src/main/java/org/apache/olingo/fit/utils/v4/XMLUtilities.java new file mode 100644 index 000000000..c61d272b8 --- /dev/null +++ b/fit/src/main/java/org/apache/olingo/fit/utils/v4/XMLUtilities.java @@ -0,0 +1,142 @@ +/* + * 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.fit.utils.v4; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import org.apache.commons.io.IOUtils; +import org.apache.olingo.fit.utils.Accept; +import org.apache.olingo.fit.utils.Commons; +import org.apache.olingo.fit.utils.Constants; +import org.apache.olingo.fit.utils.MetadataLinkInfo; +import org.apache.olingo.fit.utils.ODataVersion; +import org.apache.olingo.fit.utils.XmlElement; + +public class XMLUtilities extends org.apache.olingo.fit.utils.AbstractXMLUtilities { + + public XMLUtilities() throws Exception { + super(ODataVersion.v4); + } + + @Override + public void retrieveLinkInfoFromMetadata() throws Exception { + + final MetadataLinkInfo metadataLinkInfo = new MetadataLinkInfo(); + Commons.getLinkInfo().put(version, metadataLinkInfo); + + final InputStream metadata = fsManager.readFile(Constants.METADATA, Accept.XML); + + final ByteArrayOutputStream bos = new ByteArrayOutputStream(); + IOUtils.copy(metadata, bos); + IOUtils.closeQuietly(metadata); + + XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray())); + + final Set singletons = new HashSet(); + + try { + while (true) { + final Map.Entry entitySetElement = + extractElement(reader, null, Collections.singletonList("Singleton"), + null, false, 0, -1, -1); + + final String entitySetName = + entitySetElement.getValue().getStart().getAttributeByName(new QName("Name")).getValue().trim(); + singletons.add(entitySetName); + } + } catch (Exception e) { + } finally { + reader.close(); + } + + reader = getEventReader(new ByteArrayInputStream(bos.toByteArray())); + + try { + while (true) { + final Map.Entry entitySetElement = + extractElement(reader, null, Collections.singletonList("EntitySet"), + null, false, 0, -1, -1); + + retrieveLinks(entitySetElement.getValue(), metadataLinkInfo, singletons); + } + } catch (Exception e) { + } finally { + reader.close(); + } + + reader = getEventReader(new ByteArrayInputStream(bos.toByteArray())); + + try { + while (true) { + final Map.Entry entitySetElement = + extractElement(reader, null, Collections.singletonList("Singleton"), + null, false, 0, -1, -1); + + retrieveLinks(entitySetElement.getValue(), metadataLinkInfo, singletons); + } + } catch (Exception e) { + } finally { + reader.close(); + } + } + + private void retrieveLinks( + final XmlElement entitySetElement, final MetadataLinkInfo metadataLinkInfo, final Set singletons) + throws Exception { + + final String entitySetName = entitySetElement.getStart().getAttributeByName(new QName("Name")).getValue().trim(); + + final XMLEventReader entityReader = entitySetElement.getContentReader(); + int size = 0; + + try { + while (true) { + final XmlElement navProperty = + extractElement(entityReader, null, Collections.singletonList("NavigationPropertyBinding"), + null, false, 0, -1, -1).getValue(); + + final String linkName = navProperty.getStart().getAttributeByName(new QName("Path")).getValue(); + final String target = navProperty.getStart().getAttributeByName(new QName("Target")).getValue(); + final boolean feed = !singletons.contains(target); + + metadataLinkInfo.addLink( + entitySetName, + linkName, + target, + feed); + + size++; + } + } catch (Exception e) { + } finally { + entityReader.close(); + } + + if (size == 0) { + metadataLinkInfo.addEntitySet(entitySetName); + } + } +} diff --git a/fit/src/main/resources/v4/People/feed.full.json b/fit/src/main/resources/v4/People/feed.full.json new file mode 100644 index 000000000..0c998f60e --- /dev/null +++ b/fit/src/main/resources/v4/People/feed.full.json @@ -0,0 +1,332 @@ +{ + "@odata.context": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/$metadata#People", + "value": + [ + { + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Customer", + "@odata.id": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)", + "@odata.editLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer", + "PersonID": 1, + "FirstName": "Bob", + "LastName": "Cat", + "MiddleName": null, + "HomeAddress": + { + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.HomeAddress", + "Street": "1 Microsoft Way", + "City": "London", + "PostalCode": "98052", + "FamilyName": "Cats" + }, + "Home@odata.type": "#GeographyPoint", + "Home": + { + "type": "Point", + "coordinates": + [ + 23.1, + 32.1 + ], + "crs": + { + "type": "name", + "properties": + { + "name": "EPSG:4326" + } + } + }, + "Numbers@odata.type": "#Collection(String)", + "Numbers": + [ + "111-111-1111" + ], + "Emails@odata.type": "#Collection(String)", + "Emails": + [ + "abc@abc.com" + ], + "City": "London", + "Birthday@odata.type": "#DateTimeOffset", + "Birthday": "1957-04-03T00:00:00Z", + "TimeBetweenLastTwoOrders@odata.type": "#Duration", + "TimeBetweenLastTwoOrders": "PT0.0000001S", + "Parent@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent/$ref", + "Parent@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent", + "Orders@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders/$ref", + "Orders@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders", + "Company@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company/$ref", + "Company@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company", + "#Microsoft.Test.OData.Services.ODataWCFService.ResetAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.ResetAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress" + }, + "#Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress" + } + }, + { + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Customer", + "@odata.id": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)", + "@odata.editLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer", + "PersonID": 2, + "FirstName": "Jill", + "LastName": "Jones", + "MiddleName": null, + "HomeAddress": null, + "Home@odata.type": "#GeographyPoint", + "Home": + { + "type": "Point", + "coordinates": + [ + 161.8, + 15 + ], + "crs": + { + "type": "name", + "properties": + { + "name": "EPSG:4326" + } + } + }, + "Numbers@odata.type": "#Collection(String)", + "Numbers": + [ + ], + "Emails@odata.type": "#Collection(String)", + "Emails": + [ + ], + "City": "Sydney", + "Birthday@odata.type": "#DateTimeOffset", + "Birthday": "1983-01-15T00:00:00Z", + "TimeBetweenLastTwoOrders@odata.type": "#Duration", + "TimeBetweenLastTwoOrders": "PT0.0000002S", + "Parent@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent/$ref", + "Parent@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent", + "Orders@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders/$ref", + "Orders@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders", + "Company@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company/$ref", + "Company@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company", + "#Microsoft.Test.OData.Services.ODataWCFService.ResetAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.ResetAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress" + }, + "#Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress" + } + }, + { + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Employee", + "@odata.id": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)", + "@odata.editLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee", + "PersonID": 3, + "FirstName": "Jacob", + "LastName": "Zip", + "MiddleName": null, + "HomeAddress": + { + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Address", + "Street": "1 Microsoft Way", + "City": "Sydney", + "PostalCode": "98052" + }, + "Home@odata.type": "#GeographyPoint", + "Home": + { + "type": "Point", + "coordinates": + [ + 161.8, + 15 + ], + "crs": + { + "type": "name", + "properties": + { + "name": "EPSG:4326" + } + } + }, + "Numbers@odata.type": "#Collection(String)", + "Numbers": + [ + "333-333-3333" + ], + "Emails@odata.type": "#Collection(String)", + "Emails": + [ + null + ], + "DateHired@odata.type": "#DateTimeOffset", + "DateHired": "2010-12-13T00:00:00Z", + "Office@odata.type": "#GeographyPoint", + "Office": + { + "type": "Point", + "coordinates": + [ + 162, + 15 + ], + "crs": + { + "type": "name", + "properties": + { + "name": "EPSG:4326" + } + } + }, + "Parent@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Parent/$ref", + "Parent@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Parent", + "Company@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Company/$ref", + "Company@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Company", + "#Microsoft.Test.OData.Services.ODataWCFService.ResetAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.ResetAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress" + }, + "#Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress" + } + }, + { + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Employee", + "@odata.id": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)", + "@odata.editLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee", + "PersonID": 4, + "FirstName": "Elmo", + "LastName": "Rogers", + "MiddleName": null, + "HomeAddress": null, + "Home@odata.type": "#GeographyPoint", + "Home": + { + "type": "Point", + "coordinates": + [ + -61.8, + -15 + ], + "crs": + { + "type": "name", + "properties": + { + "name": "EPSG:4326" + } + } + }, + "Numbers@odata.type": "#Collection(String)", + "Numbers": + [ + "444-444-4444", + "555-555-5555", + "666-666-6666" + ], + "Emails@odata.type": "#Collection(String)", + "Emails": + [ + "def@def.org", + "lmn@lmn.com" + ], + "DateHired@odata.type": "#DateTimeOffset", + "DateHired": "2008-03-27T00:00:00Z", + "Office@odata.type": "#GeographyPoint", + "Office": + { + "type": "Point", + "coordinates": + [ + -62, + -15 + ], + "crs": + { + "type": "name", + "properties": + { + "name": "EPSG:4326" + } + } + }, + "Parent@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Parent/$ref", + "Parent@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Parent", + "Company@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Company/$ref", + "Company@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Company", + "#Microsoft.Test.OData.Services.ODataWCFService.ResetAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.ResetAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress" + }, + "#Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress" + } + }, + { + "@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Person", + "@odata.id": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)", + "@odata.editLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)", + "PersonID": 5, + "FirstName": "Peter", + "LastName": "Bee", + "MiddleName": null, + "HomeAddress": null, + "Home@odata.type": "#GeographyPoint", + "Home": + { + "type": "Point", + "coordinates": + [ + -261.8, + -16 + ], + "crs": + { + "type": "name", + "properties": + { + "name": "EPSG:4326" + } + } + }, + "Numbers@odata.type": "#Collection(String)", + "Numbers": + [ + "555-555-5555" + ], + "Emails@odata.type": "#Collection(String)", + "Emails": + [ + "def@test.msn" + ], + "Parent@odata.associationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)/Parent/$ref", + "Parent@odata.navigationLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)/Parent", + "#Microsoft.Test.OData.Services.ODataWCFService.ResetAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.ResetAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress" + }, + "#Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress": + { + "title": "Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress", + "target": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)/Microsoft.Test.OData.Services.ODataWCFService.GetHomeAddress" + } + } + ] +} \ No newline at end of file diff --git a/fit/src/main/resources/v4/People/feed.xml b/fit/src/main/resources/v4/People/feed.xml new file mode 100644 index 000000000..f79bb495e --- /dev/null +++ b/fit/src/main/resources/v4/People/feed.xml @@ -0,0 +1,218 @@ + + + + http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People + + <updated>2014-03-20T14:31:00Z</updated> + <entry> + <id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)</id> + <category term="#Microsoft.Test.OData.Services.ODataWCFService.Customer" scheme="http://docs.oasis-open.org/odata/ns/scheme" /> + <link rel="edit" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Orders" type="application/atom+xml;type=feed" title="Orders" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Company" type="application/atom+xml;type=entry" title="Company" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(1)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company" /> + <title /> + <updated>2014-03-20T14:31:00Z</updated> + <author> + <name /> + </author> + <content type="application/xml"> + <m:properties> + <d:PersonID m:type="Int32">1</d:PersonID> + <d:FirstName>Bob</d:FirstName> + <d:LastName>Cat</d:LastName> + <d:MiddleName m:null="true" /> + <d:HomeAddress m:type="#Microsoft.Test.OData.Services.ODataWCFService.HomeAddress"> + <d:Street>1 Microsoft Way</d:Street> + <d:City>London</d:City> + <d:PostalCode>98052</d:PostalCode> + <d:FamilyName>Cats</d:FamilyName> + </d:HomeAddress> + <d:Home m:type="GeographyPoint"> + <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"> + <gml:pos>32.1 23.1</gml:pos> + </gml:Point> + </d:Home> + <d:Numbers m:type="#Collection(String)"> + <m:element>111-111-1111</m:element> + </d:Numbers> + <d:Emails m:type="#Collection(String)"> + <m:element>abc@abc.com</m:element> + </d:Emails> + <d:City>London</d:City> + <d:Birthday m:type="DateTimeOffset">1957-04-03T00:00:00Z</d:Birthday> + <d:TimeBetweenLastTwoOrders m:type="Duration">PT0.0000001S</d:TimeBetweenLastTwoOrders> + </m:properties> + </content> + </entry> + <entry> + <id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)</id> + <category term="#Microsoft.Test.OData.Services.ODataWCFService.Customer" scheme="http://docs.oasis-open.org/odata/ns/scheme" /> + <link rel="edit" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Parent" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Orders" type="application/atom+xml;type=feed" title="Orders" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Orders" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Company" type="application/atom+xml;type=entry" title="Company" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(2)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company" /> + <title /> + <updated>2014-03-20T14:31:00Z</updated> + <author> + <name /> + </author> + <content type="application/xml"> + <m:properties> + <d:PersonID m:type="Int32">2</d:PersonID> + <d:FirstName>Jill</d:FirstName> + <d:LastName>Jones</d:LastName> + <d:MiddleName m:null="true" /> + <d:HomeAddress m:null="true" /> + <d:Home m:type="GeographyPoint"> + <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"> + <gml:pos>15 161.8</gml:pos> + </gml:Point> + </d:Home> + <d:Numbers m:type="#Collection(String)" /> + <d:Emails m:type="#Collection(String)" /> + <d:City>Sydney</d:City> + <d:Birthday m:type="DateTimeOffset">1983-01-15T00:00:00Z</d:Birthday> + <d:TimeBetweenLastTwoOrders m:type="Duration">PT0.0000002S</d:TimeBetweenLastTwoOrders> + </m:properties> + </content> + </entry> + <entry> + <id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)</id> + <category term="#Microsoft.Test.OData.Services.ODataWCFService.Employee" scheme="http://docs.oasis-open.org/odata/ns/scheme" /> + <link rel="edit" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Parent" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Company" type="application/atom+xml;type=entry" title="Company" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(3)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Company" /> + <title /> + <updated>2014-03-20T14:31:00Z</updated> + <author> + <name /> + </author> + <content type="application/xml"> + <m:properties> + <d:PersonID m:type="Int32">3</d:PersonID> + <d:FirstName>Jacob</d:FirstName> + <d:LastName>Zip</d:LastName> + <d:MiddleName m:null="true" /> + <d:HomeAddress m:type="#Microsoft.Test.OData.Services.ODataWCFService.Address"> + <d:Street>1 Microsoft Way</d:Street> + <d:City>Sydney</d:City> + <d:PostalCode>98052</d:PostalCode> + </d:HomeAddress> + <d:Home m:type="GeographyPoint"> + <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"> + <gml:pos>15 161.8</gml:pos> + </gml:Point> + </d:Home> + <d:Numbers m:type="#Collection(String)"> + <m:element>333-333-3333</m:element> + </d:Numbers> + <d:Emails m:type="#Collection(String)"> + <m:element m:null="true" /> + </d:Emails> + <d:DateHired m:type="DateTimeOffset">2010-12-13T00:00:00Z</d:DateHired> + <d:Office m:type="GeographyPoint"> + <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"> + <gml:pos>15 162</gml:pos> + </gml:Point> + </d:Office> + </m:properties> + </content> + </entry> + <entry> + <id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)</id> + <category term="#Microsoft.Test.OData.Services.ODataWCFService.Employee" scheme="http://docs.oasis-open.org/odata/ns/scheme" /> + <link rel="edit" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Parent" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Company" type="application/atom+xml;type=entry" title="Company" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(4)/Microsoft.Test.OData.Services.ODataWCFService.Employee/Company" /> + <title /> + <updated>2014-03-20T14:31:00Z</updated> + <author> + <name /> + </author> + <content type="application/xml"> + <m:properties> + <d:PersonID m:type="Int32">4</d:PersonID> + <d:FirstName>Elmo</d:FirstName> + <d:LastName>Rogers</d:LastName> + <d:MiddleName m:null="true" /> + <d:HomeAddress m:null="true" /> + <d:Home m:type="GeographyPoint"> + <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"> + <gml:pos>-15 -61.8</gml:pos> + </gml:Point> + </d:Home> + <d:Numbers m:type="#Collection(String)"> + <m:element>444-444-4444</m:element> + <m:element>555-555-5555</m:element> + <m:element>666-666-6666</m:element> + </d:Numbers> + <d:Emails m:type="#Collection(String)"> + <m:element>def@def.org</m:element> + <m:element>lmn@lmn.com</m:element> + </d:Emails> + <d:DateHired m:type="DateTimeOffset">2008-03-27T00:00:00Z</d:DateHired> + <d:Office m:type="GeographyPoint"> + <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"> + <gml:pos>-15 -62</gml:pos> + </gml:Point> + </d:Office> + </m:properties> + </content> + </entry> + <entry> + <id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)</id> + <category term="#Microsoft.Test.OData.Services.ODataWCFService.Person" scheme="http://docs.oasis-open.org/odata/ns/scheme" /> + <link rel="edit" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)" /> + <link rel="http://docs.oasis-open.org/odata/ns/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)/Parent" /> + <title /> + <updated>2014-03-20T14:31:00Z</updated> + <author> + <name /> + </author> + <content type="application/xml"> + <m:properties> + <d:PersonID m:type="Int32">5</d:PersonID> + <d:FirstName>Peter</d:FirstName> + <d:LastName>Bee</d:LastName> + <d:MiddleName m:null="true" /> + <d:HomeAddress m:null="true" /> + <d:Home m:type="GeographyPoint"> + <gml:Point gml:srsName="http://www.opengis.net/def/crs/EPSG/0/4326"> + <gml:pos>-16 -261.8</gml:pos> + </gml:Point> + </d:Home> + <d:Numbers m:type="#Collection(String)"> + <m:element>555-555-5555</m:element> + </d:Numbers> + <d:Emails m:type="#Collection(String)"> + <m:element>def@test.msn</m:element> + </d:Emails> + </m:properties> + </content> + </entry> +</feed> \ No newline at end of file diff --git a/fit/src/main/resources/v4/metadata.xml b/fit/src/main/resources/v4/metadata.xml index ae13a4eab..b51bf0f93 100644 --- a/fit/src/main/resources/v4/metadata.xml +++ b/fit/src/main/resources/v4/metadata.xml @@ -21,499 +21,418 @@ --> <edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"> <edmx:DataServices> - <Schema Namespace="NorthwindModel" xmlns="http://docs.oasis-open.org/odata/ns/edm"> - <!-- EnumType with values --> - <EnumType Name="FileAccess" UnderlyingType="Edm.Int32" IsFlags="true"> - <Member Name="Read" Value="1" /> - <Member Name="Write" Value="2" /> - <Member Name="Create" Value="4" /> - <Member Name="Delete" Value="8" /> - </EnumType> - <!-- EnumType without any values --> - <EnumType Name="ShippingMethod"> - <Member Name="FirstClass" /> - <Member Name="TwoDay" /> - <Member Name="Overnight" /> - </EnumType> - <!-- ComplexType --> - <ComplexType Name="Dimensions"> - <Property Name="Height" Nullable="false" Type="Edm.Decimal" /> - <Property Name="Weight" Nullable="false" Type="Edm.Decimal" /> - <Property Name="Length" Nullable="false" Type="Edm.Decimal" /> + <Schema Namespace="Microsoft.Test.OData.Services.ODataWCFService" xmlns="http://docs.oasis-open.org/odata/ns/edm"> + <ComplexType Name="Address"> + <Property Name="Street" Type="Edm.String" Nullable="false" /> + <Property Name="City" Type="Edm.String" Nullable="false" /> + <Property Name="PostalCode" Type="Edm.String" Nullable="false" /> </ComplexType> - <!-- ComplexType with enum property --> - <ComplexType Name="ACL"> - <Property Name="Filename" Nullable="false" Type="Edm.String" /> - <Property Name="Access" Nullable="false" Type="NorthwindModel.FileAccess" /> + <ComplexType Name="HomeAddress" BaseType="Microsoft.Test.OData.Services.ODataWCFService.Address"> + <Property Name="FamilyName" Type="Edm.String" /> </ComplexType> - <EntityType Name="Category"> + <ComplexType Name="CompanyAddress" BaseType="Microsoft.Test.OData.Services.ODataWCFService.Address"> + <Property Name="CompanyName" Type="Edm.String" Nullable="false" /> + </ComplexType> + <EnumType Name="AccessLevel" IsFlags="true"> + <Member Name="None" Value="0" /> + <Member Name="Read" Value="1" /> + <Member Name="Write" Value="2" /> + <Member Name="Execute" Value="4" /> + <Member Name="ReadWrite" Value="3" /> + </EnumType> + <EnumType Name="Color"> + <Member Name="Red" Value="1" /> + <Member Name="Green" Value="2" /> + <Member Name="Blue" Value="4" /> + </EnumType> + <EnumType Name="CompanyCategory"> + <Member Name="IT" Value="0" /> + <Member Name="Communication" Value="1" /> + <Member Name="Electronics" Value="2" /> + <Member Name="Others" Value="4" /> + </EnumType> + <EntityType Name="Person"> <Key> - <PropertyRef Name="CategoryID" /> + <PropertyRef Name="PersonID" /> </Key> - <Property Name="CategoryID" Type="Edm.Int32" Nullable="false" p5:StoreGeneratedPattern="Identity" xmlns:p5="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /> - <Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" /> - <Property Name="Description" Type="Edm.String" MaxLength="max" /> - <Property Name="Picture" Type="Edm.Binary" MaxLength="max" /> - <NavigationProperty Name="Products" Type="Collection(NorthwindModel.Product)" Partner="Category" /> + <Property Name="PersonID" Type="Edm.Int32" Nullable="false" /> + <Property Name="FirstName" Type="Edm.String" Nullable="false" /> + <Property Name="LastName" Type="Edm.String" Nullable="false" /> + <Property Name="MiddleName" Type="Edm.String" /> + <Property Name="HomeAddress" Type="Microsoft.Test.OData.Services.ODataWCFService.Address" /> + <Property Name="Home" Type="Edm.GeographyPoint" SRID="4326" /> + <Property Name="Numbers" Type="Collection(Edm.String)" Nullable="false" /> + <Property Name="Emails" Type="Collection(Edm.String)" /> + <NavigationProperty Name="Parent" Type="Microsoft.Test.OData.Services.ODataWCFService.Person" Nullable="false" /> </EntityType> - <EntityType Name="CustomerDemographic"> - <Key> - <PropertyRef Name="CustomerTypeID" /> - </Key> - <Property Name="CustomerTypeID" Type="Edm.String" Nullable="false" MaxLength="10" /> - <Property Name="CustomerDesc" Type="Edm.String" MaxLength="max" /> - <NavigationProperty Name="Customers" Type="Collection(NorthwindModel.Customer)" Partner="CustomerDemographics" /> + <EntityType Name="Customer" BaseType="Microsoft.Test.OData.Services.ODataWCFService.Person"> + <Property Name="City" Type="Edm.String" Nullable="false" /> + <Property Name="Birthday" Type="Edm.DateTimeOffset" Nullable="false" /> + <Property Name="TimeBetweenLastTwoOrders" Type="Edm.Duration" Nullable="false" /> + <NavigationProperty Name="Orders" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Order)" /> + <NavigationProperty Name="Company" Type="Microsoft.Test.OData.Services.ODataWCFService.Company" Nullable="false" Partner="VipCustomer" /> </EntityType> - <EntityType Name="Customer"> - <Key> - <PropertyRef Name="CustomerID" /> - </Key> - <Property Name="CustomerID" Type="Edm.String" Nullable="false" MaxLength="5" /> - <Property Name="CompanyName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="ContactName" Type="Edm.String" MaxLength="30" /> - <Property Name="ContactTitle" Type="Edm.String" MaxLength="30" /> - <Property Name="Address" Type="Edm.String" MaxLength="60" /> - <Property Name="City" Type="Edm.String" MaxLength="15" /> - <Property Name="Region" Type="Edm.String" MaxLength="15" /> - <Property Name="PostalCode" Type="Edm.String" MaxLength="10" /> - <Property Name="Country" Type="Edm.String" MaxLength="15" /> - <Property Name="Phone" Type="Edm.String" MaxLength="24" /> - <Property Name="Fax" Type="Edm.String" MaxLength="24" /> - <!-- EnumType attribute --> - <Property Name="FileAccess" Type="NorthwindModel.FileAccess" /> - <NavigationProperty Name="Orders" Type="Collection(NorthwindModel.Order)" Partner="Customer" /> - <NavigationProperty Name="CustomerDemographics" Type="Collection(NorthwindModel.CustomerDemographic)" Partner="Customers" /> - </EntityType> - <EntityType Name="Employee"> - <Key> - <PropertyRef Name="EmployeeID" /> - </Key> - <Property Name="EmployeeID" Type="Edm.Int32" Nullable="false" p5:StoreGeneratedPattern="Identity" xmlns:p5="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /> - <Property Name="LastName" Type="Edm.String" Nullable="false" MaxLength="20" /> - <Property Name="FirstName" Type="Edm.String" Nullable="false" MaxLength="10" /> - <Property Name="Title" Type="Edm.String" MaxLength="30" /> - <Property Name="TitleOfCourtesy" Type="Edm.String" MaxLength="25" /> - <Property Name="BirthDate" Type="Edm.DateTimeOffset" /> - <Property Name="HireDate" Type="Edm.DateTimeOffset" /> - <Property Name="Address" Type="Edm.String" MaxLength="60" /> - <Property Name="City" Type="Edm.String" MaxLength="15" /> - <Property Name="Region" Type="Edm.String" MaxLength="15" /> - <Property Name="PostalCode" Type="Edm.String" MaxLength="10" /> - <Property Name="Country" Type="Edm.String" MaxLength="15" /> - <Property Name="HomePhone" Type="Edm.String" MaxLength="24" /> - <Property Name="Extension" Type="Edm.String" MaxLength="4" /> - <Property Name="Photo" Type="Edm.Binary" MaxLength="max" /> - <Property Name="Notes" Type="Edm.String" MaxLength="max" /> - <Property Name="ReportsTo" Type="Edm.Int32" /> - <Property Name="PhotoPath" Type="Edm.String" MaxLength="255" /> - <NavigationProperty Name="Employees1" Type="Collection(NorthwindModel.Employee)" Partner="Employee1" /> - <NavigationProperty Name="Employee1" Type="NorthwindModel.Employee" Partner="Employees1"> - <ReferentialConstraint Property="ReportsTo" ReferencedProperty="EmployeeID" /> - </NavigationProperty> - <NavigationProperty Name="Orders" Type="Collection(NorthwindModel.Order)" Partner="Employee" /> - <NavigationProperty Name="Territories" Type="Collection(NorthwindModel.Territory)" Partner="Employees" /> - </EntityType> - <EntityType Name="Order_Detail"> - <Key> - <PropertyRef Name="OrderID" /> - <PropertyRef Name="ProductID" /> - </Key> - <Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> - <Property Name="ProductID" Type="Edm.Int32" Nullable="false" /> - <Property Name="UnitPrice" Type="Edm.Decimal" Nullable="false" Precision="19" Scale="4" /> - <Property Name="Quantity" Type="Edm.Int16" Nullable="false" /> - <Property Name="Discount" Type="Edm.Single" Nullable="false" /> - <NavigationProperty Name="Order" Type="NorthwindModel.Order" Nullable="false" Partner="Order_Details"> - <ReferentialConstraint Property="OrderID" ReferencedProperty="OrderID" /> - </NavigationProperty> - <NavigationProperty Name="Product" Type="NorthwindModel.Product" Nullable="false" Partner="Order_Details"> - <ReferentialConstraint Property="ProductID" ReferencedProperty="ProductID" /> - </NavigationProperty> - </EntityType> - <EntityType Name="Order"> - <Key> - <PropertyRef Name="OrderID" /> - </Key> - <Property Name="OrderID" Type="Edm.Int32" Nullable="false" p5:StoreGeneratedPattern="Identity" xmlns:p5="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /> - <Property Name="CustomerID" Type="Edm.String" MaxLength="5" /> - <Property Name="EmployeeID" Type="Edm.Int32" /> - <Property Name="OrderDate" Type="Edm.DateTimeOffset" /> - <Property Name="RequiredDate" Type="Edm.DateTimeOffset" /> - <Property Name="ShippedDate" Type="Edm.DateTimeOffset" /> - <Property Name="ShipVia" Type="Edm.Int32" /> - <Property Name="Freight" Type="Edm.Decimal" Precision="19" Scale="4" /> - <Property Name="ShipName" Type="Edm.String" MaxLength="40" /> - <Property Name="ShipAddress" Type="Edm.String" MaxLength="60" /> - <Property Name="ShipCity" Type="Edm.String" MaxLength="15" /> - <Property Name="ShipRegion" Type="Edm.String" MaxLength="15" /> - <Property Name="ShipPostalCode" Type="Edm.String" MaxLength="10" /> - <Property Name="ShipCountry" Type="Edm.String" MaxLength="15" /> - <NavigationProperty Name="Customer" Type="NorthwindModel.Customer" Partner="Orders"> - <ReferentialConstraint Property="CustomerID" ReferencedProperty="CustomerID" /> - </NavigationProperty> - <NavigationProperty Name="Employee" Type="NorthwindModel.Employee" Partner="Orders"> - <ReferentialConstraint Property="EmployeeID" ReferencedProperty="EmployeeID" /> - </NavigationProperty> - <NavigationProperty Name="Order_Details" Type="Collection(NorthwindModel.Order_Detail)" Partner="Order" /> - <NavigationProperty Name="Shipper" Type="NorthwindModel.Shipper" Partner="Orders"> - <ReferentialConstraint Property="ShipVia" ReferencedProperty="ShipperID" /> - </NavigationProperty> + <EntityType Name="Employee" BaseType="Microsoft.Test.OData.Services.ODataWCFService.Person"> + <Property Name="DateHired" Type="Edm.DateTimeOffset" Nullable="false" /> + <Property Name="Office" Type="Edm.GeographyPoint" SRID="4326" /> + <NavigationProperty Name="Company" Type="Microsoft.Test.OData.Services.ODataWCFService.Company" Nullable="false" Partner="Employees" /> </EntityType> <EntityType Name="Product"> <Key> <PropertyRef Name="ProductID" /> </Key> - <Property Name="ProductID" Type="Edm.Int32" Nullable="false" p5:StoreGeneratedPattern="Identity" xmlns:p5="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /> - <Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="SupplierID" Type="Edm.Int32" /> - <Property Name="CategoryID" Type="Edm.Int32" /> - <Property Name="QuantityPerUnit" Type="Edm.String" MaxLength="20" /> - <Property Name="UnitPrice" Type="Edm.Decimal" Precision="19" Scale="4" /> - <Property Name="UnitsInStock" Type="Edm.Int16" /> - <Property Name="UnitsOnOrder" Type="Edm.Int16" /> - <Property Name="ReorderLevel" Type="Edm.Int16" /> + <Property Name="ProductID" Type="Edm.Int32" Nullable="false" /> + <Property Name="Name" Type="Edm.String" Nullable="false" /> + <Property Name="QuantityPerUnit" Type="Edm.String" Nullable="false" /> + <Property Name="UnitPrice" Type="Edm.Single" Nullable="false" /> + <Property Name="QuantityInStock" Type="Edm.Int32" Nullable="false" /> <Property Name="Discontinued" Type="Edm.Boolean" Nullable="false" /> - <!-- ComplexType attributes --> - <Property Name="ProductDimensions" Type="NorthwindModel.Dimensions" /> - <Property Name="ShippingDimensions" Type="NorthwindModel.Dimensions" /> - <NavigationProperty Name="Category" Type="NorthwindModel.Category" Partner="Products"> - <ReferentialConstraint Property="CategoryID" ReferencedProperty="CategoryID" /> - </NavigationProperty> - <NavigationProperty Name="Order_Details" Type="Collection(NorthwindModel.Order_Detail)" Partner="Product" /> - <NavigationProperty Name="Supplier" Type="NorthwindModel.Supplier" Partner="Products"> - <ReferentialConstraint Property="SupplierID" ReferencedProperty="SupplierID" /> + <Property Name="UserAccess" Type="Microsoft.Test.OData.Services.ODataWCFService.AccessLevel" /> + <Property Name="SkinColor" Type="Microsoft.Test.OData.Services.ODataWCFService.Color" /> + <Property Name="CoverColors" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Color)" Nullable="false" /> + <NavigationProperty Name="Details" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.ProductDetail)"> + <ReferentialConstraint Property="ProductID" ReferencedProperty="ProductID" /> </NavigationProperty> </EntityType> - <EntityType Name="Region"> + <EntityType Name="ProductDetail"> <Key> - <PropertyRef Name="RegionID" /> - </Key> - <Property Name="RegionID" Type="Edm.Int32" Nullable="false" /> - <Property Name="RegionDescription" Type="Edm.String" Nullable="false" MaxLength="50" /> - <NavigationProperty Name="Territories" Type="Collection(NorthwindModel.Territory)" Partner="Region" /> - </EntityType> - <EntityType Name="Shipper"> - <Key> - <PropertyRef Name="ShipperID" /> - </Key> - <Property Name="ShipperID" Type="Edm.Int32" Nullable="false" p5:StoreGeneratedPattern="Identity" xmlns:p5="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /> - <Property Name="CompanyName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="Phone" Type="Edm.String" MaxLength="24" /> - <NavigationProperty Name="Orders" Type="Collection(NorthwindModel.Order)" Partner="Shipper" /> - </EntityType> - <EntityType Name="Supplier"> - <Key> - <PropertyRef Name="SupplierID" /> - </Key> - <Property Name="SupplierID" Type="Edm.Int32" Nullable="false" p5:StoreGeneratedPattern="Identity" xmlns:p5="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /> - <Property Name="CompanyName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="ContactName" Type="Edm.String" MaxLength="30" /> - <Property Name="ContactTitle" Type="Edm.String" MaxLength="30" /> - <Property Name="Address" Type="Edm.String" MaxLength="60" /> - <Property Name="City" Type="Edm.String" MaxLength="15" /> - <Property Name="Region" Type="Edm.String" MaxLength="15" /> - <Property Name="PostalCode" Type="Edm.String" MaxLength="10" /> - <Property Name="Country" Type="Edm.String" MaxLength="15" /> - <Property Name="Phone" Type="Edm.String" MaxLength="24" /> - <Property Name="Fax" Type="Edm.String" MaxLength="24" /> - <Property Name="HomePage" Type="Edm.String" MaxLength="max" /> - <NavigationProperty Name="Products" Type="Collection(NorthwindModel.Product)" Partner="Supplier" /> - </EntityType> - <EntityType Name="Territory"> - <Key> - <PropertyRef Name="TerritoryID" /> - </Key> - <Property Name="TerritoryID" Type="Edm.String" Nullable="false" MaxLength="20" /> - <Property Name="TerritoryDescription" Type="Edm.String" Nullable="false" MaxLength="50" /> - <Property Name="RegionID" Type="Edm.Int32" Nullable="false" /> - <NavigationProperty Name="Region" Type="NorthwindModel.Region" Nullable="false" Partner="Territories"> - <ReferentialConstraint Property="RegionID" ReferencedProperty="RegionID" /> - </NavigationProperty> - <NavigationProperty Name="Employees" Type="Collection(NorthwindModel.Employee)" Partner="Territories" /> - </EntityType> - <EntityType Name="Alphabetical_list_of_product"> - <Key> - <PropertyRef Name="CategoryName" /> - <PropertyRef Name="Discontinued" /> <PropertyRef Name="ProductID" /> - <PropertyRef Name="ProductName" /> + <PropertyRef Name="ProductDetailID" /> </Key> <Property Name="ProductID" Type="Edm.Int32" Nullable="false" /> - <Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="SupplierID" Type="Edm.Int32" /> - <Property Name="CategoryID" Type="Edm.Int32" /> - <Property Name="QuantityPerUnit" Type="Edm.String" MaxLength="20" /> - <Property Name="UnitPrice" Type="Edm.Decimal" Precision="19" Scale="4" /> - <Property Name="UnitsInStock" Type="Edm.Int16" /> - <Property Name="UnitsOnOrder" Type="Edm.Int16" /> - <Property Name="ReorderLevel" Type="Edm.Int16" /> - <Property Name="Discontinued" Type="Edm.Boolean" Nullable="false" /> - <Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" /> + <Property Name="ProductDetailID" Type="Edm.Int32" Nullable="false" /> + <Property Name="ProductName" Type="Edm.String" Nullable="false" /> + <Property Name="Description" Type="Edm.String" Nullable="false" /> + <NavigationProperty Name="RelatedProduct" Type="Microsoft.Test.OData.Services.ODataWCFService.Product" /> + <NavigationProperty Name="Reviews" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.ProductReview)"> + <ReferentialConstraint Property="ProductID" ReferencedProperty="ProductID" /> + <ReferentialConstraint Property="ProductDetailID" ReferencedProperty="ProductDetailID" /> + </NavigationProperty> </EntityType> - <EntityType Name="Category_Sales_for_1997"> - <Key> - <PropertyRef Name="CategoryName" /> - </Key> - <Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" /> - <Property Name="CategorySales" Type="Edm.Decimal" Precision="19" Scale="4" /> - </EntityType> - <EntityType Name="Current_Product_List"> + <EntityType Name="ProductReview"> <Key> <PropertyRef Name="ProductID" /> - <PropertyRef Name="ProductName" /> + <PropertyRef Name="ProductDetailID" /> + <PropertyRef Name="ReviewTitle" /> + <PropertyRef Name="RevisionID" /> </Key> - <Property Name="ProductID" Type="Edm.Int32" Nullable="false" p5:StoreGeneratedPattern="Identity" xmlns:p5="http://schemas.microsoft.com/ado/2009/02/edm/annotation" /> - <Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> + <Property Name="ProductID" Type="Edm.Int32" Nullable="false" /> + <Property Name="ProductDetailID" Type="Edm.Int32" Nullable="false" /> + <Property Name="ReviewTitle" Type="Edm.String" Nullable="false" /> + <Property Name="RevisionID" Type="Edm.Int32" Nullable="false" /> + <Property Name="Comment" Type="Edm.String" Nullable="false" /> + <Property Name="Author" Type="Edm.String" Nullable="false" /> </EntityType> - <EntityType Name="Customer_and_Suppliers_by_City"> + <EntityType Name="Order"> <Key> - <PropertyRef Name="CompanyName" /> - <PropertyRef Name="Relationship" /> - </Key> - <Property Name="City" Type="Edm.String" MaxLength="15" /> - <Property Name="CompanyName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="ContactName" Type="Edm.String" MaxLength="30" /> - <Property Name="Relationship" Type="Edm.String" Nullable="false" MaxLength="9" Unicode="false" /> - </EntityType> - <EntityType Name="Invoice"> - <Key> - <PropertyRef Name="CustomerName" /> - <PropertyRef Name="Discount" /> <PropertyRef Name="OrderID" /> - <PropertyRef Name="ProductID" /> - <PropertyRef Name="ProductName" /> - <PropertyRef Name="Quantity" /> - <PropertyRef Name="Salesperson" /> - <PropertyRef Name="ShipperName" /> - <PropertyRef Name="UnitPrice" /> </Key> - <Property Name="ShipName" Type="Edm.String" MaxLength="40" /> - <Property Name="ShipAddress" Type="Edm.String" MaxLength="60" /> - <Property Name="ShipCity" Type="Edm.String" MaxLength="15" /> - <Property Name="ShipRegion" Type="Edm.String" MaxLength="15" /> - <Property Name="ShipPostalCode" Type="Edm.String" MaxLength="10" /> - <Property Name="ShipCountry" Type="Edm.String" MaxLength="15" /> - <Property Name="CustomerID" Type="Edm.String" MaxLength="5" /> - <Property Name="CustomerName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="Address" Type="Edm.String" MaxLength="60" /> - <Property Name="City" Type="Edm.String" MaxLength="15" /> - <Property Name="Region" Type="Edm.String" MaxLength="15" /> - <Property Name="PostalCode" Type="Edm.String" MaxLength="10" /> - <Property Name="Country" Type="Edm.String" MaxLength="15" /> - <Property Name="Salesperson" Type="Edm.String" Nullable="false" MaxLength="31" /> <Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> - <Property Name="OrderDate" Type="Edm.DateTimeOffset" /> - <Property Name="RequiredDate" Type="Edm.DateTimeOffset" /> - <Property Name="ShippedDate" Type="Edm.DateTimeOffset" /> - <Property Name="ShipperName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="ProductID" Type="Edm.Int32" Nullable="false" /> - <Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="UnitPrice" Type="Edm.Decimal" Nullable="false" Precision="19" Scale="4" /> - <Property Name="Quantity" Type="Edm.Int16" Nullable="false" /> - <Property Name="Discount" Type="Edm.Single" Nullable="false" /> - <Property Name="ExtendedPrice" Type="Edm.Decimal" Precision="19" Scale="4" /> - <Property Name="Freight" Type="Edm.Decimal" Precision="19" Scale="4" /> + <Property Name="OrderDate" Type="Edm.DateTimeOffset" Nullable="false" /> + <Property Name="ShelfLife" Type="Edm.Duration" /> + <Property Name="OrderShelfLifes" Type="Collection(Edm.Duration)" /> + <NavigationProperty Name="LoggedInEmployee" Type="Microsoft.Test.OData.Services.ODataWCFService.Employee" Nullable="false" /> + <NavigationProperty Name="CustomerForOrder" Type="Microsoft.Test.OData.Services.ODataWCFService.Customer" Nullable="false" /> + <NavigationProperty Name="OrderDetails" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.OrderDetail)" /> </EntityType> - <EntityType Name="Order_Details_Extended"> + <EntityType Name="OrderDetail"> <Key> - <PropertyRef Name="Discount" /> <PropertyRef Name="OrderID" /> <PropertyRef Name="ProductID" /> - <PropertyRef Name="ProductName" /> - <PropertyRef Name="Quantity" /> - <PropertyRef Name="UnitPrice" /> </Key> <Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> <Property Name="ProductID" Type="Edm.Int32" Nullable="false" /> - <Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="UnitPrice" Type="Edm.Decimal" Nullable="false" Precision="19" Scale="4" /> - <Property Name="Quantity" Type="Edm.Int16" Nullable="false" /> - <Property Name="Discount" Type="Edm.Single" Nullable="false" /> - <Property Name="ExtendedPrice" Type="Edm.Decimal" Precision="19" Scale="4" /> + <Property Name="OrderPlaced" Type="Edm.DateTimeOffset" Nullable="false" /> + <Property Name="Quantity" Type="Edm.Int32" Nullable="false" /> + <Property Name="UnitPrice" Type="Edm.Single" Nullable="false" /> + <NavigationProperty Name="ProductOrdered" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Product)" /> + <NavigationProperty Name="AssociatedOrder" Type="Microsoft.Test.OData.Services.ODataWCFService.Order" Nullable="false" /> </EntityType> - <EntityType Name="Order_Subtotal"> + <EntityType Name="Department"> <Key> - <PropertyRef Name="OrderID" /> + <PropertyRef Name="DepartmentID" /> </Key> - <Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> - <Property Name="Subtotal" Type="Edm.Decimal" Precision="19" Scale="4" /> + <Property Name="DepartmentID" Type="Edm.Int32" Nullable="false" /> + <Property Name="Name" Type="Edm.String" Nullable="false" /> + <NavigationProperty Name="Company" Type="Microsoft.Test.OData.Services.ODataWCFService.Company" Nullable="false" Partner="Departments" /> </EntityType> - <EntityType Name="Orders_Qry"> + <EntityType Name="Company"> <Key> - <PropertyRef Name="CompanyName" /> - <PropertyRef Name="OrderID" /> + <PropertyRef Name="CompanyID" /> </Key> - <Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> - <Property Name="CustomerID" Type="Edm.String" MaxLength="5" /> - <Property Name="EmployeeID" Type="Edm.Int32" /> - <Property Name="OrderDate" Type="Edm.DateTimeOffset" /> - <Property Name="RequiredDate" Type="Edm.DateTimeOffset" /> - <Property Name="ShippedDate" Type="Edm.DateTimeOffset" /> - <Property Name="ShipVia" Type="Edm.Int32" /> - <Property Name="Freight" Type="Edm.Decimal" Precision="19" Scale="4" /> - <Property Name="ShipName" Type="Edm.String" MaxLength="40" /> - <Property Name="ShipAddress" Type="Edm.String" MaxLength="60" /> - <Property Name="ShipCity" Type="Edm.String" MaxLength="15" /> - <Property Name="ShipRegion" Type="Edm.String" MaxLength="15" /> - <Property Name="ShipPostalCode" Type="Edm.String" MaxLength="10" /> - <Property Name="ShipCountry" Type="Edm.String" MaxLength="15" /> - <Property Name="CompanyName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="Address" Type="Edm.String" MaxLength="60" /> - <Property Name="City" Type="Edm.String" MaxLength="15" /> - <Property Name="Region" Type="Edm.String" MaxLength="15" /> - <Property Name="PostalCode" Type="Edm.String" MaxLength="10" /> - <Property Name="Country" Type="Edm.String" MaxLength="15" /> + <Property Name="CompanyID" Type="Edm.Int32" Nullable="false" /> + <Property Name="CompanyCategory" Type="Microsoft.Test.OData.Services.ODataWCFService.CompanyCategory" /> + <Property Name="Revenue" Type="Edm.Int64" Nullable="false" /> + <Property Name="Name" Type="Edm.String" /> + <Property Name="Address" Type="Microsoft.Test.OData.Services.ODataWCFService.Address" /> + <NavigationProperty Name="Employees" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Employee)" Partner="Company" /> + <NavigationProperty Name="VipCustomer" Type="Microsoft.Test.OData.Services.ODataWCFService.Customer" Nullable="false" Partner="Company" /> + <NavigationProperty Name="Departments" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Department)" Partner="Company" /> + <NavigationProperty Name="CoreDepartment" Type="Microsoft.Test.OData.Services.ODataWCFService.Department" Nullable="false" /> </EntityType> - <EntityType Name="Product_Sales_for_1997"> + <EntityType Name="PublicCompany" BaseType="Microsoft.Test.OData.Services.ODataWCFService.Company"> + <Property Name="StockExchange" Type="Edm.String" /> + <NavigationProperty Name="Assets" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Asset)" ContainsTarget="true" /> + <NavigationProperty Name="Club" Type="Microsoft.Test.OData.Services.ODataWCFService.Club" Nullable="false" ContainsTarget="true" /> + <NavigationProperty Name="LabourUnion" Type="Microsoft.Test.OData.Services.ODataWCFService.LabourUnion" Nullable="false" /> + </EntityType> + <EntityType Name="Asset"> <Key> - <PropertyRef Name="CategoryName" /> - <PropertyRef Name="ProductName" /> + <PropertyRef Name="AssetID" /> </Key> - <Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" /> - <Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="ProductSales" Type="Edm.Decimal" Precision="19" Scale="4" /> + <Property Name="AssetID" Type="Edm.Int32" Nullable="false" /> + <Property Name="Name" Type="Edm.String" /> + <Property Name="Number" Type="Edm.Int32" Nullable="false" /> </EntityType> - <EntityType Name="Products_Above_Average_Price"> + <EntityType Name="Club"> <Key> - <PropertyRef Name="ProductName" /> + <PropertyRef Name="ClubID" /> </Key> - <Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="UnitPrice" Type="Edm.Decimal" Precision="19" Scale="4" /> + <Property Name="ClubID" Type="Edm.Int32" Nullable="false" /> + <Property Name="Name" Type="Edm.String" /> </EntityType> - <EntityType Name="Products_by_Category"> + <EntityType Name="LabourUnion"> <Key> - <PropertyRef Name="CategoryName" /> - <PropertyRef Name="Discontinued" /> - <PropertyRef Name="ProductName" /> + <PropertyRef Name="LabourUnionID" /> </Key> - <Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" /> - <Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="QuantityPerUnit" Type="Edm.String" MaxLength="20" /> - <Property Name="UnitsInStock" Type="Edm.Int16" /> - <Property Name="Discontinued" Type="Edm.Boolean" Nullable="false" /> + <Property Name="LabourUnionID" Type="Edm.Int32" Nullable="false" /> + <Property Name="Name" Type="Edm.String" /> </EntityType> - <EntityType Name="Sales_by_Category"> - <Key> - <PropertyRef Name="CategoryID" /> - <PropertyRef Name="CategoryName" /> - <PropertyRef Name="ProductName" /> - </Key> - <Property Name="CategoryID" Type="Edm.Int32" Nullable="false" /> - <Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" /> - <Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="ProductSales" Type="Edm.Decimal" Precision="19" Scale="4" /> - </EntityType> - <EntityType Name="Sales_Totals_by_Amount"> - <Key> - <PropertyRef Name="CompanyName" /> - <PropertyRef Name="OrderID" /> - </Key> - <Property Name="SaleAmount" Type="Edm.Decimal" Precision="19" Scale="4" /> - <Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> - <Property Name="CompanyName" Type="Edm.String" Nullable="false" MaxLength="40" /> - <Property Name="ShippedDate" Type="Edm.DateTimeOffset" /> - </EntityType> - <EntityType Name="Summary_of_Sales_by_Quarter"> - <Key> - <PropertyRef Name="OrderID" /> - </Key> - <Property Name="ShippedDate" Type="Edm.DateTimeOffset" /> - <Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> - <Property Name="Subtotal" Type="Edm.Decimal" Precision="19" Scale="4" /> - </EntityType> - <EntityType Name="Summary_of_Sales_by_Year"> - <Key> - <PropertyRef Name="OrderID" /> - </Key> - <Property Name="ShippedDate" Type="Edm.DateTimeOffset" /> - <Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> - <Property Name="Subtotal" Type="Edm.Decimal" Precision="19" Scale="4" /> - </EntityType> - <Annotations Target="ODataWebExperimental.Northwind.Model.NorthwindEntities"> - <Annotation Term="Com.Microsoft.OData.Service.Conventions.V1.UrlConventions" String="KeyAsSegment" /> - </Annotations> - <!-- Function --> - <Function Name="TopSellingProducts" ReturnType="Collection(NorthwindModel.Product)" IsComposable="true" EntitySetPath="ODataWebExperimental.Northwind.Model.Products"> - <Parameter Name="Year" Type="Edm.Decimal" Precision="4" Scale="0" /> - </Function> - <Function Name="TopSellingProducts2" ReturnType="Collection(NorthwindModel.Product)" IsComposable="true" EntitySetPath="ODataWebExperimental.Northwind.Model.Products" IsBound="true"> - <Parameter Name="Product" Type="NorthwindModel.Product" /> - <Parameter Name="Year" Type="Edm.Decimal" Precision="4" Scale="0" /> - </Function> - <!-- Action --> - <Action Name="TopSellingProducts" EntitySetPath="ODataWebExperimental.Northwind.Model.Products" IsBound="true"> - <Parameter Name="Product" Type="NorthwindModel.Product" /> - <Parameter Name="Year" Type="Edm.Decimal" Precision="4" Scale="0" /> + <Action Name="AddAccessRight" IsBound="true"> + <Parameter Name="product" Type="Microsoft.Test.OData.Services.ODataWCFService.Product" Nullable="false" /> + <Parameter Name="accessRight" Type="Microsoft.Test.OData.Services.ODataWCFService.AccessLevel" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.AccessLevel" /> </Action> - </Schema> - <Schema Namespace="ODataWebExperimental.Northwind.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm"> - <EntityContainer Name="NorthwindEntities" p4:LazyLoadingEnabled="true" xmlns:p4="http://schemas.microsoft.com/ado/2009/02/edm/annotation"> - <EntitySet Name="Categories" EntityType="NorthwindModel.Category"> - <NavigationPropertyBinding Path="Products" Target="Products" /> + <Action Name="IncreaseRevenue" IsBound="true"> + <Parameter Name="p" Type="Microsoft.Test.OData.Services.ODataWCFService.Company" Nullable="false" /> + <Parameter Name="IncreaseValue" Type="Edm.Int64" /> + <ReturnType Type="Edm.Int64" Nullable="false" /> + </Action> + <Action Name="ResetAddress" IsBound="true" EntitySetPath="person"> + <Parameter Name="person" Type="Microsoft.Test.OData.Services.ODataWCFService.Person" Nullable="false" /> + <Parameter Name="addresses" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Address)" Nullable="false" /> + <Parameter Name="index" Type="Edm.Int32" Nullable="false" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.Person" Nullable="false" /> + </Action> + <Action Name="Discount" IsBound="true" EntitySetPath="products"> + <Parameter Name="products" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Product)" Nullable="false" /> + <Parameter Name="percentage" Type="Edm.Int32" Nullable="false" /> + <ReturnType Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Product)" Nullable="false" /> + </Action> + <Action Name="Discount"> + <Parameter Name="percentage" Type="Edm.Int32" Nullable="false" /> + </Action> + <Action Name="ResetBossEmail"> + <Parameter Name="emails" Type="Collection(Edm.String)" Nullable="false" /> + <ReturnType Type="Collection(Edm.String)" Nullable="false" /> + </Action> + <Action Name="ResetBossAddress"> + <Parameter Name="address" Type="Microsoft.Test.OData.Services.ODataWCFService.Address" Nullable="false" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.Address" Nullable="false" /> + </Action> + <Function Name="GetEmployeesCount" IsBound="true"> + <Parameter Name="p" Type="Microsoft.Test.OData.Services.ODataWCFService.Company" Nullable="false" /> + <ReturnType Type="Edm.Int32" Nullable="false" /> + </Function> + <Function Name="GetProductDetails" IsBound="true" EntitySetPath="product/Details" IsComposable="true"> + <Parameter Name="product" Type="Microsoft.Test.OData.Services.ODataWCFService.Product" Nullable="false" /> + <Parameter Name="count" Type="Edm.Int32" /> + <ReturnType Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.ProductDetail)" Nullable="false" /> + </Function> + <Function Name="GetRelatedProduct" IsBound="true" EntitySetPath="productDetail/Products" IsComposable="true"> + <Parameter Name="productDetail" Type="Microsoft.Test.OData.Services.ODataWCFService.ProductDetail" Nullable="false" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.Product" Nullable="false" /> + </Function> + <Function Name="GetDefaultColor" IsComposable="true"> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.Color" /> + </Function> + <Function Name="GetPerson" IsComposable="true"> + <Parameter Name="address" Type="Microsoft.Test.OData.Services.ODataWCFService.Address" Nullable="false" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.Person" Nullable="false" /> + </Function> + <Function Name="GetPerson2" IsComposable="true"> + <Parameter Name="city" Type="Edm.String" Nullable="false" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.Person" Nullable="false" /> + </Function> + <Function Name="GetAllProducts" IsComposable="true"> + <ReturnType Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Product)" Nullable="false" /> + </Function> + <Function Name="GetBossEmails"> + <Parameter Name="start" Type="Edm.Int32" Nullable="false" /> + <Parameter Name="count" Type="Edm.Int32" Nullable="false" /> + <ReturnType Type="Collection(Edm.String)" Nullable="false" /> + </Function> + <Function Name="GetProductsByAccessLevel"> + <Parameter Name="accessLevel" Type="Microsoft.Test.OData.Services.ODataWCFService.AccessLevel" /> + <ReturnType Type="Collection(Edm.String)" Nullable="false" /> + </Function> + <Function Name="GetActualAmount" IsBound="true"> + <Parameter Name="giftcard" Type="Microsoft.Test.OData.Services.ODataWCFService.GiftCard" Nullable="false" /> + <Parameter Name="bonusRate" Type="Edm.Double" /> + <ReturnType Type="Edm.Double" Nullable="false" /> + </Function> + <Function Name="GetDefaultPI" IsBound="true" EntitySetPath="account/MyPaymentInstruments"> + <Parameter Name="account" Type="Microsoft.Test.OData.Services.ODataWCFService.Account" Nullable="false" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument" /> + </Function> + <Action Name="RefreshDefaultPI" IsBound="true" EntitySetPath="account/MyPaymentInstruments"> + <Parameter Name="account" Type="Microsoft.Test.OData.Services.ODataWCFService.Account" Nullable="false" /> + <Parameter Name="newDate" Type="Edm.DateTimeOffset" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument" /> + </Action> + <Function Name="GetHomeAddress" IsBound="true" IsComposable="true"> + <Parameter Name="person" Type="Microsoft.Test.OData.Services.ODataWCFService.Person" Nullable="false" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.HomeAddress" Nullable="false" /> + </Function> + <Function Name="GetAccountInfo" IsBound="true" IsComposable="true"> + <Parameter Name="account" Type="Microsoft.Test.OData.Services.ODataWCFService.Account" Nullable="false" /> + <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.AccountInfo" Nullable="false" /> + </Function> + <ComplexType Name="AccountInfo" OpenType="true"> + <Property Name="FirstName" Type="Edm.String" Nullable="false" /> + <Property Name="LastName" Type="Edm.String" Nullable="false" /> + </ComplexType> + <EntityType Name="Account"> + <Key> + <PropertyRef Name="AccountID" /> + </Key> + <Property Name="AccountID" Type="Edm.Int32" Nullable="false" /> + <Property Name="Country" Type="Edm.String" Nullable="false" /> + <Property Name="AccountInfo" Type="Microsoft.Test.OData.Services.ODataWCFService.AccountInfo" /> + <NavigationProperty Name="MyGiftCard" Type="Microsoft.Test.OData.Services.ODataWCFService.GiftCard" ContainsTarget="true" /> + <NavigationProperty Name="MyPaymentInstruments" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument)" ContainsTarget="true" /> + <NavigationProperty Name="ActiveSubscriptions" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Subscription)" ContainsTarget="true" /> + <NavigationProperty Name="AvailableSubscriptionTemplatess" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Subscription)" /> + </EntityType> + <EntityType Name="GiftCard"> + <Key> + <PropertyRef Name="GiftCardID" /> + </Key> + <Property Name="GiftCardID" Type="Edm.Int32" Nullable="false" /> + <Property Name="GiftCardNO" Type="Edm.String" Nullable="false" /> + <Property Name="Amount" Type="Edm.Double" Nullable="false" /> + <Property Name="ExperationDate" Type="Edm.DateTimeOffset" Nullable="false" /> + </EntityType> + <EntityType Name="PaymentInstrument"> + <Key> + <PropertyRef Name="PaymentInstrumentID" /> + </Key> + <Property Name="PaymentInstrumentID" Type="Edm.Int32" Nullable="false" /> + <Property Name="FriendlyName" Type="Edm.String" Nullable="false" /> + <Property Name="CreatedDate" Type="Edm.DateTimeOffset" Nullable="false" /> + <NavigationProperty Name="TheStoredPI" Type="Microsoft.Test.OData.Services.ODataWCFService.StoredPI" Nullable="false" /> + <NavigationProperty Name="BillingStatements" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Statement)" ContainsTarget="true" /> + <NavigationProperty Name="BackupStoredPI" Type="Microsoft.Test.OData.Services.ODataWCFService.StoredPI" Nullable="false" /> + </EntityType> + <EntityType Name="CreditCardPI" BaseType="Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument"> + <Property Name="CardNumber" Type="Edm.String" Nullable="false" /> + <Property Name="CVV" Type="Edm.String" Nullable="false" /> + <Property Name="HolderName" Type="Edm.String" Nullable="false" /> + <Property Name="Balance" Type="Edm.Double" Nullable="false" /> + <Property Name="ExperationDate" Type="Edm.DateTimeOffset" Nullable="false" /> + <NavigationProperty Name="CreditRecords" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.CreditRecord)" ContainsTarget="true" /> + </EntityType> + <EntityType Name="StoredPI"> + <Key> + <PropertyRef Name="StoredPIID" /> + </Key> + <Property Name="StoredPIID" Type="Edm.Int32" Nullable="false" /> + <Property Name="PIName" Type="Edm.String" Nullable="false" /> + <Property Name="PIType" Type="Edm.String" Nullable="false" /> + <Property Name="CreatedDate" Type="Edm.DateTimeOffset" Nullable="false" /> + </EntityType> + <EntityType Name="Statement"> + <Key> + <PropertyRef Name="StatementID" /> + </Key> + <Property Name="StatementID" Type="Edm.Int32" Nullable="false" /> + <Property Name="TransactionType" Type="Edm.String" Nullable="false" /> + <Property Name="TransactionDescription" Type="Edm.String" Nullable="false" /> + <Property Name="Amount" Type="Edm.Double" Nullable="false" /> + </EntityType> + <EntityType Name="CreditRecord"> + <Key> + <PropertyRef Name="CreditRecordID" /> + </Key> + <Property Name="CreditRecordID" Type="Edm.Int32" Nullable="false" /> + <Property Name="IsGood" Type="Edm.Boolean" Nullable="false" /> + <Property Name="Reason" Type="Edm.String" Nullable="false" /> + <Property Name="CreatedDate" Type="Edm.DateTimeOffset" Nullable="false" /> + </EntityType> + <EntityType Name="Subscription"> + <Key> + <PropertyRef Name="SubscriptionID" /> + </Key> + <Property Name="SubscriptionID" Type="Edm.Int32" Nullable="false" /> + <Property Name="TemplateGuid" Type="Edm.String" Nullable="false" /> + <Property Name="Title" Type="Edm.String" Nullable="false" /> + <Property Name="Category" Type="Edm.String" Nullable="false" /> + <Property Name="CreatedDate" Type="Edm.DateTimeOffset" Nullable="false" /> + </EntityType> + <EntityContainer Name="InMemoryEntities"> + <EntitySet Name="People" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Person"> + <NavigationPropertyBinding Path="Parent" Target="People" /> </EntitySet> - <EntitySet Name="CustomerDemographics" EntityType="NorthwindModel.CustomerDemographic"> - <NavigationPropertyBinding Path="Customers" Target="Customers" /> - </EntitySet> - <EntitySet Name="Customers" EntityType="NorthwindModel.Customer"> - <NavigationPropertyBinding Path="CustomerDemographics" Target="CustomerDemographics" /> + <Singleton Name="Boss" Type="Microsoft.Test.OData.Services.ODataWCFService.Person" /> + <EntitySet Name="Customers" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Customer"> <NavigationPropertyBinding Path="Orders" Target="Orders" /> </EntitySet> - <EntitySet Name="Employees" EntityType="NorthwindModel.Employee"> - <NavigationPropertyBinding Path="Employees1" Target="Employees" /> - <NavigationPropertyBinding Path="Employee1" Target="Employees" /> + <Singleton Name="VipCustomer" Type="Microsoft.Test.OData.Services.ODataWCFService.Customer"> <NavigationPropertyBinding Path="Orders" Target="Orders" /> - <NavigationPropertyBinding Path="Territories" Target="Territories" /> - </EntitySet> - <EntitySet Name="Order_Details" EntityType="NorthwindModel.Order_Detail"> - <NavigationPropertyBinding Path="Order" Target="Orders" /> - <NavigationPropertyBinding Path="Product" Target="Products" /> - </EntitySet> - <EntitySet Name="Orders" EntityType="NorthwindModel.Order"> - <NavigationPropertyBinding Path="Customer" Target="Customers" /> - <NavigationPropertyBinding Path="Employee" Target="Employees" /> - <NavigationPropertyBinding Path="Order_Details" Target="Order_Details" /> - <NavigationPropertyBinding Path="Shipper" Target="Shippers" /> - </EntitySet> - <EntitySet Name="Products" EntityType="NorthwindModel.Product"> - <NavigationPropertyBinding Path="Category" Target="Categories" /> - <NavigationPropertyBinding Path="Order_Details" Target="Order_Details" /> - <NavigationPropertyBinding Path="Supplier" Target="Suppliers" /> - </EntitySet> - <EntitySet Name="Regions" EntityType="NorthwindModel.Region"> - <NavigationPropertyBinding Path="Territories" Target="Territories" /> - </EntitySet> - <EntitySet Name="Shippers" EntityType="NorthwindModel.Shipper"> - <NavigationPropertyBinding Path="Orders" Target="Orders" /> - </EntitySet> - <EntitySet Name="Suppliers" EntityType="NorthwindModel.Supplier"> - <NavigationPropertyBinding Path="Products" Target="Products" /> - </EntitySet> - <EntitySet Name="Territories" EntityType="NorthwindModel.Territory"> - <NavigationPropertyBinding Path="Employees" Target="Employees" /> - <NavigationPropertyBinding Path="Region" Target="Regions" /> - </EntitySet> - <EntitySet Name="Alphabetical_list_of_products" EntityType="NorthwindModel.Alphabetical_list_of_product" /> - <EntitySet Name="Category_Sales_for_1997" EntityType="NorthwindModel.Category_Sales_for_1997" /> - <EntitySet Name="Current_Product_Lists" EntityType="NorthwindModel.Current_Product_List" /> - <EntitySet Name="Customer_and_Suppliers_by_Cities" EntityType="NorthwindModel.Customer_and_Suppliers_by_City" /> - <EntitySet Name="Invoices" EntityType="NorthwindModel.Invoice" /> - <EntitySet Name="Order_Details_Extendeds" EntityType="NorthwindModel.Order_Details_Extended" /> - <EntitySet Name="Order_Subtotals" EntityType="NorthwindModel.Order_Subtotal" /> - <EntitySet Name="Orders_Qries" EntityType="NorthwindModel.Orders_Qry" /> - <EntitySet Name="Product_Sales_for_1997" EntityType="NorthwindModel.Product_Sales_for_1997" /> - <EntitySet Name="Products_Above_Average_Prices" EntityType="NorthwindModel.Products_Above_Average_Price" /> - <EntitySet Name="Products_by_Categories" EntityType="NorthwindModel.Products_by_Category" /> - <EntitySet Name="Sales_by_Categories" EntityType="NorthwindModel.Sales_by_Category" /> - <EntitySet Name="Sales_Totals_by_Amounts" EntityType="NorthwindModel.Sales_Totals_by_Amount" /> - <EntitySet Name="Summary_of_Sales_by_Quarters" EntityType="NorthwindModel.Summary_of_Sales_by_Quarter" /> - <EntitySet Name="Summary_of_Sales_by_Years" EntityType="NorthwindModel.Summary_of_Sales_by_Year" /> - <!-- Singleton --> - <Singleton Name="Contoso" Type="NorthwindModel.Supplier"> - <NavigationPropertyBinding Path="Products" Target="Products"/> + <NavigationPropertyBinding Path="Company" Target="Company" /> </Singleton> - <!-- FunctionImport --> - <FunctionImport Name="TopSellingProducts" EntitySet="Products" Function="NorthwindModel.TopSellingProducts"/> + <EntitySet Name="Employees" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Employee"> + <NavigationPropertyBinding Path="Company" Target="Company" /> + </EntitySet> + <EntitySet Name="Products" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Product"> + <NavigationPropertyBinding Path="Details" Target="ProductDetails" /> + </EntitySet> + <EntitySet Name="ProductDetails" EntityType="Microsoft.Test.OData.Services.ODataWCFService.ProductDetail"> + <NavigationPropertyBinding Path="RelatedProduct" Target="Products" /> + <NavigationPropertyBinding Path="Reviews" Target="ProductReviews" /> + </EntitySet> + <EntitySet Name="ProductReviews" EntityType="Microsoft.Test.OData.Services.ODataWCFService.ProductReview" /> + <EntitySet Name="Orders" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Order"> + <NavigationPropertyBinding Path="LoggedInEmployee" Target="Employees" /> + <NavigationPropertyBinding Path="CustomerForOrder" Target="Customers" /> + <NavigationPropertyBinding Path="OrderDetails" Target="OrderDetails" /> + </EntitySet> + <EntitySet Name="OrderDetails" EntityType="Microsoft.Test.OData.Services.ODataWCFService.OrderDetail"> + <NavigationPropertyBinding Path="AssociatedOrder" Target="Orders" /> + <NavigationPropertyBinding Path="ProductOrdered" Target="Products" /> + </EntitySet> + <EntitySet Name="Departments" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Department"> + <NavigationPropertyBinding Path="Company" Target="Company" /> + </EntitySet> + <Singleton Name="Company" Type="Microsoft.Test.OData.Services.ODataWCFService.Company"> + <NavigationPropertyBinding Path="Employees" Target="Employees" /> + <NavigationPropertyBinding Path="VipCustomer" Target="VipCustomer" /> + <NavigationPropertyBinding Path="Departments" Target="Departments" /> + <NavigationPropertyBinding Path="CoreDepartment" Target="Departments" /> + </Singleton> + <Singleton Name="PublicCompany" Type="Microsoft.Test.OData.Services.ODataWCFService.Company"> + <NavigationPropertyBinding Path="Microsoft.Test.OData.Services.ODataWCFService.PublicCompany/LabourUnion" Target="LabourUnion" /> + </Singleton> + <Singleton Name="LabourUnion" Type="Microsoft.Test.OData.Services.ODataWCFService.LabourUnion" /> + <ActionImport Name="Discount" Action="Microsoft.Test.OData.Services.ODataWCFService.Discount" /> + <ActionImport Name="ResetBossEmail" Action="Microsoft.Test.OData.Services.ODataWCFService.ResetBossEmail" /> + <ActionImport Name="ResetBossAddress" Action="Microsoft.Test.OData.Services.ODataWCFService.ResetBossAddress" /> + <FunctionImport Name="GetDefaultColor" Function="Microsoft.Test.OData.Services.ODataWCFService.GetDefaultColor" /> + <FunctionImport Name="GetPerson" Function="Microsoft.Test.OData.Services.ODataWCFService.GetPerson" EntitySet="People" /> + <FunctionImport Name="GetPerson2" Function="Microsoft.Test.OData.Services.ODataWCFService.GetPerson2" EntitySet="People" /> + <FunctionImport Name="GetAllProducts" Function="Microsoft.Test.OData.Services.ODataWCFService.GetAllProducts" EntitySet="Products" /> + <FunctionImport Name="GetBossEmails" Function="Microsoft.Test.OData.Services.ODataWCFService.GetBossEmails" /> + <FunctionImport Name="GetProductsByAccessLevel" Function="Microsoft.Test.OData.Services.ODataWCFService.GetProductsByAccessLevel" /> + <EntitySet Name="Accounts" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Account"> + <NavigationPropertyBinding Path="Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument/TheStoredPI" Target="StoredPIs" /> + <NavigationPropertyBinding Path="AvailableSubscriptionTemplatess" Target="SubscriptionTemplates" /> + <NavigationPropertyBinding Path="Microsoft.Test.OData.Services.ODataWCFService.PaymentInstrument/BackupStoredPI" Target="DefaultStoredPI" /> + </EntitySet> + <EntitySet Name="StoredPIs" EntityType="Microsoft.Test.OData.Services.ODataWCFService.StoredPI" /> + <EntitySet Name="SubscriptionTemplates" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Subscription" /> + <Singleton Name="DefaultStoredPI" Type="Microsoft.Test.OData.Services.ODataWCFService.StoredPI" /> </EntityContainer> </Schema> </edmx:DataServices> </edmx:Edmx> + diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/ODataBasicRequest.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/ODataBasicRequest.java index f64b23362..7ba38f8a1 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/ODataBasicRequest.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/ODataBasicRequest.java @@ -20,6 +20,7 @@ package org.apache.olingo.client.api.communication.request; import java.util.concurrent.Future; import org.apache.olingo.client.api.communication.response.ODataResponse; +import org.apache.olingo.client.api.format.Format; /** * Basic OData request. @@ -27,7 +28,7 @@ import org.apache.olingo.client.api.communication.response.ODataResponse; * @param <V> OData response type corresponding to the request implementation. * @param <T> Accepted content-type formats by the request in object. */ -public interface ODataBasicRequest<V extends ODataResponse, T extends Enum<T>> extends ODataRequest { +public interface ODataBasicRequest<V extends ODataResponse, T extends Format> extends ODataRequest { /** * Request execute. diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/retrieve/ODataRetrieveRequest.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/retrieve/ODataRetrieveRequest.java index edabb96af..14f907efa 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/retrieve/ODataRetrieveRequest.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/communication/request/retrieve/ODataRetrieveRequest.java @@ -20,9 +20,10 @@ package org.apache.olingo.client.api.communication.request.retrieve; import org.apache.olingo.client.api.communication.request.ODataBasicRequest; import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; +import org.apache.olingo.client.api.format.Format; /** * This is an abstract representation of an OData retrieve query request returning one or more result item. */ -public interface ODataRetrieveRequest<V, T extends Enum<T>> extends ODataBasicRequest<ODataRetrieveResponse<V>, T> { +public interface ODataRetrieveRequest<V, T extends Format> extends ODataBasicRequest<ODataRetrieveResponse<V>, T> { } diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ODataLinkType.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ODataLinkType.java index 6702c006e..179f9cc93 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ODataLinkType.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/domain/ODataLinkType.java @@ -20,7 +20,6 @@ package org.apache.olingo.client.api.domain; import org.apache.commons.lang3.StringUtils; import org.apache.http.entity.ContentType; -import org.apache.olingo.client.api.format.ODataPubFormat; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; /** @@ -31,11 +30,11 @@ public enum ODataLinkType { /** * Entity navigation link. */ - ENTITY_NAVIGATION(ODataPubFormat.ATOM + ";type=entry"), + ENTITY_NAVIGATION(ContentType.APPLICATION_ATOM_XML.getMimeType() + ";type=entry"), /** * Entity set navigation link. */ - ENTITY_SET_NAVIGATION(ODataPubFormat.ATOM + ";type=feed"), + ENTITY_SET_NAVIGATION(ContentType.APPLICATION_ATOM_XML.getMimeType() + ";type=feed"), /** * Association link. */ @@ -57,7 +56,8 @@ public enum ODataLinkType { } /** - * Gets <code>LinkType</code> instance from the given rel and type. + * Gets + * <code>LinkType</code> instance from the given rel and type. * * @param client OData client. * @param rel rel. diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/format/Format.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/Format.java new file mode 100644 index 000000000..1d5266441 --- /dev/null +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/Format.java @@ -0,0 +1,26 @@ +/* + * 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.client.api.format; + +import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; + +public interface Format { + + String toString(ODataServiceVersion version); +} diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataFormat.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataFormat.java index 2ee704b33..8f52ea35a 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataFormat.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataFormat.java @@ -19,11 +19,12 @@ package org.apache.olingo.client.api.format; import org.apache.http.entity.ContentType; +import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; /** * Available formats to be used in various contexts. */ -public enum ODataFormat { +public enum ODataFormat implements Format{ /** * JSON format with no metadata. @@ -94,4 +95,9 @@ public enum ODataFormat { return result; } + + @Override + public String toString(final ODataServiceVersion version) { + return this.toString(); + } } diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataMediaFormat.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataMediaFormat.java index 353edc440..5d49ddbef 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataMediaFormat.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataMediaFormat.java @@ -19,11 +19,12 @@ package org.apache.olingo.client.api.format; import org.apache.http.entity.ContentType; +import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; /** * Available formats for media. */ -public enum ODataMediaFormat { +public enum ODataMediaFormat implements Format{ CHARSET_PARAMETER("charset"), MEDIA_TYPE_WILDCARD("*"), @@ -68,4 +69,9 @@ public enum ODataMediaFormat { return result; } + + @Override + public String toString(final ODataServiceVersion version) { + return this.toString(); + } } diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataPubFormat.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataPubFormat.java index 62e5322cd..aea294fe5 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataPubFormat.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataPubFormat.java @@ -18,34 +18,49 @@ */ package org.apache.olingo.client.api.format; +import java.util.EnumMap; import org.apache.http.entity.ContentType; +import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; /** * Available formats for AtomPub exchange. */ -public enum ODataPubFormat { +public enum ODataPubFormat implements Format { /** * JSON format with no metadata. */ - JSON_NO_METADATA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=nometadata"), + JSON_NO_METADATA(), /** * JSON format with minimal metadata (default). */ - JSON(ContentType.APPLICATION_JSON.getMimeType() + ";odata=minimalmetadata"), + JSON(), /** * JSON format with no metadata. */ - JSON_FULL_METADATA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=fullmetadata"), + JSON_FULL_METADATA(), /** * Atom format. */ - ATOM(ContentType.APPLICATION_ATOM_XML.getMimeType()); + ATOM(); - private final String format; + final static EnumMap<ODataServiceVersion, EnumMap<ODataPubFormat, String>> formatPerVersion = + new EnumMap<ODataServiceVersion, EnumMap<ODataPubFormat, String>>(ODataServiceVersion.class); - ODataPubFormat(final String format) { - this.format = format; + static { + final EnumMap<ODataPubFormat, String> v3 = new EnumMap<ODataPubFormat, String>(ODataPubFormat.class); + v3.put(JSON_NO_METADATA, ContentType.APPLICATION_JSON.getMimeType() + ";odata=nometadata"); + v3.put(JSON, ContentType.APPLICATION_JSON.getMimeType() + ";odata=minimalmetadata"); + v3.put(JSON_FULL_METADATA, ContentType.APPLICATION_JSON.getMimeType() + ";odata=fullmetadata"); + v3.put(ATOM, ContentType.APPLICATION_ATOM_XML.getMimeType()); + formatPerVersion.put(ODataServiceVersion.V30, v3); + + final EnumMap<ODataPubFormat, String> v4 = new EnumMap<ODataPubFormat, String>(ODataPubFormat.class); + v4.put(JSON_NO_METADATA, ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=none"); + v4.put(JSON, ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=minimal"); + v4.put(JSON_FULL_METADATA, ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=full"); + v4.put(ATOM, ContentType.APPLICATION_ATOM_XML.getMimeType()); + formatPerVersion.put(ODataServiceVersion.V40, v4); } /** @@ -53,9 +68,18 @@ public enum ODataPubFormat { * * @return format as a string. */ + @Override + public String toString(final ODataServiceVersion version) { + if (version.ordinal() < ODataServiceVersion.V30.ordinal()) { + throw new IllegalArgumentException("Unsupported version " + version); + } + + return ODataPubFormat.formatPerVersion.get(version).get(this); + } + @Override public String toString() { - return format; + throw new UnsupportedOperationException(); } /** @@ -72,7 +96,7 @@ public enum ODataPubFormat { final String[] parts = format.split(";"); _format.append(parts[0].trim()); if (ContentType.APPLICATION_JSON.getMimeType().equals(parts[0].trim())) { - if (parts.length > 1 && parts[1].startsWith("odata=")) { + if (parts.length > 1 && parts[1].startsWith("odata")) { _format.append(';').append(parts[1].trim()); } else { result = ODataPubFormat.JSON; @@ -82,7 +106,8 @@ public enum ODataPubFormat { if (result == null) { final String candidate = _format.toString(); for (ODataPubFormat value : values()) { - if (candidate.equals(value.toString())) { + if (candidate.equals(value.toString(ODataServiceVersion.V30)) + || candidate.equals(value.toString(ODataServiceVersion.V40))) { result = value; } } diff --git a/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataValueFormat.java b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataValueFormat.java index b04ce7d4b..818b1048f 100644 --- a/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataValueFormat.java +++ b/lib/client-api/src/main/java/org/apache/olingo/client/api/format/ODataValueFormat.java @@ -19,11 +19,12 @@ package org.apache.olingo.client.api.format; import org.apache.http.entity.ContentType; +import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; /** * Available formats for property values. */ -public enum ODataValueFormat { +public enum ODataValueFormat implements Format{ /** * Application octet stream. @@ -73,4 +74,9 @@ public enum ODataValueFormat { return result; } + + @Override + public String toString(final ODataServiceVersion version) { + return this.toString(); + } } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AbstractODataBasicRequest.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AbstractODataBasicRequest.java index 307cdc908..8cd5819ee 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AbstractODataBasicRequest.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/AbstractODataBasicRequest.java @@ -31,6 +31,7 @@ import org.apache.olingo.client.api.communication.request.ODataBasicRequest; import org.apache.olingo.client.api.communication.request.ODataStreamer; import org.apache.olingo.client.api.communication.request.batch.ODataBatchRequest; import org.apache.olingo.client.api.communication.response.ODataResponse; +import org.apache.olingo.client.api.format.Format; import org.apache.olingo.client.api.http.HttpMethod; /** @@ -39,88 +40,87 @@ import org.apache.olingo.client.api.http.HttpMethod; * @param <V> OData response type corresponding to the request implementation. * @param <T> OData format being used. */ -public abstract class AbstractODataBasicRequest<V extends ODataResponse, T extends Enum<T>> +public abstract class AbstractODataBasicRequest<V extends ODataResponse, T extends Format> extends ODataRequestImpl<T> implements ODataBasicRequest<V, T> { - /** - * Constructor. - * - * @param odataClient client instance getting this request - * @param formatRef reference class for the format being used - * @param method request method. - * @param uri OData request URI. - */ - public AbstractODataBasicRequest(final CommonODataClient odataClient, - final Class<T> formatRef, final HttpMethod method, final URI uri) { + /** + * Constructor. + * + * @param odataClient client instance getting this request + * @param formatRef reference class for the format being used + * @param method request method. + * @param uri OData request URI. + */ + public AbstractODataBasicRequest(final CommonODataClient odataClient, + final Class<T> formatRef, final HttpMethod method, final URI uri) { - super(odataClient, formatRef, method, uri); + super(odataClient, formatRef, method, uri); + } + + /** + * {@inheritDoc} + */ + @Override + public void setFormat(final T format) { + if (format != null) { + setAccept(format.toString(odataClient.getServiceVersion())); + setContentType(format.toString(odataClient.getServiceVersion())); } + } - /** - * {@inheritDoc} - */ - @Override - public void setFormat(final T format) { - if (format != null) { - setAccept(format.toString()); - setContentType(format.toString()); - } - } - - /** - * {@inheritDoc} - */ - @Override - public final Future<V> asyncExecute() { - return odataClient.getConfiguration().getExecutor().submit(new Callable<V>() { - - @Override - public V call() throws Exception { - return execute(); - } - }); - } - - /** - * Gets payload as an InputStream. - * - * @return InputStream for entire payload. - */ - protected abstract InputStream getPayload(); - - /** - * Serializes the full request into the given batch request. - * - * @param req destination batch request. - */ - public void batch(final ODataBatchRequest req) { - batch(req, null); - } - - /** - * Serializes the full request into the given batch request. - * <p> - * This method have to be used to serialize a changeset item with the specified contentId. - * - * @param req destination batch request. - * @param contentId contentId of the changeset item. - */ - public void batch(final ODataBatchRequest req, final String contentId) { - try { - req.rawAppend(toByteArray()); - if (StringUtils.isNotBlank(contentId)) { - req.rawAppend((ODataBatchConstants.CHANGESET_CONTENT_ID_NAME + ": " + contentId).getBytes()); - req.rawAppend(ODataStreamer.CRLF); - } - req.rawAppend(ODataStreamer.CRLF); - - final InputStream payload = getPayload(); - if (payload != null) { - req.rawAppend(IOUtils.toByteArray(getPayload())); - } - } catch (IOException e) { - throw new IllegalStateException(e); - } + /** + * {@inheritDoc} + */ + @Override + public final Future<V> asyncExecute() { + return odataClient.getConfiguration().getExecutor().submit(new Callable<V>() { + @Override + public V call() throws Exception { + return execute(); + } + }); + } + + /** + * Gets payload as an InputStream. + * + * @return InputStream for entire payload. + */ + protected abstract InputStream getPayload(); + + /** + * Serializes the full request into the given batch request. + * + * @param req destination batch request. + */ + public void batch(final ODataBatchRequest req) { + batch(req, null); + } + + /** + * Serializes the full request into the given batch request. + * <p> + * This method have to be used to serialize a changeset item with the specified contentId. + * + * @param req destination batch request. + * @param contentId contentId of the changeset item. + */ + public void batch(final ODataBatchRequest req, final String contentId) { + try { + req.rawAppend(toByteArray()); + if (StringUtils.isNotBlank(contentId)) { + req.rawAppend((ODataBatchConstants.CHANGESET_CONTENT_ID_NAME + ": " + contentId).getBytes()); + req.rawAppend(ODataStreamer.CRLF); + } + req.rawAppend(ODataStreamer.CRLF); + + final InputStream payload = getPayload(); + if (payload != null) { + req.rawAppend(IOUtils.toByteArray(getPayload())); + } + } catch (IOException e) { + throw new IllegalStateException(e); } + } } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/ODataRequestImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/ODataRequestImpl.java index d088e97ef..2e60a7d49 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/ODataRequestImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/ODataRequestImpl.java @@ -42,6 +42,10 @@ import org.apache.olingo.client.api.communication.header.ODataHeaderValues; import org.apache.olingo.client.api.communication.header.ODataHeaders; import org.apache.olingo.client.api.communication.request.ODataRequest; import org.apache.olingo.client.api.communication.request.ODataStreamer; +import org.apache.olingo.client.api.communication.request.batch.v3.BatchRequestFactory; +import org.apache.olingo.client.api.communication.request.cud.v3.CUDRequestFactory; +import org.apache.olingo.client.api.communication.request.invoke.v3.InvokeRequestFactory; +import org.apache.olingo.client.api.communication.request.streamed.v3.StreamedRequestFactory; import org.apache.olingo.client.api.communication.response.ODataResponse; import org.apache.olingo.client.api.format.ODataMediaFormat; import org.apache.olingo.client.api.format.ODataPubFormat; @@ -51,6 +55,7 @@ import org.apache.olingo.client.api.http.HttpMethod; import org.apache.olingo.client.core.data.JSONErrorImpl; import org.apache.olingo.client.core.data.XMLErrorImpl; import org.apache.olingo.client.api.data.ODataError; +import org.apache.olingo.client.api.format.Format; import org.apache.olingo.client.core.communication.header.ODataHeadersImpl; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; import org.slf4j.Logger; @@ -66,7 +71,7 @@ import org.slf4j.LoggerFactory; * @see InvokeRequestFactory * @see StreamedRequestFactory */ -public class ODataRequestImpl<T extends Enum<T>> implements ODataRequest { +public class ODataRequestImpl<T extends Format> implements ODataRequest { /** * Logger. @@ -251,7 +256,7 @@ public class ODataRequestImpl<T extends Enum<T>> implements ODataRequest { @Override public String getAccept() { final String acceptHead = odataHeaders.getHeader(HeaderName.accept); - return StringUtils.isBlank(acceptHead) ? getDefaultFormat().toString() : acceptHead; + return StringUtils.isBlank(acceptHead) ? getDefaultFormat().toString(odataClient.getServiceVersion()) : acceptHead; } /** @@ -284,7 +289,8 @@ public class ODataRequestImpl<T extends Enum<T>> implements ODataRequest { @Override public String getContentType() { final String contentTypeHead = odataHeaders.getHeader(HeaderName.contentType); - return StringUtils.isBlank(contentTypeHead) ? getDefaultFormat().toString() : contentTypeHead; + return StringUtils.isBlank(contentTypeHead) + ? getDefaultFormat().toString(odataClient.getServiceVersion()) : contentTypeHead; } /** diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/invoke/ODataInvokeRequestImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/invoke/ODataInvokeRequestImpl.java index c6355e4b3..abef76c75 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/invoke/ODataInvokeRequestImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/invoke/ODataInvokeRequestImpl.java @@ -100,7 +100,7 @@ public class ODataInvokeRequestImpl<T extends ODataInvokeResult> public void setFormat(final ODataPubFormat format) { final String _format = (reference.isAssignableFrom(ODataProperty.class) && format == ODataPubFormat.ATOM) ? ODataFormat.XML.toString() - : format.toString(); + : format.toString(odataClient.getServiceVersion()); setAccept(_format); setContentType(_format); } @@ -163,7 +163,7 @@ public class ODataInvokeRequestImpl<T extends ODataInvokeResult> } else if (this.method == HttpMethod.POST) { ((HttpPost) request).setEntity(URIUtils.buildInputStreamEntity(odataClient, input)); - setContentType(ODataPubFormat.JSON.toString()); + setContentType(ODataPubFormat.JSON.toString(odataClient.getServiceVersion())); } } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/AbstractODataRetrieveRequest.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/AbstractODataRetrieveRequest.java index fe5172226..628e8360b 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/AbstractODataRetrieveRequest.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/AbstractODataRetrieveRequest.java @@ -26,6 +26,7 @@ import org.apache.olingo.client.api.CommonODataClient; import org.apache.olingo.client.api.communication.request.ODataBatchableRequest; import org.apache.olingo.client.api.communication.request.retrieve.ODataRetrieveRequest; import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; +import org.apache.olingo.client.api.format.Format; import org.apache.olingo.client.api.http.HttpMethod; import org.apache.olingo.client.core.communication.request.AbstractODataBasicRequest; import org.apache.olingo.client.core.communication.response.AbstractODataResponse; @@ -33,7 +34,7 @@ import org.apache.olingo.client.core.communication.response.AbstractODataRespons /** * This is an abstract representation of an OData retrieve query request returning one or more result item. */ -public abstract class AbstractODataRetrieveRequest<V, T extends Enum<T>> +public abstract class AbstractODataRetrieveRequest<V, T extends Format> extends AbstractODataBasicRequest<ODataRetrieveResponse<V>, T> implements ODataRetrieveRequest<V, T>, ODataBatchableRequest { diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/ODataRawRequestImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/ODataRawRequestImpl.java index 4226cc208..777d86a24 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/ODataRawRequestImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/retrieve/ODataRawRequestImpl.java @@ -92,7 +92,7 @@ public class ODataRawRequestImpl extends ODataRequestImpl<ODataPubFormat> this.close(); } } - + return odataClient.getReader().read(new ByteArrayInputStream(obj), getContentType(), reference); } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/streamed/AbstractODataStreamedEntityRequest.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/streamed/AbstractODataStreamedEntityRequest.java index d19d0d5ef..c7f7c52fb 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/streamed/AbstractODataStreamedEntityRequest.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/communication/request/streamed/AbstractODataStreamedEntityRequest.java @@ -48,7 +48,7 @@ public abstract class AbstractODataStreamedEntityRequest<V extends ODataResponse public AbstractODataStreamedEntityRequest(final CommonODataClient odataClient, final HttpMethod method, URI uri) { super(odataClient, method, uri); - setAccept(getFormat().toString()); + setAccept(getFormat().toString(odataClient.getServiceVersion())); } /** @@ -65,6 +65,6 @@ public abstract class AbstractODataStreamedEntityRequest<V extends ODataResponse @Override public final void setFormat(final ODataPubFormat format) { this.format = format; - setAccept(format.toString()); + setAccept(format.toString(odataClient.getServiceVersion())); } } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AbstractJsonDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AbstractJsonDeserializer.java index 74b29fbce..3aca585f8 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AbstractJsonDeserializer.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AbstractJsonDeserializer.java @@ -57,7 +57,7 @@ abstract class AbstractJsonDeserializer<T> extends ODataJacksonDeserializer<T> { } private ODataPropertyType guessPropertyType(final JsonNode node) { - ODataPropertyType type = null; + final ODataPropertyType type; if (node.isValueNode() || node.isNull()) { type = ODataPropertyType.PRIMITIVE; @@ -73,7 +73,7 @@ abstract class AbstractJsonDeserializer<T> extends ODataJacksonDeserializer<T> { } private Value fromPrimitive(final JsonNode node, final EdmTypeInfo typeInfo) { - Value value = null; + final Value value; if (node.isNull()) { value = new NullValueImpl(); @@ -172,5 +172,4 @@ abstract class AbstractJsonDeserializer<T> extends ODataJacksonDeserializer<T> { property.setValue(new PrimitiveValueImpl(StringUtils.EMPTY)); } } - } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AtomDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AtomDeserializer.java index 8893b9171..835d17420 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AtomDeserializer.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AtomDeserializer.java @@ -153,7 +153,6 @@ public class AtomDeserializer extends AbstractAtomDealer { private void properties(final XMLEventReader reader, final StartElement start, final AtomEntryImpl entry) throws XMLStreamException { - boolean foundEndProperties = false; while (reader.hasNext() && !foundEndProperties) { final XMLEvent event = reader.nextEvent(); @@ -316,7 +315,6 @@ public class AtomDeserializer extends AbstractAtomDealer { boolean foundEndFeed = false; while (reader.hasNext() && !foundEndFeed) { final XMLEvent event = reader.nextEvent(); - if (event.isStartElement()) { if (countQName.equals(event.asStartElement().getName())) { count(reader, event.asStartElement(), feed); diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AtomPropertyDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AtomPropertyDeserializer.java index 884d81583..42d250439 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AtomPropertyDeserializer.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/data/AtomPropertyDeserializer.java @@ -139,7 +139,7 @@ class AtomPropertyDeserializer extends AbstractAtomDealer { } } - ODataPropertyType type = null; + final ODataPropertyType type; if (child == null) { type = ODataPropertyType.PRIMITIVE; } else { @@ -168,16 +168,19 @@ class AtomPropertyDeserializer extends AbstractAtomDealer { property.setName(start.getName().getLocalPart()); final Attribute typeAttr = start.getAttributeByName(this.typeQName); - if (typeAttr != null) { - property.setType(typeAttr.getValue()); - } Value value; final Attribute nullAttr = start.getAttributeByName(this.nullQName); + final String typeAttrValue = typeAttr == null ? null : typeAttr.getValue(); + if (nullAttr == null) { - final EdmTypeInfo typeInfo = StringUtils.isBlank(property.getType()) + final EdmTypeInfo typeInfo = StringUtils.isBlank(typeAttrValue) ? null - : new EdmTypeInfo.Builder().setTypeExpression(property.getType()).build(); + : new EdmTypeInfo.Builder().setTypeExpression(typeAttrValue).build(); + + if (typeInfo != null) { + property.setType(typeInfo.getTypeExpression()); + } final ODataPropertyType propType = typeInfo == null ? guessPropertyType(reader) @@ -207,6 +210,7 @@ class AtomPropertyDeserializer extends AbstractAtomDealer { } else { value = new NullValueImpl(); } + property.setValue(value); return property; diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/data/JSONGeoValueDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/data/JSONGeoValueDeserializer.java index eebfef3bb..c77369abf 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/data/JSONGeoValueDeserializer.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/data/JSONGeoValueDeserializer.java @@ -60,7 +60,7 @@ class JSONGeoValueDeserializer { private MultiPoint multipoint(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final String crs) { - MultiPoint multiPoint = null; + final MultiPoint multiPoint; if (itor.hasNext()) { final List<Point> points = new ArrayList<Point>(); @@ -79,7 +79,7 @@ class JSONGeoValueDeserializer { private LineString lineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final String crs) { - LineString lineString = null; + final LineString lineString; if (itor.hasNext()) { final List<Point> points = new ArrayList<Point>(); @@ -98,7 +98,7 @@ class JSONGeoValueDeserializer { private MultiLineString multiLineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final String crs) { - MultiLineString multiLineString = null; + final MultiLineString multiLineString; if (itor.hasNext()) { final List<LineString> lineStrings = new ArrayList<LineString>(); @@ -147,7 +147,7 @@ class JSONGeoValueDeserializer { private MultiPolygon multiPolygon(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final String crs) { - MultiPolygon multiPolygon = null; + final MultiPolygon multiPolygon; if (itor.hasNext()) { final List<Polygon> polygons = new ArrayList<Polygon>(); @@ -166,7 +166,7 @@ class JSONGeoValueDeserializer { private GeospatialCollection collection(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, final String crs) { - GeospatialCollection collection = null; + final GeospatialCollection collection; if (itor.hasNext()) { final List<Geospatial> geospatials = new ArrayList<Geospatial>(); @@ -262,5 +262,4 @@ class JSONGeoValueDeserializer { return value; } - } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmActionImportImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmActionImportImpl.java index 382741807..bf047af20 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmActionImportImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmActionImportImpl.java @@ -19,7 +19,6 @@ package org.apache.olingo.client.core.edm; import org.apache.olingo.client.api.edm.xml.v4.ActionImport; -import org.apache.olingo.client.core.edm.EdmTypeInfo; import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmAction; import org.apache.olingo.commons.api.edm.EdmActionImport; diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmOperationImpl.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmOperationImpl.java index f54d6c16c..da29a681b 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmOperationImpl.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmOperationImpl.java @@ -70,12 +70,12 @@ public abstract class EdmOperationImpl extends AbstractEdmOperation { @Override public FullQualifiedName getBindingParameterTypeFqn() { - FullQualifiedName fqn = null; + FullQualifiedName bpfqn = null; final EdmParameter bindingParam = getBindingParameter(); if (bindingParam != null) { - fqn = new FullQualifiedName(bindingParam.getType().getNamespace(), bindingParam.getType().getName()); + bpfqn = new FullQualifiedName(bindingParam.getType().getNamespace(), bindingParam.getType().getName()); } - return fqn; + return bpfqn; } @Override @@ -85,6 +85,6 @@ public abstract class EdmOperationImpl extends AbstractEdmOperation { if (bindingParam != null) { result = bindingParam.isCollection(); } - return null; + return result; } } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmTypeInfo.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmTypeInfo.java index 461e829a8..abf1a540e 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmTypeInfo.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/edm/EdmTypeInfo.java @@ -23,6 +23,7 @@ import org.apache.olingo.commons.api.edm.Edm; import org.apache.olingo.commons.api.edm.EdmComplexType; import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmEnumType; +import org.apache.olingo.commons.api.edm.EdmPrimitiveType; import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeKind; import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.slf4j.Logger; @@ -56,12 +57,11 @@ public class EdmTypeInfo { } public EdmTypeInfo build() { - return new EdmTypeInfo(edm, typeExpression.indexOf('.') == -1 + return new EdmTypeInfo(edm, typeExpression.indexOf('.') == -1 && StringUtils.isNotBlank(defaultNamespace) ? defaultNamespace + "." + typeExpression : typeExpression); } } - private final Edm edm; private final String typeExpression; @@ -80,7 +80,6 @@ public class EdmTypeInfo { private EdmTypeInfo(final Edm edm, final String typeExpression) { this.edm = edm; - this.typeExpression = typeExpression; String baseType; final int collStartIdx = typeExpression.indexOf("Collection("); @@ -97,16 +96,30 @@ public class EdmTypeInfo { baseType = typeExpression.substring(collStartIdx + 11, collEndIdx); } + + baseType = baseType.replaceAll("^#", ""); + + final String typeName; + final String namespace; + final int lastDotIdx = baseType.lastIndexOf('.'); if (lastDotIdx == -1) { - throw new IllegalArgumentException("Cannot find namespace or alias in " + typeExpression); + namespace = EdmPrimitiveType.EDM_NAMESPACE; + typeName = baseType; + baseType = new FullQualifiedName(EdmPrimitiveType.EDM_NAMESPACE, baseType).toString(); + } else { + namespace = baseType.substring(0, lastDotIdx); + typeName = baseType.substring(lastDotIdx + 1); } - final String namespace = baseType.substring(0, lastDotIdx); - final String typeName = baseType.substring(lastDotIdx + 1); + if (StringUtils.isBlank(typeName)) { throw new IllegalArgumentException("Null or empty type name in " + typeExpression); } + final StringBuilder exp = new StringBuilder(); + exp.append(baseType); + + this.typeExpression = (this.collection ? exp.insert(0, "Collection(").append(")") : exp).toString(); this.fullQualifiedName = new FullQualifiedName(namespace, typeName); try { @@ -168,5 +181,4 @@ public class EdmTypeInfo { public EdmEntityType getEntityType() { return entityType; } - } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/op/impl/AbstractODataBinder.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/op/impl/AbstractODataBinder.java index 2c2cdea26..09c39efb4 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/op/impl/AbstractODataBinder.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/op/impl/AbstractODataBinder.java @@ -268,7 +268,7 @@ public abstract class AbstractODataBinder implements CommonODataBinder { } final URI base = defaultBaseURI == null ? resource.getBaseURI() : defaultBaseURI; - + final URI next = resource.getNext(); final ODataEntitySet entitySet = next == null @@ -282,7 +282,7 @@ public abstract class AbstractODataBinder implements CommonODataBinder { for (Entry entryResource : resource.getEntries()) { entitySet.addEntity(getODataEntity(entryResource)); } - + return entitySet; } @@ -310,11 +310,11 @@ public abstract class AbstractODataBinder implements CommonODataBinder { if (StringUtils.isNotBlank(resource.getETag())) { entity.setETag(resource.getETag()); } - + if (resource.getEditLink() != null) { entity.setEditLink(URIUtils.getURI(base, resource.getEditLink().getHref())); } - + for (Link link : resource.getAssociationLinks()) { entity.addLink(client.getObjectFactory().newAssociationLink(link.getTitle(), base, link.getHref())); } diff --git a/lib/client-core/src/main/java/org/apache/olingo/client/core/op/impl/AbstractODataDeserializer.java b/lib/client-core/src/main/java/org/apache/olingo/client/core/op/impl/AbstractODataDeserializer.java index 67acc09b3..103f81d54 100644 --- a/lib/client-core/src/main/java/org/apache/olingo/client/core/op/impl/AbstractODataDeserializer.java +++ b/lib/client-core/src/main/java/org/apache/olingo/client/core/op/impl/AbstractODataDeserializer.java @@ -103,5 +103,4 @@ public abstract class AbstractODataDeserializer extends AbstractJacksonTool impl throw new IllegalArgumentException("While deserializing " + reference.getName(), e); } } - } diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/EntityRetrieveTestITCase.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/EntityRetrieveTestITCase.java index 663734648..c69b46973 100644 --- a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/EntityRetrieveTestITCase.java +++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/EntityRetrieveTestITCase.java @@ -148,7 +148,7 @@ public class EntityRetrieveTestITCase extends AbstractTestITCase { appendEntitySetSegment("Car").appendKeySegment(16); final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build()); - req.setFormat(format.toString()); + req.setFormat(format.toString(client.getServiceVersion())); final ODataRawResponse res = req.execute(); assertNotNull(res); diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/EntitySetTestITCase.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/EntitySetTestITCase.java index 35cc3d6c7..3e69affcc 100644 --- a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/EntitySetTestITCase.java +++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/EntitySetTestITCase.java @@ -138,7 +138,7 @@ public class EntitySetTestITCase extends AbstractTestITCase { uriBuilder.appendEntitySetSegment("Car"); final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build()); - req.setFormat(format.toString()); + req.setFormat(format.toString(client.getServiceVersion())); final ODataRawResponse res = req.execute(); assertNotNull(res); diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/QueryOptionsTestITCase.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/QueryOptionsTestITCase.java index 350148248..21cf9ae83 100644 --- a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/QueryOptionsTestITCase.java +++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v3/QueryOptionsTestITCase.java @@ -107,7 +107,8 @@ public class QueryOptionsTestITCase extends AbstractTestITCase { final ODataRetrieveResponse<ODataEntity> res = req.execute(); assertNotNull(res); - assertTrue(res.getContentType().replaceAll(" ", "").startsWith(ODataPubFormat.JSON.toString())); + assertTrue(res.getContentType().replaceAll(" ", ""). + startsWith(ODataPubFormat.JSON.toString(client.getServiceVersion()))); } /** diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v4/AbstractTestITCase.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v4/AbstractTestITCase.java index 46a59bde1..a74538031 100644 --- a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v4/AbstractTestITCase.java +++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v4/AbstractTestITCase.java @@ -35,8 +35,8 @@ public abstract class AbstractTestITCase extends org.apache.olingo.client.core.i @BeforeClass public static void setUpODataServiceRoot() throws IOException { - testStaticServiceRootURL = "http://localhost:9080/StaticService/V30/Static.svc"; - testLargeModelServiceRootURL = "http://localhost:9080/StaticService/V30/Static.svc/large"; + testStaticServiceRootURL = "http://localhost:9080/StaticService/V40/Static.svc"; + testLargeModelServiceRootURL = "http://localhost:9080/StaticService/V40/Static.svc/large"; testAuthServiceRootURL = "http://localhost:9080/DefaultService.svc"; } diff --git a/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v4/EntitySetTestITCase.java b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v4/EntitySetTestITCase.java new file mode 100644 index 000000000..9e2527a4f --- /dev/null +++ b/lib/client-core/src/test/java/org/apache/olingo/client/core/it/v4/EntitySetTestITCase.java @@ -0,0 +1,152 @@ +/* + * 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.client.core.it.v4; + +import static org.junit.Assert.assertEquals; + +import java.io.IOException; +import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetIteratorRequest; +import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest; +import org.apache.olingo.client.api.communication.request.retrieve.ODataRawRequest; +import org.apache.olingo.client.api.communication.response.ODataRawResponse; +import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; +import org.apache.olingo.client.api.domain.ODataEntitySet; +import org.apache.olingo.client.api.domain.ODataEntitySetIterator; +import org.apache.olingo.client.api.format.ODataPubFormat; +import org.apache.olingo.client.api.uri.CommonURIBuilder; +import org.apache.olingo.client.core.op.impl.ResourceFactory; +import static org.junit.Assert.assertNotNull; +import org.junit.Ignore; +import org.junit.Test; + +/** + * This is the unit test class to check basic feed operations. + */ +public class EntitySetTestITCase extends AbstractTestITCase { + + protected String getServiceRoot() { + return testStaticServiceRootURL; + } + + @Test + public void rawRequestAsAtom() throws IOException { + rawRequest(ODataPubFormat.ATOM); + } + + @Test + @Ignore + public void rawRequestAsJSON() throws IOException { + rawRequest(ODataPubFormat.JSON); + } + + @Test + public void readODataEntitySetIteratorFromAtom() { + readODataEntitySetIterator(ODataPubFormat.ATOM); + } + + @Test + @Ignore + public void readODataEntitySetIteratorFromJSON() { + readODataEntitySetIterator(ODataPubFormat.JSON); + } + + @Test + @Ignore + public void readODataEntitySetIteratorFromJSONFullMeta() { + readODataEntitySetIterator(ODataPubFormat.JSON_FULL_METADATA); + } + + @Test + @Ignore + public void readODataEntitySetIteratorFromJSONNoMeta() { + readODataEntitySetIterator(ODataPubFormat.JSON_NO_METADATA); + } + + @Test + public void readODataEntitySetWithNextFromAtom() { + readEntitySetWithNextLink(ODataPubFormat.ATOM); + } + + @Test + @Ignore + public void readODataEntitySetWithNextFromJSON() { + readEntitySetWithNextLink(ODataPubFormat.JSON_FULL_METADATA); + } + + private void readEntitySetWithNextLink(final ODataPubFormat format) { + final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(getServiceRoot()); + uriBuilder.appendEntitySetSegment("People"); + + final ODataEntitySetRequest req = client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build()); + req.setFormat(format); + + final ODataRetrieveResponse<ODataEntitySet> res = req.execute(); + final ODataEntitySet feed = res.getBody(); + + assertNotNull(feed); + + debugFeed(client.getBinder().getFeed(feed, ResourceFactory.feedClassForFormat( + ODataPubFormat.ATOM == format)), "Just retrieved feed"); + + assertEquals(5, feed.getEntities().size()); +// assertNotNull(feed.getNext()); + +// final URI expected = URI.create(getServiceRoot() + "/Customer?$skiptoken=-9"); +// final URI found = URIUtils.getURI(getServiceRoot(), feed.getNext().toASCIIString()); + +// assertEquals(expected, found); + } + + private void readODataEntitySetIterator(final ODataPubFormat format) { + final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(getServiceRoot()); + uriBuilder.appendEntitySetSegment("People"); + + final ODataEntitySetIteratorRequest req = + client.getRetrieveRequestFactory().getEntitySetIteratorRequest(uriBuilder.build()); + req.setFormat(format); + + final ODataRetrieveResponse<ODataEntitySetIterator> res = req.execute(); + final ODataEntitySetIterator feedIterator = res.getBody(); + + assertNotNull(feedIterator); + + int count = 0; + + while (feedIterator.hasNext()) { + assertNotNull(feedIterator.next()); + count++; + } + assertEquals(5, count); +// assertTrue(feedIterator.getNext().toASCIIString().endsWith("Customer?$skiptoken=-9")); + } + + private void rawRequest(final ODataPubFormat format) { + final CommonURIBuilder<?> uriBuilder = client.getURIBuilder(getServiceRoot()); + uriBuilder.appendEntitySetSegment("People"); + + final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build()); + req.setFormat(format.toString(client.getServiceVersion())); + + final ODataRawResponse res = req.execute(); + assertNotNull(res); + + final ODataEntitySet entitySet = res.getBodyAs(ODataEntitySet.class); + assertNotNull(entitySet); + } +} diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/Edm.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/Edm.java index c7aeff09a..32e6fc849 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/Edm.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/Edm.java @@ -26,92 +26,93 @@ import java.util.List; * Interface representing a Entity Data Model as described in the Conceptual Schema Definition. */ public interface Edm { - - /** - * This method DOES NOT support lazy loading. All schemas are loaded completely! - * @return all schemas defined for this EDM - */ - List<EdmSchema> getSchemas(); - /** - * Get entity container by full qualified name. - * <br/> - * See {@link EdmEntityContainer} for more information. - * - * @param name - * @return {@link EdmEntityContainer} - */ - EdmEntityContainer getEntityContainer(FullQualifiedName name); + /** + * This method DOES NOT support lazy loading. All schemas are loaded completely! + * + * @return all schemas defined for this EDM + */ + List<EdmSchema> getSchemas(); - /** - * Get enum type by full qualified name. - * <br/> - * See {@link EdmEnumType} for more information - * - * @param name - * @return {@link EdmEnumType} - */ - EdmEnumType getEnumType(FullQualifiedName name); + /** + * Get entity container by full qualified name. + * <br/> + * See {@link EdmEntityContainer} for more information. + * + * @param name + * @return {@link EdmEntityContainer} + */ + EdmEntityContainer getEntityContainer(FullQualifiedName name); - /** - * Get a type definition by full qualified name. - * <br/> - * See {@link EdmTypeDefinition} for more information - * - * @param name - * @return {@link EdmTypeDefinition} - */ - EdmTypeDefinition getTypeDefinition(FullQualifiedName name); + /** + * Get enum type by full qualified name. + * <br/> + * See {@link EdmEnumType} for more information + * + * @param name + * @return {@link EdmEnumType} + */ + EdmEnumType getEnumType(FullQualifiedName name); - /** - * Get entity type by full qualified name. - * <br/> - * See {@link EdmEntityType} for more information. - * - * @param name - * @return {@link EdmEntityType} - */ - EdmEntityType getEntityType(FullQualifiedName name); + /** + * Get a type definition by full qualified name. + * <br/> + * See {@link EdmTypeDefinition} for more information + * + * @param name + * @return {@link EdmTypeDefinition} + */ + EdmTypeDefinition getTypeDefinition(FullQualifiedName name); - /** - * Get complex type by full qualified name.. - * <br/> - * See {@link EdmComplexType} for more information. - * - * @param name - * @return {@link EdmComplexType} - */ - EdmComplexType getComplexType(FullQualifiedName name); + /** + * Get entity type by full qualified name. + * <br/> + * See {@link EdmEntityType} for more information. + * + * @param name + * @return {@link EdmEntityType} + */ + EdmEntityType getEntityType(FullQualifiedName name); - /** - * Get Action by full qualified name and binding parameter type. - * - * @param actionName must not be null - * @param bindingParameterTypeName may be null if it is an unbound action - * @param isBindingParameterCollection may be null if it is an unbound action - * @return {@link EdmAction} - */ - EdmAction getAction(FullQualifiedName actionName, FullQualifiedName bindingParameterTypeName, - Boolean isBindingParameterCollection); + /** + * Get complex type by full qualified name.. + * <br/> + * See {@link EdmComplexType} for more information. + * + * @param name + * @return {@link EdmComplexType} + */ + EdmComplexType getComplexType(FullQualifiedName name); - /** - * Get Function by full qualified name and binding parameter type and binding parameter names. - * - * @param functionName - * @param bindingParameterTypeName may be null if it is an unbound function - * @param isBindingParameterCollection may be null if it is an unbound function - * @param parameterNames may be null if it is an unbound function - * @return {@link EdmFunction} - */ - EdmFunction getFunction(FullQualifiedName functionName, FullQualifiedName bindingParameterTypeName, - Boolean isBindingParameterCollection, List<String> parameterNames); + /** + * Get Action by full qualified name and binding parameter type. + * + * @param actionName must not be null + * @param bindingParameterTypeName may be null if it is an unbound action + * @param isBindingParameterCollection may be null if it is an unbound action + * @return {@link EdmAction} + */ + EdmAction getAction(FullQualifiedName actionName, FullQualifiedName bindingParameterTypeName, + Boolean isBindingParameterCollection); - /** - * Get service metadata. - * <br/> - * See {@link EdmServiceMetadata} for more information. - * - * @return {@link EdmServiceMetadata} - */ - EdmServiceMetadata getServiceMetadata(); + /** + * Get Function by full qualified name and binding parameter type and binding parameter names. + * + * @param functionName + * @param bindingParameterTypeName may be null if it is an unbound function + * @param isBindingParameterCollection may be null if it is an unbound function + * @param parameterNames may be null if it is an unbound function + * @return {@link EdmFunction} + */ + EdmFunction getFunction(FullQualifiedName functionName, FullQualifiedName bindingParameterTypeName, + Boolean isBindingParameterCollection, List<String> parameterNames); + + /** + * Get service metadata. + * <br/> + * See {@link EdmServiceMetadata} for more information. + * + * @return {@link EdmServiceMetadata} + */ + EdmServiceMetadata getServiceMetadata(); } diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmActionImport.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmActionImport.java index 428fbdffd..a302b9e5c 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmActionImport.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/EdmActionImport.java @@ -23,5 +23,5 @@ package org.apache.olingo.commons.api.edm; */ public interface EdmActionImport extends EdmOperationImport { - EdmAction getAction(); + EdmAction getAction(); } diff --git a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/constants/ODataServiceVersion.java b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/constants/ODataServiceVersion.java index f50d40043..d637814cf 100644 --- a/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/constants/ODataServiceVersion.java +++ b/lib/commons-api/src/main/java/org/apache/olingo/commons/api/edm/constants/ODataServiceVersion.java @@ -40,8 +40,6 @@ public enum ODataServiceVersion { public static final String NS_METADATA = "metadata"; - public static final String NS_DATA = "data"; - public static final String NS_SCHEME = "scheme"; public static final String NAVIGATION_LINK_REL = "navigationLinkRel"; @@ -70,8 +68,11 @@ public enum ODataServiceVersion { { put(NS_METADATA, "http://docs.oasis-open.org/odata/ns/metadata"); - put(NS_DATA, "http://docs.oasis-open.org/odata/ns/data"); + put(NS_DATASERVICES, "http://docs.oasis-open.org/odata/ns/data"); put(NS_SCHEME, "http://docs.oasis-open.org/odata/ns/scheme"); + put(NAVIGATION_LINK_REL, "http://docs.oasis-open.org/odata/ns/related/"); + put(ASSOCIATION_LINK_REL, "http://docs.oasis-open.org/odata/ns/relatedlinks/"); + put(MEDIA_EDIT_LINK_REL, "http://docs.oasis-open.org/odata/ns/edit-media/"); } }); diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmComplexType.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmComplexType.java index 346eb2e72..732f29fea 100644 --- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmComplexType.java +++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmComplexType.java @@ -27,24 +27,29 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind; public abstract class AbstractEdmComplexType extends AbstractEdmStructuredType implements EdmComplexType { - public AbstractEdmComplexType(final Edm edm, final FullQualifiedName fqn, final FullQualifiedName baseTypeName) { - super(edm, fqn, EdmTypeKind.COMPLEX, baseTypeName); - } - - @Override - protected EdmStructuredType buildBaseType(final FullQualifiedName baseTypeName) { - EdmComplexType baseType = null; - if (baseTypeName != null) { - baseType = edm.getComplexType(baseTypeName); - if (baseType == null) { - throw new EdmException("Can't find base type with name: " + baseTypeName + " for complex type: " + getName()); - } + public AbstractEdmComplexType( + final Edm edm, + final FullQualifiedName fqn, + final FullQualifiedName baseTypeName) { + super(edm, fqn, EdmTypeKind.COMPLEX, baseTypeName); } - return baseType; - } - @Override - public EdmComplexType getBaseType() { - return (EdmComplexType) baseType; - } + @Override + protected EdmStructuredType buildBaseType(final FullQualifiedName baseTypeName) { + // TODO: check for comment + EdmComplexType baseType = null; + if (baseTypeName != null) { + baseType = edm.getComplexType(baseTypeName); + if (baseType == null) { + throw new EdmException("Can't find base type with name: " + baseTypeName + " for complex type: " + + getName()); + } + } + return baseType; + } + + @Override + public EdmComplexType getBaseType() { + return (EdmComplexType) baseType; + } } diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmEntityContainer.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmEntityContainer.java index aba62ba55..41eb36832 100644 --- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmEntityContainer.java +++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmEntityContainer.java @@ -33,119 +33,123 @@ import org.apache.olingo.commons.api.edm.FullQualifiedName; public abstract class AbstractEdmEntityContainer extends EdmNamedImpl implements EdmEntityContainer { - protected final FullQualifiedName entityContainerName; + protected final FullQualifiedName entityContainerName; - protected final Map<String, EdmSingleton> singletons = new HashMap<String, EdmSingleton>(); - private boolean allSingletonsLoaded = false; + protected final Map<String, EdmSingleton> singletons = new HashMap<String, EdmSingleton>(); - protected final Map<String, EdmEntitySet> entitySets = new HashMap<String, EdmEntitySet>(); - private boolean allEntitySetsLoaded = false; + private boolean allSingletonsLoaded = false; - protected final Map<String, EdmActionImport> actionImports = new HashMap<String, EdmActionImport>(); - private boolean allActionImportsLoaded = false; + protected final Map<String, EdmEntitySet> entitySets = new HashMap<String, EdmEntitySet>(); - protected final Map<String, EdmFunctionImport> functionImports = new HashMap<String, EdmFunctionImport>(); - private boolean allFunctionImportsLoaded = false; + private boolean allEntitySetsLoaded = false; - public AbstractEdmEntityContainer(final Edm edm, final FullQualifiedName entityContainerName) { - super(edm, entityContainerName.getName()); - this.entityContainerName = entityContainerName; - } + protected final Map<String, EdmActionImport> actionImports = new HashMap<String, EdmActionImport>(); - @Override - public String getNamespace() { - return entityContainerName.getNamespace(); - } + private boolean allActionImportsLoaded = false; - protected abstract EdmSingleton createSingleton(String singletonName); + protected final Map<String, EdmFunctionImport> functionImports = new HashMap<String, EdmFunctionImport>(); - @Override - public EdmSingleton getSingleton(final String singletonName) { - EdmSingleton singleton = singletons.get(singletonName); - if (singleton == null) { - singleton = createSingleton(singletonName); - singletons.put(singletonName, singleton); + private boolean allFunctionImportsLoaded = false; + + public AbstractEdmEntityContainer(final Edm edm, final FullQualifiedName entityContainerName) { + super(edm, entityContainerName.getName()); + this.entityContainerName = entityContainerName; } - return singleton; - } - protected abstract EdmEntitySet createEntitySet(String entitySetName); - - @Override - public EdmEntitySet getEntitySet(final String entitySetName) { - EdmEntitySet entitySet = entitySets.get(entitySetName); - if (entitySet == null) { - entitySet = createEntitySet(entitySetName); - entitySets.put(entitySetName, entitySet); + @Override + public String getNamespace() { + return entityContainerName.getNamespace(); } - return entitySet; - } - protected abstract EdmActionImport createActionImport(String actionImportName); + protected abstract EdmSingleton createSingleton(String singletonName); - @Override - public EdmActionImport getActionImport(final String actionImportName) { - EdmActionImport actionImport = actionImports.get(actionImportName); - if (actionImport == null) { - actionImport = createActionImport(actionImportName); - actionImports.put(actionImportName, actionImport); + @Override + public EdmSingleton getSingleton(final String singletonName) { + EdmSingleton singleton = singletons.get(singletonName); + if (singleton == null) { + singleton = createSingleton(singletonName); + singletons.put(singletonName, singleton); + } + return singleton; } - return actionImport; - } - protected abstract EdmFunctionImport createFunctionImport(String functionImportName); + protected abstract EdmEntitySet createEntitySet(String entitySetName); - @Override - public EdmFunctionImport getFunctionImport(final String functionImportName) { - EdmFunctionImport functionImport = functionImports.get(functionImportName); - if (functionImport == null) { - functionImport = createFunctionImport(functionImportName); - functionImports.put(functionImportName, functionImport); + @Override + public EdmEntitySet getEntitySet(final String entitySetName) { + EdmEntitySet entitySet = entitySets.get(entitySetName); + if (entitySet == null) { + entitySet = createEntitySet(entitySetName); + entitySets.put(entitySetName, entitySet); + } + return entitySet; } - return functionImport; - } - @Override - public List<EdmEntitySet> getEntitySets() { - if (!allEntitySetsLoaded) { - loadAllEntitySets(); - allEntitySetsLoaded = true; + protected abstract EdmActionImport createActionImport(String actionImportName); + + @Override + public EdmActionImport getActionImport(final String actionImportName) { + EdmActionImport actionImport = actionImports.get(actionImportName); + if (actionImport == null) { + actionImport = createActionImport(actionImportName); + actionImports.put(actionImportName, actionImport); + } + return actionImport; } - return new ArrayList<EdmEntitySet>(entitySets.values()); - } - protected abstract void loadAllEntitySets(); + protected abstract EdmFunctionImport createFunctionImport(String functionImportName); - @Override - public List<EdmFunctionImport> getFunctionImports() { - if (!allFunctionImportsLoaded) { - loadAllFunctionImports(); - allFunctionImportsLoaded = true; + @Override + public EdmFunctionImport getFunctionImport(final String functionImportName) { + EdmFunctionImport functionImport = functionImports.get(functionImportName); + if (functionImport == null) { + functionImport = createFunctionImport(functionImportName); + functionImports.put(functionImportName, functionImport); + } + return functionImport; } - return new ArrayList<EdmFunctionImport>(functionImports.values()); - } - protected abstract void loadAllFunctionImports(); - - @Override - public List<EdmSingleton> getSingletons() { - if (!allSingletonsLoaded) { - loadAllSingletons(); - allSingletonsLoaded = true; + @Override + public List<EdmEntitySet> getEntitySets() { + if (!allEntitySetsLoaded) { + loadAllEntitySets(); + allEntitySetsLoaded = true; + } + return new ArrayList<EdmEntitySet>(entitySets.values()); } - return new ArrayList<EdmSingleton>(singletons.values()); - } - protected abstract void loadAllSingletons(); + protected abstract void loadAllEntitySets(); - @Override - public List<EdmActionImport> getActionImports() { - if (!allActionImportsLoaded) { - loadAllActionImports(); - allActionImportsLoaded = true; + @Override + public List<EdmFunctionImport> getFunctionImports() { + if (!allFunctionImportsLoaded) { + loadAllFunctionImports(); + allFunctionImportsLoaded = true; + } + return new ArrayList<EdmFunctionImport>(functionImports.values()); } - return new ArrayList<EdmActionImport>(actionImports.values()); - } - protected abstract void loadAllActionImports(); + protected abstract void loadAllFunctionImports(); + + @Override + public List<EdmSingleton> getSingletons() { + if (!allSingletonsLoaded) { + loadAllSingletons(); + allSingletonsLoaded = true; + } + return new ArrayList<EdmSingleton>(singletons.values()); + } + + protected abstract void loadAllSingletons(); + + @Override + public List<EdmActionImport> getActionImports() { + if (!allActionImportsLoaded) { + loadAllActionImports(); + allActionImportsLoaded = true; + } + return new ArrayList<EdmActionImport>(actionImports.values()); + } + + protected abstract void loadAllActionImports(); } diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java index b8485409c..3c2f8948a 100644 --- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java +++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperation.java @@ -35,80 +35,83 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind; public abstract class AbstractEdmOperation extends EdmTypeImpl implements EdmOperation { - private final Map<String, EdmParameter> parameters = new LinkedHashMap<String, EdmParameter>(); + private final Map<String, EdmParameter> parameters = new LinkedHashMap<String, EdmParameter>(); - private String entitySetPath; + private String entitySetPath; - private boolean isBound; + private boolean isBound; - private EdmReturnType returnType; + private EdmReturnType returnType; - private List<String> parameterNames; + private List<String> parameterNames; - protected AbstractEdmOperation(final Edm edm, final FullQualifiedName fqn, final EdmTypeKind kind) { - super(edm, fqn, kind); - } - - protected void setParameters(final List<EdmParameter> _parameters) { - for (EdmParameter parameter : _parameters) { - parameters.put(parameter.getName(), parameter); + protected AbstractEdmOperation( + final Edm edm, + final FullQualifiedName fqn, + final EdmTypeKind kind) { + super(edm, fqn, kind); } - } - protected void setEntitySetPath(final String entitySetPath) { - this.entitySetPath = entitySetPath; - } - - protected void setIsBound(final boolean isBound) { - this.isBound = isBound; - } - - protected void setReturnType(final EdmReturnType returnType) { - this.returnType = returnType; - } - - @Override - public EdmParameter getParameter(final String name) { - return parameters.get(name); - } - - @Override - public List<String> getParameterNames() { - if (parameterNames == null) { - parameterNames = new ArrayList<String>(parameters.size()); - for (String parameterName : parameters.keySet()) { - parameterNames.add(parameterName); - } + protected void setParameters(final List<EdmParameter> _parameters) { + for (EdmParameter parameter : _parameters) { + parameters.put(parameter.getName(), parameter); + } } - return parameterNames; - } - @Override - public EdmEntitySet getReturnedEntitySet(final EdmEntitySet bindingParameterEntitySet) { - EdmEntitySet returnedEntitySet = null; - if (bindingParameterEntitySet != null && entitySetPath != null) { - final EdmBindingTarget relatedBindingTarget = bindingParameterEntitySet. - getRelatedBindingTarget(entitySetPath); - if (relatedBindingTarget == null) { - throw new EdmException("Cannot find entity set with path: " + entitySetPath); - } - if (relatedBindingTarget instanceof EdmEntitySet) { - returnedEntitySet = (EdmEntitySet) relatedBindingTarget; - } else { - throw new EdmException("BindingTarget with name: " + relatedBindingTarget.getName() + " must be an entity set"); - } + protected void setEntitySetPath(final String entitySetPath) { + this.entitySetPath = entitySetPath; } - return returnedEntitySet; - } - @Override - public EdmReturnType getReturnType() { - return returnType; - } + protected void setIsBound(final boolean isBound) { + this.isBound = isBound; + } - @Override - public boolean isBound() { - return isBound; - } + protected void setReturnType(final EdmReturnType returnType) { + this.returnType = returnType; + } + @Override + public EdmParameter getParameter(final String name) { + return parameters.get(name); + } + + @Override + public List<String> getParameterNames() { + if (parameterNames == null) { + parameterNames = new ArrayList<String>(parameters.size()); + for (String parameterName : parameters.keySet()) { + parameterNames.add(parameterName); + } + } + return parameterNames; + } + + @Override + public EdmEntitySet getReturnedEntitySet(final EdmEntitySet bindingParameterEntitySet) { + EdmEntitySet returnedEntitySet = null; + if (bindingParameterEntitySet != null && entitySetPath != null) { + final EdmBindingTarget relatedBindingTarget = bindingParameterEntitySet. + getRelatedBindingTarget(entitySetPath); + if (relatedBindingTarget == null) { + throw new EdmException("Cannot find entity set with path: " + entitySetPath); + } + if (relatedBindingTarget instanceof EdmEntitySet) { + returnedEntitySet = (EdmEntitySet) relatedBindingTarget; + } else { + throw new EdmException("BindingTarget with name: " + relatedBindingTarget.getName() + + " must be an entity set"); + } + } + return returnedEntitySet; + } + + @Override + public EdmReturnType getReturnType() { + return returnType; + } + + @Override + public boolean isBound() { + return isBound; + } } diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperationImport.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperationImport.java index 96aa49f26..fe8153393 100644 --- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperationImport.java +++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmOperationImport.java @@ -27,37 +27,40 @@ import org.apache.olingo.commons.api.edm.Target; public abstract class AbstractEdmOperationImport extends EdmNamedImpl implements EdmOperationImport { - protected final EdmEntityContainer container; + protected final EdmEntityContainer container; - private final Target entitySet; + private final Target entitySet; - private EdmEntitySet returnedEntitySet; + private EdmEntitySet returnedEntitySet; - public AbstractEdmOperationImport(final Edm edm, final EdmEntityContainer container, final String name, - final Target entitySet) { + public AbstractEdmOperationImport( + final Edm edm, + final EdmEntityContainer container, + final String name, + final Target entitySet) { - super(edm, name); - this.container = container; - this.entitySet = entitySet; - } - - @Override - public EdmEntitySet getReturnedEntitySet() { - if (entitySet != null && returnedEntitySet == null) { - EdmEntityContainer entityContainer = edm.getEntityContainer(entitySet.getEntityContainer()); - if (entityContainer == null) { - throw new EdmException("Can´t find entity container with name: " + entitySet.getEntityContainer()); - } - returnedEntitySet = entityContainer.getEntitySet(entitySet.getTargetName()); - if (returnedEntitySet == null) { - throw new EdmException("Can´t find entity set with name: " + entitySet.getTargetName()); - } + super(edm, name); + this.container = container; + this.entitySet = entitySet; } - return returnedEntitySet; - } - @Override - public EdmEntityContainer getEntityContainer() { - return container; - } + @Override + public EdmEntitySet getReturnedEntitySet() { + if (entitySet != null && returnedEntitySet == null) { + EdmEntityContainer entityContainer = edm.getEntityContainer(entitySet.getEntityContainer()); + if (entityContainer == null) { + throw new EdmException("Can´t find entity container with name: " + entitySet.getEntityContainer()); + } + returnedEntitySet = entityContainer.getEntitySet(entitySet.getTargetName()); + if (returnedEntitySet == null) { + throw new EdmException("Can´t find entity set with name: " + entitySet.getTargetName()); + } + } + return returnedEntitySet; + } + + @Override + public EdmEntityContainer getEntityContainer() { + return container; + } } diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmStructuredType.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmStructuredType.java index d48fda440..a807052bb 100644 --- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmStructuredType.java +++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/AbstractEdmStructuredType.java @@ -34,96 +34,99 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind; public abstract class AbstractEdmStructuredType extends EdmTypeImpl implements EdmStructuredType { - protected EdmStructuredType baseType; + protected EdmStructuredType baseType; - private List<String> propertyNames; + private List<String> propertyNames; - private List<String> navigationPropertyNames; + private List<String> navigationPropertyNames; - public AbstractEdmStructuredType(final Edm edm, final FullQualifiedName fqn, final EdmTypeKind kind, - final FullQualifiedName baseTypeName) { + public AbstractEdmStructuredType( + final Edm edm, + final FullQualifiedName fqn, + final EdmTypeKind kind, + final FullQualifiedName baseTypeName) { - super(edm, fqn, kind); - } - - protected abstract EdmStructuredType buildBaseType(FullQualifiedName baseTypeName); - - protected abstract Map<String, EdmProperty> getProperties(); - - protected abstract Map<String, EdmNavigationProperty> getNavigationProperties(); - - @Override - public List<String> getPropertyNames() { - if (propertyNames == null) { - propertyNames = new ArrayList<String>(); - if (baseType != null) { - propertyNames.addAll(baseType.getPropertyNames()); - } - propertyNames.addAll(getProperties().keySet()); - } - return propertyNames; - } - - @Override - public List<String> getNavigationPropertyNames() { - if (navigationPropertyNames == null) { - navigationPropertyNames = new ArrayList<String>(); - if (baseType != null) { - navigationPropertyNames.addAll(baseType.getNavigationPropertyNames()); - } - navigationPropertyNames.addAll(getNavigationProperties().keySet()); - } - return navigationPropertyNames; - } - - @Override - public EdmElement getProperty(final String name) { - EdmElement property = getStructuralProperty(name); - if (property == null) { - property = getNavigationProperty(name); - } - return property; - } - - @Override - public EdmProperty getStructuralProperty(final String name) { - EdmProperty property = null; - if (baseType != null) { - property = baseType.getStructuralProperty(name); - } - if (property == null) { - property = getProperties().get(name); - } - return property; - } - - @Override - public EdmNavigationProperty getNavigationProperty(final String name) { - EdmNavigationProperty property = null; - if (baseType != null) { - property = baseType.getNavigationProperty(name); - } - if (property == null) { - property = getNavigationProperties().get(name); - } - return property; - } - - @Override - public boolean compatibleTo(final EdmType targetType) { - EdmStructuredType sourceType = this; - if (targetType == null) { - throw new EdmException("Target type must not be null"); - } - while (!sourceType.getName().equals(targetType.getName()) - || !sourceType.getNamespace().equals(targetType.getNamespace())) { - - sourceType = sourceType.getBaseType(); - if (sourceType == null) { - return false; - } + super(edm, fqn, kind); } - return true; - } + protected abstract EdmStructuredType buildBaseType(FullQualifiedName baseTypeName); + + protected abstract Map<String, EdmProperty> getProperties(); + + protected abstract Map<String, EdmNavigationProperty> getNavigationProperties(); + + @Override + public List<String> getPropertyNames() { + if (propertyNames == null) { + propertyNames = new ArrayList<String>(); + if (baseType != null) { + propertyNames.addAll(baseType.getPropertyNames()); + } + propertyNames.addAll(getProperties().keySet()); + } + return propertyNames; + } + + @Override + public List<String> getNavigationPropertyNames() { + if (navigationPropertyNames == null) { + navigationPropertyNames = new ArrayList<String>(); + if (baseType != null) { + navigationPropertyNames.addAll(baseType.getNavigationPropertyNames()); + } + navigationPropertyNames.addAll(getNavigationProperties().keySet()); + } + return navigationPropertyNames; + } + + @Override + public EdmElement getProperty(final String name) { + EdmElement property = getStructuralProperty(name); + if (property == null) { + property = getNavigationProperty(name); + } + return property; + } + + @Override + public EdmProperty getStructuralProperty(final String name) { + EdmProperty property = null; + if (baseType != null) { + property = baseType.getStructuralProperty(name); + } + if (property == null) { + property = getProperties().get(name); + } + return property; + } + + @Override + public EdmNavigationProperty getNavigationProperty(final String name) { + EdmNavigationProperty property = null; + if (baseType != null) { + property = baseType.getNavigationProperty(name); + } + if (property == null) { + property = getNavigationProperties().get(name); + } + return property; + } + + @Override + public boolean compatibleTo(final EdmType targetType) { + EdmStructuredType sourceType = this; + if (targetType == null) { + throw new EdmException("Target type must not be null"); + } + while (!sourceType.getName().equals(targetType.getName()) + || !sourceType.getNamespace().equals(targetType.getNamespace())) { + + sourceType = sourceType.getBaseType(); + if (sourceType == null) { + return false; + } + } + + return true; + } } diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmNamedImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmNamedImpl.java index 8f82d567b..0f0bd5dfb 100644 --- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmNamedImpl.java +++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmNamedImpl.java @@ -23,18 +23,17 @@ import org.apache.olingo.commons.api.edm.EdmNamed; public abstract class EdmNamedImpl implements EdmNamed { - protected final Edm edm; + protected final Edm edm; - private final String name; + private final String name; - public EdmNamedImpl(final Edm edm, final String name) { - this.edm = edm; - this.name = name; - } - - @Override - public String getName() { - return name; - } + public EdmNamedImpl(final Edm edm, final String name) { + this.edm = edm; + this.name = name; + } + @Override + public String getName() { + return name; + } } diff --git a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmTypeImpl.java b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmTypeImpl.java index 7fc2808e8..ed20afa95 100644 --- a/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmTypeImpl.java +++ b/lib/commons-core/src/main/java/org/apache/olingo/commons/core/edm/EdmTypeImpl.java @@ -25,24 +25,23 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind; public class EdmTypeImpl extends EdmNamedImpl implements EdmType { - protected final FullQualifiedName fqn; + protected final FullQualifiedName fqn; - protected final EdmTypeKind kind; + protected final EdmTypeKind kind; - public EdmTypeImpl(final Edm edm, final FullQualifiedName fqn, final EdmTypeKind kind) { - super(edm, fqn.getName()); - this.fqn = fqn; - this.kind = kind; - } + public EdmTypeImpl(final Edm edm, final FullQualifiedName fqn, final EdmTypeKind kind) { + super(edm, fqn.getName()); + this.fqn = fqn; + this.kind = kind; + } - @Override - public String getNamespace() { - return fqn.getNamespace(); - } - - @Override - public EdmTypeKind getKind() { - return kind; - } + @Override + public String getNamespace() { + return fqn.getNamespace(); + } + @Override + public EdmTypeKind getKind() { + return kind; + } }