Java tutorial
/* * 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; import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.apache.cxf.interceptor.InInterceptors; import org.apache.cxf.jaxrs.ext.multipart.Attachment; import org.apache.cxf.jaxrs.ext.multipart.Multipart; import org.apache.cxf.jaxrs.ext.multipart.MultipartBody; import org.apache.olingo.commons.api.data.Entity; import org.apache.olingo.commons.api.data.EntitySet; import org.apache.olingo.commons.api.data.Link; import org.apache.olingo.commons.api.data.Property; import org.apache.olingo.commons.api.data.ResWrap; import org.apache.olingo.commons.api.data.ValueType; import org.apache.olingo.commons.api.edm.constants.ODataServiceVersion; import org.apache.olingo.commons.api.format.ContentType; import org.apache.olingo.commons.core.data.EntityImpl; import org.apache.olingo.commons.core.data.EntitySetImpl; import org.apache.olingo.commons.core.data.LinkImpl; import org.apache.olingo.commons.core.data.PropertyImpl; import org.apache.olingo.commons.core.edm.EdmTypeInfo; import org.apache.olingo.fit.metadata.Metadata; import org.apache.olingo.fit.methods.PATCH; import org.apache.olingo.fit.rest.ResolvingReferencesInterceptor; import org.apache.olingo.fit.rest.XHTTPMethodInterceptor; import org.apache.olingo.fit.utils.AbstractUtilities; import org.apache.olingo.fit.utils.Accept; import org.apache.olingo.fit.utils.Commons; import org.apache.olingo.fit.utils.ConstantKey; import org.apache.olingo.fit.utils.Constants; import org.apache.olingo.fit.utils.FSManager; import org.apache.olingo.fit.utils.LinkInfo; import org.springframework.stereotype.Service; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMultipart; import javax.ws.rs.Consumes; import javax.ws.rs.DELETE; import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.NotFoundException; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import javax.ws.rs.core.Response.Status; import javax.ws.rs.core.UriInfo; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.OutputStreamWriter; import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.regex.Pattern; import javax.ws.rs.BadRequestException; @Service @Path("/V40/Static.svc") @InInterceptors(classes = { XHTTPMethodInterceptor.class, ResolvingReferencesInterceptor.class }) public class V4Services extends AbstractServices { /** * CR/LF. */ 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 final Map<String, String> providedAsync = new HashMap<String, String>(); public V4Services() throws IOException { super(ODataServiceVersion.V40, Commons.getMetadata(ODataServiceVersion.V40)); } protected V4Services(final Metadata metadata) throws IOException { super(ODataServiceVersion.V40, metadata); } @GET @Path("/redirect/{name}({id})") public Response conformanceRedirect(@Context final UriInfo uriInfo, @PathParam("name") final String name, @PathParam("id") final String id) { return Response .temporaryRedirect(URI.create(uriInfo.getRequestUri().toASCIIString().replace("/redirect", ""))) .build(); } @GET @Path("/$crossjoin({elements:.*})") public Response crossjoin(@PathParam("elements") final String elements, @QueryParam("$filter") final 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 IOException("Unexpected crossjoin pattern"); } } catch (Exception e) { return xml.createFaultResponse(Accept.JSON.toString(version), e); } } @GET @Path("/relatedEntitySelect/{path:.*}") public Response relatedEntitySelect(@PathParam("path") final String path, @QueryParam("$expand") final 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(@PathParam("name") final String name) { providedAsync.remove(name); return xml.createResponse(null, null, null, Status.NO_CONTENT); } @GET @Path("/monitor/{name}") public Response async(@PathParam("name") final String name) { try { if (!providedAsync.containsKey(name)) { throw new NotFoundException(); } final InputStream res = IOUtils.toInputStream(providedAsync.get(name), Constants.ENCODING); providedAsync.remove(name); return xml.createMonitorResponse(res); } catch (Exception e) { return xml.createFaultResponse(Accept.JSON_FULLMETA.toString(), e); } } @POST @Path("/async/$batch") public Response async(@Context final UriInfo uriInfo, @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer, final @Multipart MultipartBody attachment) { try { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); bos.write("HTTP/1.1 200 Ok".getBytes()); bos.write(CRLF); bos.write("OData-Version: 4.0".getBytes()); bos.write(CRLF); bos.write( ("Content-Type: " + ContentType.APPLICATION_OCTET_STREAM + ";boundary=" + BOUNDARY).getBytes()); bos.write(CRLF); bos.write(CRLF); bos.write(("--" + BOUNDARY).getBytes()); bos.write(CRLF); bos.write("Content-Type: application/http".getBytes()); bos.write(CRLF); bos.write("Content-Transfer-Encoding: binary".getBytes()); bos.write(CRLF); bos.write(CRLF); bos.write("HTTP/1.1 202 Accepted".getBytes()); bos.write(CRLF); bos.write("Location: http://service-root/async-monitor".getBytes()); bos.write(CRLF); bos.write("Retry-After: 10".getBytes()); bos.write(CRLF); bos.write(CRLF); bos.write(("--" + BOUNDARY + "--").getBytes()); bos.write(CRLF); final UUID uuid = UUID.randomUUID(); providedAsync.put(uuid.toString(), bos.toString(Constants.ENCODING.toString())); bos.flush(); bos.close(); return xml.createAsyncResponse(uriInfo.getRequestUri().toASCIIString().replace("async/$batch", "") + "monitor/" + uuid.toString()); } catch (Exception e) { return xml.createFaultResponse(Accept.JSON.toString(), e); } } @GET @Path("/async/{name}") public Response async(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("name") final String name) { try { final Accept acceptType = Accept.parse(accept, version); if (acceptType == Accept.XML || acceptType == Accept.TEXT) { throw new UnsupportedMediaTypeException("Unsupported media type"); } final String basePath = name + File.separatorChar; final StringBuilder path = new StringBuilder(basePath); path.append(metadata.getEntitySet(name).isSingleton() ? Constants.get(version, ConstantKey.ENTITY) : Constants.get(version, ConstantKey.FEED)); final InputStream feed = FSManager.instance(version).readFile(path.toString(), acceptType); final StringBuilder builder = new StringBuilder(); builder.append("HTTP/1.1 200 Ok").append(new String(CRLF)); builder.append("Content-Type: ").append(accept).append(new String(CRLF)).append(new String(CRLF)); builder.append(IOUtils.toString(feed)); IOUtils.closeQuietly(feed); final UUID uuid = UUID.randomUUID(); providedAsync.put(uuid.toString(), builder.toString()); return xml.createAsyncResponse(uriInfo.getRequestUri().toASCIIString().replaceAll("async/" + name, "") + "monitor/" + uuid.toString()); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @Override protected void setInlineCount(final EntitySet entitySet, final String count) { if ("true".equals(count)) { entitySet.setCount(entitySet.getEntities().size()); } } @Override public InputStream exploreMultipart(final List<Attachment> attachments, final String boundary, final boolean continueOnError) throws IOException { final ByteArrayOutputStream bos = new ByteArrayOutputStream(); Response res = null; boolean goon = true; for (int i = 0; i < attachments.size() && goon; i++) { try { final Attachment obj = attachments.get(i); bos.write(("--" + boundary).getBytes()); bos.write(Constants.CRLF); final Object content = obj.getDataHandler().getContent(); if (content instanceof MimeMultipart) { final ByteArrayOutputStream chbos = new ByteArrayOutputStream(); String lastContebtID = null; try { final Map<String, String> references = new HashMap<String, String>(); final String cboundary = "changeset_" + UUID.randomUUID().toString(); chbos.write(("Content-Type: multipart/mixed;boundary=" + cboundary).getBytes()); chbos.write(Constants.CRLF); chbos.write(Constants.CRLF); for (int j = 0; j < ((MimeMultipart) content).getCount(); j++) { final MimeBodyPart part = (MimeBodyPart) ((MimeMultipart) content).getBodyPart(j); lastContebtID = part.getContentID(); addChangesetItemIntro(chbos, lastContebtID, cboundary); res = bodyPartRequest(new MimeBodyPart(part.getInputStream()), references); if (!continueOnError && (res == null || res.getStatus() >= 400)) { throw new Exception("Failure processing changeset"); } addSingleBatchResponse(res, lastContebtID, chbos); references.put("$" + lastContebtID, res.getHeaderString("Location")); } chbos.write(("--" + cboundary + "--").getBytes()); chbos.write(Constants.CRLF); bos.write(chbos.toByteArray()); IOUtils.closeQuietly(chbos); } catch (Exception e) { LOG.warn("While processing changeset", e); IOUtils.closeQuietly(chbos); addItemIntro(bos, lastContebtID); if (res == null || res.getStatus() < 400) { addErrorBatchResponse(e, "1", bos); } else { addSingleBatchResponse(res, lastContebtID, bos); } goon = continueOnError; } } else { addItemIntro(bos); res = bodyPartRequest(new MimeBodyPart(obj.getDataHandler().getInputStream())); if (res.getStatus() >= 400) { goon = continueOnError; throw new Exception("Failure processing batch item"); } addSingleBatchResponse(res, bos); } } catch (Exception e) { if (res == null || res.getStatus() < 400) { addErrorBatchResponse(e, bos); } else { addSingleBatchResponse(res, bos); } } } bos.write(("--" + boundary + "--").getBytes()); return new ByteArrayInputStream(bos.toByteArray()); } @GET @Path("/People/{type:.*}") public Response getPeople(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("type") final String type, @QueryParam("$top") @DefaultValue(StringUtils.EMPTY) final String top, @QueryParam("$skip") @DefaultValue(StringUtils.EMPTY) final String skip, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, @QueryParam("$inlinecount") @DefaultValue(StringUtils.EMPTY) final String count, @QueryParam("$filter") @DefaultValue(StringUtils.EMPTY) final String filter, @QueryParam("$search") @DefaultValue(StringUtils.EMPTY) final String search, @QueryParam("$orderby") @DefaultValue(StringUtils.EMPTY) final String orderby, @QueryParam("$skiptoken") @DefaultValue(StringUtils.EMPTY) final String skiptoken) { return StringUtils.isBlank(filter) && StringUtils.isBlank(search) ? NumberUtils.isNumber(type) ? super.getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "People", type, format, null, null) : super.getEntitySet(accept, "People", type) : super.getEntitySet(uriInfo, accept, "People", top, skip, format, count, filter, orderby, skiptoken); } @GET @Path("/Boss") public Response getSingletonBoss(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "Boss", StringUtils.EMPTY, format, null, null); } @GET @Path("/Company") public Response getSingletonCompany(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "Company", StringUtils.EMPTY, format, null, null); } @PATCH @Path("/Company") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON }) public Response patchSingletonCompany(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer, @HeaderParam("If-Match") @DefaultValue(StringUtils.EMPTY) final String ifMatch, final String changes) { return super.patchEntity(uriInfo, accept, contentType, prefer, ifMatch, "Company", StringUtils.EMPTY, changes); } @GET @Path("/Customers") public Response getCustomers(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer, @QueryParam("$deltatoken") @DefaultValue(StringUtils.EMPTY) final String deltatoken) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final InputStream output; if (StringUtils.isBlank(deltatoken)) { final InputStream input = (InputStream) getEntitySet(uriInfo, accept, "Customers", null, null, format, null, null, null, null).getEntity(); final EntitySet entitySet = xml.readEntitySet(acceptType, input); boolean trackChanges = prefer.contains("odata.track-changes"); if (trackChanges) { entitySet.setDeltaLink(URI.create("Customers?$deltatoken=8015")); } output = xml.writeEntitySet(acceptType, new ResWrap<EntitySet>( URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX) + "Customers"), null, entitySet)); } else { output = FSManager.instance(version).readFile("delta", acceptType); } final Response response = xml.createResponse(null, output, null, acceptType); if (StringUtils.isNotBlank(prefer)) { response.getHeaders().put("Preference-Applied", Collections.<Object>singletonList(prefer)); } return response; } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @GET @Path("/Company/Microsoft.Test.OData.Services.ODataWCFService.GetEmployeesCount{paren:[\\(\\)]*}") public Response functionGetEmployeesCount( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final Property property = new PropertyImpl(); property.setType("Edm.Int32"); property.setValue(ValueType.PRIMITIVE, 2); final ResWrap<Property> container = new ResWrap<Property>( URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX) + property.getType()), null, property); return xml.createResponse(null, xml.writeProperty(acceptType, container), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @POST @Path("/Company/Microsoft.Test.OData.Services.ODataWCFService.IncreaseRevenue{paren:[\\(\\)]*}") public Response actionIncreaseRevenue( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String param) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final Accept contentTypeValue = Accept.parse(contentType, version); final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING)); return xml.createResponse(null, xml.writeProperty(acceptType, entry.getProperty("IncreaseValue")), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @GET @Path("/Products({entityId})/Microsoft.Test.OData.Services.ODataWCFService.GetProductDetails({param:.*})") public Response functionGetProductDetails( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("entityId") final String entityId, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final EntityImpl entry = new EntityImpl(); entry.setType("Microsoft.Test.OData.Services.ODataWCFService.ProductDetail"); final Property productId = new PropertyImpl(); productId.setName("ProductID"); productId.setType("Edm.Int32"); productId.setValue(ValueType.PRIMITIVE, Integer.valueOf(entityId)); entry.getProperties().add(productId); final Property productDetailId = new PropertyImpl(); productDetailId.setName("ProductDetailID"); productDetailId.setType("Edm.Int32"); productDetailId.setValue(ValueType.PRIMITIVE, 2); entry.getProperties().add(productDetailId); final Link link = new LinkImpl(); link.setRel("edit"); link.setHref(URI.create(Constants.get(version, ConstantKey.DEFAULT_SERVICE_URL) + "ProductDetails(ProductID=6,ProductDetailID=1)").toASCIIString()); entry.setEditLink(link); final EntitySetImpl feed = new EntitySetImpl(); feed.getEntities().add(entry); final ResWrap<EntitySet> container = new ResWrap<EntitySet>( URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX) + "ProductDetail"), null, feed); return xml.createResponse(null, xml.writeEntitySet(acceptType, container), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @POST @Path("/Products({entityId})/Microsoft.Test.OData.Services.ODataWCFService.AddAccessRight{paren:[\\(\\)]*}") public Response actionAddAccessRight( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String param) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final Accept contentTypeValue = Accept.parse(contentType, version); final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING)); assert 1 == entry.getProperties().size(); assert entry.getProperty("accessRight") != null; final Property property = entry.getProperty("accessRight"); property.setType("Microsoft.Test.OData.Services.ODataWCFService.AccessLevel"); final ResWrap<Property> result = new ResWrap<Property>( URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX) + property.getType()), null, property); return xml.createResponse(null, xml.writeProperty(acceptType, result), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @POST @Path("/Customers({personId})/Microsoft.Test.OData.Services.ODataWCFService.ResetAddress{paren:[\\(\\)]*}") public Response actionResetAddress(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("personId") final String personId, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String param) { try { final Accept contentTypeValue = Accept.parse(contentType, version); final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING)); assert 2 == entry.getProperties().size(); assert entry.getProperty("addresses") != null; assert entry.getProperty("index") != null; return getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "Customers", personId, format, null, null); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @GET @Path("/ProductDetails(ProductID={productId},ProductDetailID={productDetailId})" + "/Microsoft.Test.OData.Services.ODataWCFService.GetRelatedProduct{paren:[\\(\\)]*}") public Response functionGetRelatedProduct(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("productId") final String productId, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "Products", productId, format, null, null); } @POST @Path("/Accounts({entityId})/Microsoft.Test.OData.Services.ODataWCFService.RefreshDefaultPI{paren:[\\(\\)]*}") public Response actionRefreshDefaultPI( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @PathParam("entityId") final String entityId, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String param) { try { final Accept contentTypeValue = Accept.parse(contentType, version); final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING)); assert 1 == entry.getProperties().size(); assert entry.getProperty("newDate") != null; return functionGetDefaultPI(accept, entityId, format); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @GET @Path("/Accounts({entityId})/Microsoft.Test.OData.Services.ODataWCFService.GetDefaultPI{paren:[\\(\\)]*}") public Response functionGetDefaultPI( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("entityId") final String entityId, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getContainedEntity(accept, entityId, "MyPaymentInstruments", entityId + "901", format); } @GET @Path("/Accounts({entityId})/Microsoft.Test.OData.Services.ODataWCFService.GetAccountInfo{paren:[\\(\\)]*}") public Response functionGetAccountInfo( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("entityId") final String entityId, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getPath(accept, "Accounts", entityId, "AccountInfo", format); } @GET @Path("/Accounts({entityId})/MyGiftCard/Microsoft.Test.OData.Services.ODataWCFService.GetActualAmount({param:.*})") public Response functionGetActualAmount( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("entityId") final String entityId, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final Property property = new PropertyImpl(); property.setType("Edm.Double"); property.setValue(ValueType.PRIMITIVE, 41.79); final ResWrap<Property> container = new ResWrap<Property>((URI) null, null, property); return xml.createResponse(null, xml.writeProperty(acceptType, container), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } /** * Retrieve entity reference sample. * * @param accept Accept header. * @param path path. * @param format format query option. * @return entity reference or feed of entity reference. */ @GET @Path("/{path:.*}/$ref") public Response getEntityReference(@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("path") final String path, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { try { final Map.Entry<Accept, AbstractUtilities> utils = getUtilities(accept, format); if (utils.getKey() == Accept.TEXT) { throw new UnsupportedMediaTypeException("Unsupported media type"); } final String filename = Base64.encodeBase64String(path.getBytes("UTF-8")); return utils.getValue() .createResponse(FSManager.instance(version).readFile( Constants.get(version, ConstantKey.REF) + File.separatorChar + filename, utils.getKey()), null, utils.getKey()); } catch (Exception e) { LOG.error("Error retrieving entity", e); return xml.createFaultResponse(accept, e); } } @POST @Path("/People") @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.APPLICATION_ATOM_XML, MediaType.APPLICATION_JSON, MediaType.APPLICATION_OCTET_STREAM }) public Response postPeople(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @HeaderParam("Prefer") @DefaultValue(StringUtils.EMPTY) final String prefer, final String entity) { if ("{\"@odata.type\":\"#Microsoft.Test.OData.Services.ODataWCFService.Person\"}".equals(entity)) { return xml.createFaultResponse(accept, new BadRequestException()); } return super.postNewEntity(uriInfo, accept, contentType, prefer, "People", entity); } @Override public Response patchEntity(final UriInfo uriInfo, final String accept, final String contentType, final String prefer, final String ifMatch, final String entitySetName, final String entityId, final String changes) { final Response response = getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY); return response.getStatus() >= 400 ? super.postNewEntity(uriInfo, accept, contentType, prefer, entitySetName, changes) : super.patchEntity(uriInfo, accept, contentType, prefer, ifMatch, entitySetName, entityId, changes); } @Override public Response replaceEntity(final UriInfo uriInfo, final String accept, final String contentType, final String prefer, final String entitySetName, final String entityId, final String entity) { try { getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, entitySetName, entityId, accept, StringUtils.EMPTY, StringUtils.EMPTY); return super.replaceEntity(uriInfo, accept, contentType, prefer, entitySetName, entityId, entity); } catch (NotFoundException e) { return postNewEntity(uriInfo, accept, contentType, prefer, entitySetName, entityId); } } private StringBuilder containedPath(final String entityId, final String containedEntitySetName) { return new StringBuilder("Accounts").append(File.separatorChar).append(entityId).append(File.separatorChar) .append("links").append(File.separatorChar).append(containedEntitySetName); } @GET @Path("/Accounts({entityId})/{containedEntitySetName}({containedEntityId})") public Response getContainedEntity(@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("entityId") final String entityId, @PathParam("containedEntitySetName") final String containedEntitySetName, @PathParam("containedEntityId") final String containedEntityId, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } if (acceptType == Accept.XML || acceptType == Accept.TEXT) { throw new UnsupportedMediaTypeException("Unsupported media type"); } final StringBuilder containedPath = containedPath(entityId, containedEntitySetName); if (StringUtils.isNotBlank(containedEntityId)) { containedPath.append('(').append(containedEntityId).append(')'); } final InputStream entry = FSManager.instance(version).readFile(containedPath.toString(), Accept.ATOM); final ResWrap<Entity> container = atomDeserializer.toEntity(entry); return xml.createResponse(null, xml.writeEntity(acceptType, container), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @POST @Path("/Accounts({entityId})/{containedEntitySetName:.*}") public Response postContainedEntity(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @PathParam("entityId") final String entityId, @PathParam("containedEntitySetName") final String containedEntitySetName, final String entity) { try { final Accept acceptType = Accept.parse(accept, version); if (acceptType == Accept.XML || acceptType == Accept.TEXT) { throw new UnsupportedMediaTypeException("Unsupported media type"); } final AbstractUtilities utils = getUtilities(acceptType); // 1. parse the entry (from Atom or JSON) final ResWrap<Entity> entryContainer; final Entity entry; final Accept contentTypeValue = Accept.parse(contentType, version); if (Accept.ATOM == contentTypeValue) { entryContainer = atomDeserializer.toEntity(IOUtils.toInputStream(entity, Constants.ENCODING)); entry = entryContainer.getPayload(); } else { final ResWrap<Entity> jcontainer = jsonDeserializer .toEntity(IOUtils.toInputStream(entity, Constants.ENCODING)); entry = jcontainer.getPayload(); entryContainer = new ResWrap<Entity>(jcontainer.getContextURL(), jcontainer.getMetadataETag(), entry); } final EdmTypeInfo contained = new EdmTypeInfo.Builder() .setTypeExpression( metadata.getNavigationProperties("Accounts").get(containedEntitySetName).getType()) .build(); final String entityKey = getUtilities(contentTypeValue) .getDefaultEntryKey(contained.getFullQualifiedName().getName(), entry); // 2. Store the new entity final String atomEntryRelativePath = containedPath(entityId, containedEntitySetName).append('(') .append(entityKey).append(')').toString(); FSManager.instance(version).putInMemory(utils.writeEntity(Accept.ATOM, entryContainer), FSManager.instance(version).getAbsolutePath(atomEntryRelativePath, Accept.ATOM)); // 3. Update the contained entity set final String atomFeedRelativePath = containedPath(entityId, containedEntitySetName).toString(); final InputStream feedIS = FSManager.instance(version).readFile(atomFeedRelativePath, Accept.ATOM); final ResWrap<EntitySet> feedContainer = atomDeserializer.toEntitySet(feedIS); feedContainer.getPayload().getEntities().add(entry); final ByteArrayOutputStream content = new ByteArrayOutputStream(); final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING); atomSerializer.write(writer, feedContainer); writer.flush(); writer.close(); FSManager.instance(version).putInMemory(new ByteArrayInputStream(content.toByteArray()), FSManager.instance(version).getAbsolutePath(atomFeedRelativePath, Accept.ATOM)); // Finally, return return utils.createResponse(uriInfo.getRequestUri().toASCIIString() + "(" + entityKey + ")", utils.writeEntity(acceptType, entryContainer), null, acceptType, Response.Status.CREATED); } catch (Exception e) { LOG.error("While creating new contained entity", e); return xml.createFaultResponse(accept, e); } } @PATCH @Path("/{entitySetName}({entityId})/{containedEntitySetName}({containedEntityId})") public Response patchContainedEntity( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @PathParam("entitySetName") final String entitySetName, @PathParam("entityId") final String entityId, @PathParam("containedEntitySetName") final String containedEntitySetName, @PathParam("containedEntityId") final String containedEntityId, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String changes) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } if (acceptType == Accept.XML || acceptType == Accept.TEXT) { throw new UnsupportedMediaTypeException("Unsupported media type"); } final Accept contentTypeValue; if (StringUtils.isBlank(contentType)) { throw new IllegalArgumentException(); } contentTypeValue = Accept.parse(contentType, version); final LinkInfo links = xml.readLinks(entitySetName, entityId, containedEntitySetName + "(" + containedEntityId + ")", Accept.ATOM); ResWrap<Entity> container = atomDeserializer.toEntity(links.getLinks()); final Entity original = container.getPayload(); final Entity entryChanges; if (Accept.ATOM == contentTypeValue) { container = atomDeserializer.toEntity(IOUtils.toInputStream(changes, Constants.ENCODING)); entryChanges = container.getPayload(); } else { final String entityType = metadata.getEntitySet(entitySetName).getType(); final String containedType = metadata.getEntityOrComplexType(entityType) .getNavigationProperty(containedEntitySetName).getType(); final EdmTypeInfo typeInfo = new EdmTypeInfo.Builder().setTypeExpression(containedType).build(); final ResWrap<Entity> jsonContainer = jsonDeserializer .toEntity(IOUtils.toInputStream(changes, Constants.ENCODING)); jsonContainer.getPayload().setType(typeInfo.getFullQualifiedName().toString()); entryChanges = jsonContainer.getPayload(); } for (Property property : entryChanges.getProperties()) { final Property old = original.getProperty(property.getName()); if (old != null) { original.getProperties().remove(old); } original.getProperties().add(property); } FSManager.instance(version).putInMemory(new ResWrap<Entity>((URI) null, null, original), xml.getLinksBasePath(entitySetName, entityId) + containedEntitySetName + "(" + containedEntityId + ")"); return xml.createResponse(null, null, acceptType, Response.Status.NO_CONTENT); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @DELETE @Path("/Accounts({entityId})/{containedEntitySetName}({containedEntityId})") public Response removeContainedEntity(@PathParam("entityId") final String entityId, @PathParam("containedEntitySetName") final String containedEntitySetName, @PathParam("containedEntityId") final String containedEntityId) { try { // 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); final ResWrap<Entity> container = atomDeserializer.toEntity(entry); // 2. Remove the contained entity final String atomEntryRelativePath = containedPath(entityId, containedEntitySetName).append('(') .append(containedEntityId).append(')').toString(); FSManager.instance(version).deleteFile(atomEntryRelativePath); // 3. Update the contained entity set final String atomFeedRelativePath = containedPath(entityId, containedEntitySetName).toString(); final InputStream feedIS = FSManager.instance(version).readFile(atomFeedRelativePath, Accept.ATOM); final ResWrap<EntitySet> feedContainer = atomDeserializer.toEntitySet(feedIS); feedContainer.getPayload().getEntities().remove(container.getPayload()); final ByteArrayOutputStream content = new ByteArrayOutputStream(); final OutputStreamWriter writer = new OutputStreamWriter(content, Constants.ENCODING); atomSerializer.write(writer, feedContainer); writer.flush(); writer.close(); FSManager.instance(version).putInMemory(new ByteArrayInputStream(content.toByteArray()), FSManager.instance(version).getAbsolutePath(atomFeedRelativePath, Accept.ATOM)); return xml.createResponse(null, null, null, null, Response.Status.NO_CONTENT); } catch (Exception e) { return xml.createFaultResponse(Accept.XML.toString(version), e); } } @GET @Path("/Accounts({entityId})/{containedEntitySetName:.*}") public Response getContainedEntitySet( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @PathParam("entityId") final String entityId, @PathParam("containedEntitySetName") String containedEntitySetName, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { if ("MyGiftCard".equals(containedEntitySetName)) { return getContainedEntity(accept, entityId, containedEntitySetName, null, format); } try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } if (acceptType == Accept.XML || acceptType == Accept.TEXT) { throw new UnsupportedMediaTypeException("Unsupported media type"); } String derivedType = null; if (containedEntitySetName.contains("/")) { final String[] parts = containedEntitySetName.split("/"); containedEntitySetName = parts[0]; derivedType = parts[1]; } final InputStream feed = FSManager.instance(version) .readFile(containedPath(entityId, containedEntitySetName).toString(), Accept.ATOM); final ResWrap<EntitySet> container = atomDeserializer.toEntitySet(feed); if (derivedType != null) { final List<Entity> nonMatching = new ArrayList<Entity>(); for (Entity entity : container.getPayload().getEntities()) { if (!derivedType.equals(entity.getType())) { nonMatching.add(entity); } } container.getPayload().getEntities().removeAll(nonMatching); } return xml.createResponse(null, xml.writeEntitySet(acceptType, container), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @GET @Path("/GetDefaultColor()") public Response functionGetDefaultColor( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final PropertyImpl property = new PropertyImpl(); property.setType("Microsoft.Test.OData.Services.ODataWCFService.Color"); property.setValue(ValueType.ENUM, "Red"); final ResWrap<Property> container = new ResWrap<Property>( URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX) + property.getType()), null, property); return xml.createResponse(null, xml.writeProperty(acceptType, container), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @GET @Path("/GetPerson2({param:.*})") public Response functionGetPerson2(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "Customers", "1", format, null, null); } @GET @Path("/GetPerson2({param:.*})/Emails") public Response functionGetPerson2Emails( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getPath(accept, "Customers", "1", "Emails", format); } @GET @Path("/GetPerson2({param:.*})/HomeAddress") public Response functionGetPerson2HomeAddress( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getPath(accept, "Customers", "1", "HomeAddress", format); } @GET @Path("/GetPerson2({param:.*})/Parent") public Response functionGetPerson2Parent(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "Customers", "2", format, null, null); } @GET @Path("/GetPerson({param:.*})") public Response functionGetPerson(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "Customers", "1", format, null, null); } @GET @Path("/GetAllProducts()") public Response functionGetAllProducts(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { return getEntitySet(uriInfo, accept, "Products", null, null, format, null, null, null, null); } @GET @Path("/GetProductsByAccessLevel({param:.*})") public Response functionGetProductsByAccessLevel( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final PropertyImpl property = new PropertyImpl(); property.setType("Collection(String)"); final List<String> value = Arrays.asList("Cheetos", "Mushrooms", "Apple", "Car", "Computer"); property.setValue(ValueType.COLLECTION_PRIMITIVE, value); final ResWrap<Property> container = new ResWrap<Property>( URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX) + property.getType()), null, property); return xml.createResponse(null, xml.writeProperty(acceptType, container), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @GET @Path("/GetBossEmails({param:.*})") public Response functionGetBossEmails( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final PropertyImpl property = new PropertyImpl(); property.setType("Collection(Edm.String)"); property.setValue(ValueType.COLLECTION_PRIMITIVE, Arrays.asList("first@olingo.apache.org", "second@olingo.apache.org")); final ResWrap<Property> container = new ResWrap<Property>( URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX) + property.getType()), null, property); return xml.createResponse(null, xml.writeProperty(acceptType, container), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @POST @Path("/Discount()") public Response actionDiscount(@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String param) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final Accept contentTypeValue = Accept.parse(contentType, version); Property property; if (contentTypeValue == Accept.ATOM) { final ResWrap<Property> paramContainer = atomDeserializer .toProperty(IOUtils.toInputStream(param, Constants.ENCODING)); property = paramContainer.getPayload(); } else { final ResWrap<Property> paramContainer = jsonDeserializer .toProperty(IOUtils.toInputStream(param, Constants.ENCODING)); property = paramContainer.getPayload(); } assert property.isComplex(); assert 1 == property.asComplex().size(); assert "Edm.Int32".equals(property.asComplex().get(0).getType()); assert property.asComplex().get(0).isPrimitive(); assert "percentage".equals(property.asComplex().get(0).getName()); return xml.createResponse(null, null, null, acceptType, Response.Status.NO_CONTENT); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @POST @Path("/GetAllProducts()/Discount") public Response actionBoundDiscount() { try { final String basePath = "Products" + File.separatorChar + "feed"; final InputStream feed = FSManager.instance(version).readFile(basePath, Accept.JSON_FULLMETA); return xml.createResponse(null, feed, Commons.getETag(basePath, version), Accept.JSON_FULLMETA); } catch (Exception e) { return xml.createFaultResponse(Accept.JSON_FULLMETA.toString(version), e); } } @POST @Path("/ResetBossAddress()") public Response actionResetBossAddress( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String param) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final Accept contentTypeValue = Accept.parse(contentType, version); final Entity entity = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING)); assert "Microsoft.Test.OData.Services.ODataWCFService.Address".equals(entity.getType()); assert entity.getProperty("address").isComplex(); final ResWrap<Property> result = new ResWrap<Property>( URI.create(Constants.get(version, ConstantKey.ODATA_METADATA_PREFIX) + "Microsoft.Test.OData.Services.ODataWCFService.Address"), null, entity.getProperty("address")); return xml.createResponse(null, xml.writeProperty(acceptType, result), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @POST @Path("/ResetBossEmail()") public Response actionResetBossEmail( @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String param) { try { final Accept acceptType; if (StringUtils.isNotBlank(format)) { acceptType = Accept.valueOf(format.toUpperCase()); } else { acceptType = Accept.parse(accept, version); } final Accept contentTypeValue = Accept.parse(contentType, version); final Entity entry = xml.readEntity(contentTypeValue, IOUtils.toInputStream(param, Constants.ENCODING)); assert 1 == entry.getProperties().size(); assert "Collection(Edm.String)".equals(entry.getProperty("emails").getType()); assert entry.getProperty("emails").isCollection(); return xml.createResponse(null, xml.writeProperty(acceptType, entry.getProperty("emails")), null, acceptType); } catch (Exception e) { return xml.createFaultResponse(accept, e); } } @POST @Path("/Products({productId})/Categories/$ref") public Response createLinked(@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String entity) { return xml.createResponse(null, null, null, Status.NO_CONTENT); } @POST @Path("/Customers(1)/Orders/$ref") public Response linkOrderViaRef(@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String entity) { return xml.createResponse(null, null, null, Status.NO_CONTENT); } @DELETE @Path("/Products({productId})/Categories({categoryId})/$ref") public Response deleteLinked(@HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @HeaderParam("Content-Type") @DefaultValue(StringUtils.EMPTY) final String contentType, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, final String entity) { return xml.createResponse(null, null, null, Status.NO_CONTENT); } @GET @Path("/Company/VipCustomer") public Response getVipCustomer(@Context final UriInfo uriInfo, @HeaderParam("Accept") @DefaultValue(StringUtils.EMPTY) final String accept, @QueryParam("$format") @DefaultValue(StringUtils.EMPTY) final String format, @QueryParam("$expand") @DefaultValue(StringUtils.EMPTY) final String expand, @QueryParam("$select") @DefaultValue(StringUtils.EMPTY) final String select) { return super.getEntityInternal(uriInfo.getRequestUri().toASCIIString(), accept, "VipCustomer", "1", format, expand, select); } }