package com.interaction.example.odata.airline;
/*
* #%L
* interaction-example-odata-airline
* %%
* Copyright (C) 2012 - 2013 Temenos Holdings N.V.
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* #L%
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.core4j.Enumerable;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.odata4j.consumer.ODataConsumer;
import org.odata4j.core.OEntity;
import org.odata4j.core.OLink;
import org.odata4j.jersey.consumer.ODataJerseyConsumer;
/**
* This test ensures that this projects OData entities have working
* OData associations (links).
*
* @author aphethean
*/
public class ODataAssociationsITCase {
private final static String FLIGHT_ENTITYSET_NAME = "Flights";
private final static String FLIGHT_SCHEDULE_ENTITYSET_NAME = "FlightSchedules";
private final static String AIRPORT_ENTITYSET_NAME = "Airports";
private final static String NON_STRICT_ODATA_COMPLIANCE_URI_SUFFIX = "NonStrictOData";
private static final String FLIGHT_RESPONDER_MODEL_NAME = "FlightResponder";
public ODataAssociationsITCase() throws Exception {
super();
}
@Before
public void initTest() {}
@After
public void tearDown() {}
/**
* GET collection, check link to self and other entities for each item
*/
@Test
public void getFlightsLinksToFlightSchedule() throws Exception {
ODataConsumer consumer = ODataJerseyConsumer.newBuilder(ConfigurationHelper.getTestEndpointUri(Configuration.TEST_ENDPOINT_URI)).build();
Enumerable<OEntity> flights = consumer.getEntities(FLIGHT_ENTITYSET_NAME).execute();
assertEquals(4, flights.toSet().size());
for (OEntity flight : flights.toSet()) {
Long flightID = (Long) flight.getProperty("flightID").getValue();
Long flightScheduleNum = (Long) flight.getProperty("flightScheduleNum").getValue();
if(consumer.getServiceRootUri().contains(FLIGHT_RESPONDER_MODEL_NAME)) {
assertEquals(3, flight.getLinks().size());
}
else {
assertEquals(1, flight.getLinks().size());
}
// there should be one link to one flight schedule for this flight
assertTrue(containsLink(flight.getLinks(), FLIGHT_ENTITYSET_NAME + "(" + flightID + ")/flightSchedule") ||
containsLink(flight.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "(" + flightScheduleNum + ")"));
}
}
/**
* GET item, check link to another entity
*/
@Test
public void getFlightLinksToFlightSchedule() throws Exception {
ODataConsumer consumer = ODataJerseyConsumer.newBuilder(ConfigurationHelper.getTestEndpointUri(Configuration.TEST_ENDPOINT_URI)).build();
OEntity flight = consumer.getEntity(FLIGHT_ENTITYSET_NAME, 2).execute();
Long flightID = (Long) flight.getProperty("flightID").getValue();
assertEquals(2, flightID.intValue());
Long flightScheduleNum = (Long) flight.getProperty("flightScheduleNum").getValue();
// there should be one link to one flight schedule for this flight
if(consumer.getServiceRootUri().contains(FLIGHT_RESPONDER_MODEL_NAME)) {
assertEquals(3, flight.getLinks().size());
}
else {
assertEquals(1, flight.getLinks().size());
}
assertTrue(containsLink(flight.getLinks(), FLIGHT_ENTITYSET_NAME + "(" + flightID + ")/flightSchedule") ||
containsLink(flight.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "(" + flightScheduleNum + ")"));
}
/**
* GET collection, check link to self and other entities for each item
*/
@Test
public void getFlightSchedulesLinksToFlightSchedule() throws Exception {
ODataConsumer consumer = ODataJerseyConsumer.newBuilder(ConfigurationHelper.getTestEndpointUri(Configuration.TEST_ENDPOINT_URI)).build();
Enumerable<OEntity> flightSchedules = consumer.getEntities(FLIGHT_SCHEDULE_ENTITYSET_NAME).execute();
// if the test is run multiple times it will be greater than 7
assertTrue(flightSchedules.toSet().size() >= 7);
for (OEntity flightSchedule : flightSchedules.toSet()) {
Long id = (Long) flightSchedule.getProperty("flightScheduleID").getValue();
String departureAirportCode = (String) flightSchedule.getProperty("departureAirportCode").getValue();
String arrivalAirportCode = (String) flightSchedule.getProperty("arrivalAirportCode").getValue();
// there should be one link to self (OData4j swallows this)
// there should be one link to flights
// there should be one link to one departureAirport for this flight schedule
// there should be one link to one departureAirport for this flight schedule
if(consumer.getServiceRootUri().contains(NON_STRICT_ODATA_COMPLIANCE_URI_SUFFIX)) {
assertTrue(containsLink(flightSchedule.getLinks(), "Flights()?filter=flightScheduleNum+eq+'" + id + "'", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Flights"));
assertTrue(containsLink(flightSchedule.getLinks(), AIRPORT_ENTITYSET_NAME + "('" + departureAirportCode + "')", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Airport"));
assertTrue(containsLink(flightSchedule.getLinks(), AIRPORT_ENTITYSET_NAME + "('" + arrivalAirportCode + "')", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Airport"));
} else {
assertTrue(containsLink(flightSchedule.getLinks(), "FlightSchedules(" + id + ")/flights", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Flights"));
assertTrue(containsLink(flightSchedule.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "(" + id + ")/departureAirport", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Airport"));
assertTrue(containsLink(flightSchedule.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "(" + id + ")/arrivalAirport", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Airport"));
}
if(consumer.getServiceRootUri().contains(FLIGHT_RESPONDER_MODEL_NAME)) {
assertEquals(5, flightSchedule.getLinks().size());
}
else {
assertEquals(3, flightSchedule.getLinks().size());
}
}
}
/**
* GET item, check link to another entity
*/
@Test
public void getFlightScheduleLinksToAirports() throws Exception {
ODataConsumer consumer = ODataJerseyConsumer.newBuilder(ConfigurationHelper.getTestEndpointUri(Configuration.TEST_ENDPOINT_URI)).build();
OEntity flightSchedule = consumer.getEntity(FLIGHT_SCHEDULE_ENTITYSET_NAME, 2).execute();
Long id = (Long) flightSchedule.getProperty("flightScheduleID").getValue();
String departureAirportCode = (String) flightSchedule.getProperty("departureAirportCode").getValue();
String arrivalAirportCode = (String) flightSchedule.getProperty("arrivalAirportCode").getValue();
assertEquals(2, id.intValue());
// there should be one link to self (OData4j swallows this)
// there should be one link to flights
// there should be one link to one departureAirport for this flight schedule
// there should be one link to one arrivalAirport for this flight schedule
if(consumer.getServiceRootUri().contains(NON_STRICT_ODATA_COMPLIANCE_URI_SUFFIX)) {
assertTrue(containsLink(flightSchedule.getLinks(), AIRPORT_ENTITYSET_NAME + "('" + departureAirportCode + "')", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Airport"));
assertTrue(containsLink(flightSchedule.getLinks(), AIRPORT_ENTITYSET_NAME + "('" + arrivalAirportCode + "')", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Airport"));
} else {
assertTrue(containsLink(flightSchedule.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "(" + id + ")/departureAirport", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Airport"));
assertTrue(containsLink(flightSchedule.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "(" + id + ")/arrivalAirport", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/Airport"));
}
if(consumer.getServiceRootUri().contains(FLIGHT_RESPONDER_MODEL_NAME)) {
assertEquals(5, flightSchedule.getLinks().size());
}
else {
assertEquals(3, flightSchedule.getLinks().size());
}
}
/**
* GET nav properties for an item
*/
@Test
public void getFlightScheduleNavProperties() throws Exception {
ODataConsumer consumer = ODataJerseyConsumer.newBuilder(ConfigurationHelper.getTestEndpointUri(Configuration.TEST_ENDPOINT_URI)).build();
// now follow links to departure airport and arrival airport
if(!consumer.getServiceRootUri().contains(NON_STRICT_ODATA_COMPLIANCE_URI_SUFFIX)) {
//do this only for strict odata
OEntity departureAirport = consumer
.getEntity(FLIGHT_SCHEDULE_ENTITYSET_NAME, 2055)
.nav("departureAirport")
.execute();
assertEquals("LTN", departureAirport.getProperty("code").getValue());
OEntity arrivalAirport = consumer
.getEntity(FLIGHT_SCHEDULE_ENTITYSET_NAME, 2055)
.nav("arrivalAirport")
.execute();
assertEquals("GVA", arrivalAirport.getProperty("code").getValue());
}
}
/**
* GET collection, check link to self and other entities for each item
*/
@Test
public void getAirportsLinksToAirport() throws Exception {
ODataConsumer consumer = ODataJerseyConsumer.newBuilder(ConfigurationHelper.getTestEndpointUri(Configuration.TEST_ENDPOINT_URI)).build();
Enumerable<OEntity> airports = consumer.getEntities(AIRPORT_ENTITYSET_NAME).execute();
assertEquals(6, airports.toSet().size());
for (OEntity airport : airports.toSet()) {
String code = airport.getProperty("code").getValue().toString();
if(consumer.getServiceRootUri().contains(FLIGHT_RESPONDER_MODEL_NAME)) {
assertEquals(4, airport.getLinks().size());
}
else {
assertEquals(2, airport.getLinks().size());
}
// there should be one link to departures
if(consumer.getServiceRootUri().contains(NON_STRICT_ODATA_COMPLIANCE_URI_SUFFIX)) {
assertTrue(containsLink(airport.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "()?filter=departureAirportCode+eq+'" + code + "'"));
assertTrue(containsLink(airport.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "()?filter=arrivalAirportCode+eq+'" + code + "'"));
}
else {
assertTrue(containsLink(airport.getLinks(), AIRPORT_ENTITYSET_NAME + "('" + code + "')/departures"));
assertTrue(containsLink(airport.getLinks(), AIRPORT_ENTITYSET_NAME + "('" + code + "')/arrivals"));
}
}
}
/**
* GET item, check link to another entity
*/
@Test
public void getAirportLinksToArrivalsDepartures() throws Exception {
ODataConsumer consumer = ODataJerseyConsumer.newBuilder(ConfigurationHelper.getTestEndpointUri(Configuration.TEST_ENDPOINT_URI)).build();
OEntity airport = consumer.getEntity(AIRPORT_ENTITYSET_NAME, "LTN").execute();
String code = airport.getProperty("code").getValue().toString();
assertEquals("LTN", code);
if(consumer.getServiceRootUri().contains(FLIGHT_RESPONDER_MODEL_NAME)) {
assertEquals(4, airport.getLinks().size());
}
else {
assertEquals(2, airport.getLinks().size());
}
if(consumer.getServiceRootUri().contains(NON_STRICT_ODATA_COMPLIANCE_URI_SUFFIX)) {
assertTrue(containsLink(airport.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "()?filter=arrivalAirportCode+eq+'" + code + "'", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/" + FLIGHT_SCHEDULE_ENTITYSET_NAME));
assertTrue(containsLink(airport.getLinks(), FLIGHT_SCHEDULE_ENTITYSET_NAME + "()?filter=departureAirportCode+eq+'" + code + "'", "http://schemas.microsoft.com/ado/2007/08/dataservices/related/" + FLIGHT_SCHEDULE_ENTITYSET_NAME));
}
else {
assertTrue(containsLink(airport.getLinks(), AIRPORT_ENTITYSET_NAME + "('" + code + "')/departures"));
assertTrue(containsLink(airport.getLinks(), AIRPORT_ENTITYSET_NAME + "('" + code + "')/arrivals"));
}
}
/**
* GET nav properties for an item
*/
@Test
public void getAirportNavProperties() throws Exception {
ODataConsumer consumer = ODataJerseyConsumer.newBuilder(ConfigurationHelper.getTestEndpointUri(Configuration.TEST_ENDPOINT_URI)).build();
// now follow links to departure airport and arrival airport
if(!consumer.getServiceRootUri().contains(NON_STRICT_ODATA_COMPLIANCE_URI_SUFFIX)) {
OEntity departuresFlightSchedule = consumer
.getEntity(AIRPORT_ENTITYSET_NAME, "LTN")
.nav("departures")
.execute();
assertEquals(2051L, departuresFlightSchedule.getProperty("flightScheduleID").getValue());
OEntity arrivalsFlightSchedule = consumer
.getEntity(AIRPORT_ENTITYSET_NAME, "LTN")
.nav("arrivals")
.execute();
assertEquals(2052L, arrivalsFlightSchedule.getProperty("flightScheduleID").getValue());
}
}
private boolean containsLink(List<OLink> links, String link) {
return containsLink(links, link, null);
}
private boolean containsLink(List<OLink> links, String link, String relation) {
assert(links != null);
for (OLink l : links) {
if (l.getHref().equals(link) && (relation == null || l.getRelation().equals(relation))) {
return true;
}
}
//Link not found => print debug info
System.out.println("Links with rel [" + relation + "] and href [" + link + "] does not exist:");
for(OLink l : links) {
System.out.println(" Link: rel [" + l.getRelation() + "], href [" + l.getHref() + "]");
}
return false;
}
}