/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.translator.odata4;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StringReader;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.activation.DataSource;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service.Mode;
import javax.xml.ws.handler.MessageContext;
import javax.xml.ws.http.HTTPBinding;
import org.apache.olingo.commons.api.edm.provider.CsdlComplexType;
import org.apache.olingo.commons.api.edm.provider.CsdlReturnType;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mockito;
import org.teiid.cdk.api.TranslationUtility;
import org.teiid.core.types.InputStreamFactory.ClobInputStreamFactory;
import org.teiid.core.util.ObjectConverterUtil;
import org.teiid.core.util.UnitTestUtil;
import org.teiid.language.Call;
import org.teiid.language.Command;
import org.teiid.language.QueryExpression;
import org.teiid.metadata.MetadataFactory;
import org.teiid.translator.ExecutionContext;
import org.teiid.translator.ProcedureExecution;
import org.teiid.translator.ResultSetExecution;
import org.teiid.translator.TranslatorException;
import org.teiid.translator.UpdateExecution;
import org.teiid.translator.WSConnection;
@SuppressWarnings({"nls", "unused"})
public class TestODataUpdateExecution {
private UpdateExecution helpExecute(MetadataFactory mf, String query, String expectedPayload,
final String resultJson, String expectedURL, String expectedMethod, int responseCode)
throws Exception {
ODataExecutionFactory translator = new ODataExecutionFactory();
translator.start();
TranslationUtility utility = new TranslationUtility(
TestODataMetadataProcessor.getTransformationMetadata(mf,translator));
Command cmd = utility.parseCommand(query);
ExecutionContext context = Mockito.mock(ExecutionContext.class);
WSConnection connection = Mockito.mock(WSConnection.class);
Map<String, Object> headers = new HashMap<String, Object>();
headers.put(MessageContext.HTTP_REQUEST_HEADERS, new HashMap<String, List<String>>());
headers.put(WSConnection.STATUS_CODE, new Integer(responseCode));
Dispatch<DataSource> dispatch = Mockito.mock(Dispatch.class);
Mockito.stub(dispatch.getRequestContext()).toReturn(headers);
Mockito.stub(dispatch.getResponseContext()).toReturn(headers);
Mockito.stub(connection.createDispatch(Mockito.eq(HTTPBinding.HTTP_BINDING), Mockito.anyString(),
Mockito.eq(DataSource.class), Mockito.eq(Mode.MESSAGE))).toReturn(dispatch);
DataSource ds = new DataSource() {
@Override
public OutputStream getOutputStream() throws IOException {
return new ByteArrayOutputStream();
}
@Override
public String getName() {
return "result";
}
@Override
public InputStream getInputStream() throws IOException {
ByteArrayInputStream in = new ByteArrayInputStream(resultJson.getBytes());
return in;
}
@Override
public String getContentType() {
return "application/json";
}
};
ArgumentCaptor<DataSource> data = ArgumentCaptor.forClass(DataSource.class);
Mockito.stub(dispatch.invoke(data.capture())).toReturn(ds);
UpdateExecution execution = translator
.createUpdateExecution(cmd, context,
utility.createRuntimeMetadata(), connection);
execution.execute();
ArgumentCaptor<String> endpoint = ArgumentCaptor.forClass(String.class);
ArgumentCaptor<String> binding = ArgumentCaptor.forClass(String.class);
Mockito.verify(connection).createDispatch(binding.capture(),
endpoint.capture(), Mockito.eq(DataSource.class),
Mockito.eq(Mode.MESSAGE));
assertEquals(expectedURL, URLDecoder.decode(endpoint.getValue(), "utf-8"));
String payload = new String(ObjectConverterUtil.convertToByteArray(
((ClobInputStreamFactory)data.getValue()).getInputStream()));
assertEquals(expectedPayload, payload);
assertEquals(expectedMethod, dispatch.getRequestContext().get(MessageContext.HTTP_REQUEST_METHOD));
return execution;
}
@Test
public void testInsertEntitySet() throws Exception {
String query = "INSERT INTO People(UserName,FirstName,LastName, EMails, Gender, Concurrency) "
+ "values ('jdoe', 'John', 'Doe', ('jdoe@cantfind.ws',), 'Male', 1234)";
String expectedURL = "People";
String returnResponse = "{\n" +
" \"UserName\":\"russellwhyte\",\n" +
" \"FirstName\":\"Russell\",\n" +
" \"LastName\":\"Whyte\"\n" +
"}";
String expectedPayload = "{\"@odata.type\":\"#Microsoft.OData.SampleService.Models.TripPin.Person\","
+ "\"UserName@odata.type\":\"String\",\"UserName\":\"jdoe\","
+ "\"FirstName@odata.type\":\"String\",\"FirstName\":\"John\","
+ "\"LastName@odata.type\":\"String\",\"LastName\":\"Doe\","
+ "\"Emails@odata.type\":\"#Collection(String)\",\"Emails\":[\"jdoe@cantfind.ws\"],"
+ "\"Gender@odata.type\":\"#Microsoft.OData.SampleService.Models.TripPin.PersonGender\","
+ "\"Gender\":\"Male\","
+ "\"Concurrency@odata.type\":\"Int64\",\"Concurrency\":1234}";
UpdateExecution excution = helpExecute(TestODataMetadataProcessor.tripPinMetadata(),
query, expectedPayload, returnResponse, expectedURL, "POST", 201);
}
@Test
public void testInsertComplexType() throws Exception {
String query = "INSERT INTO Persons_address(street, city, state, ssn) "
+ "VALUES('sesame street', 'Newyork', 'NY', 1234)";
String expectedURL = "Persons(1234)/address";
String returnResponse = "{\n" +
" \"UserName\":\"russellwhyte\",\n" +
" \"FirstName\":\"Russell\",\n" +
" \"LastName\":\"Whyte\"\n" +
"}";
String expectedPayload = "{\"@odata.type\":\"#Edm.Address\","
+ "\"street@odata.type\":\"String\",\"street\":\"sesame street\","
+ "\"city@odata.type\":\"String\",\"city\":\"Newyork\","
+ "\"state@odata.type\":\"String\",\"state\":\"NY\"}";
// single complex requires PATCH
UpdateExecution excution = helpExecute(TestODataMetadataProcessor.getEntityWithComplexProperty(),
query, expectedPayload, returnResponse, expectedURL, "PATCH", 201);
}
@Test
public void testInsertComplexTypeTripPin() throws Exception {
String query = "INSERT INTO People_AddressInfo(Address, People_UserName) "
+ "VALUES('sesame street', 'russel')";
String expectedURL = "People('russel')/AddressInfo";
String returnResponse = "{\n" +
" \"Address\":\"russellwhyte\",\n" +
" \"FirstName\":\"Russell\",\n" +
" \"LastName\":\"Whyte\"\n" +
"}";
String expectedPayload = "{\"@odata.type\":\"#Microsoft.OData.SampleService.Models.TripPin.Location\","
+ "\"value\":[{\"@odata.type\":\"#Microsoft.OData.SampleService.Models.TripPin.Location\","
+ "\"Address@odata.type\":\"String\","
+ "\"Address\":\"sesame street\"}]}";
//collection needs PUT
UpdateExecution excution = helpExecute(TestODataMetadataProcessor.tripPinMetadata(),
query, expectedPayload, returnResponse, expectedURL, "PUT", 201);
}
@Test
public void testInsertNavigation() throws Exception {
String query = "INSERT INTO People_Friends(UserName, FirstName, LastName, People_UserName) "
+ "VALUES('jdoe', 'John', 'Doe', 'russel')";
String expectedURL = "People('russel')/Friends";
String returnResponse = "{\n" +
" \"UserName\":\"jdoe\",\n" +
" \"FirstName\":\"John\",\n" +
" \"LastName\":\"Doe\"\n" +
"}";
String expectedPayload = "{\"@odata.type\":\"#Microsoft.OData.SampleService.Models.TripPin.Person\","
+ "\"UserName@odata.type\":\"String\",\"UserName\":\"jdoe\","
+ "\"FirstName@odata.type\":\"String\",\"FirstName\":\"John\","
+ "\"LastName@odata.type\":\"String\",\"LastName\":\"Doe\"}";
UpdateExecution excution = helpExecute(TestODataMetadataProcessor.tripPinMetadata(),
query, expectedPayload, returnResponse, expectedURL, "POST", 201);
}
}