| /******************************************************************************* |
| * 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.odata2.fit.ref; |
| |
| import static org.custommonkey.xmlunit.XMLAssert.assertXpathEvaluatesTo; |
| import static org.custommonkey.xmlunit.XMLAssert.assertXpathNotExists; |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertNull; |
| |
| import java.lang.reflect.Field; |
| |
| import org.apache.http.HttpHeaders; |
| import org.apache.http.HttpResponse; |
| import org.apache.olingo.odata2.api.commons.HttpContentType; |
| import org.apache.olingo.odata2.api.commons.HttpStatusCodes; |
| import org.apache.olingo.odata2.ref.model.DataContainer; |
| import org.apache.olingo.odata2.ref.model.Photo; |
| import org.apache.olingo.odata2.ref.processor.ListsProcessor; |
| import org.apache.olingo.odata2.ref.processor.ScenarioDataSource; |
| import org.apache.olingo.odata2.testutil.server.ServletType; |
| import org.custommonkey.xmlunit.XMLAssert; |
| import org.junit.Test; |
| |
| /** |
| * Tests employing the reference scenario reading a single entity in XML format. |
| * |
| */ |
| public class EntryXmlReadOnlyTest extends AbstractRefXmlTest { |
| |
| public EntryXmlReadOnlyTest(final ServletType servletType) { |
| super(servletType); |
| } |
| |
| @Test |
| public void entry() throws Exception { |
| HttpResponse response = callUri("Employees('2')"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| assertNull(response.getFirstHeader(HttpHeaders.ETAG)); |
| assertXpathEvaluatesTo(EMPLOYEE_2_NAME, "/atom:entry/m:properties/d:EmployeeName", getBody(response)); |
| |
| response = callUri("Managers('3')"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| assertXpathEvaluatesTo(EMPLOYEE_3_NAME, "/atom:entry/m:properties/d:EmployeeName", getBody(response)); |
| |
| response = callUri("Teams('2')"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| assertXpathEvaluatesTo("2", "/atom:entry/atom:content/m:properties/d:Id", getBody(response)); |
| |
| response = callUri("Rooms('1')"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| checkEtag(response, "W/\"1\""); |
| String body = getBody(response); |
| assertXpathEvaluatesTo("W/\"1\"", "/atom:entry/@m:etag", body); |
| assertXpathEvaluatesTo("1", "/atom:entry/atom:content/m:properties/d:Id", body); |
| |
| response = callUri("Rooms('1')?$expand=nr_Employees"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| // assertNull(response.getFirstHeader(HttpHeaders.ETAG)); |
| assertXpathEvaluatesTo( |
| EMPLOYEE_1_NAME, |
| "/atom:entry/atom:link[@href=\"Rooms('1')/nr_Employees\"]" + |
| "/m:inline/atom:feed/atom:entry/m:properties/d:EmployeeName", |
| getBody(response)); |
| |
| response = callUri("Container2.Photos(Id=1,Type='image%2Fpng')"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| body = getBody(response); |
| assertXpathEvaluatesTo("image/png", "/atom:entry/m:properties/d:Type", body); |
| assertXpathEvaluatesTo(IMAGE_JPEG, "/atom:entry/m:properties/d:Image/@m:MimeType", body); |
| assertXpathEvaluatesTo(PHOTO_DEFAULT_IMAGE, "/atom:entry/m:properties/d:Image", body); |
| |
| response = callUri("Container2.Photos(Id=4,Type='foo')"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| assertXpathEvaluatesTo("Container2.Photos(Id=4,Type='foo')/$value", "/atom:entry/atom:content/@src", |
| getBody(response)); |
| |
| notFound("Managers('5')"); |
| notFound("Managers('1%2C2')"); |
| badRequest("Managers('3')?$top=1"); |
| badRequest("Rooms(X'33')"); |
| } |
| |
| @Test |
| public void entryWithSpecialKey() throws Exception { |
| // Ugly hack to create an entity with a key containing special characters just for this test. |
| ListsProcessor processor = (ListsProcessor) getService().getEntityProcessor(); |
| Field field = getField(processor.getClass(), "dataSource"); |
| field.setAccessible(true); |
| ScenarioDataSource dataSource = (ScenarioDataSource) field.get(processor); |
| field = getField(dataSource.getClass(), "dataContainer"); |
| field.setAccessible(true); |
| DataContainer dataContainer = (DataContainer) field.get(dataSource); |
| // Add a new Photo where the "Type" property is set to, space-separated, |
| // a literal percent character, all gen-delims, and all sub-delims |
| // as specified by RFC 3986. |
| dataContainer.getPhotos().add(new Photo(42, "strange Photo", "% :/?#[]@ !$&'()*+,;=")); |
| |
| // Check that percent-decoding and -encoding works as expected. |
| final String url = |
| "Container2.Photos(Id=42,Type='%25%20%3A%2F%3F%23%5B%5D%40%20%21%24%26%27%28%29%2A%2B%2C%3B%3D')"; |
| final String expected = url.replace("%27", "''"); |
| final HttpResponse response = callUri(url); |
| final String body = getBody(response); |
| assertXpathEvaluatesTo("strange Photo", "/atom:entry/m:properties/d:Name", body); |
| assertXpathEvaluatesTo(expected, "/atom:entry/atom:link[@rel=\"edit\"]/@href", body); |
| assertXpathEvaluatesTo(expected + "/$value", "/atom:entry/atom:link[@rel=\"edit-media\"]/@href", body); |
| } |
| |
| private Field getField(final Class<?> clazz, final String string) throws Exception { |
| try { |
| return clazz.getDeclaredField(string); |
| } catch (NoSuchFieldException e) { |
| if (clazz == Object.class) { |
| throw e; |
| } |
| return getField(clazz.getSuperclass(), string); |
| } |
| } |
| |
| @Test |
| public void expand() throws Exception { |
| HttpResponse response = callUri("Employees('5')?$expand=ne_Manager"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| String body = getBody(response); |
| assertXpathEvaluatesTo(EMPLOYEE_5_NAME, "/atom:entry/m:properties/d:EmployeeName", body); |
| assertXpathEvaluatesTo(EMPLOYEE_3_NAME, |
| "/atom:entry/atom:link[@href=\"Employees('5')/ne_Manager\"]/m:inline/atom:entry/m:properties/d:EmployeeName", |
| body); |
| |
| response = callUri("Rooms('3')?$expand=nr_Employees/ne_Manager"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| body = getBody(response); |
| assertXpathEvaluatesTo("3", "/atom:entry/atom:content[@type=\"application/xml\"]/m:properties/d:Id", body); |
| assertXpathEvaluatesTo("1", |
| "count(/atom:entry/atom:link[@href=\"Rooms('3')/nr_Employees\"]/m:inline/atom:feed/atom:entry)", body); |
| assertXpathEvaluatesTo( |
| EMPLOYEE_5_NAME, |
| "/atom:entry/atom:link[@href=\"Rooms('3')/nr_Employees\"]" + |
| "/m:inline/atom:feed/atom:entry/m:properties/d:EmployeeName", |
| body); |
| assertXpathEvaluatesTo( |
| EMPLOYEE_3_NAME, |
| "/atom:entry/atom:link[@href=\"Rooms('3')/nr_Employees\"]" + |
| "/m:inline/atom:feed/atom:entry/atom:link[@href=\"Employees('5')/ne_Manager\"]" + |
| "/m:inline/atom:entry/m:properties/d:EmployeeName", |
| body); |
| |
| notFound("Employees('3')?$expand=noNavProp"); |
| badRequest("Employees('3')?$expand=Age"); |
| badRequest("Employees()?$expand=ne_Room/Seats"); |
| notFound("Employees()?$expand=ne_Room/noNavProp"); |
| } |
| |
| @Test |
| public void select() throws Exception { |
| HttpResponse response = callUri("Employees('6')?$select=EmployeeId,Age"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| String body = getBody(response); |
| assertXpathEvaluatesTo("6", "/atom:entry/m:properties/d:EmployeeId", body); |
| assertXpathEvaluatesTo(EMPLOYEE_6_AGE, "/atom:entry/m:properties/d:Age", body); |
| assertXpathNotExists("/atom:entry/m:properties/d:Location", body); |
| assertXpathEvaluatesTo("2", "count(/atom:entry/atom:link)", body); |
| |
| response = callUri("Employees('3')/ne_Room?$select=Seats"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| body = getBody(response); |
| assertXpathEvaluatesTo("5", "/atom:entry/atom:content/m:properties/d:Seats", body); |
| assertXpathNotExists("/atom:entry/m:properties/d:Id", body); |
| |
| final String entry = getBody(callUri("Employees('6')")); |
| assertEquals(entry, getBody(callUri("Employees('6')?$select=*,Age"))); |
| assertEquals(entry, getBody(callUri("Employees('6')?$select=*,ne_Room"))); |
| |
| checkUri("Container2.Photos(Id=4,Type='foo')?$select=%D0%A1%D0%BE%D0%B4%D0%B5%D1%80%D0%B6" + |
| "%D0%B0%D0%BD%D0%B8%D0%B5,Id"); |
| |
| response = callUri("Employees('6')?$expand=ne_Room&$select=ne_Room/Version"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| body = getBody(response); |
| assertXpathEvaluatesTo( |
| "2", |
| "/atom:entry/atom:link[@href=\"Employees('6')/ne_Room\"]/m:inline/atom:entry/atom:content" + |
| "[@type=\"application/xml\"]/m:properties/d:Version", |
| body); |
| assertXpathNotExists("/atom:entry/m:properties/d:Location", body); |
| assertXpathNotExists( |
| "/atom:entry/atom:link[@href=\"Employees('6')/ne_Room\"]/m:inline/atom:entry/atom:content" + |
| "[@type=\"application/xml\"]/m:properties/d:Seats", |
| body); |
| |
| response = callUri("Rooms('3')?$expand=nr_Employees/ne_Team&$select=nr_Employees/ne_Team/Name"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| body = getBody(response); |
| assertXpathEvaluatesTo( |
| "Team 2", |
| "/atom:entry/atom:link[@href=\"Rooms('3')/nr_Employees\"]/m:inline/atom:feed/atom:entry" + |
| "/atom:link[@href=\"Employees('5')/ne_Team\"]/m:inline/atom:entry/atom:content/m:properties/d:Name", |
| body); |
| assertXpathNotExists("/atom:entry/atom:content/m:properties", body); |
| assertXpathNotExists( |
| "/atom:entry/atom:link[@href=\"Rooms('3')/nr_Employees\"]/m:inline/atom:feed/atom:entry/m:properties", body); |
| assertXpathNotExists( |
| "/atom:entry/atom:link[@href=\"Rooms('3')/nr_Employees\"]/m:inline/atom:feed/atom:entry" + |
| "/atom:link[@href=\"Employees('5')/ne_Team\"]/m:inline/atom:entry/atom:content/m:properties/d:Id", |
| body); |
| |
| notFound("Teams('3')?$select=noProp"); |
| notFound("Teams()?$select=nt_Employees/noProp"); |
| notFound("Employees('3')/ne_Room?$select=Age"); |
| notFound("Employees('3')/ne_Room?$select=ne_Room"); |
| } |
| |
| @Test |
| public void entryMediaResource() throws Exception { |
| HttpResponse response = callUri("Employees('2')/$value"); |
| checkMediaType(response, IMAGE_JPEG); |
| assertNotNull(getBody(response)); |
| |
| response = callUri("Employees('2')/$value?$format=xml", HttpStatusCodes.BAD_REQUEST); |
| String body = getBody(response); |
| XMLAssert.assertXpathExists("/m:error/m:message", body); |
| } |
| |
| @Test |
| public void navigationEntry() throws Exception { |
| HttpResponse response = callUri("Employees('2')/ne_Manager"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| assertXpathEvaluatesTo(MANAGER_NAME, "/atom:entry/m:properties/d:EmployeeName", getBody(response)); |
| |
| response = callUri("Employees('2')/ne_Team/nt_Employees('1')"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| assertXpathEvaluatesTo(EMPLOYEE_1_NAME, "/atom:entry/m:properties/d:EmployeeName", getBody(response)); |
| |
| response = callUri("Employees('2')/ne_Manager/nm_Employees('6')"); |
| checkMediaType(response, HttpContentType.APPLICATION_ATOM_XML_UTF8 + ";type=entry"); |
| assertXpathEvaluatesTo(EMPLOYEE_6_NAME, "/atom:entry/m:properties/d:EmployeeName", getBody(response)); |
| |
| badRequest("Employees('2')/ne_Manager()"); |
| } |
| } |