[OLINGO-205, OLINGO-200] provided atom v4 deserialization for entity type/set + entity set request

This commit is contained in:
fmartelli 2014-03-24 09:50:23 +01:00
parent 4780fc513b
commit 9aefb95905
51 changed files with 2151 additions and 1095 deletions

View File

@ -19,8 +19,8 @@
package org.apache.olingo.fit; package org.apache.olingo.fit;
import org.apache.olingo.fit.utils.Accept; import org.apache.olingo.fit.utils.Accept;
import org.apache.olingo.fit.utils.XMLUtilities; import org.apache.olingo.fit.utils.AbstractXMLUtilities;
import org.apache.olingo.fit.utils.JSONUtilities; import org.apache.olingo.fit.utils.AbstractJSONUtilities;
import org.apache.olingo.fit.utils.ODataVersion; import org.apache.olingo.fit.utils.ODataVersion;
import org.apache.olingo.fit.utils.FSManager; import org.apache.olingo.fit.utils.FSManager;
@ -70,13 +70,18 @@ public abstract class AbstractServices {
private static Set<ODataVersion> initialized = EnumSet.noneOf(ODataVersion.class); private static Set<ODataVersion> initialized = EnumSet.noneOf(ODataVersion.class);
protected abstract ODataVersion getVersion(); protected abstract ODataVersion getVersion();
protected final XMLUtilities xml; protected final AbstractXMLUtilities xml;
protected final JSONUtilities json; protected final AbstractJSONUtilities json;
public AbstractServices() throws Exception { public AbstractServices() throws Exception {
this.xml = new XMLUtilities(getVersion()); if (ODataVersion.v3 == getVersion()) {
this.json = new JSONUtilities(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())) { if (!initialized.contains(getVersion())) {
xml.retrieveLinkInfoFromMetadata(); xml.retrieveLinkInfoFromMetadata();
@ -135,7 +140,7 @@ public abstract class AbstractServices {
return xml. return xml.
createResponse(FSManager.instance(getVersion()).readFile(filename, Accept.XML), null, Accept.XML); createResponse(FSManager.instance(getVersion()).readFile(filename, Accept.XML), null, Accept.XML);
} catch (Exception e) { } 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); return xml.createResponse(null, null, null, Response.Status.NO_CONTENT);
} catch (Exception e) { } 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) { } catch (Exception e) {
LOG.error("Error retrieving entity", 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, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
final String changes) { final String changes) {
if (xml.isMediaContent(entitySetName + "/" + path)) { if (xml.isMediaContent(entitySetName + "/" + path)) {
return replaceMediaProperty(prefer, entitySetName, entityId, path, format, changes); return replaceMediaProperty(prefer, entitySetName, entityId, path, changes);
} else { } else {
return replaceProperty(accept, prefer, entitySetName, entityId, path, format, changes, false); return replaceProperty(accept, prefer, entitySetName, entityId, path, format, changes, false);
} }
@ -786,7 +791,6 @@ public abstract class AbstractServices {
final String entitySetName, final String entitySetName,
final String entityId, final String entityId,
final String path, final String path,
final String format,
final String value) { final String value) {
try { try {
final AbstractUtilities utils = getUtilities(null); final AbstractUtilities utils = getUtilities(null);
@ -809,7 +813,7 @@ public abstract class AbstractServices {
} catch (Exception e) { } catch (Exception e) {
LOG.error("Error retrieving entity", e); LOG.error("Error retrieving entity", e);
return xml.createFaultResponse(Accept.JSON.toString(), e); return xml.createFaultResponse(Accept.JSON.toString(getVersion()), e);
} }
} }

View File

@ -41,9 +41,9 @@ import javax.ws.rs.NotFoundException;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils; 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); super(version);
} }

View File

@ -384,7 +384,7 @@ public abstract class AbstractUtilities {
} }
if (accept != null) { if (accept != null) {
builder.header("Content-Type", accept.toString()); builder.header("Content-Type", accept.toString(version));
} else { } else {
builder.header("Content-Type", "*/*"); builder.header("Content-Type", "*/*");
} }
@ -423,7 +423,6 @@ public abstract class AbstractUtilities {
public Response createFaultResponse(final String accept, final Exception e) { public Response createFaultResponse(final String accept, final Exception e) {
LOG.debug("Create fault response about .... ", e); LOG.debug("Create fault response about .... ", e);
e.printStackTrace();
final Response.ResponseBuilder builder = Response.serverError(); final Response.ResponseBuilder builder = Response.serverError();
if (version == ODataVersion.v3) { if (version == ODataVersion.v3) {

View File

@ -55,103 +55,17 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.commons.vfs2.FileObject; import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException; import org.apache.commons.vfs2.FileSystemException;
public class XMLUtilities extends AbstractUtilities { public abstract class AbstractXMLUtilities extends AbstractUtilities {
protected static XMLInputFactory ifactory = null; protected static XMLInputFactory ifactory = null;
protected static XMLOutputFactory ofactory = null; protected static XMLOutputFactory ofactory = null;
public XMLUtilities(final ODataVersion version) throws Exception { public AbstractXMLUtilities(final ODataVersion version) throws Exception {
super(version); super(version);
} }
public void retrieveLinkInfoFromMetadata() throws Exception { public abstract 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<Integer, XmlElement> entityType =
extractElement(reader, null, Collections.<String>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.<String>singletonList("NavigationProperty"),
null, false, 0, -1, -1).getValue();
final String linkName = navProperty.getStart().getAttributeByName(new QName("Name")).getValue();
final Map.Entry<String, Boolean> 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<String, Boolean> 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<Integer, XmlElement> association = extractElement(
reader, null, Collections.<String>singletonList("Association"),
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>(
"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<Integer, XmlElement> associationEnd = extractElement(
reader, null, Collections.<String>singletonList("End"),
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>("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<String, Boolean>(target, feed);
}
@Override @Override
protected Accept getDefaultFormat() { protected Accept getDefaultFormat() {

View File

@ -28,24 +28,35 @@ public enum Accept {
TEXT(ContentType.TEXT_PLAIN.getMimeType(), ".txt"), TEXT(ContentType.TEXT_PLAIN.getMimeType(), ".txt"),
XML(ContentType.APPLICATION_XML.getMimeType(), ".xml"), XML(ContentType.APPLICATION_XML.getMimeType(), ".xml"),
ATOM(ContentType.APPLICATION_ATOM_XML.getMimeType(), ".xml"), ATOM(ContentType.APPLICATION_ATOM_XML.getMimeType(), ".xml"),
JSON(ContentType.APPLICATION_JSON.getMimeType() + ";odata=minimalmetadata", ".full.json"), JSON(ContentType.APPLICATION_JSON.getMimeType() + ";odata=minimalmetadata",
JSON_NOMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=nometadata", ".full.json"), ContentType.APPLICATION_JSON.getMimeType() + ";odata.metadata=minimal", ".full.json"),
JSON_FULLMETA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=fullmetadata", ".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 final String fileExtension;
private static Pattern allTypesPattern = Pattern.compile("(.*,)?\\*/\\*([,;].*)?"); private static Pattern allTypesPattern = Pattern.compile("(.*,)?\\*/\\*([,;].*)?");
Accept(final String contentType, final String fileExtension) { Accept(final String contentTypeV3, final String fileExtension) {
this.contentType = contentType; this.contentTypeV3 = contentTypeV3;
this.contentTypeV4 = contentTypeV3;
this.fileExtension = fileExtension; this.fileExtension = fileExtension;
} }
@Override Accept(final String contentTypeV3, final String contentTypeV4, final String fileExtension) {
public String toString() { this.contentTypeV3 = contentTypeV3;
return contentType; this.contentTypeV4 = contentTypeV4;
this.fileExtension = fileExtension;
}
public String toString(final ODataVersion version) {
return ODataVersion.v3 == version ? contentTypeV3 : contentTypeV4;
} }
public String getExtension() { public String getExtension() {
@ -53,23 +64,30 @@ public enum Accept {
} }
public static Accept parse(final String contentType, final ODataVersion version) { 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) { public static Accept parse(final String contentType, final ODataVersion version, final Accept def) {
if (StringUtils.isBlank(contentType) || allTypesPattern.matcher(contentType).matches()) { if (StringUtils.isBlank(contentType) || allTypesPattern.matcher(contentType).matches()) {
return def; return def;
} else if (JSON_NOMETA.toString().equals(contentType)) { } else if (JSON_NOMETA.toString(version).equals(contentType)) {
return JSON_NOMETA; 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; return JSON;
} else if (JSON_FULLMETA.toString().equals(contentType)) { } else if (JSON_FULLMETA.toString(version).equals(contentType)) {
return JSON_FULLMETA; return JSON_FULLMETA;
} else if (XML.toString().equals(contentType)) { } else if (XML.toString(version).equals(contentType)) {
return XML; return XML;
} else if (ATOM.toString().equals(contentType)) { } else if (ATOM.toString(version).equals(contentType)) {
return ATOM; return ATOM;
} else if (TEXT.toString().equals(contentType)) { } else if (TEXT.toString(version).equals(contentType)) {
return TEXT; return TEXT;
} else { } else {
throw new UnsupportedMediaTypeException("Unsupported media type"); throw new UnsupportedMediaTypeException("Unsupported media type");

View File

@ -74,6 +74,10 @@ public abstract class Commons {
mediaContent.put("Car/Photo", null); mediaContent.put("Car/Photo", null);
} }
public static Map<ODataVersion, MetadataLinkInfo> getLinkInfo() {
return linkInfo;
}
public static String getEntityURI(final String entitySetName, final String entityKey) { public static String getEntityURI(final String entitySetName, final String entityKey) {
return entitySetName + "(" + entityKey + ")"; return entitySetName + "(" + entityKey + ")";
} }
@ -230,7 +234,7 @@ public abstract class Commons {
break; break;
default: default:
throw new UnsupportedOperationException(target.toString()); throw new UnsupportedOperationException(target.name());
} }
for (String field : toBeRemoved) { for (String field : toBeRemoved) {

View File

@ -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);
}
}

View File

@ -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<Integer, XmlElement> entitySetElement =
extractElement(reader, null, Collections.<String>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<Map.Entry<String, String>> filter = new HashSet<Map.Entry<String, String>>();
filter.add(new SimpleEntry<String, String>(
"Name", entityType.substring(entityType.lastIndexOf(".") + 1, entityType.length())));
filter.add(new SimpleEntry<String, String>("BaseType", entityType));
final XMLEventReader reader = getEventReader(new ByteArrayInputStream(bos.toByteArray()));
final Map.Entry<Integer, XmlElement> entityTypeElement = extractElement(
reader, null, Collections.<String>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.<String>singletonList("NavigationProperty"),
null, false, 0, -1, -1).getValue();
final String linkName = navProperty.getStart().getAttributeByName(new QName("Name")).getValue();
final Map.Entry<String, Boolean> 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<String, Boolean> 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<Integer, XmlElement> association = extractElement(
reader, null, Collections.<String>singletonList("Association"),
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>(
"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<Integer, XmlElement> associationEnd = extractElement(
reader, null, Collections.<String>singletonList("End"),
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>("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<Integer, XmlElement> associationSet = extractElement(
reader, null, Collections.<String>singletonList("AssociationSet"),
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>(
"Association", associationName)), false, 0, -1, -1);
reader.close();
associationContent = associationSet.getValue().toStream();
reader = getEventReader(associationContent);
associationEnd = extractElement(
reader, null, Collections.<String>singletonList("End"),
Collections.<Map.Entry<String, String>>singleton(new SimpleEntry<String, String>("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<String, Boolean>(target, feed);
}
}

View File

@ -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);
}
}

View File

@ -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<String> singletons = new HashSet<String>();
try {
while (true) {
final Map.Entry<Integer, XmlElement> entitySetElement =
extractElement(reader, null, Collections.<String>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<Integer, XmlElement> entitySetElement =
extractElement(reader, null, Collections.<String>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<Integer, XmlElement> entitySetElement =
extractElement(reader, null, Collections.<String>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<String> 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.<String>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);
}
}
}

View File

@ -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"
}
}
]
}

View File

@ -0,0 +1,218 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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.
-->
<feed xml:base="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/"
xmlns="http://www.w3.org/2005/Atom" xmlns:d="http://docs.oasis-open.org/odata/ns/data"
xmlns:m="http://docs.oasis-open.org/odata/ns/metadata"
xmlns:georss="http://www.georss.org/georss"
xmlns:gml="http://www.opengis.net/gml"
m:context="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/$metadata#People">
<id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People</id>
<title />
<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>

View File

@ -21,499 +21,418 @@
--> -->
<edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx"> <edmx:Edmx Version="4.0" xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx">
<edmx:DataServices> <edmx:DataServices>
<Schema Namespace="NorthwindModel" xmlns="http://docs.oasis-open.org/odata/ns/edm"> <Schema Namespace="Microsoft.Test.OData.Services.ODataWCFService" xmlns="http://docs.oasis-open.org/odata/ns/edm">
<!-- EnumType with values --> <ComplexType Name="Address">
<EnumType Name="FileAccess" UnderlyingType="Edm.Int32" IsFlags="true"> <Property Name="Street" Type="Edm.String" Nullable="false" />
<Member Name="Read" Value="1" /> <Property Name="City" Type="Edm.String" Nullable="false" />
<Member Name="Write" Value="2" /> <Property Name="PostalCode" Type="Edm.String" Nullable="false" />
<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" />
</ComplexType> </ComplexType>
<!-- ComplexType with enum property --> <ComplexType Name="HomeAddress" BaseType="Microsoft.Test.OData.Services.ODataWCFService.Address">
<ComplexType Name="ACL"> <Property Name="FamilyName" Type="Edm.String" />
<Property Name="Filename" Nullable="false" Type="Edm.String" />
<Property Name="Access" Nullable="false" Type="NorthwindModel.FileAccess" />
</ComplexType> </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> <Key>
<PropertyRef Name="CategoryID" /> <PropertyRef Name="PersonID" />
</Key> </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="PersonID" Type="Edm.Int32" Nullable="false" />
<Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" /> <Property Name="FirstName" Type="Edm.String" Nullable="false" />
<Property Name="Description" Type="Edm.String" MaxLength="max" /> <Property Name="LastName" Type="Edm.String" Nullable="false" />
<Property Name="Picture" Type="Edm.Binary" MaxLength="max" /> <Property Name="MiddleName" Type="Edm.String" />
<NavigationProperty Name="Products" Type="Collection(NorthwindModel.Product)" Partner="Category" /> <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>
<EntityType Name="CustomerDemographic"> <EntityType Name="Customer" BaseType="Microsoft.Test.OData.Services.ODataWCFService.Person">
<Key> <Property Name="City" Type="Edm.String" Nullable="false" />
<PropertyRef Name="CustomerTypeID" /> <Property Name="Birthday" Type="Edm.DateTimeOffset" Nullable="false" />
</Key> <Property Name="TimeBetweenLastTwoOrders" Type="Edm.Duration" Nullable="false" />
<Property Name="CustomerTypeID" Type="Edm.String" Nullable="false" MaxLength="10" /> <NavigationProperty Name="Orders" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Order)" />
<Property Name="CustomerDesc" Type="Edm.String" MaxLength="max" /> <NavigationProperty Name="Company" Type="Microsoft.Test.OData.Services.ODataWCFService.Company" Nullable="false" Partner="VipCustomer" />
<NavigationProperty Name="Customers" Type="Collection(NorthwindModel.Customer)" Partner="CustomerDemographics" />
</EntityType> </EntityType>
<EntityType Name="Customer"> <EntityType Name="Employee" BaseType="Microsoft.Test.OData.Services.ODataWCFService.Person">
<Key> <Property Name="DateHired" Type="Edm.DateTimeOffset" Nullable="false" />
<PropertyRef Name="CustomerID" /> <Property Name="Office" Type="Edm.GeographyPoint" SRID="4326" />
</Key> <NavigationProperty Name="Company" Type="Microsoft.Test.OData.Services.ODataWCFService.Company" Nullable="false" Partner="Employees" />
<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> </EntityType>
<EntityType Name="Product"> <EntityType Name="Product">
<Key> <Key>
<PropertyRef Name="ProductID" /> <PropertyRef Name="ProductID" />
</Key> </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="ProductID" Type="Edm.Int32" Nullable="false" />
<Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> <Property Name="Name" Type="Edm.String" Nullable="false" />
<Property Name="SupplierID" Type="Edm.Int32" /> <Property Name="QuantityPerUnit" Type="Edm.String" Nullable="false" />
<Property Name="CategoryID" Type="Edm.Int32" /> <Property Name="UnitPrice" Type="Edm.Single" Nullable="false" />
<Property Name="QuantityPerUnit" Type="Edm.String" MaxLength="20" /> <Property Name="QuantityInStock" Type="Edm.Int32" Nullable="false" />
<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="Discontinued" Type="Edm.Boolean" Nullable="false" />
<!-- ComplexType attributes --> <Property Name="UserAccess" Type="Microsoft.Test.OData.Services.ODataWCFService.AccessLevel" />
<Property Name="ProductDimensions" Type="NorthwindModel.Dimensions" /> <Property Name="SkinColor" Type="Microsoft.Test.OData.Services.ODataWCFService.Color" />
<Property Name="ShippingDimensions" Type="NorthwindModel.Dimensions" /> <Property Name="CoverColors" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Color)" Nullable="false" />
<NavigationProperty Name="Category" Type="NorthwindModel.Category" Partner="Products"> <NavigationProperty Name="Details" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.ProductDetail)">
<ReferentialConstraint Property="CategoryID" ReferencedProperty="CategoryID" /> <ReferentialConstraint Property="ProductID" ReferencedProperty="ProductID" />
</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" />
</NavigationProperty> </NavigationProperty>
</EntityType> </EntityType>
<EntityType Name="Region"> <EntityType Name="ProductDetail">
<Key> <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="ProductID" />
<PropertyRef Name="ProductName" /> <PropertyRef Name="ProductDetailID" />
</Key> </Key>
<Property Name="ProductID" 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="ProductDetailID" Type="Edm.Int32" Nullable="false" />
<Property Name="SupplierID" Type="Edm.Int32" /> <Property Name="ProductName" Type="Edm.String" Nullable="false" />
<Property Name="CategoryID" Type="Edm.Int32" /> <Property Name="Description" Type="Edm.String" Nullable="false" />
<Property Name="QuantityPerUnit" Type="Edm.String" MaxLength="20" /> <NavigationProperty Name="RelatedProduct" Type="Microsoft.Test.OData.Services.ODataWCFService.Product" />
<Property Name="UnitPrice" Type="Edm.Decimal" Precision="19" Scale="4" /> <NavigationProperty Name="Reviews" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.ProductReview)">
<Property Name="UnitsInStock" Type="Edm.Int16" /> <ReferentialConstraint Property="ProductID" ReferencedProperty="ProductID" />
<Property Name="UnitsOnOrder" Type="Edm.Int16" /> <ReferentialConstraint Property="ProductDetailID" ReferencedProperty="ProductDetailID" />
<Property Name="ReorderLevel" Type="Edm.Int16" /> </NavigationProperty>
<Property Name="Discontinued" Type="Edm.Boolean" Nullable="false" />
<Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" />
</EntityType> </EntityType>
<EntityType Name="Category_Sales_for_1997"> <EntityType Name="ProductReview">
<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">
<Key> <Key>
<PropertyRef Name="ProductID" /> <PropertyRef Name="ProductID" />
<PropertyRef Name="ProductName" /> <PropertyRef Name="ProductDetailID" />
<PropertyRef Name="ReviewTitle" />
<PropertyRef Name="RevisionID" />
</Key> </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="ProductID" Type="Edm.Int32" Nullable="false" />
<Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> <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>
<EntityType Name="Customer_and_Suppliers_by_City"> <EntityType Name="Order">
<Key> <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="OrderID" />
<PropertyRef Name="ProductID" />
<PropertyRef Name="ProductName" />
<PropertyRef Name="Quantity" />
<PropertyRef Name="Salesperson" />
<PropertyRef Name="ShipperName" />
<PropertyRef Name="UnitPrice" />
</Key> </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="OrderID" Type="Edm.Int32" Nullable="false" />
<Property Name="OrderDate" Type="Edm.DateTimeOffset" /> <Property Name="OrderDate" Type="Edm.DateTimeOffset" Nullable="false" />
<Property Name="RequiredDate" Type="Edm.DateTimeOffset" /> <Property Name="ShelfLife" Type="Edm.Duration" />
<Property Name="ShippedDate" Type="Edm.DateTimeOffset" /> <Property Name="OrderShelfLifes" Type="Collection(Edm.Duration)" />
<Property Name="ShipperName" Type="Edm.String" Nullable="false" MaxLength="40" /> <NavigationProperty Name="LoggedInEmployee" Type="Microsoft.Test.OData.Services.ODataWCFService.Employee" Nullable="false" />
<Property Name="ProductID" Type="Edm.Int32" Nullable="false" /> <NavigationProperty Name="CustomerForOrder" Type="Microsoft.Test.OData.Services.ODataWCFService.Customer" Nullable="false" />
<Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> <NavigationProperty Name="OrderDetails" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.OrderDetail)" />
<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" />
</EntityType> </EntityType>
<EntityType Name="Order_Details_Extended"> <EntityType Name="OrderDetail">
<Key> <Key>
<PropertyRef Name="Discount" />
<PropertyRef Name="OrderID" /> <PropertyRef Name="OrderID" />
<PropertyRef Name="ProductID" /> <PropertyRef Name="ProductID" />
<PropertyRef Name="ProductName" />
<PropertyRef Name="Quantity" />
<PropertyRef Name="UnitPrice" />
</Key> </Key>
<Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> <Property Name="OrderID" Type="Edm.Int32" Nullable="false" />
<Property Name="ProductID" 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="OrderPlaced" Type="Edm.DateTimeOffset" Nullable="false" />
<Property Name="UnitPrice" Type="Edm.Decimal" Nullable="false" Precision="19" Scale="4" /> <Property Name="Quantity" Type="Edm.Int32" Nullable="false" />
<Property Name="Quantity" Type="Edm.Int16" Nullable="false" /> <Property Name="UnitPrice" Type="Edm.Single" Nullable="false" />
<Property Name="Discount" Type="Edm.Single" Nullable="false" /> <NavigationProperty Name="ProductOrdered" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Product)" />
<Property Name="ExtendedPrice" Type="Edm.Decimal" Precision="19" Scale="4" /> <NavigationProperty Name="AssociatedOrder" Type="Microsoft.Test.OData.Services.ODataWCFService.Order" Nullable="false" />
</EntityType> </EntityType>
<EntityType Name="Order_Subtotal"> <EntityType Name="Department">
<Key> <Key>
<PropertyRef Name="OrderID" /> <PropertyRef Name="DepartmentID" />
</Key> </Key>
<Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> <Property Name="DepartmentID" Type="Edm.Int32" Nullable="false" />
<Property Name="Subtotal" Type="Edm.Decimal" Precision="19" Scale="4" /> <Property Name="Name" Type="Edm.String" Nullable="false" />
<NavigationProperty Name="Company" Type="Microsoft.Test.OData.Services.ODataWCFService.Company" Nullable="false" Partner="Departments" />
</EntityType> </EntityType>
<EntityType Name="Orders_Qry"> <EntityType Name="Company">
<Key> <Key>
<PropertyRef Name="CompanyName" /> <PropertyRef Name="CompanyID" />
<PropertyRef Name="OrderID" />
</Key> </Key>
<Property Name="OrderID" Type="Edm.Int32" Nullable="false" /> <Property Name="CompanyID" Type="Edm.Int32" Nullable="false" />
<Property Name="CustomerID" Type="Edm.String" MaxLength="5" /> <Property Name="CompanyCategory" Type="Microsoft.Test.OData.Services.ODataWCFService.CompanyCategory" />
<Property Name="EmployeeID" Type="Edm.Int32" /> <Property Name="Revenue" Type="Edm.Int64" Nullable="false" />
<Property Name="OrderDate" Type="Edm.DateTimeOffset" /> <Property Name="Name" Type="Edm.String" />
<Property Name="RequiredDate" Type="Edm.DateTimeOffset" /> <Property Name="Address" Type="Microsoft.Test.OData.Services.ODataWCFService.Address" />
<Property Name="ShippedDate" Type="Edm.DateTimeOffset" /> <NavigationProperty Name="Employees" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Employee)" Partner="Company" />
<Property Name="ShipVia" Type="Edm.Int32" /> <NavigationProperty Name="VipCustomer" Type="Microsoft.Test.OData.Services.ODataWCFService.Customer" Nullable="false" Partner="Company" />
<Property Name="Freight" Type="Edm.Decimal" Precision="19" Scale="4" /> <NavigationProperty Name="Departments" Type="Collection(Microsoft.Test.OData.Services.ODataWCFService.Department)" Partner="Company" />
<Property Name="ShipName" Type="Edm.String" MaxLength="40" /> <NavigationProperty Name="CoreDepartment" Type="Microsoft.Test.OData.Services.ODataWCFService.Department" Nullable="false" />
<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" />
</EntityType> </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> <Key>
<PropertyRef Name="CategoryName" /> <PropertyRef Name="AssetID" />
<PropertyRef Name="ProductName" />
</Key> </Key>
<Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" /> <Property Name="AssetID" Type="Edm.Int32" Nullable="false" />
<Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> <Property Name="Name" Type="Edm.String" />
<Property Name="ProductSales" Type="Edm.Decimal" Precision="19" Scale="4" /> <Property Name="Number" Type="Edm.Int32" Nullable="false" />
</EntityType> </EntityType>
<EntityType Name="Products_Above_Average_Price"> <EntityType Name="Club">
<Key> <Key>
<PropertyRef Name="ProductName" /> <PropertyRef Name="ClubID" />
</Key> </Key>
<Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> <Property Name="ClubID" Type="Edm.Int32" Nullable="false" />
<Property Name="UnitPrice" Type="Edm.Decimal" Precision="19" Scale="4" /> <Property Name="Name" Type="Edm.String" />
</EntityType> </EntityType>
<EntityType Name="Products_by_Category"> <EntityType Name="LabourUnion">
<Key> <Key>
<PropertyRef Name="CategoryName" /> <PropertyRef Name="LabourUnionID" />
<PropertyRef Name="Discontinued" />
<PropertyRef Name="ProductName" />
</Key> </Key>
<Property Name="CategoryName" Type="Edm.String" Nullable="false" MaxLength="15" /> <Property Name="LabourUnionID" Type="Edm.Int32" Nullable="false" />
<Property Name="ProductName" Type="Edm.String" Nullable="false" MaxLength="40" /> <Property Name="Name" Type="Edm.String" />
<Property Name="QuantityPerUnit" Type="Edm.String" MaxLength="20" />
<Property Name="UnitsInStock" Type="Edm.Int16" />
<Property Name="Discontinued" Type="Edm.Boolean" Nullable="false" />
</EntityType> </EntityType>
<EntityType Name="Sales_by_Category"> <Action Name="AddAccessRight" IsBound="true">
<Key> <Parameter Name="product" Type="Microsoft.Test.OData.Services.ODataWCFService.Product" Nullable="false" />
<PropertyRef Name="CategoryID" /> <Parameter Name="accessRight" Type="Microsoft.Test.OData.Services.ODataWCFService.AccessLevel" />
<PropertyRef Name="CategoryName" /> <ReturnType Type="Microsoft.Test.OData.Services.ODataWCFService.AccessLevel" />
<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> </Action>
</Schema> <Action Name="IncreaseRevenue" IsBound="true">
<Schema Namespace="ODataWebExperimental.Northwind.Model" xmlns="http://docs.oasis-open.org/odata/ns/edm"> <Parameter Name="p" Type="Microsoft.Test.OData.Services.ODataWCFService.Company" Nullable="false" />
<EntityContainer Name="NorthwindEntities" p4:LazyLoadingEnabled="true" xmlns:p4="http://schemas.microsoft.com/ado/2009/02/edm/annotation"> <Parameter Name="IncreaseValue" Type="Edm.Int64" />
<EntitySet Name="Categories" EntityType="NorthwindModel.Category"> <ReturnType Type="Edm.Int64" Nullable="false" />
<NavigationPropertyBinding Path="Products" Target="Products" /> </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>
<EntitySet Name="CustomerDemographics" EntityType="NorthwindModel.CustomerDemographic"> <Singleton Name="Boss" Type="Microsoft.Test.OData.Services.ODataWCFService.Person" />
<NavigationPropertyBinding Path="Customers" Target="Customers" /> <EntitySet Name="Customers" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Customer">
</EntitySet>
<EntitySet Name="Customers" EntityType="NorthwindModel.Customer">
<NavigationPropertyBinding Path="CustomerDemographics" Target="CustomerDemographics" />
<NavigationPropertyBinding Path="Orders" Target="Orders" /> <NavigationPropertyBinding Path="Orders" Target="Orders" />
</EntitySet> </EntitySet>
<EntitySet Name="Employees" EntityType="NorthwindModel.Employee"> <Singleton Name="VipCustomer" Type="Microsoft.Test.OData.Services.ODataWCFService.Customer">
<NavigationPropertyBinding Path="Employees1" Target="Employees" />
<NavigationPropertyBinding Path="Employee1" Target="Employees" />
<NavigationPropertyBinding Path="Orders" Target="Orders" /> <NavigationPropertyBinding Path="Orders" Target="Orders" />
<NavigationPropertyBinding Path="Territories" Target="Territories" /> <NavigationPropertyBinding Path="Company" Target="Company" />
</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"/>
</Singleton> </Singleton>
<!-- FunctionImport --> <EntitySet Name="Employees" EntityType="Microsoft.Test.OData.Services.ODataWCFService.Employee">
<FunctionImport Name="TopSellingProducts" EntitySet="Products" Function="NorthwindModel.TopSellingProducts"/> <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> </EntityContainer>
</Schema> </Schema>
</edmx:DataServices> </edmx:DataServices>
</edmx:Edmx> </edmx:Edmx>

View File

@ -20,6 +20,7 @@ package org.apache.olingo.client.api.communication.request;
import java.util.concurrent.Future; import java.util.concurrent.Future;
import org.apache.olingo.client.api.communication.response.ODataResponse; import org.apache.olingo.client.api.communication.response.ODataResponse;
import org.apache.olingo.client.api.format.Format;
/** /**
* Basic OData request. * 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 <V> OData response type corresponding to the request implementation.
* @param <T> Accepted content-type formats by the request in object. * @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. * Request execute.

View File

@ -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.request.ODataBasicRequest;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse; 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. * 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> {
} }

View File

@ -20,7 +20,6 @@ package org.apache.olingo.client.api.domain;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.olingo.client.api.format.ODataPubFormat;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
/** /**
@ -31,11 +30,11 @@ public enum ODataLinkType {
/** /**
* Entity navigation link. * 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 link.
*/ */
ENTITY_SET_NAVIGATION(ODataPubFormat.ATOM + ";type=feed"), ENTITY_SET_NAVIGATION(ContentType.APPLICATION_ATOM_XML.getMimeType() + ";type=feed"),
/** /**
* Association link. * 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 client OData client.
* @param rel rel. * @param rel rel.

View File

@ -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);
}

View File

@ -19,11 +19,12 @@
package org.apache.olingo.client.api.format; package org.apache.olingo.client.api.format;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
/** /**
* Available formats to be used in various contexts. * Available formats to be used in various contexts.
*/ */
public enum ODataFormat { public enum ODataFormat implements Format{
/** /**
* JSON format with no metadata. * JSON format with no metadata.
@ -94,4 +95,9 @@ public enum ODataFormat {
return result; return result;
} }
@Override
public String toString(final ODataServiceVersion version) {
return this.toString();
}
} }

View File

@ -19,11 +19,12 @@
package org.apache.olingo.client.api.format; package org.apache.olingo.client.api.format;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
/** /**
* Available formats for media. * Available formats for media.
*/ */
public enum ODataMediaFormat { public enum ODataMediaFormat implements Format{
CHARSET_PARAMETER("charset"), CHARSET_PARAMETER("charset"),
MEDIA_TYPE_WILDCARD("*"), MEDIA_TYPE_WILDCARD("*"),
@ -68,4 +69,9 @@ public enum ODataMediaFormat {
return result; return result;
} }
@Override
public String toString(final ODataServiceVersion version) {
return this.toString();
}
} }

View File

@ -18,34 +18,49 @@
*/ */
package org.apache.olingo.client.api.format; package org.apache.olingo.client.api.format;
import java.util.EnumMap;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
/** /**
* Available formats for AtomPub exchange. * Available formats for AtomPub exchange.
*/ */
public enum ODataPubFormat { public enum ODataPubFormat implements Format {
/** /**
* JSON format with no metadata. * JSON format with no metadata.
*/ */
JSON_NO_METADATA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=nometadata"), JSON_NO_METADATA(),
/** /**
* JSON format with minimal metadata (default). * JSON format with minimal metadata (default).
*/ */
JSON(ContentType.APPLICATION_JSON.getMimeType() + ";odata=minimalmetadata"), JSON(),
/** /**
* JSON format with no metadata. * JSON format with no metadata.
*/ */
JSON_FULL_METADATA(ContentType.APPLICATION_JSON.getMimeType() + ";odata=fullmetadata"), JSON_FULL_METADATA(),
/** /**
* Atom format. * 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) { static {
this.format = format; 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. * @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 @Override
public String toString() { public String toString() {
return format; throw new UnsupportedOperationException();
} }
/** /**
@ -72,7 +96,7 @@ public enum ODataPubFormat {
final String[] parts = format.split(";"); final String[] parts = format.split(";");
_format.append(parts[0].trim()); _format.append(parts[0].trim());
if (ContentType.APPLICATION_JSON.getMimeType().equals(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()); _format.append(';').append(parts[1].trim());
} else { } else {
result = ODataPubFormat.JSON; result = ODataPubFormat.JSON;
@ -82,7 +106,8 @@ public enum ODataPubFormat {
if (result == null) { if (result == null) {
final String candidate = _format.toString(); final String candidate = _format.toString();
for (ODataPubFormat value : values()) { for (ODataPubFormat value : values()) {
if (candidate.equals(value.toString())) { if (candidate.equals(value.toString(ODataServiceVersion.V30))
|| candidate.equals(value.toString(ODataServiceVersion.V40))) {
result = value; result = value;
} }
} }

View File

@ -19,11 +19,12 @@
package org.apache.olingo.client.api.format; package org.apache.olingo.client.api.format;
import org.apache.http.entity.ContentType; import org.apache.http.entity.ContentType;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
/** /**
* Available formats for property values. * Available formats for property values.
*/ */
public enum ODataValueFormat { public enum ODataValueFormat implements Format{
/** /**
* Application octet stream. * Application octet stream.
@ -73,4 +74,9 @@ public enum ODataValueFormat {
return result; return result;
} }
@Override
public String toString(final ODataServiceVersion version) {
return this.toString();
}
} }

View File

@ -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.ODataStreamer;
import org.apache.olingo.client.api.communication.request.batch.ODataBatchRequest; 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.communication.response.ODataResponse;
import org.apache.olingo.client.api.format.Format;
import org.apache.olingo.client.api.http.HttpMethod; 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 <V> OData response type corresponding to the request implementation.
* @param <T> OData format being used. * @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> extends ODataRequestImpl<T>
implements ODataBasicRequest<V, T> { implements ODataBasicRequest<V, T> {
/** /**
* Constructor. * Constructor.
* *
* @param odataClient client instance getting this request * @param odataClient client instance getting this request
* @param formatRef reference class for the format being used * @param formatRef reference class for the format being used
* @param method request method. * @param method request method.
* @param uri OData request URI. * @param uri OData request URI.
*/ */
public AbstractODataBasicRequest(final CommonODataClient odataClient, public AbstractODataBasicRequest(final CommonODataClient odataClient,
final Class<T> formatRef, final HttpMethod method, final URI uri) { 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} * {@inheritDoc}
*/ */
@Override @Override
public void setFormat(final T format) { public final Future<V> asyncExecute() {
if (format != null) { return odataClient.getConfiguration().getExecutor().submit(new Callable<V>() {
setAccept(format.toString()); @Override
setContentType(format.toString()); public V call() throws Exception {
} return execute();
} }
});
/** }
* {@inheritDoc}
*/ /**
@Override * Gets payload as an InputStream.
public final Future<V> asyncExecute() { *
return odataClient.getConfiguration().getExecutor().submit(new Callable<V>() { * @return InputStream for entire payload.
*/
@Override protected abstract InputStream getPayload();
public V call() throws Exception {
return execute(); /**
} * Serializes the full request into the given batch request.
}); *
} * @param req destination batch request.
*/
/** public void batch(final ODataBatchRequest req) {
* Gets payload as an InputStream. batch(req, null);
* }
* @return InputStream for entire payload.
*/ /**
protected abstract InputStream getPayload(); * 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.
* Serializes the full request into the given batch request. *
* * @param req destination batch request.
* @param req destination batch request. * @param contentId contentId of the changeset item.
*/ */
public void batch(final ODataBatchRequest req) { public void batch(final ODataBatchRequest req, final String contentId) {
batch(req, null); try {
} req.rawAppend(toByteArray());
if (StringUtils.isNotBlank(contentId)) {
/** req.rawAppend((ODataBatchConstants.CHANGESET_CONTENT_ID_NAME + ": " + contentId).getBytes());
* Serializes the full request into the given batch request. req.rawAppend(ODataStreamer.CRLF);
* <p> }
* This method have to be used to serialize a changeset item with the specified contentId. req.rawAppend(ODataStreamer.CRLF);
*
* @param req destination batch request. final InputStream payload = getPayload();
* @param contentId contentId of the changeset item. if (payload != null) {
*/ req.rawAppend(IOUtils.toByteArray(getPayload()));
public void batch(final ODataBatchRequest req, final String contentId) { }
try { } catch (IOException e) {
req.rawAppend(toByteArray()); throw new IllegalStateException(e);
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);
}
} }
}
} }

View File

@ -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.header.ODataHeaders;
import org.apache.olingo.client.api.communication.request.ODataRequest; 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.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.communication.response.ODataResponse;
import org.apache.olingo.client.api.format.ODataMediaFormat; import org.apache.olingo.client.api.format.ODataMediaFormat;
import org.apache.olingo.client.api.format.ODataPubFormat; 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.JSONErrorImpl;
import org.apache.olingo.client.core.data.XMLErrorImpl; import org.apache.olingo.client.core.data.XMLErrorImpl;
import org.apache.olingo.client.api.data.ODataError; 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.client.core.communication.header.ODataHeadersImpl;
import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -66,7 +71,7 @@ import org.slf4j.LoggerFactory;
* @see InvokeRequestFactory * @see InvokeRequestFactory
* @see StreamedRequestFactory * @see StreamedRequestFactory
*/ */
public class ODataRequestImpl<T extends Enum<T>> implements ODataRequest { public class ODataRequestImpl<T extends Format> implements ODataRequest {
/** /**
* Logger. * Logger.
@ -251,7 +256,7 @@ public class ODataRequestImpl<T extends Enum<T>> implements ODataRequest {
@Override @Override
public String getAccept() { public String getAccept() {
final String acceptHead = odataHeaders.getHeader(HeaderName.accept); 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 @Override
public String getContentType() { public String getContentType() {
final String contentTypeHead = odataHeaders.getHeader(HeaderName.contentType); final String contentTypeHead = odataHeaders.getHeader(HeaderName.contentType);
return StringUtils.isBlank(contentTypeHead) ? getDefaultFormat().toString() : contentTypeHead; return StringUtils.isBlank(contentTypeHead)
? getDefaultFormat().toString(odataClient.getServiceVersion()) : contentTypeHead;
} }
/** /**

View File

@ -100,7 +100,7 @@ public class ODataInvokeRequestImpl<T extends ODataInvokeResult>
public void setFormat(final ODataPubFormat format) { public void setFormat(final ODataPubFormat format) {
final String _format = (reference.isAssignableFrom(ODataProperty.class) && format == ODataPubFormat.ATOM) final String _format = (reference.isAssignableFrom(ODataProperty.class) && format == ODataPubFormat.ATOM)
? ODataFormat.XML.toString() ? ODataFormat.XML.toString()
: format.toString(); : format.toString(odataClient.getServiceVersion());
setAccept(_format); setAccept(_format);
setContentType(_format); setContentType(_format);
} }
@ -163,7 +163,7 @@ public class ODataInvokeRequestImpl<T extends ODataInvokeResult>
} else if (this.method == HttpMethod.POST) { } else if (this.method == HttpMethod.POST) {
((HttpPost) request).setEntity(URIUtils.buildInputStreamEntity(odataClient, input)); ((HttpPost) request).setEntity(URIUtils.buildInputStreamEntity(odataClient, input));
setContentType(ODataPubFormat.JSON.toString()); setContentType(ODataPubFormat.JSON.toString(odataClient.getServiceVersion()));
} }
} }

View File

@ -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.ODataBatchableRequest;
import org.apache.olingo.client.api.communication.request.retrieve.ODataRetrieveRequest; 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.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.format.Format;
import org.apache.olingo.client.api.http.HttpMethod; import org.apache.olingo.client.api.http.HttpMethod;
import org.apache.olingo.client.core.communication.request.AbstractODataBasicRequest; import org.apache.olingo.client.core.communication.request.AbstractODataBasicRequest;
import org.apache.olingo.client.core.communication.response.AbstractODataResponse; 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. * 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> extends AbstractODataBasicRequest<ODataRetrieveResponse<V>, T>
implements ODataRetrieveRequest<V, T>, ODataBatchableRequest { implements ODataRetrieveRequest<V, T>, ODataBatchableRequest {

View File

@ -92,7 +92,7 @@ public class ODataRawRequestImpl extends ODataRequestImpl<ODataPubFormat>
this.close(); this.close();
} }
} }
return odataClient.getReader().read(new ByteArrayInputStream(obj), getContentType(), reference); return odataClient.getReader().read(new ByteArrayInputStream(obj), getContentType(), reference);
} }

View File

@ -48,7 +48,7 @@ public abstract class AbstractODataStreamedEntityRequest<V extends ODataResponse
public AbstractODataStreamedEntityRequest(final CommonODataClient odataClient, final HttpMethod method, public AbstractODataStreamedEntityRequest(final CommonODataClient odataClient, final HttpMethod method,
URI uri) { URI uri) {
super(odataClient, method, 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 @Override
public final void setFormat(final ODataPubFormat format) { public final void setFormat(final ODataPubFormat format) {
this.format = format; this.format = format;
setAccept(format.toString()); setAccept(format.toString(odataClient.getServiceVersion()));
} }
} }

View File

@ -57,7 +57,7 @@ abstract class AbstractJsonDeserializer<T> extends ODataJacksonDeserializer<T> {
} }
private ODataPropertyType guessPropertyType(final JsonNode node) { private ODataPropertyType guessPropertyType(final JsonNode node) {
ODataPropertyType type = null; final ODataPropertyType type;
if (node.isValueNode() || node.isNull()) { if (node.isValueNode() || node.isNull()) {
type = ODataPropertyType.PRIMITIVE; type = ODataPropertyType.PRIMITIVE;
@ -73,7 +73,7 @@ abstract class AbstractJsonDeserializer<T> extends ODataJacksonDeserializer<T> {
} }
private Value fromPrimitive(final JsonNode node, final EdmTypeInfo typeInfo) { private Value fromPrimitive(final JsonNode node, final EdmTypeInfo typeInfo) {
Value value = null; final Value value;
if (node.isNull()) { if (node.isNull()) {
value = new NullValueImpl(); value = new NullValueImpl();
@ -172,5 +172,4 @@ abstract class AbstractJsonDeserializer<T> extends ODataJacksonDeserializer<T> {
property.setValue(new PrimitiveValueImpl(StringUtils.EMPTY)); property.setValue(new PrimitiveValueImpl(StringUtils.EMPTY));
} }
} }
} }

View File

@ -153,7 +153,6 @@ public class AtomDeserializer extends AbstractAtomDealer {
private void properties(final XMLEventReader reader, final StartElement start, final AtomEntryImpl entry) private void properties(final XMLEventReader reader, final StartElement start, final AtomEntryImpl entry)
throws XMLStreamException { throws XMLStreamException {
boolean foundEndProperties = false; boolean foundEndProperties = false;
while (reader.hasNext() && !foundEndProperties) { while (reader.hasNext() && !foundEndProperties) {
final XMLEvent event = reader.nextEvent(); final XMLEvent event = reader.nextEvent();
@ -316,7 +315,6 @@ public class AtomDeserializer extends AbstractAtomDealer {
boolean foundEndFeed = false; boolean foundEndFeed = false;
while (reader.hasNext() && !foundEndFeed) { while (reader.hasNext() && !foundEndFeed) {
final XMLEvent event = reader.nextEvent(); final XMLEvent event = reader.nextEvent();
if (event.isStartElement()) { if (event.isStartElement()) {
if (countQName.equals(event.asStartElement().getName())) { if (countQName.equals(event.asStartElement().getName())) {
count(reader, event.asStartElement(), feed); count(reader, event.asStartElement(), feed);

View File

@ -139,7 +139,7 @@ class AtomPropertyDeserializer extends AbstractAtomDealer {
} }
} }
ODataPropertyType type = null; final ODataPropertyType type;
if (child == null) { if (child == null) {
type = ODataPropertyType.PRIMITIVE; type = ODataPropertyType.PRIMITIVE;
} else { } else {
@ -168,16 +168,19 @@ class AtomPropertyDeserializer extends AbstractAtomDealer {
property.setName(start.getName().getLocalPart()); property.setName(start.getName().getLocalPart());
final Attribute typeAttr = start.getAttributeByName(this.typeQName); final Attribute typeAttr = start.getAttributeByName(this.typeQName);
if (typeAttr != null) {
property.setType(typeAttr.getValue());
}
Value value; Value value;
final Attribute nullAttr = start.getAttributeByName(this.nullQName); final Attribute nullAttr = start.getAttributeByName(this.nullQName);
final String typeAttrValue = typeAttr == null ? null : typeAttr.getValue();
if (nullAttr == null) { if (nullAttr == null) {
final EdmTypeInfo typeInfo = StringUtils.isBlank(property.getType()) final EdmTypeInfo typeInfo = StringUtils.isBlank(typeAttrValue)
? null ? 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 final ODataPropertyType propType = typeInfo == null
? guessPropertyType(reader) ? guessPropertyType(reader)
@ -207,6 +210,7 @@ class AtomPropertyDeserializer extends AbstractAtomDealer {
} else { } else {
value = new NullValueImpl(); value = new NullValueImpl();
} }
property.setValue(value); property.setValue(value);
return property; return property;

View File

@ -60,7 +60,7 @@ class JSONGeoValueDeserializer {
private MultiPoint multipoint(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, private MultiPoint multipoint(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
final String crs) { final String crs) {
MultiPoint multiPoint = null; final MultiPoint multiPoint;
if (itor.hasNext()) { if (itor.hasNext()) {
final List<Point> points = new ArrayList<Point>(); final List<Point> points = new ArrayList<Point>();
@ -79,7 +79,7 @@ class JSONGeoValueDeserializer {
private LineString lineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, private LineString lineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
final String crs) { final String crs) {
LineString lineString = null; final LineString lineString;
if (itor.hasNext()) { if (itor.hasNext()) {
final List<Point> points = new ArrayList<Point>(); final List<Point> points = new ArrayList<Point>();
@ -98,7 +98,7 @@ class JSONGeoValueDeserializer {
private MultiLineString multiLineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, private MultiLineString multiLineString(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
final String crs) { final String crs) {
MultiLineString multiLineString = null; final MultiLineString multiLineString;
if (itor.hasNext()) { if (itor.hasNext()) {
final List<LineString> lineStrings = new ArrayList<LineString>(); final List<LineString> lineStrings = new ArrayList<LineString>();
@ -147,7 +147,7 @@ class JSONGeoValueDeserializer {
private MultiPolygon multiPolygon(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, private MultiPolygon multiPolygon(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
final String crs) { final String crs) {
MultiPolygon multiPolygon = null; final MultiPolygon multiPolygon;
if (itor.hasNext()) { if (itor.hasNext()) {
final List<Polygon> polygons = new ArrayList<Polygon>(); final List<Polygon> polygons = new ArrayList<Polygon>();
@ -166,7 +166,7 @@ class JSONGeoValueDeserializer {
private GeospatialCollection collection(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type, private GeospatialCollection collection(final Iterator<JsonNode> itor, final EdmPrimitiveTypeKind type,
final String crs) { final String crs) {
GeospatialCollection collection = null; final GeospatialCollection collection;
if (itor.hasNext()) { if (itor.hasNext()) {
final List<Geospatial> geospatials = new ArrayList<Geospatial>(); final List<Geospatial> geospatials = new ArrayList<Geospatial>();
@ -262,5 +262,4 @@ class JSONGeoValueDeserializer {
return value; return value;
} }
} }

View File

@ -19,7 +19,6 @@
package org.apache.olingo.client.core.edm; package org.apache.olingo.client.core.edm;
import org.apache.olingo.client.api.edm.xml.v4.ActionImport; 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.Edm;
import org.apache.olingo.commons.api.edm.EdmAction; import org.apache.olingo.commons.api.edm.EdmAction;
import org.apache.olingo.commons.api.edm.EdmActionImport; import org.apache.olingo.commons.api.edm.EdmActionImport;

View File

@ -70,12 +70,12 @@ public abstract class EdmOperationImpl extends AbstractEdmOperation {
@Override @Override
public FullQualifiedName getBindingParameterTypeFqn() { public FullQualifiedName getBindingParameterTypeFqn() {
FullQualifiedName fqn = null; FullQualifiedName bpfqn = null;
final EdmParameter bindingParam = getBindingParameter(); final EdmParameter bindingParam = getBindingParameter();
if (bindingParam != null) { 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 @Override
@ -85,6 +85,6 @@ public abstract class EdmOperationImpl extends AbstractEdmOperation {
if (bindingParam != null) { if (bindingParam != null) {
result = bindingParam.isCollection(); result = bindingParam.isCollection();
} }
return null; return result;
} }
} }

View File

@ -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.EdmComplexType;
import org.apache.olingo.commons.api.edm.EdmEntityType; import org.apache.olingo.commons.api.edm.EdmEntityType;
import org.apache.olingo.commons.api.edm.EdmEnumType; 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.EdmPrimitiveTypeKind;
import org.apache.olingo.commons.api.edm.FullQualifiedName; import org.apache.olingo.commons.api.edm.FullQualifiedName;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -56,12 +57,11 @@ public class EdmTypeInfo {
} }
public EdmTypeInfo build() { public EdmTypeInfo build() {
return new EdmTypeInfo(edm, typeExpression.indexOf('.') == -1 return new EdmTypeInfo(edm, typeExpression.indexOf('.') == -1 && StringUtils.isNotBlank(defaultNamespace)
? defaultNamespace + "." + typeExpression ? defaultNamespace + "." + typeExpression
: typeExpression); : typeExpression);
} }
} }
private final Edm edm; private final Edm edm;
private final String typeExpression; private final String typeExpression;
@ -80,7 +80,6 @@ public class EdmTypeInfo {
private EdmTypeInfo(final Edm edm, final String typeExpression) { private EdmTypeInfo(final Edm edm, final String typeExpression) {
this.edm = edm; this.edm = edm;
this.typeExpression = typeExpression;
String baseType; String baseType;
final int collStartIdx = typeExpression.indexOf("Collection("); final int collStartIdx = typeExpression.indexOf("Collection(");
@ -97,16 +96,30 @@ public class EdmTypeInfo {
baseType = typeExpression.substring(collStartIdx + 11, collEndIdx); baseType = typeExpression.substring(collStartIdx + 11, collEndIdx);
} }
baseType = baseType.replaceAll("^#", "");
final String typeName;
final String namespace;
final int lastDotIdx = baseType.lastIndexOf('.'); final int lastDotIdx = baseType.lastIndexOf('.');
if (lastDotIdx == -1) { 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)) { if (StringUtils.isBlank(typeName)) {
throw new IllegalArgumentException("Null or empty type name in " + typeExpression); 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); this.fullQualifiedName = new FullQualifiedName(namespace, typeName);
try { try {
@ -168,5 +181,4 @@ public class EdmTypeInfo {
public EdmEntityType getEntityType() { public EdmEntityType getEntityType() {
return entityType; return entityType;
} }
} }

View File

@ -268,7 +268,7 @@ public abstract class AbstractODataBinder implements CommonODataBinder {
} }
final URI base = defaultBaseURI == null ? resource.getBaseURI() : defaultBaseURI; final URI base = defaultBaseURI == null ? resource.getBaseURI() : defaultBaseURI;
final URI next = resource.getNext(); final URI next = resource.getNext();
final ODataEntitySet entitySet = next == null final ODataEntitySet entitySet = next == null
@ -282,7 +282,7 @@ public abstract class AbstractODataBinder implements CommonODataBinder {
for (Entry entryResource : resource.getEntries()) { for (Entry entryResource : resource.getEntries()) {
entitySet.addEntity(getODataEntity(entryResource)); entitySet.addEntity(getODataEntity(entryResource));
} }
return entitySet; return entitySet;
} }
@ -310,11 +310,11 @@ public abstract class AbstractODataBinder implements CommonODataBinder {
if (StringUtils.isNotBlank(resource.getETag())) { if (StringUtils.isNotBlank(resource.getETag())) {
entity.setETag(resource.getETag()); entity.setETag(resource.getETag());
} }
if (resource.getEditLink() != null) { if (resource.getEditLink() != null) {
entity.setEditLink(URIUtils.getURI(base, resource.getEditLink().getHref())); entity.setEditLink(URIUtils.getURI(base, resource.getEditLink().getHref()));
} }
for (Link link : resource.getAssociationLinks()) { for (Link link : resource.getAssociationLinks()) {
entity.addLink(client.getObjectFactory().newAssociationLink(link.getTitle(), base, link.getHref())); entity.addLink(client.getObjectFactory().newAssociationLink(link.getTitle(), base, link.getHref()));
} }

View File

@ -103,5 +103,4 @@ public abstract class AbstractODataDeserializer extends AbstractJacksonTool impl
throw new IllegalArgumentException("While deserializing " + reference.getName(), e); throw new IllegalArgumentException("While deserializing " + reference.getName(), e);
} }
} }
} }

View File

@ -148,7 +148,7 @@ public class EntityRetrieveTestITCase extends AbstractTestITCase {
appendEntitySetSegment("Car").appendKeySegment(16); appendEntitySetSegment("Car").appendKeySegment(16);
final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build()); final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build());
req.setFormat(format.toString()); req.setFormat(format.toString(client.getServiceVersion()));
final ODataRawResponse res = req.execute(); final ODataRawResponse res = req.execute();
assertNotNull(res); assertNotNull(res);

View File

@ -138,7 +138,7 @@ public class EntitySetTestITCase extends AbstractTestITCase {
uriBuilder.appendEntitySetSegment("Car"); uriBuilder.appendEntitySetSegment("Car");
final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build()); final ODataRawRequest req = client.getRetrieveRequestFactory().getRawRequest(uriBuilder.build());
req.setFormat(format.toString()); req.setFormat(format.toString(client.getServiceVersion()));
final ODataRawResponse res = req.execute(); final ODataRawResponse res = req.execute();
assertNotNull(res); assertNotNull(res);

View File

@ -107,7 +107,8 @@ public class QueryOptionsTestITCase extends AbstractTestITCase {
final ODataRetrieveResponse<ODataEntity> res = req.execute(); final ODataRetrieveResponse<ODataEntity> res = req.execute();
assertNotNull(res); assertNotNull(res);
assertTrue(res.getContentType().replaceAll(" ", "").startsWith(ODataPubFormat.JSON.toString())); assertTrue(res.getContentType().replaceAll(" ", "").
startsWith(ODataPubFormat.JSON.toString(client.getServiceVersion())));
} }
/** /**

View File

@ -35,8 +35,8 @@ public abstract class AbstractTestITCase extends org.apache.olingo.client.core.i
@BeforeClass @BeforeClass
public static void setUpODataServiceRoot() throws IOException { public static void setUpODataServiceRoot() throws IOException {
testStaticServiceRootURL = "http://localhost:9080/StaticService/V30/Static.svc"; testStaticServiceRootURL = "http://localhost:9080/StaticService/V40/Static.svc";
testLargeModelServiceRootURL = "http://localhost:9080/StaticService/V30/Static.svc/large"; testLargeModelServiceRootURL = "http://localhost:9080/StaticService/V40/Static.svc/large";
testAuthServiceRootURL = "http://localhost:9080/DefaultService.svc"; testAuthServiceRootURL = "http://localhost:9080/DefaultService.svc";
} }

View File

@ -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);
}
}

View File

@ -26,92 +26,93 @@ import java.util.List;
* Interface representing a Entity Data Model as described in the Conceptual Schema Definition. * Interface representing a Entity Data Model as described in the Conceptual Schema Definition.
*/ */
public interface Edm { 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. * This method DOES NOT support lazy loading. All schemas are loaded completely!
* <br/> *
* See {@link EdmEntityContainer} for more information. * @return all schemas defined for this EDM
* */
* @param name List<EdmSchema> getSchemas();
* @return {@link EdmEntityContainer}
*/
EdmEntityContainer getEntityContainer(FullQualifiedName name);
/** /**
* Get enum type by full qualified name. * Get entity container by full qualified name.
* <br/> * <br/>
* See {@link EdmEnumType} for more information * See {@link EdmEntityContainer} for more information.
* *
* @param name * @param name
* @return {@link EdmEnumType} * @return {@link EdmEntityContainer}
*/ */
EdmEnumType getEnumType(FullQualifiedName name); EdmEntityContainer getEntityContainer(FullQualifiedName name);
/** /**
* Get a type definition by full qualified name. * Get enum type by full qualified name.
* <br/> * <br/>
* See {@link EdmTypeDefinition} for more information * See {@link EdmEnumType} for more information
* *
* @param name * @param name
* @return {@link EdmTypeDefinition} * @return {@link EdmEnumType}
*/ */
EdmTypeDefinition getTypeDefinition(FullQualifiedName name); EdmEnumType getEnumType(FullQualifiedName name);
/** /**
* Get entity type by full qualified name. * Get a type definition by full qualified name.
* <br/> * <br/>
* See {@link EdmEntityType} for more information. * See {@link EdmTypeDefinition} for more information
* *
* @param name * @param name
* @return {@link EdmEntityType} * @return {@link EdmTypeDefinition}
*/ */
EdmEntityType getEntityType(FullQualifiedName name); EdmTypeDefinition getTypeDefinition(FullQualifiedName name);
/** /**
* Get complex type by full qualified name.. * Get entity type by full qualified name.
* <br/> * <br/>
* See {@link EdmComplexType} for more information. * See {@link EdmEntityType} for more information.
* *
* @param name * @param name
* @return {@link EdmComplexType} * @return {@link EdmEntityType}
*/ */
EdmComplexType getComplexType(FullQualifiedName name); EdmEntityType getEntityType(FullQualifiedName name);
/** /**
* Get Action by full qualified name and binding parameter type. * Get complex type by full qualified name..
* * <br/>
* @param actionName must not be null * See {@link EdmComplexType} for more information.
* @param bindingParameterTypeName may be null if it is an unbound action *
* @param isBindingParameterCollection may be null if it is an unbound action * @param name
* @return {@link EdmAction} * @return {@link EdmComplexType}
*/ */
EdmAction getAction(FullQualifiedName actionName, FullQualifiedName bindingParameterTypeName, EdmComplexType getComplexType(FullQualifiedName name);
Boolean isBindingParameterCollection);
/** /**
* Get Function by full qualified name and binding parameter type and binding parameter names. * Get Action by full qualified name and binding parameter type.
* *
* @param functionName * @param actionName must not be null
* @param bindingParameterTypeName may be null if it is an unbound function * @param bindingParameterTypeName may be null if it is an unbound action
* @param isBindingParameterCollection may be null if it is an unbound function * @param isBindingParameterCollection may be null if it is an unbound action
* @param parameterNames may be null if it is an unbound function * @return {@link EdmAction}
* @return {@link EdmFunction} */
*/ EdmAction getAction(FullQualifiedName actionName, FullQualifiedName bindingParameterTypeName,
EdmFunction getFunction(FullQualifiedName functionName, FullQualifiedName bindingParameterTypeName, Boolean isBindingParameterCollection);
Boolean isBindingParameterCollection, List<String> parameterNames);
/** /**
* Get service metadata. * Get Function by full qualified name and binding parameter type and binding parameter names.
* <br/> *
* See {@link EdmServiceMetadata} for more information. * @param functionName
* * @param bindingParameterTypeName may be null if it is an unbound function
* @return {@link EdmServiceMetadata} * @param isBindingParameterCollection may be null if it is an unbound function
*/ * @param parameterNames may be null if it is an unbound function
EdmServiceMetadata getServiceMetadata(); * @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();
} }

View File

@ -23,5 +23,5 @@ package org.apache.olingo.commons.api.edm;
*/ */
public interface EdmActionImport extends EdmOperationImport { public interface EdmActionImport extends EdmOperationImport {
EdmAction getAction(); EdmAction getAction();
} }

View File

@ -40,8 +40,6 @@ public enum ODataServiceVersion {
public static final String NS_METADATA = "metadata"; 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 NS_SCHEME = "scheme";
public static final String NAVIGATION_LINK_REL = "navigationLinkRel"; 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_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(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/");
} }
}); });

View File

@ -27,24 +27,29 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
public abstract class AbstractEdmComplexType extends AbstractEdmStructuredType implements EdmComplexType { public abstract class AbstractEdmComplexType extends AbstractEdmStructuredType implements EdmComplexType {
public AbstractEdmComplexType(final Edm edm, final FullQualifiedName fqn, final FullQualifiedName baseTypeName) { public AbstractEdmComplexType(
super(edm, fqn, EdmTypeKind.COMPLEX, baseTypeName); final Edm edm,
} final FullQualifiedName fqn,
final FullQualifiedName baseTypeName) {
@Override super(edm, fqn, EdmTypeKind.COMPLEX, baseTypeName);
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());
}
} }
return baseType;
}
@Override @Override
public EdmComplexType getBaseType() { protected EdmStructuredType buildBaseType(final FullQualifiedName baseTypeName) {
return (EdmComplexType) baseType; // 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;
}
} }

View File

@ -33,119 +33,123 @@ import org.apache.olingo.commons.api.edm.FullQualifiedName;
public abstract class AbstractEdmEntityContainer extends EdmNamedImpl implements EdmEntityContainer { 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>(); protected final Map<String, EdmSingleton> singletons = new HashMap<String, EdmSingleton>();
private boolean allSingletonsLoaded = false;
protected final Map<String, EdmEntitySet> entitySets = new HashMap<String, EdmEntitySet>(); private boolean allSingletonsLoaded = false;
private boolean allEntitySetsLoaded = false;
protected final Map<String, EdmActionImport> actionImports = new HashMap<String, EdmActionImport>(); protected final Map<String, EdmEntitySet> entitySets = new HashMap<String, EdmEntitySet>();
private boolean allActionImportsLoaded = false;
protected final Map<String, EdmFunctionImport> functionImports = new HashMap<String, EdmFunctionImport>(); private boolean allEntitySetsLoaded = false;
private boolean allFunctionImportsLoaded = false;
public AbstractEdmEntityContainer(final Edm edm, final FullQualifiedName entityContainerName) { protected final Map<String, EdmActionImport> actionImports = new HashMap<String, EdmActionImport>();
super(edm, entityContainerName.getName());
this.entityContainerName = entityContainerName;
}
@Override private boolean allActionImportsLoaded = false;
public String getNamespace() {
return entityContainerName.getNamespace();
}
protected abstract EdmSingleton createSingleton(String singletonName); protected final Map<String, EdmFunctionImport> functionImports = new HashMap<String, EdmFunctionImport>();
@Override private boolean allFunctionImportsLoaded = false;
public EdmSingleton getSingleton(final String singletonName) {
EdmSingleton singleton = singletons.get(singletonName); public AbstractEdmEntityContainer(final Edm edm, final FullQualifiedName entityContainerName) {
if (singleton == null) { super(edm, entityContainerName.getName());
singleton = createSingleton(singletonName); this.entityContainerName = entityContainerName;
singletons.put(singletonName, singleton);
} }
return singleton;
}
protected abstract EdmEntitySet createEntitySet(String entitySetName); @Override
public String getNamespace() {
@Override return entityContainerName.getNamespace();
public EdmEntitySet getEntitySet(final String entitySetName) {
EdmEntitySet entitySet = entitySets.get(entitySetName);
if (entitySet == null) {
entitySet = createEntitySet(entitySetName);
entitySets.put(entitySetName, entitySet);
} }
return entitySet;
}
protected abstract EdmActionImport createActionImport(String actionImportName); protected abstract EdmSingleton createSingleton(String singletonName);
@Override @Override
public EdmActionImport getActionImport(final String actionImportName) { public EdmSingleton getSingleton(final String singletonName) {
EdmActionImport actionImport = actionImports.get(actionImportName); EdmSingleton singleton = singletons.get(singletonName);
if (actionImport == null) { if (singleton == null) {
actionImport = createActionImport(actionImportName); singleton = createSingleton(singletonName);
actionImports.put(actionImportName, actionImport); singletons.put(singletonName, singleton);
}
return singleton;
} }
return actionImport;
}
protected abstract EdmFunctionImport createFunctionImport(String functionImportName); protected abstract EdmEntitySet createEntitySet(String entitySetName);
@Override @Override
public EdmFunctionImport getFunctionImport(final String functionImportName) { public EdmEntitySet getEntitySet(final String entitySetName) {
EdmFunctionImport functionImport = functionImports.get(functionImportName); EdmEntitySet entitySet = entitySets.get(entitySetName);
if (functionImport == null) { if (entitySet == null) {
functionImport = createFunctionImport(functionImportName); entitySet = createEntitySet(entitySetName);
functionImports.put(functionImportName, functionImport); entitySets.put(entitySetName, entitySet);
}
return entitySet;
} }
return functionImport;
}
@Override protected abstract EdmActionImport createActionImport(String actionImportName);
public List<EdmEntitySet> getEntitySets() {
if (!allEntitySetsLoaded) { @Override
loadAllEntitySets(); public EdmActionImport getActionImport(final String actionImportName) {
allEntitySetsLoaded = true; 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 @Override
public List<EdmFunctionImport> getFunctionImports() { public EdmFunctionImport getFunctionImport(final String functionImportName) {
if (!allFunctionImportsLoaded) { EdmFunctionImport functionImport = functionImports.get(functionImportName);
loadAllFunctionImports(); if (functionImport == null) {
allFunctionImportsLoaded = true; functionImport = createFunctionImport(functionImportName);
functionImports.put(functionImportName, functionImport);
}
return functionImport;
} }
return new ArrayList<EdmFunctionImport>(functionImports.values());
}
protected abstract void loadAllFunctionImports(); @Override
public List<EdmEntitySet> getEntitySets() {
@Override if (!allEntitySetsLoaded) {
public List<EdmSingleton> getSingletons() { loadAllEntitySets();
if (!allSingletonsLoaded) { allEntitySetsLoaded = true;
loadAllSingletons(); }
allSingletonsLoaded = true; return new ArrayList<EdmEntitySet>(entitySets.values());
} }
return new ArrayList<EdmSingleton>(singletons.values());
}
protected abstract void loadAllSingletons(); protected abstract void loadAllEntitySets();
@Override @Override
public List<EdmActionImport> getActionImports() { public List<EdmFunctionImport> getFunctionImports() {
if (!allActionImportsLoaded) { if (!allFunctionImportsLoaded) {
loadAllActionImports(); loadAllFunctionImports();
allActionImportsLoaded = true; 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();
} }

View File

@ -35,80 +35,83 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
public abstract class AbstractEdmOperation extends EdmTypeImpl implements EdmOperation { 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) { protected AbstractEdmOperation(
super(edm, fqn, kind); final Edm edm,
} final FullQualifiedName fqn,
final EdmTypeKind kind) {
protected void setParameters(final List<EdmParameter> _parameters) { super(edm, fqn, kind);
for (EdmParameter parameter : _parameters) {
parameters.put(parameter.getName(), parameter);
} }
}
protected void setEntitySetPath(final String entitySetPath) { protected void setParameters(final List<EdmParameter> _parameters) {
this.entitySetPath = entitySetPath; for (EdmParameter parameter : _parameters) {
} parameters.put(parameter.getName(), parameter);
}
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);
}
} }
return parameterNames;
}
@Override protected void setEntitySetPath(final String entitySetPath) {
public EdmEntitySet getReturnedEntitySet(final EdmEntitySet bindingParameterEntitySet) { this.entitySetPath = entitySetPath;
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 protected void setIsBound(final boolean isBound) {
public EdmReturnType getReturnType() { this.isBound = isBound;
return returnType; }
}
@Override protected void setReturnType(final EdmReturnType returnType) {
public boolean isBound() { this.returnType = returnType;
return isBound; }
}
@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;
}
} }

View File

@ -27,37 +27,40 @@ import org.apache.olingo.commons.api.edm.Target;
public abstract class AbstractEdmOperationImport extends EdmNamedImpl implements EdmOperationImport { 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, public AbstractEdmOperationImport(
final Target entitySet) { final Edm edm,
final EdmEntityContainer container,
final String name,
final Target entitySet) {
super(edm, name); super(edm, name);
this.container = container; this.container = container;
this.entitySet = entitySet; 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());
}
} }
return returnedEntitySet;
}
@Override @Override
public EdmEntityContainer getEntityContainer() { public EdmEntitySet getReturnedEntitySet() {
return container; 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;
}
} }

View File

@ -34,96 +34,99 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
public abstract class AbstractEdmStructuredType extends EdmTypeImpl implements EdmStructuredType { 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, public AbstractEdmStructuredType(
final FullQualifiedName baseTypeName) { final Edm edm,
final FullQualifiedName fqn,
final EdmTypeKind kind,
final FullQualifiedName baseTypeName) {
super(edm, fqn, kind); 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;
}
} }
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;
}
} }

View File

@ -23,18 +23,17 @@ import org.apache.olingo.commons.api.edm.EdmNamed;
public abstract class EdmNamedImpl implements 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) { public EdmNamedImpl(final Edm edm, final String name) {
this.edm = edm; this.edm = edm;
this.name = name; this.name = name;
} }
@Override
public String getName() {
return name;
}
@Override
public String getName() {
return name;
}
} }

View File

@ -25,24 +25,23 @@ import org.apache.olingo.commons.api.edm.constants.EdmTypeKind;
public class EdmTypeImpl extends EdmNamedImpl implements EdmType { 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) { public EdmTypeImpl(final Edm edm, final FullQualifiedName fqn, final EdmTypeKind kind) {
super(edm, fqn.getName()); super(edm, fqn.getName());
this.fqn = fqn; this.fqn = fqn;
this.kind = kind; this.kind = kind;
} }
@Override @Override
public String getNamespace() { public String getNamespace() {
return fqn.getNamespace(); return fqn.getNamespace();
} }
@Override
public EdmTypeKind getKind() {
return kind;
}
@Override
public EdmTypeKind getKind() {
return kind;
}
} }