[OLINGO-253] fix v4 compliance + added tests for , ,

This commit is contained in:
fmartelli 2014-04-24 17:31:39 +02:00
parent fac8c0ae6f
commit 149c51c7a7
22 changed files with 1074 additions and 70 deletions

View File

@ -29,6 +29,7 @@ import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.URI;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.ConcurrentModificationException;
@ -417,7 +418,7 @@ public abstract class AbstractServices {
} else {
final Container<JSONEntryImpl> jcont = mapper.readValue(IOUtils.toInputStream(changes, Constants.ENCODING),
new TypeReference<JSONEntryImpl>() {
});
});
entryChanges = dataBinder.toAtomEntry(jcont.getObject());
}
@ -607,8 +608,8 @@ public abstract class AbstractServices {
} else {
final Container<JSONEntryImpl> jcontainer =
mapper.readValue(IOUtils.toInputStream(entity, Constants.ENCODING),
new TypeReference<JSONEntryImpl>() {
});
new TypeReference<JSONEntryImpl>() {
});
entry = dataBinder.toAtomEntry(jcontainer.getObject());
@ -635,7 +636,7 @@ public abstract class AbstractServices {
Container<AtomEntryImpl> result = atomDeserializer.read(serialization, AtomEntryImpl.class);
result = new Container<AtomEntryImpl>(
URI.create(Constants.get(version, ConstantKey.DEFAULT_SERVICE_URL)
+ "$metadata#" + entitySetName + "/$entity"), null, result.getObject());
+ "$metadata#" + entitySetName + "/$entity"), null, result.getObject());
final String path = Commons.getEntityBasePath(entitySetName, entityKey);
FSManager.instance(version).putInMemory(
@ -697,13 +698,13 @@ public abstract class AbstractServices {
replaceAll("\"Salary\":[0-9]*,", "\"Salary\":0,").
replaceAll("\"Title\":\".*\"", "\"Title\":\"[Sacked]\"").
replaceAll("\\<d:Salary m:type=\"Edm.Int32\"\\>.*\\</d:Salary\\>",
"<d:Salary m:type=\"Edm.Int32\">0</d:Salary>").
"<d:Salary m:type=\"Edm.Int32\">0</d:Salary>").
replaceAll("\\<d:Title\\>.*\\</d:Title\\>", "<d:Title>[Sacked]</d:Title>");
final FSManager fsManager = FSManager.instance(version);
fsManager.putInMemory(IOUtils.toInputStream(newContent, Constants.ENCODING),
fsManager.getAbsolutePath(Commons.getEntityBasePath("Person", entityId) + Constants.get(version,
ConstantKey.ENTITY), utils.getKey()));
ConstantKey.ENTITY), utils.getKey()));
return utils.getValue().createResponse(null, null, null, utils.getKey(), Response.Status.NO_CONTENT);
} catch (Exception e) {
@ -755,9 +756,9 @@ public abstract class AbstractServices {
final Long newSalary = Long.valueOf(salaryMatcher.group(1)) + n;
newContent = newContent.
replaceAll("\"Salary\":" + salaryMatcher.group(1) + ",",
"\"Salary\":" + newSalary + ",").
"\"Salary\":" + newSalary + ",").
replaceAll("\\<d:Salary m:type=\"Edm.Int32\"\\>" + salaryMatcher.group(1) + "</d:Salary\\>",
"<d:Salary m:type=\"Edm.Int32\">" + newSalary + "</d:Salary>");
"<d:Salary m:type=\"Edm.Int32\">" + newSalary + "</d:Salary>");
}
FSManager.instance(version).putInMemory(IOUtils.toInputStream(newContent, Constants.ENCODING),
@ -824,6 +825,8 @@ public abstract class AbstractServices {
@Context UriInfo uriInfo,
@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
@PathParam("name") String name,
@QueryParam("$top") @DefaultValue(StringUtils.EMPTY) String top,
@QueryParam("$skip") @DefaultValue(StringUtils.EMPTY) String skip,
@QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format,
@QueryParam("$inlinecount") @DefaultValue(StringUtils.EMPTY) String count,
@QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) String filter,
@ -880,6 +883,23 @@ public abstract class AbstractServices {
final ByteArrayOutputStream content = new ByteArrayOutputStream();
final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING);
// -----------------------------------------------
// Evaluate $skip and $top
// -----------------------------------------------
List<Entry> entries = new ArrayList<Entry>(container.getObject().getEntries());
if (StringUtils.isNotBlank(skip)) {
entries = entries.subList(Integer.valueOf(skip), entries.size());
}
if (StringUtils.isNotBlank(top)) {
entries = entries.subList(0, Integer.valueOf(top));
}
container.getObject().getEntries().clear();
container.getObject().getEntries().addAll(entries);
// -----------------------------------------------
if (acceptType == Accept.ATOM) {
atomSerializer.write(writer, container);
writer.flush();
@ -887,7 +907,7 @@ public abstract class AbstractServices {
} else {
mapper.writeValue(
writer, new JSONFeedContainer(container.getContextURL(), container.getMetadataETag(),
dataBinder.toJSONFeed(container.getObject())));
dataBinder.toJSONFeed(container.getObject())));
}
return xml.createResponse(
@ -1503,8 +1523,8 @@ public abstract class AbstractServices {
mapper.writeValue(
writer,
new JSONFeedContainer(container.getContextURL(),
container.getMetadataETag(),
dataBinder.toJSONFeed((AtomFeedImpl) container.getObject())));
container.getMetadataETag(),
dataBinder.toJSONFeed((AtomFeedImpl) container.getObject())));
}
} else {
final Container<Entry> container = atomDeserializer.<Entry, AtomEntryImpl>read(stream, AtomEntryImpl.class);
@ -1516,8 +1536,8 @@ public abstract class AbstractServices {
mapper.writeValue(
writer,
new JSONEntryContainer(container.getContextURL(),
container.getMetadataETag(),
dataBinder.toJSONEntry((AtomEntryImpl) container.getObject())));
container.getMetadataETag(),
dataBinder.toJSONEntry((AtomEntryImpl) container.getObject())));
}
}

View File

@ -30,6 +30,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.regex.Pattern;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMultipart;
import javax.ws.rs.DELETE;
@ -84,7 +85,12 @@ public class V4Services extends AbstractServices {
/**
* CR/LF.
*/
public static final byte[] CRLF = {13, 10};
protected static final byte[] CRLF = {13, 10};
protected static final Pattern RELENTITY_SELECT_PATTERN = Pattern.compile("^.*\\(\\$select=.*\\)$");
protected static final Pattern CROSSJOIN_PATTERN = Pattern.compile(
"^\\$crossjoin\\(.*\\)\\?\\$filter=\\([a-zA-Z/]+ eq [a-zA-Z/]+\\)$");
private Map<String, String> providedAsync = new HashMap<String, String>();
@ -92,6 +98,38 @@ public class V4Services extends AbstractServices {
super(ODataServiceVersion.V40);
}
@GET
@Path("/$crossjoin({elements:.*})")
public Response crossjoin(
@PathParam("elements") String elements,
@QueryParam("$filter") String filter) {
try {
if (CROSSJOIN_PATTERN.matcher("$crossjoin(" + elements + ")?$filter=" + filter).matches()) {
final InputStream feed = FSManager.instance(version).readFile("crossjoin", Accept.JSON);
return xml.createResponse(feed, null, Accept.JSON_FULLMETA);
} else {
throw new Exception("Unexpected crossjoin pattern");
}
} catch (Exception e) {
return xml.createFaultResponse(Accept.JSON.toString(version), e);
}
}
@GET
@Path("/relatedEntitySelect/{path:.*}")
public Response relatedEntitySelect(
@PathParam("path") String path,
@QueryParam("$expand") String expand) {
if (RELENTITY_SELECT_PATTERN.matcher(expand).matches()) {
return xml.createResponse(null, null, Accept.JSON_FULLMETA);
} else {
return xml.createFaultResponse(Accept.JSON.toString(version), new Exception("Unexpected expand pattern"));
}
}
@DELETE
@Path("/monitor/{name}")
public Response removeMonitor(@Context final UriInfo uriInfo, @PathParam("name") final String name) {
@ -530,7 +568,7 @@ public class V4Services extends AbstractServices {
return utils.getValue().createResponse(
FSManager.instance(version).readFile(Constants.get(version, ConstantKey.REF)
+ File.separatorChar + filename, utils.getKey()),
+ File.separatorChar + filename, utils.getKey()),
null,
utils.getKey());
} catch (Exception e) {
@ -552,7 +590,7 @@ public class V4Services extends AbstractServices {
final Response response =
getEntityInternal(uriInfo.getRequestUri().toASCIIString(),
accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY, false);
accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY, false);
return response.getStatus() >= 400
? postNewEntity(uriInfo, accept, contentType, prefer, entitySetName, changes)
: super.patchEntity(uriInfo, accept, contentType, prefer, ifMatch, entitySetName, entityId, changes);
@ -650,8 +688,8 @@ public class V4Services extends AbstractServices {
} else {
final Container<JSONEntryImpl> jcontainer =
mapper.readValue(IOUtils.toInputStream(entity, Constants.ENCODING),
new TypeReference<JSONEntryImpl>() {
});
new TypeReference<JSONEntryImpl>() {
});
entry = dataBinder.toAtomEntry(jcontainer.getObject());
@ -749,7 +787,7 @@ public class V4Services extends AbstractServices {
final Container<JSONEntryImpl> jsonContainer = mapper.readValue(
IOUtils.toInputStream(changes, Constants.ENCODING), new TypeReference<JSONEntryImpl>() {
});
});
jsonContainer.getObject().setType(typeInfo.getFullQualifiedName().toString());
entryChanges = dataBinder.toAtomEntry(jsonContainer.getObject());
}
@ -782,7 +820,7 @@ public class V4Services extends AbstractServices {
// 1. Fetch the contained entity to be removed
final InputStream entry = FSManager.instance(version).
readFile(containedPath(entityId, containedEntitySetName).
append('(').append(containedEntityId).append(')').toString(), Accept.ATOM);
append('(').append(containedEntityId).append(')').toString(), Accept.ATOM);
final Container<AtomEntryImpl> container = atomDeserializer.read(entry, AtomEntryImpl.class);
// 2. Remove the contained entity
@ -910,7 +948,7 @@ public class V4Services extends AbstractServices {
@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) String accept,
@QueryParam("$format") @DefaultValue(StringUtils.EMPTY) String format) {
return getEntitySet(uriInfo, accept, "Products", format, null, null, null, null);
return getEntitySet(uriInfo, accept, "Products", null, null, format, null, null, null, null);
}
@GET
@ -1011,8 +1049,8 @@ public class V4Services extends AbstractServices {
} else {
final Container<JSONPropertyImpl> paramContainer =
mapper.readValue(IOUtils.toInputStream(param, Constants.ENCODING),
new TypeReference<JSONPropertyImpl>() {
});
new TypeReference<JSONPropertyImpl>() {
});
property = paramContainer.getObject();
}
@ -1053,8 +1091,8 @@ public class V4Services extends AbstractServices {
} else {
final Container<JSONPropertyImpl> paramContainer =
mapper.readValue(IOUtils.toInputStream(param, Constants.ENCODING),
new TypeReference<JSONPropertyImpl>() {
});
new TypeReference<JSONPropertyImpl>() {
});
property = paramContainer.getObject();
}

View File

@ -1,10 +1,10 @@
{
"@odata.context": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Customers",
"@odata.context": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/$metadata#Customers",
"value":
[
{
"@odata.id": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)",
"@odata.editLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)",
"@odata.id": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/Customers(PersonID=1)",
"@odata.editLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/Customers(PersonID=1)",
"PersonID": 1,
"FirstName": "Bob",
"LastName": "Cat",
@ -51,8 +51,8 @@
"TimeBetweenLastTwoOrders": "PT0.0000001S"
},
{
"@odata.id": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)",
"@odata.editLink": "http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)",
"@odata.id": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/Customers(PersonID=2)",
"@odata.editLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/Customers(PersonID=2)",
"PersonID": 2,
"FirstName": "Jill",
"LastName": "Jones",

View File

@ -19,17 +19,17 @@
under the License.
-->
<feed xml:base="http://odatae2etest.azurewebsites.net/javatest/DefaultService/" 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://odatae2etest.azurewebsites.net/javatest/DefaultService/$metadata#Customers">
<id>http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers</id>
<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#Customers">
<id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/Customers</id>
<title />
<updated>2014-04-23T10:01:18Z</updated>
<entry>
<id>http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)</id>
<id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/Customers(PersonID=1)</id>
<category term="#Microsoft.Test.OData.Services.ODataWCFService.Customer" scheme="http://docs.oasis-open.org/odata/ns/scheme" />
<link rel="edit" href="http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)" />
<link rel="http://docs.oasis-open.org/odata/ns/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)/Parent" />
<link rel="http://docs.oasis-open.org/odata/ns/related/Orders" type="application/atom+xml;type=feed" title="Orders" href="http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)/Orders" />
<link rel="http://docs.oasis-open.org/odata/ns/related/Company" type="application/atom+xml;type=entry" title="Company" href="http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=1)/Company" />
<link rel="edit" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/Customers(PersonID=1)" />
<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/Customers(PersonID=1)/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/Customers(PersonID=1)/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/Customers(PersonID=1)/Company" />
<title />
<updated>2014-04-23T10:01:18Z</updated>
<author>
@ -69,12 +69,12 @@
</content>
</entry>
<entry>
<id>http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)</id>
<id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/Customers(PersonID=2)</id>
<category term="#Microsoft.Test.OData.Services.ODataWCFService.Customer" scheme="http://docs.oasis-open.org/odata/ns/scheme" />
<link rel="edit" href="http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)" />
<link rel="http://docs.oasis-open.org/odata/ns/related/Parent" type="application/atom+xml;type=entry" title="Parent" href="http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)/Parent" />
<link rel="http://docs.oasis-open.org/odata/ns/related/Orders" type="application/atom+xml;type=feed" title="Orders" href="http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)/Orders" />
<link rel="http://docs.oasis-open.org/odata/ns/related/Company" type="application/atom+xml;type=entry" title="Company" href="http://odatae2etest.azurewebsites.net/javatest/DefaultService/Customers(PersonID=2)/Company" />
<link rel="edit" href="http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/Customers(PersonID=2)" />
<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/Customers(PersonID=2)/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/Customers(PersonID=2)/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/Customers(PersonID=2)/Company" />
<title />
<updated>2014-04-23T10:01:18Z</updated>
<author>

View File

@ -0,0 +1,55 @@
{
"@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(5)",
"@odata.editLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)/Microsoft.Test.OData.Services.ODataWCFService.Customer",
"PersonID": 5,
"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":
{
"type": "Point",
"coordinates":
[
23.1,
32.1
],
"crs":
{
"type": "name",
"properties":
{
"name": "EPSG:4326"
}
}
},
"Numbers":
[
"111-111-1111",
"012",
"310",
"bca",
"ayz"
],
"Emails":
[
"abc@abc.com"
],
"City": "London",
"Birthday": "1957-04-03T00:00:00Z",
"TimeBetweenLastTwoOrders": "PT0.0000001S"
}
]
}

View File

@ -0,0 +1,58 @@
<?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-04-24T11:35:03Z</updated>
<entry>
<id>http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(5)</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(5)/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(5)/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(5)/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(5)/Microsoft.Test.OData.Services.ODataWCFService.Customer/Company" />
<title />
<updated>2014-04-24T11:35:03Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:PersonID m:type="Int32">5</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>
</feed>

View File

@ -0,0 +1,91 @@
{
"@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":
{
"type": "Point",
"coordinates":
[
23.1,
32.1
],
"crs":
{
"type": "name",
"properties":
{
"name": "EPSG:4326"
}
}
},
"Numbers":
[
"111-111-1111",
"012",
"310",
"bca",
"ayz"
],
"Emails":
[
"abc@abc.com"
],
"City": "London",
"Birthday": "1957-04-03T00:00:00Z",
"TimeBetweenLastTwoOrders": "PT0.0000001S"
},
{
"@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":
{
"type": "Point",
"coordinates":
[
161.8,
15
],
"crs":
{
"type": "name",
"properties":
{
"name": "EPSG:4326"
}
}
},
"Numbers":
[
],
"Emails":
[
],
"City": "Sydney",
"Birthday": "1983-01-15T00:00:00Z",
"TimeBetweenLastTwoOrders": "PT0.0000002S"
}
]
}

View File

@ -0,0 +1,103 @@
<?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-04-24T11:33:37Z</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-04-24T11:33:37Z</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>
<m:element>012</m:element>
<m:element>310</m:element>
<m:element>bca</m:element>
<m:element>ayz</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-04-24T11:33:37Z</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>
</feed>

View File

@ -0,0 +1,91 @@
{
"@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(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":
{
"type": "Point",
"coordinates":
[
161.8,
15
],
"crs":
{
"type": "name",
"properties":
{
"name": "EPSG:4326"
}
}
},
"Numbers":
[
],
"Emails":
[
],
"City": "Sydney",
"Birthday": "1983-01-15T00:00:00Z",
"TimeBetweenLastTwoOrders": "PT0.0000002S"
},
{
"@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":
{
"type": "Point",
"coordinates":
[
23.1,
32.1
],
"crs":
{
"type": "name",
"properties":
{
"name": "EPSG:4326"
}
}
},
"Numbers":
[
"111-111-1111",
"012",
"310",
"bca",
"ayz"
],
"Emails":
[
"abc@abc.com"
],
"City": "London",
"Birthday": "1957-04-03T00:00:00Z",
"TimeBetweenLastTwoOrders": "PT0.0000001S"
}
]
}

View File

@ -0,0 +1,103 @@
<?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-04-24T11:35:03Z</updated>
<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-04-24T11:35:03Z</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(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-04-24T11:35:03Z</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>
<m:element>012</m:element>
<m:element>310</m:element>
<m:element>bca</m:element>
<m:element>ayz</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>
</feed>

View File

@ -0,0 +1,56 @@
{
"@odata.context": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/$metadata#People",
"value":
[
{
"@odata.type": "#Microsoft.Test.OData.Services.ODataWCFService.Person",
"@odata.id": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(6)",
"@odata.editLink": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/People(6)",
"PersonID": 6,
"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,62 @@
<?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(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(6)" />
<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(6)/Parent" />
<title />
<updated>2014-03-20T14:31:00Z</updated>
<author>
<name />
</author>
<content type="application/xml">
<m:properties>
<d:PersonID m:type="Int32">6</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

@ -0,0 +1,18 @@
{
"@odata.context": "http://localhost:${cargo.servlet.port}/StaticService/V40/Static.svc/$metadata#Customers",
"value":
[
{
"Products@odata.navigationLink": "Products(0)",
"Sales@odata.navigationLink": "Sales(42)"
},
{
"Products@odata.navigationLink": "Products(0)",
"Sales@odata.navigationLink": "Sales(57)"
},
{
"Products@odata.navigationLink": "Products(99)",
"Sales@odata.navigationLink": "Sales(21)"
}
]
}

View File

@ -119,4 +119,16 @@ public interface URIBuilder extends CommonURIBuilder<URIBuilder> {
* @see org.apache.olingo.client.api.uri.QueryOption#EXPAND
*/
URIBuilder expandWithOptions(String expandItem, Map<String, Object> options);
/**
* Properties of related entities can be specified by including the $select query option within the $expand.
* <br />
* <tt>http://host/service/Products?$expand=Category($select=Name)</tt>
* @param expandItem related entity name.
* @param selectItems properties to be selected.
* @return current URIBuilder instance.
* @see org.apache.olingo.client.api.uri.QueryOption#EXPAND
* @see org.apache.olingo.client.api.uri.QueryOption#SELECT
*/
URIBuilder expandWithSelect(String expandItem, String... selectItems);
}

View File

@ -23,7 +23,6 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@ -104,7 +103,12 @@ public abstract class AbstractURIBuilder<UB extends CommonURIBuilder<?>> impleme
@Override
public UB addQueryOption(final String option, final String value) {
queryOptions.put(option, value);
final StringBuilder builder = new StringBuilder();
if (queryOptions.containsKey(option)) {
builder.append(queryOptions.get(option)).append(',');
}
builder.append(value);
queryOptions.put(option, builder.toString());
return getThis();
}
@ -199,14 +203,7 @@ public abstract class AbstractURIBuilder<UB extends CommonURIBuilder<?>> impleme
@Override
public UB expand(final String... expandItems) {
final List<String> values = new ArrayList<String>();
if (queryOptions.containsKey(QueryOption.EXPAND.toString())) {
values.add(queryOptions.get(QueryOption.EXPAND.toString()));
}
values.addAll(Arrays.asList(expandItems));
return addQueryOption(QueryOption.EXPAND, StringUtils.join(values, ","));
return addQueryOption(QueryOption.EXPAND, StringUtils.join(expandItems, ","));
}
@Override
@ -231,14 +228,7 @@ public abstract class AbstractURIBuilder<UB extends CommonURIBuilder<?>> impleme
@Override
public UB select(final String... selectItems) {
final List<String> values = new ArrayList<String>();
if (queryOptions.containsKey(QueryOption.SELECT.toString())) {
values.add(queryOptions.get(QueryOption.SELECT.toString()));
}
values.addAll(Arrays.asList(selectItems));
return addQueryOption(QueryOption.SELECT, StringUtils.join(values, ","));
return addQueryOption(QueryOption.SELECT, StringUtils.join(selectItems, ","));
}
@Override

View File

@ -134,4 +134,9 @@ public class URIBuilderImpl extends AbstractURIBuilder<URIBuilder> implements UR
public URIBuilder expandWithOptions(final String expandItem, final Map<String, Object> options) {
return expand(expandItem + buildMultiKeySegment(options, false));
}
@Override
public URIBuilder expandWithSelect(final String expandItem, final String... selectItems) {
return expand(expandItem + "($select=" + StringUtils.join(selectItems, ",") + ")");
}
}

View File

@ -47,7 +47,7 @@ public class QueryOptionsTestITCase extends AbstractTestITCase {
/**
* Test <tt>$expand</tt>.
*
* @see EntityRetrieveTest#readODataEntityWithInline(com.msopentech.odatajclient.engine.types.ODataPubFormat)
* @see EntityRetrieveTest#readODataEntityWithInline(org.apache.olingo.commons.api.format.ODataPubFormat)
*/
public void expand() {
// empty
@ -115,7 +115,7 @@ public class QueryOptionsTestITCase extends AbstractTestITCase {
/**
* Test <tt>$skip</tt>.
*
* @see FeedTest#readFeedWithNextLink(com.msopentech.odatajclient.engine.types.ODataPubFormat)
* @see FeedTest#readFeedWithNextLink(org.apache.olingo.commons.api.format.ODataPubFormat)
*/
public void skip() {
// empty
@ -124,7 +124,7 @@ public class QueryOptionsTestITCase extends AbstractTestITCase {
/**
* Test <tt>$top</tt>.
*
* @see FeedTest#readFeed(com.msopentech.odatajclient.engine.types.ODataPubFormat)
* @see FeedTest#readFeed(org.apache.olingo.commons.api.format.ODataPubFormat)
*/
public void top() {
// empty

View File

@ -0,0 +1,64 @@
/*
* 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 org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
import static org.junit.Assert.assertEquals;
import org.apache.olingo.client.api.uri.URIFilter;
import org.apache.olingo.client.api.uri.v4.FilterArgFactory;
import org.apache.olingo.client.api.uri.v4.FilterFactory;
import org.apache.olingo.client.api.uri.v4.URIBuilder;
import static org.apache.olingo.client.core.it.v4.AbstractTestITCase.client;
import org.apache.olingo.commons.api.domain.v4.ODataEntity;
import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
import org.apache.olingo.commons.api.format.ODataPubFormat;
import org.junit.Test;
public class FilterFactoryTestITCase extends AbstractTestITCase {
private FilterFactory getFilterFactory() {
return getClient().getFilterFactory();
}
private FilterArgFactory getFilterArgFactory() {
return getFilterFactory().getArgFactory();
}
@Test
public void crossjoin() {
final URIFilter filter = getFilterFactory().eq(
getFilterArgFactory().property("Orders/OrderID"), getFilterArgFactory().property("Customers/Order"));
final URIBuilder uriBuilder =
client.getURIBuilder(testStaticServiceRootURL).appendCrossjoinSegment("Customers", "Orders").filter(filter);
final ODataEntitySetRequest<ODataEntitySet> req =
client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build());
req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
final ODataEntitySet feed = req.execute().getBody();
assertEquals(3, feed.getEntities().size());
for (ODataEntity entity : feed.getEntities()) {
assertEquals(2, entity.getNavigationLinks().size());
}
}
}

View File

@ -27,7 +27,6 @@ import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRe
import org.apache.olingo.client.api.communication.response.ODataEntityUpdateResponse;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.uri.v4.URIBuilder;
import static org.apache.olingo.client.core.it.v4.AbstractTestITCase.testStaticServiceRootURL;
import org.apache.olingo.commons.api.domain.v4.ODataEntity;
import org.apache.olingo.commons.api.domain.v4.ODataProperty;
import org.apache.olingo.commons.api.edm.FullQualifiedName;

View File

@ -0,0 +1,215 @@
/*
* 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 static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.apache.olingo.client.api.communication.request.retrieve.ODataEntityRequest;
import org.apache.olingo.client.api.communication.request.retrieve.ODataEntitySetRequest;
import org.apache.olingo.client.api.communication.response.ODataRetrieveResponse;
import org.apache.olingo.client.api.uri.v4.URIBuilder;
import static org.apache.olingo.client.core.it.v4.AbstractTestITCase.client;
import org.apache.olingo.commons.api.domain.ODataInlineEntitySet;
import org.apache.olingo.commons.api.domain.v4.ODataEntity;
import org.apache.olingo.commons.api.domain.v4.ODataEntitySet;
import org.apache.olingo.commons.api.edm.EdmPrimitiveTypeException;
import org.apache.olingo.commons.api.format.ODataPubFormat;
import org.junit.Test;
/**
* This is the unit test class to check for query options.
*/
public class QueryOptionsTestITCase extends AbstractTestITCase {
/**
* Test <tt>$expand</tt>.
*/
public void expand() {
final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
appendEntitySetSegment("Customers").appendKeySegment(1).expand("Orders");
final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
final ODataEntity customer = req.execute().getBody();
assertTrue(customer.getNavigationLink("Orders") instanceof ODataInlineEntitySet);
}
/**
* Test <tt>$filter</tt> and <tt>$orderby</tt>.
*
* @see org.apache.olingo.client.core.v3.FilterFactoryTest for more tests.
*/
@Test
public void filterOrderby() throws EdmPrimitiveTypeException {
final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
appendEntitySetSegment("People").filter("(PersonID lt 3)");
// 1. check that filtered entity set looks as expected
ODataEntitySetRequest<ODataEntitySet> req =
client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build());
req.setFormat(ODataPubFormat.JSON);
ODataEntitySet feed = req.execute().getBody();
assertNotNull(feed);
assertEquals(2, feed.getEntities().size());
// 2. extract PersonID values - sorted ASC by default
final List<Integer> former = new ArrayList<Integer>(2);
for (ODataEntity entity : feed.getEntities()) {
final Integer personID = entity.getProperty("PersonID").getPrimitiveValue().toCastValue(Integer.class);
assertTrue(personID < 3);
former.add(personID);
}
// 3. add orderby clause to filter above
req = client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.orderBy("PersonID desc").build());
req.setFormat(ODataPubFormat.JSON);
feed = req.execute().getBody();
assertNotNull(feed);
assertEquals(2, feed.getEntities().size());
// 4. extract again VIN value - now they were required to be sorted DESC
final List<Integer> latter = new ArrayList<Integer>(2);
for (ODataEntity entity : feed.getEntities()) {
final Integer personID = entity.getProperty("PersonID").getPrimitiveValue().toCastValue(Integer.class);
assertTrue(personID < 3);
latter.add(personID);
}
// 5. reverse latter and expect to be equal to former
Collections.reverse(latter);
assertEquals(former, latter);
}
/**
* Test <tt>$format</tt>.
*/
@Test
public void format() {
final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
appendEntitySetSegment("Customers").appendKeySegment(1).format("json");
final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
req.setFormat(ODataPubFormat.ATOM);
final ODataRetrieveResponse<ODataEntity> res = req.execute();
assertNotNull(res);
assertTrue(res.getContentType().replaceAll(" ", "").
startsWith(ODataPubFormat.JSON.toString(client.getServiceVersion())));
}
/**
* Test <tt>$skip</tt>.
*/
public void skip() {
final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("People");
// 1. check that filtered entity set looks as expected
ODataEntitySetRequest<ODataEntitySet> req =
client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.skip(2).build());
ODataEntitySet feed = req.execute().getBody();
assertEquals(3, feed.getEntities().size());
}
/**
* Test <tt>$top</tt>.
*/
public void top() {
final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("People");
// 1. check that filtered entity set looks as expected
ODataEntitySetRequest<ODataEntitySet> req = client.getRetrieveRequestFactory().
getEntitySetRequest(uriBuilder.top(2).build());
ODataEntitySet feed = req.execute().getBody();
assertEquals(2, feed.getEntities().size());
}
/**
* Test <tt>$skiptoken</tt>.
*/
@Test
public void skiptoken() throws EdmPrimitiveTypeException {
final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL);
uriBuilder.appendEntitySetSegment("People").skipToken("5");
final ODataEntitySetRequest<ODataEntitySet> req =
client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build());
req.setFormat(ODataPubFormat.JSON);
final ODataEntitySet feed = req.execute().getBody();
assertNotNull(feed);
assertEquals(1, feed.getEntities().size());
for (ODataEntity entity : feed.getEntities()) {
assertTrue(entity.getProperty("PersonID").getPrimitiveValue().toCastValue(Integer.class) > 5);
}
}
/**
* Test <tt>$inlinecount</tt>.
*/
@Test
public void inlinecount() {
final URIBuilder uriBuilder =
client.getURIBuilder(testStaticServiceRootURL).appendEntitySetSegment("Customers").count(true);
final ODataEntitySetRequest<ODataEntitySet> req =
client.getRetrieveRequestFactory().getEntitySetRequest(uriBuilder.build());
req.setFormat(ODataPubFormat.JSON);
final ODataEntitySet feed = req.execute().getBody();
assertNotNull(feed);
assertEquals(feed.getEntities().size(), feed.getCount());
}
/**
* Test <tt>$select</tt>.
*/
@Test
public void select() {
final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
appendEntitySetSegment("Customers").appendKeySegment(1).select("PersonID,Orders").expand("Orders");
final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
final ODataEntity customer = req.execute().getBody();
assertEquals(1, customer.getProperties().size());
assertEquals(1, customer.getNavigationLinks().size());
assertTrue((customer.getNavigationLinks().get(0) instanceof ODataInlineEntitySet));
}
@Test
public void issue253() {
final URIBuilder uriBuilder = client.getURIBuilder(testStaticServiceRootURL).
appendEntitySetSegment("relatedEntitySelect").appendEntitySetSegment("Customers").appendKeySegment(1).
expandWithSelect("Orders", "OrderID", "OrderDetails");
final ODataEntityRequest<ODataEntity> req = client.getRetrieveRequestFactory().getEntityRequest(uriBuilder.build());
req.setFormat(ODataPubFormat.JSON_FULL_METADATA);
final ODataRetrieveResponse<ODataEntity> res = req.execute();
assertEquals(200, res.getStatusCode());
}
}

View File

@ -85,15 +85,15 @@ public class JSONTest extends AbstractTest {
if (field.getKey().charAt(0) == '#'
|| field.getKey().endsWith(
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_TYPE))
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_TYPE))
|| field.getKey().endsWith(
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_MEDIAEDIT_LINK))
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_MEDIAEDIT_LINK))
|| field.getKey().endsWith(
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_MEDIA_CONTENT_TYPE))
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_MEDIA_CONTENT_TYPE))
|| field.getKey().endsWith(
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_ASSOCIATION_LINK))
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_ASSOCIATION_LINK))
|| field.getKey().endsWith(
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_MEDIA_ETAG))) {
getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_MEDIA_ETAG))) {
toRemove.add(field.getKey());
} else if (field.getValue().isObject()) {
@ -113,7 +113,7 @@ public class JSONTest extends AbstractTest {
protected void assertSimilar(final String filename, final String actual) throws Exception {
final JsonNode expected = OBJECT_MAPPER.readTree(IOUtils.toString(getClass().getResourceAsStream(filename)).
replace(getClient().getServiceVersion().getJSONMap().get(ODataServiceVersion.JSON_NAVIGATION_LINK),
Constants.JSON_BIND_LINK_SUFFIX));
Constants.JSON_BIND_LINK_SUFFIX));
cleanup((ObjectNode) expected);
final ObjectNode actualNode = (ObjectNode) OBJECT_MAPPER.readTree(new ByteArrayInputStream(actual.getBytes()));
cleanup(actualNode);
@ -175,4 +175,10 @@ public class JSONTest extends AbstractTest {
property("Employees_3_HomeAddress", getODataFormat());
property("Employees_3_HomeAddress", getODataFormat());
}
@Test
public void crossjoin() throws Exception {
getClient().getDeserializer().toFeed(
getClass().getResourceAsStream("crossjoin.json"), ODataPubFormat.JSON_FULL_METADATA);
}
}

View File

@ -0,0 +1,18 @@
{
"@odata.context": "http://host/service/$metadata#Collection(Edm.ComplexType)",
"value":
[
{
"Products@odata.navigationLink": "Products(0)",
"Sales@odata.navigationLink": "Sales(42)"
},
{
"Products@odata.navigationLink": "Products(0)",
"Sales@odata.navigationLink": "Sales(57)"
},
{
"Products@odata.navigationLink": "Products(99)",
"Sales@odata.navigationLink": "Sales(21)"
}
]
}