/**
* 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.cxf.aegis.type.encoded;
import java.math.BigDecimal;
import java.util.Arrays;
import javax.xml.namespace.QName;
import org.apache.cxf.aegis.Context;
import org.apache.cxf.aegis.type.AegisType;
import org.apache.cxf.aegis.type.basic.BeanTypeInfo;
import org.apache.cxf.aegis.xml.stax.ElementReader;
import org.junit.Test;
public class SoapArrayTypeTest extends AbstractEncodedTest {
private static final String[][][] ARRAY_2_3_4 = new String[][][] {
new String[][]{
new String[]{"row1 col1 dep1", "row1 col1 dep2", "row1 col1 dep3", "row1 col1 dep4"},
new String[]{"row1 col2 dep1", "row1 col2 dep2", "row1 col2 dep3", "row1 col2 dep4"},
new String[]{"row1 col3 dep1", "row1 col3 dep2", "row1 col3 dep3", "row1 col3 dep4"},
},
new String[][]{
new String[]{"row2 col1 dep1", "row2 col1 dep2", "row2 col1 dep3", "row2 col1 dep4"},
new String[]{"row2 col2 dep1", "row2 col2 dep2", "row2 col2 dep3", "row2 col2 dep4"},
new String[]{"row2 col3 dep1", "row2 col3 dep2", "row2 col3 dep3", "row2 col3 dep4"},
},
};
public void setUp() throws Exception {
super.setUp();
// address type
BeanTypeInfo addressInfo = new BeanTypeInfo(Address.class, "urn:Bean");
addressInfo.setTypeMapping(mapping);
StructType addressType = new StructType(addressInfo);
addressType.setTypeClass(Address.class);
addressType.setSchemaType(new QName("urn:Bean", "address"));
mapping.register(addressType);
// purchase order type
BeanTypeInfo poInfo = new BeanTypeInfo(PurchaseOrder.class, "urn:Bean");
poInfo.setTypeMapping(mapping);
StructType purchaseOrderType = new StructType(poInfo);
purchaseOrderType.setTypeClass(PurchaseOrder.class);
purchaseOrderType.setTypeMapping(mapping);
purchaseOrderType.setSchemaType(new QName("urn:Bean", "po"));
mapping.register(purchaseOrderType);
// String[][][]
SoapArrayType arrayOfString =
createArrayType(String[].class, new QName("urn:Bean", "SOAPArrayOfString"));
mapping.register(arrayOfString);
SoapArrayType arrayOfArrayOfString =
createArrayType(String[][].class, new QName("urn:Bean", "SOAPArrayOfArrayOfString"));
mapping.register(arrayOfArrayOfString);
SoapArrayType arrayOfArrayOfArrayOfString =
createArrayType(String[][][].class, new QName("urn:Bean", "SOAPArrayOfArrayOfArrayOfString"));
mapping.register(arrayOfArrayOfArrayOfString);
// int[][]
SoapArrayType arrayOfInt =
createArrayType(int[].class, new QName("urn:Bean", "SOAPArrayOfInt"));
mapping.register(arrayOfInt);
SoapArrayType arrayOfArrayOfInt =
createArrayType(int[][].class, new QName("urn:Bean", "SOAPArrayOfArrayOfInt"));
mapping.register(arrayOfArrayOfInt);
// Object[]
SoapArrayType arrayOfAddress =
createArrayType(Address[].class, new QName("urn:Bean", "SOAPArrayOfAddress"));
mapping.register(arrayOfAddress);
SoapArrayType arrayOfAny =
createArrayType(Object[].class, new QName("urn:Bean", "SOAPArrayOfAny"));
mapping.register(arrayOfAny);
}
@Test
public void testSimpleArray() throws Exception {
Context context = getContext();
// xsd:int[2]
ElementReader reader = new ElementReader(getClass().getResourceAsStream("arraySimple.xml"));
int[] numbers = (int[]) createArrayType(int[].class).readObject(reader, context);
reader.getXMLStreamReader().close();
assertArrayEquals(new int[]{3, 4}, numbers);
// round trip tests
numbers = readWriteReadRef("arraySimple.xml", int[].class);
assertArrayEquals(new int[]{3, 4}, numbers);
}
@Test
public void testUrTypeArray() throws Exception {
Context context = getContext();
// ur-type[4] nested elements have xsi:type
ElementReader reader = new ElementReader(getClass().getResourceAsStream("arrayUrType1.xml"));
Object[] objects = (Object[]) createArrayType(Object[].class).readObject(reader, context);
reader.getXMLStreamReader().close();
assertArrayEquals(new Object[]{42, (float)42.42, "Forty Two"}, objects);
// ur-type[4] nested element name have a global schema type
reader = new ElementReader(getClass().getResourceAsStream("arrayUrType2.xml"));
objects = (Object[]) createArrayType(Object[].class).readObject(reader, context);
reader.getXMLStreamReader().close();
assertArrayEquals(Arrays.asList(objects).toString(),
new Object[]{42, new BigDecimal("42.42"), "Forty Two"},
objects);
}
@Test
public void testUrTypeArrayReadWriteRef1() throws Exception {
Object[] objects;
// round trip tests
objects = readWriteReadRef("arrayUrType1.xml", Object[].class);
assertArrayEquals(new Object[]{42, new Float(42.42f), "Forty Two"}, objects);
}
@Test
public void testUrTypeArrayReadWriteRef2() throws Exception {
Object[] objects;
// round trip tests
objects = readWriteReadRef("arrayUrType2.xml", Object[].class);
assertArrayEquals(new Object[]{42, new BigDecimal("42.42"), "Forty Two"}, objects);
}
@Test
public void testAnyTypeArray() throws Exception {
Context context = getContext();
// ur-type[4] nested elements have xsi:type
ElementReader reader = new ElementReader(getClass().getResourceAsStream("arrayAnyType1.xml"));
Object[] objects = (Object[]) createArrayType(Object[].class).readObject(reader, context);
reader.getXMLStreamReader().close();
assertArrayEquals(new Object[]{42, (float)42.42, "Forty Two"}, objects);
// ur-type[4] nested element name have a global schema type
reader = new ElementReader(getClass().getResourceAsStream("arrayAnyType2.xml"));
objects = (Object[]) createArrayType(Object[].class).readObject(reader, context);
reader.getXMLStreamReader().close();
assertArrayEquals(new Object[]{42, new BigDecimal("42.42"), "Forty Two"}, objects);
// round trip tests
objects = readWriteReadRef("arrayAnyType1.xml", Object[].class);
assertArrayEquals(new Object[]{42, (float)42.42, "Forty Two"}, objects);
objects = readWriteReadRef("arrayAnyType2.xml", Object[].class);
assertArrayEquals(new Object[]{42, new BigDecimal("42.42"), "Forty Two"}, objects);
}
@Test
public void testStructArray() throws Exception {
Context context = getContext();
// b:address[2]
ElementReader reader = new ElementReader(getClass().getResourceAsStream("arrayStructs.xml"));
Address[] addresses = (Address[]) createArrayType(Address[].class).readObject(reader, context);
reader.getXMLStreamReader().close();
StructTypeTest.validateShippingAddress(addresses[0]);
StructTypeTest.validateBillingAddress(addresses[1]);
// round trip tests
addresses = readWriteReadRef("arrayStructs.xml", Address[].class);
StructTypeTest.validateShippingAddress(addresses[0]);
StructTypeTest.validateBillingAddress(addresses[1]);
}
@Test
public void testSquareArray() throws Exception {
Context context = getContext();
// xsd:string[2,3,4]
ElementReader reader = new ElementReader(getClass().getResourceAsStream("arraySquare.xml"));
String[][][] strings = (String[][][]) createArrayType(String[][][].class).readObject(reader, context);
reader.getXMLStreamReader().close();
assertArrayEquals(ARRAY_2_3_4, strings);
// round trip tests
strings = readWriteReadRef("arraySquare.xml", String[][][].class);
assertArrayEquals(ARRAY_2_3_4, strings);
}
@Test
public void testArrayOfArrays() throws Exception {
Context context = getContext();
// xsd:string[,][2]
ElementReader reader = new ElementReader(getClass().getResourceAsStream("arrayArrayOfArrays1.xml"));
String[][][] strings = (String[][][]) createArrayType(String[][][].class).readObject(reader, context);
reader.getXMLStreamReader().close();
assertArrayEquals(ARRAY_2_3_4, strings);
// round trip tests
strings = readWriteReadRef("arrayArrayOfArrays1.xml", String[][][].class);
assertArrayEquals(ARRAY_2_3_4, strings);
}
@Test
public void testPartiallyTransmitted() throws Exception {
Context context = getContext();
// xsd:int[5] offset="[2]"
ElementReader reader = new ElementReader(
getClass().getResourceAsStream("arrayPartiallyTransmitted.xml"));
int[] numbers = (int[]) createArrayType(int[].class).readObject(reader, context);
reader.getXMLStreamReader().close();
assertArrayEquals(new int[]{0, 0, 3, 4, 0}, numbers);
// round trip tests
numbers = readWriteReadRef("arrayPartiallyTransmitted.xml", int[].class);
assertArrayEquals(new int[]{0, 0, 3, 4, 0}, numbers);
}
@Test
public void testSparseArray() throws Exception {
Context context = getContext();
// xsd:string[2,3,4]
ElementReader reader = new ElementReader(getClass().getResourceAsStream("arraySparse1.xml"));
String[][][] strings = (String[][][]) createArrayType(String[][][].class).readObject(reader, context);
reader.getXMLStreamReader().close();
verifySparseArray(strings);
// xsd:string[,][4] -> xsd:string[3,4]
reader = new ElementReader(getClass().getResourceAsStream("arraySparse2.xml"));
strings = (String[][][]) createArrayType(String[][][].class).readObject(reader, context);
reader.getXMLStreamReader().close();
verifySparseArray(strings);
// xsd:string[,][4] -> xsd:string[][3] -> xsd:string[4]
reader = new ElementReader(getClass().getResourceAsStream("arraySparse3.xml"));
strings = (String[][][]) createArrayType(String[][][].class).readObject(reader, context);
reader.getXMLStreamReader().close();
verifySparseArray(strings);
// round trip tests
strings = readWriteReadRef("arraySparse1.xml", String[][][].class);
verifySparseArray(strings);
strings = readWriteReadRef("arraySparse2.xml", String[][][].class);
verifySparseArray(strings);
strings = readWriteReadRef("arraySparse3.xml", String[][][].class);
verifySparseArray(strings);
}
@Test
public void testInvalidArray() throws Exception {
// to many elements
verifyInvalid("arrayInvalid1.xml", int[].class);
// position out of bounds
verifyInvalid("arrayInvalid2.xml", int[].class);
// array dimensions mismatch
verifyInvalid("arrayInvalid3.xml", int[].class);
verifyInvalid("arrayInvalid4.xml", int[][].class);
// array offset to large
verifyInvalid("arrayInvalid5.xml", int[].class);
verifyInvalid("arrayInvalid6.xml", int[].class);
// duplicate entry in sparse array
verifyInvalid("arrayInvalid7.xml", String[][][].class);
// position doesn't have enough positions
verifyInvalid("arrayInvalid8.xml", String[][][].class);
// position has too many positions
verifyInvalid("arrayInvalid9.xml", String[][][].class);
}
private void verifySparseArray(String[][][] strings) {
assertEquals("row1 col1 dep1", strings[0][0][0]);
strings[0][0][0] = null;
assertEquals("row2 col1 dep1", strings[1][0][0]);
strings[1][0][0] = null;
assertEquals("row1 col2 dep1", strings[0][1][0]);
strings[0][1][0] = null;
assertEquals("row1 col1 dep2", strings[0][0][1]);
strings[0][0][1] = null;
assertEquals("row1 col3 dep1", strings[0][2][0]);
strings[0][2][0] = null;
assertEquals("row1 col1 dep4", strings[0][0][3]);
strings[0][0][3] = null;
assertEquals("row2 col3 dep4", strings[1][2][3]);
strings[1][2][3] = null;
assertEquals("row2 col3 dep2", strings[1][2][1]);
strings[1][2][1] = null;
assertEquals("row1 col2 dep3", strings[0][1][2]);
strings[0][1][2] = null;
assertEquals(2, strings.length);
for (int i = 0; i < strings.length; i++) {
if (strings[i] != null) {
assertEquals(3, strings[i].length);
for (int j = 0; j < strings[i].length; j++) {
if (strings[i][j] != null) {
assertEquals(4, strings[i][j].length);
for (int k = 0; k < strings[i][j].length; k++) {
assertNull("strings[" + i + "][" + j + "][" + k + "] is not null",
strings[i][j][k]);
}
}
}
}
}
}
private SoapArrayType createArrayType(Class<?> typeClass) {
return createArrayType(typeClass, new QName("urn:Bean", "stuff"));
}
private SoapArrayType createArrayType(Class<?> typeClass, QName schemaType) {
AegisType type = mapping.getType(typeClass);
if (type != null) {
return (SoapArrayType) type;
}
SoapArrayType arrayType = new SoapArrayType();
arrayType.setTypeClass(typeClass);
arrayType.setTypeMapping(mapping);
arrayType.setSchemaType(schemaType);
return arrayType;
}
}