/**
* 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.basic;
import java.beans.PropertyDescriptor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.util.Date;
import java.util.Set;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamReader;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.apache.cxf.aegis.AbstractAegisTest;
import org.apache.cxf.aegis.AegisContext;
import org.apache.cxf.aegis.Context;
import org.apache.cxf.aegis.services.SimpleBean;
import org.apache.cxf.aegis.type.AegisType;
import org.apache.cxf.aegis.type.TypeCreationOptions;
import org.apache.cxf.aegis.type.TypeMapping;
import org.apache.cxf.aegis.xml.stax.ElementReader;
import org.apache.cxf.aegis.xml.stax.ElementWriter;
import org.apache.cxf.common.util.SOAPConstants;
import org.apache.cxf.common.xmlschema.XmlSchemaConstants;
import org.apache.cxf.helpers.DOMUtils;
import org.apache.cxf.staxutils.StaxUtils;
import org.apache.ws.commons.schema.XmlSchema;
import org.apache.ws.commons.schema.XmlSchemaAttribute;
import org.apache.ws.commons.schema.XmlSchemaComplexType;
import org.apache.ws.commons.schema.XmlSchemaElement;
import org.apache.ws.commons.schema.XmlSchemaObject;
import org.apache.ws.commons.schema.XmlSchemaSequence;
import org.junit.Test;
public class BeanTest extends AbstractAegisTest {
TypeMapping mapping;
private AegisContext context;
public void setUp() throws Exception {
super.setUp();
addNamespace("b", "urn:Bean");
addNamespace("bz", "urn:beanz");
addNamespace("a", "urn:anotherns");
addNamespace("xsi", SOAPConstants.XSI_NS);
}
private void defaultContext() {
context = new AegisContext();
context.initialize();
mapping = context.getTypeMapping();
}
@Test
public void testBean() throws Exception {
defaultContext();
BeanType type = new BeanType();
type.setTypeClass(SimpleBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
// Test reading
ElementReader reader = new ElementReader(getResourceAsStream("bean1.xml"));
SimpleBean bean = (SimpleBean)type.readObject(reader, getContext());
assertEquals("bleh", bean.getBleh());
assertEquals("howdy", bean.getHowdy());
reader.getXMLStreamReader().close();
// Test reading with extra elements
reader = new ElementReader(getResourceAsStream("bean2.xml"));
bean = (SimpleBean)type.readObject(reader, getContext());
assertEquals("bleh", bean.getBleh());
assertEquals("howdy", bean.getHowdy());
reader.getXMLStreamReader().close();
// test <bleh/> element
reader = new ElementReader(getResourceAsStream("bean7.xml"));
bean = (SimpleBean)type.readObject(reader, getContext());
assertEquals("", bean.getBleh());
assertEquals("howdy", bean.getHowdy());
reader.getXMLStreamReader().close();
bean.setBleh("bleh");
// Test writing
Element element = writeObjectToElement(type, bean, getContext());
assertValid("/b:root/b:bleh[text()='bleh']", element);
assertValid("/b:root/b:howdy[text()='howdy']", element);
}
@Test
public void testBeanWithXsiType() throws Exception {
defaultContext();
BeanType type = new BeanType();
type.setTypeClass(SimpleBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
// Test reading
ElementReader reader = new ElementReader(getResourceAsStream("bean9.xml"));
Context ctx = getContext();
ctx.getGlobalContext().setReadXsiTypes(false);
SimpleBean bean = (SimpleBean)type.readObject(reader, ctx);
assertEquals("bleh", bean.getBleh());
assertEquals("howdy", bean.getHowdy());
reader.getXMLStreamReader().close();
Element element = writeObjectToElement(type, bean, getContext());
assertValid("/b:root/b:bleh[text()='bleh']", element);
assertValid("/b:root/b:howdy[text()='howdy']", element);
}
@Test
public void testUnmappedProperty() throws Exception {
defaultContext();
String ns = "urn:Bean";
BeanTypeInfo info = new BeanTypeInfo(SimpleBean.class, ns, false);
QName name = new QName(ns, "howdycustom");
info.mapElement("howdy", name);
info.setTypeMapping(mapping);
assertEquals("howdy", info.getPropertyDescriptorFromMappedName(name).getName());
BeanType type = new BeanType(info);
type.setTypeClass(SimpleBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
ElementReader reader = new ElementReader(getResourceAsStream("bean3.xml"));
SimpleBean bean = (SimpleBean)type.readObject(reader, getContext());
assertEquals("howdy", bean.getHowdy());
assertNull(bean.getBleh());
reader.getXMLStreamReader().close();
Element element = writeObjectToElement(type, bean, getContext());
assertInvalid("/b:root/b:bleh", element);
assertValid("/b:root/b:howdycustom[text()='howdy']", element);
}
@Test
public void testAttributeMap() throws Exception {
defaultContext();
BeanTypeInfo info = new BeanTypeInfo(SimpleBean.class, "urn:Bean");
info.mapAttribute("howdy", new QName("urn:Bean", "howdy"));
info.mapAttribute("bleh", new QName("urn:Bean", "bleh"));
info.setTypeMapping(mapping);
BeanType type = new BeanType(info);
type.setTypeClass(SimpleBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
ElementReader reader = new ElementReader(getResourceAsStream("bean4.xml"));
SimpleBean bean = (SimpleBean)type.readObject(reader, getContext());
assertEquals("bleh", bean.getBleh());
assertEquals("howdy", bean.getHowdy());
reader.getXMLStreamReader().close();
// Test writing
Element element = writeObjectToElement(type, bean, getContext());
assertValid("/b:root[@b:bleh='bleh']", element);
assertValid("/b:root[@b:howdy='howdy']", element);
XmlSchema schema = newXmlSchema("urn:Bean");
type.writeSchema(schema);
XmlSchemaComplexType stype = (XmlSchemaComplexType)schema.getTypeByName("bean");
boolean howdy = false;
boolean bleh = false;
for (int x = 0; x < stype.getAttributes().getCount(); x++) {
XmlSchemaObject o = stype.getAttributes().getItem(x);
if (o instanceof XmlSchemaAttribute) {
XmlSchemaAttribute a = (XmlSchemaAttribute)o;
if ("howdy".equals(a.getName())) {
howdy = true;
}
if ("bleh".equals(a.getName())) {
bleh = true;
}
}
}
assertTrue(howdy);
assertTrue(bleh);
}
@Test
public void testAttributeMapDifferentNS() throws Exception {
defaultContext();
BeanTypeInfo info = new BeanTypeInfo(SimpleBean.class, "urn:Bean");
info.mapAttribute("howdy", new QName("urn:Bean2", "howdy"));
info.mapAttribute("bleh", new QName("urn:Bean2", "bleh"));
info.setTypeMapping(mapping);
BeanType type = new BeanType(info);
type.setTypeClass(SimpleBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
ElementReader reader = new ElementReader(getResourceAsStream("bean8.xml"));
SimpleBean bean = (SimpleBean)type.readObject(reader, getContext());
assertEquals("bleh", bean.getBleh());
assertEquals("howdy", bean.getHowdy());
reader.getXMLStreamReader().close();
// Test writing
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ElementWriter writer = new ElementWriter(bos, "root", "urn:Bean");
type.writeObject(bean, writer, getContext());
writer.close();
writer.flush();
bos.close();
Document doc = DOMUtils.readXml(new ByteArrayInputStream(bos.toByteArray()));
Element element = doc.getDocumentElement();
addNamespace("b2", "urn:Bean2");
assertValid("/b:root[@b2:bleh='bleh']", element);
assertValid("/b:root[@b2:howdy='howdy']", element);
}
@Test
public void testNullProperties() throws Exception {
defaultContext();
BeanTypeInfo info = new BeanTypeInfo(SimpleBean.class, "urn:Bean");
info.setTypeMapping(mapping);
info.mapAttribute("howdy", new QName("urn:Bean", "howdy"));
info.mapElement("bleh", new QName("urn:Bean", "bleh"));
BeanType type = new BeanType(info);
type.setTypeClass(SimpleBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
SimpleBean bean = new SimpleBean();
// Test writing
Element element = writeObjectToElement(type, bean, getContext());
assertInvalid("/b:root[@b:howdy]", element);
assertValid("/b:root/b:bleh[@xsi:nil='true']", element);
XmlSchema schema = newXmlSchema("urn:Bean");
type.writeSchema(schema);
XmlSchemaComplexType stype = (XmlSchemaComplexType)schema.getTypeByName("bean");
XmlSchemaSequence seq = (XmlSchemaSequence) stype.getParticle();
boolean howdy = false;
boolean bleh = false;
for (int x = 0; x < seq.getItems().getCount(); x++) {
XmlSchemaObject o = seq.getItems().getItem(x);
if (o instanceof XmlSchemaElement) {
XmlSchemaElement a = (XmlSchemaElement)o;
if ("bleh".equals(a.getName())) {
bleh = true;
}
}
}
for (int x = 0; x < stype.getAttributes().getCount(); x++) {
XmlSchemaObject o = stype.getAttributes().getItem(x);
if (o instanceof XmlSchemaAttribute) {
XmlSchemaAttribute a = (XmlSchemaAttribute)o;
if ("howdy".equals(a.getName())) {
howdy = true;
}
}
}
assertTrue(howdy);
assertTrue(bleh);
}
@Test
public void testNillableInt() throws Exception {
defaultContext();
BeanTypeInfo info = new BeanTypeInfo(IntBean.class, "urn:Bean");
info.setTypeMapping(mapping);
BeanType type = new BeanType(info);
type.setTypeClass(IntBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
XmlSchema schema = newXmlSchema("urn:Bean");
type.writeSchema(schema);
XmlSchemaComplexType btype = (XmlSchemaComplexType)schema.getTypeByName("bean");
XmlSchemaSequence seq = (XmlSchemaSequence)btype.getParticle();
boolean int1ok = false;
boolean int2ok = false;
for (int x = 0; x < seq.getItems().getCount(); x++) {
XmlSchemaObject o = seq.getItems().getItem(x);
if (o instanceof XmlSchemaElement) {
XmlSchemaElement oe = (XmlSchemaElement) o;
if ("int1".equals(oe.getName())) {
int1ok = true;
assertTrue(oe.isNillable());
assertEquals(0, oe.getMinOccurs());
} else if ("int2".equals(oe.getName())) {
int2ok = true;
assertEquals(0, oe.getMinOccurs());
assertFalse(oe.isNillable());
}
}
}
assertTrue(int1ok);
assertTrue(int2ok);
}
@Test
public void testNillableAnnotation() throws Exception {
context = new AegisContext();
TypeCreationOptions config = new TypeCreationOptions();
config.setDefaultNillable(false);
config.setDefaultMinOccurs(1);
context.setTypeCreationOptions(config);
context.initialize();
mapping = context.getTypeMapping();
BeanType type = (BeanType)mapping.getTypeCreator().createType(BeanWithNillableItem.class);
type.setTypeClass(BeanWithNillableItem.class);
type.setTypeMapping(mapping);
XmlSchema schema = newXmlSchema("urn:Bean");
type.writeSchema(schema);
XmlSchemaComplexType btype = (XmlSchemaComplexType)schema.getTypeByName("BeanWithNillableItem");
XmlSchemaSequence seq = (XmlSchemaSequence)btype.getParticle();
boolean itemFound = false;
boolean itemNotNillableFound = false;
for (int x = 0; x < seq.getItems().getCount(); x++) {
XmlSchemaObject o = seq.getItems().getItem(x);
if (o instanceof XmlSchemaElement) {
XmlSchemaElement oe = (XmlSchemaElement) o;
if ("item".equals(oe.getName())) {
itemFound = true;
assertTrue(oe.isNillable());
assertEquals(0, oe.getMinOccurs());
} else if ("itemNotNillable".equals(oe.getName())) {
itemNotNillableFound = true;
assertFalse(oe.isNillable());
}
}
}
assertTrue(itemFound);
assertTrue(itemNotNillableFound);
}
@Test
public void testNillableIntMinOccurs1() throws Exception {
context = new AegisContext();
TypeCreationOptions config = new TypeCreationOptions();
config.setDefaultMinOccurs(1);
config.setDefaultNillable(false);
context.setTypeCreationOptions(config);
context.initialize();
mapping = context.getTypeMapping();
BeanType type = (BeanType)mapping.getTypeCreator().createType(IntBean.class);
type.setTypeClass(IntBean.class);
type.setTypeMapping(mapping);
XmlSchema schema = newXmlSchema("urn:Bean");
type.writeSchema(schema);
XmlSchemaComplexType btype = (XmlSchemaComplexType)schema.getTypeByName("IntBean");
XmlSchemaSequence seq = (XmlSchemaSequence)btype.getParticle();
boolean int1ok = false;
for (int x = 0; x < seq.getItems().getCount(); x++) {
XmlSchemaObject o = seq.getItems().getItem(x);
if (o instanceof XmlSchemaElement) {
XmlSchemaElement oe = (XmlSchemaElement) o;
if ("int1".equals(oe.getName())) {
int1ok = true;
assertFalse(oe.isNillable());
assertEquals(1, oe.getMinOccurs());
}
}
}
assertTrue(int1ok);
}
@Test
public void testCharMappings() throws Exception {
defaultContext();
BeanType type = (BeanType)mapping.getTypeCreator().createType(SimpleBean.class);
type.setTypeClass(SimpleBean.class);
type.setTypeMapping(mapping);
XmlSchema schema = newXmlSchema("urn:Bean");
type.writeSchema(schema);
XmlSchemaComplexType btype = (XmlSchemaComplexType)schema.getTypeByName("SimpleBean");
XmlSchemaSequence seq = (XmlSchemaSequence)btype.getParticle();
boolean charok = false;
for (int x = 0; x < seq.getItems().getCount(); x++) {
XmlSchemaObject o = seq.getItems().getItem(x);
if (o instanceof XmlSchemaElement) {
XmlSchemaElement oe = (XmlSchemaElement) o;
if ("character".equals(oe.getName())) {
charok = true;
assertNotNull(oe.getSchemaTypeName());
assertTrue(oe.isNillable());
assertEquals(CharacterAsStringType.CHARACTER_AS_STRING_TYPE_QNAME,
oe.getSchemaTypeName());
}
}
}
assertTrue(charok);
}
@Test
public void testByteMappings() throws Exception {
defaultContext();
BeanType type = (BeanType)mapping.getTypeCreator().createType(SimpleBean.class);
type.setTypeClass(SimpleBean.class);
type.setTypeMapping(mapping);
XmlSchema schema = newXmlSchema("urn:Bean");
type.writeSchema(schema);
XmlSchemaComplexType btype = (XmlSchemaComplexType)schema.getTypeByName("SimpleBean");
XmlSchemaSequence seq = (XmlSchemaSequence)btype.getParticle();
boolean littleByteOk = false;
boolean bigByteOk = false;
for (int x = 0; x < seq.getItems().getCount(); x++) {
XmlSchemaObject o = seq.getItems().getItem(x);
if (o instanceof XmlSchemaElement) {
XmlSchemaElement oe = (XmlSchemaElement) o;
if ("littleByte".equals(oe.getName())) {
littleByteOk = true;
assertNotNull(oe.getSchemaTypeName());
assertEquals(XmlSchemaConstants.BYTE_QNAME, oe.getSchemaTypeName());
} else if ("bigByte".equals(oe.getName())) {
bigByteOk = true;
assertNotNull(oe.getSchemaTypeName());
assertEquals(XmlSchemaConstants.BYTE_QNAME, oe.getSchemaTypeName());
}
}
}
assertTrue(littleByteOk);
assertTrue(bigByteOk);
SimpleBean bean = new SimpleBean();
bean.setBigByte(new Byte((byte)0xfe));
bean.setLittleByte((byte)0xfd);
Element element = writeObjectToElement(type, bean, getContext());
Byte bb = new Byte((byte)0xfe);
String bbs = bb.toString();
assertValid("/b:root/bz:bigByte[text()='" + bbs + "']", element);
// Test reading
ElementReader reader = new ElementReader(getResourceAsStream("byteBeans.xml"));
bean = (SimpleBean)type.readObject(reader, getContext());
assertEquals(-5, bean.getLittleByte());
assertEquals(25, bean.getBigByte().byteValue());
reader.getXMLStreamReader().close();
}
@Test
public void testNullNonNillableWithDate() throws Exception {
defaultContext();
BeanTypeInfo info = new BeanTypeInfo(DateBean.class, "urn:Bean");
info.setTypeMapping(mapping);
BeanType type = new BeanType(info);
type.setTypeClass(DateBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
DateBean bean = new DateBean();
// Test writing
Element element = writeObjectToElement(type, bean, getContext());
// Make sure the date doesn't have an element. Its non nillable so it
// just
// shouldn't be there.
assertInvalid("/b:root/b:date", element);
assertValid("/b:root", element);
}
@Test
public void testExtendedBean() throws Exception {
defaultContext();
BeanTypeInfo info = new BeanTypeInfo(ExtendedBean.class, "urn:Bean");
info.setTypeMapping(mapping);
BeanType type = new BeanType(info);
type.setTypeClass(ExtendedBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
PropertyDescriptor[] pds = info.getPropertyDescriptors();
assertEquals(9, pds.length);
ExtendedBean bean = new ExtendedBean();
bean.setHowdy("howdy");
Element element = writeObjectToElement(type, bean, getContext());
assertValid("/b:root/b:howdy[text()='howdy']", element);
}
@Test
public void testByteBean() throws Exception {
defaultContext();
BeanTypeInfo info = new BeanTypeInfo(ByteBean.class, "urn:Bean");
info.setTypeMapping(mapping);
BeanType type = new BeanType(info);
type.setTypeClass(ByteBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:Bean", "bean"));
QName name = new QName("urn:Bean", "data");
AegisType dataType = type.getTypeInfo().getType(name);
assertNotNull(dataType);
assertTrue(type.getTypeInfo().isNillable(name));
ByteBean bean = new ByteBean();
// Test writing
Element element = writeObjectToElement(type, bean, getContext());
// Make sure the date doesn't have an element. Its non nillable so it
// just
// shouldn't be there.
addNamespace("xsi", SOAPConstants.XSI_NS);
assertValid("/b:root/b:data[@xsi:nil='true']", element);
XMLStreamReader sreader = StaxUtils.createXMLStreamReader(element);
bean = (ByteBean)type.readObject(new ElementReader(sreader), getContext());
assertNotNull(bean);
assertNull(bean.getData());
}
@Test
public void testGetSetRequired() throws Exception {
defaultContext();
BeanType type = new BeanType();
type.setTypeClass(GoodBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:foo", "BadBean"));
assertTrue(type.getTypeInfo().getElements().iterator().hasNext());
type = new BeanType();
type.setTypeClass(BadBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:foo", "BadBean"));
assertFalse(type.getTypeInfo().getElements().iterator().hasNext());
type = new BeanType();
type.setTypeClass(BadBean2.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:foo", "BadBean2"));
assertFalse(type.getTypeInfo().getElements().iterator().hasNext());
}
@Test
public void testInterfaceBeans() throws Exception {
defaultContext();
BeanType type = new BeanType();
type.setTypeClass(SerializableBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:foo", "SerializableBean"));
AegisType stringType = mapping.getType(String.class);
assertTrue(type.getDependencies().contains(stringType));
type = new BeanType();
type.setTypeClass(CloneableBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:foo", "CloneableBean"));
assertEquals(1, type.getDependencies().size());
assertTrue(type.getDependencies().contains(stringType));
type = new BeanType();
type.setTypeClass(SimpleInterface.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:foo", "SimpleInterface"));
assertEquals(1, type.getDependencies().size());
assertTrue(type.getDependencies().contains(stringType));
type = new BeanType();
type.setTypeClass(ExtendingInterface.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:foo", "ExtendingInterface"));
Set<AegisType> dependencies = type.getDependencies();
assertEquals(1, dependencies.size());
assertEquals(String.class, dependencies.iterator().next().getTypeClass());
}
@Test
public void testEnumBean() throws Exception {
defaultContext();
BeanType type = new BeanType();
type.setTypeClass(EnumBean.class);
type.setTypeMapping(mapping);
type.setSchemaType(new QName("urn:foo", "EnumBean"));
assertTrue(type.getDependencies().isEmpty());
}
public static class DateBean {
private Date date;
public Date getDate() {
return date;
}
public void setDate(Date date) {
this.date = date;
}
}
public static class IntBean {
private Integer int1;
private int int2;
public Integer getInt1() {
return int1;
}
public void setInt1(Integer int1) {
this.int1 = int1;
}
public int getInt2() {
return int2;
}
public void setInt2(int int2) {
this.int2 = int2;
}
}
public static class BeanWithNillableItem {
private IntBean item;
private Integer itemNotNillable;
@XmlElement(nillable = true)
public IntBean getItem() {
return item;
}
public void setItem(IntBean item) {
this.item = item;
}
public Integer getItemNotNillable() {
return itemNotNillable;
}
public void setItemNotNillable(Integer itemNotNillable) {
this.itemNotNillable = itemNotNillable;
}
}
public static class ByteBean {
private byte[] data;
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
}
// This class only has a read property, no write
public static class GoodBean {
private String string;
public String getString() {
return string;
}
}
public static class BadBean {
public String delete() {
return null;
}
}
public static class BadBean2 {
public void setString(String string) {
}
}
public static class ExtendedBean extends SimpleBean {
private String howdy;
public String getHowdy() {
return howdy;
}
public void setHowdy(String howdy) {
this.howdy = howdy;
}
}
public interface SerializableBean extends Serializable {
String getString();
}
public interface CloneableBean extends Cloneable {
String getString();
}
public interface SimpleInterface {
String getString();
}
public interface ExtendingInterface extends SimpleInterface {
String getAnotherString();
}
public enum EnumBean {
VALUE1, VALUE2;
}
}