diff --git a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/LocalNameVariant.java b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/LocalNameVariant.java new file mode 100644 index 0000000..811125a --- /dev/null +++ b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/LocalNameVariant.java @@ -0,0 +1,36 @@ +package com.sun.xml.bind.v2.model.impl; + +import com.sun.xml.bind.api.impl.NameConverter; + +enum LocalNameVariant { + CLASS_NAME { + String convert(String name) { + return NameConverter.standard.toClassName(name); + } + }, + CONSTANT_NAME { + String convert(String name) { + return NameConverter.standard.toConstantName(name); + } + }, + UNCHANGED, + LOWER_CASE { + String convert(String name) { + return name.toLowerCase(); + } + }, + MIXED_CLASS_NAME { + String convert(String name) { + return NameConverter.standard.toVariableName(name); + } + }, + UPPER_CASE { + String convert(String name) { + return name.toUpperCase(); + } + }; + + String convert(String name) { + return name; + } +} \ No newline at end of file diff --git a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/PropertyInfoImpl.java b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/PropertyInfoImpl.java index fbd3fb1..a38ea64 100644 --- a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/PropertyInfoImpl.java +++ b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/PropertyInfoImpl.java @@ -77,6 +77,11 @@ */ abstract class PropertyInfoImpl implements PropertyInfo, Locatable, Comparable /*by their names*/ { + + // XXX: should it be instance or static field? + protected static LocalNameVariant propertyDefaultLocalNameVariant = + LocalNameVariant.valueOf( + System.getProperty("com.sun.xml.bind.v2.model.impl.PropertyDefaultLocalNameVariant", "UNCHANGED")); /** * Object that reads annotations. @@ -360,7 +365,7 @@ // compute the default TODO.checkSpec(); if(local.length()==0 || local.equals("##default")) - local = seed.getName(); + local = propertyDefaultLocalNameVariant.convert(seed.getName()); if(uri.equals("##default")) { XmlSchema xs = reader().getPackageAnnotation( XmlSchema.class, parent.getClazz(), this ); // JAX-RPC doesn't want the default namespace URI swapping to take effect to diff --git a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/TypeInfoImpl.java b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/TypeInfoImpl.java index e6268df..dd90fd3 100644 --- a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/TypeInfoImpl.java +++ b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/model/impl/TypeInfoImpl.java @@ -45,7 +45,6 @@ import javax.xml.bind.annotation.XmlType; import javax.xml.namespace.QName; -import com.sun.xml.bind.api.impl.NameConverter; import com.sun.xml.bind.v2.model.annotation.AnnotationReader; import com.sun.xml.bind.v2.model.annotation.Locatable; import com.sun.xml.bind.v2.model.core.TypeInfo; @@ -59,6 +58,16 @@ */ abstract class TypeInfoImpl implements TypeInfo, Locatable { + + // XXX: should it be instance or static field? + protected static LocalNameVariant elementDefaultLocalNameVariant = + LocalNameVariant.valueOf( + System.getProperty("com.sun.xml.bind.v2.model.impl.ElementDefaultLocalNameVariant", "MIXED_CLASS_NAME")); + + // XXX: should it be instance or static field? + protected static LocalNameVariant typeDefaultLocalNameVariant = + LocalNameVariant.valueOf( + System.getProperty("com.sun.xml.bind.v2.model.impl.TypeDefaultLocalNameVariant", "MIXED_CLASS_NAME")); /** * The Java class that caused this Java class to be a part of the JAXB processing. @@ -118,7 +127,7 @@ String local = e.name(); if(local.equals("##default")) { // if defaulted... - local = NameConverter.standard.toVariableName(nav().getClassShortName(clazz)); + local = elementDefaultLocalNameVariant.convert(nav().getClassShortName(clazz)); } String nsUri = e.namespace(); if(nsUri.equals("##default")) { @@ -163,7 +172,7 @@ if(local.equals("##default")) // if defaulted ... - local = NameConverter.standard.toVariableName(nav().getClassShortName(clazz)); + local = typeDefaultLocalNameVariant.convert(nav().getClassShortName(clazz)); if(nsUri.equals("##default")) { // if defaulted ... diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/model/impl/PropertyInfoImplTest.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/model/impl/PropertyInfoImplTest.java new file mode 100644 index 0000000..4b97721 --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/model/impl/PropertyInfoImplTest.java @@ -0,0 +1,162 @@ +package com.sun.xml.bind.v2.model.impl; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.*; + +import java.beans.Introspector; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.namespace.QName; + +import org.junit.Before; +import org.junit.Test; + +import com.sun.xml.bind.api.impl.NameConverter; +import com.sun.xml.bind.v2.model.annotation.RuntimeInlineAnnotationReader; +import com.sun.xml.bind.v2.model.core.PropertyKind; +import com.sun.xml.bind.v2.model.core.TypeInfo; + +/** + * Unit Test for abstract PropertyInfoImpl class. + * + * @author Przemyslaw Bielicki + */ +@SuppressWarnings("rawtypes") +public class PropertyInfoImplTest { + + List> propertyInfoImplList; + List propertyList; + + @Before + public void before() { + ModelBuilder builder = + new RuntimeModelBuilder(null, new RuntimeInlineAnnotationReader(), new HashMap(), ""); + + ClassInfoImpl parent = new ClassInfoImpl(builder, null, TestClass.class); + List getter = new ArrayList(); + List setter = new ArrayList(); + propertyList = new ArrayList(); + for (Method m : TestClass.class.getDeclaredMethods()) { + if (m.getName().startsWith("get")) { + getter.add(m); + propertyList.add(m.getName().substring(3)); + } else if (m.getName().startsWith("set")) { + setter.add(m); + } + } + assertEquals("Different number of setters and getters!", getter.size(), setter.size()); + + PropertyInfoImpl.propertyDefaultLocalNameVariant = LocalNameVariant.CLASS_NAME; + propertyInfoImplList = new ArrayList>(); + for (int i = 0; i < getter.size(); i++) { + propertyInfoImplList.add(new TestPropertyInfoImpl(parent, + new GetterSetterPropertySeed(parent, getter.get(i), setter.get(i)))); + } + } + + @Test + public void testCalcXmlNameXmlElement() { + for (int i = 0; i < propertyList.size(); i++) { + XmlElement xmlElement = mock(XmlElement.class); + when(xmlElement.namespace()).thenReturn("namespace"); + when(xmlElement.name()).thenReturn("property", "", "##default"); + QName result = propertyInfoImplList.get(i).calcXmlName(xmlElement); + assertEquals("property", result.getLocalPart()); + result = propertyInfoImplList.get(i).calcXmlName(xmlElement); + assertEquals(propertyList.get(i), result.getLocalPart()); + result = propertyInfoImplList.get(i).calcXmlName(xmlElement); + assertEquals(propertyList.get(i), result.getLocalPart()); + } + } + + @Test + public void testCalcXmlName() { + for (int i = 0; i < propertyList.size(); i++) { + QName result = propertyInfoImplList.get(i).calcXmlName((XmlElement) null); + assertEquals(propertyList.get(i), result.getLocalPart()); + } + + PropertyInfoImpl.propertyDefaultLocalNameVariant = LocalNameVariant.CONSTANT_NAME; + for (int i = 0; i < propertyList.size(); i++) { + QName result = propertyInfoImplList.get(i).calcXmlName((XmlElement) null); + assertEquals(NameConverter.standard.toConstantName(propertyList.get(i)), result.getLocalPart()); + } + + PropertyInfoImpl.propertyDefaultLocalNameVariant = LocalNameVariant.LOWER_CASE; + for (int i = 0; i < propertyList.size(); i++) { + QName result = propertyInfoImplList.get(i).calcXmlName((XmlElement) null); + assertEquals(propertyList.get(i).toLowerCase(), result.getLocalPart()); + } + + PropertyInfoImpl.propertyDefaultLocalNameVariant = LocalNameVariant.MIXED_CLASS_NAME; + for (int i = 0; i < propertyList.size(); i++) { + QName result = propertyInfoImplList.get(i).calcXmlName((XmlElement) null); + assertEquals(NameConverter.standard.toVariableName(propertyList.get(i)), result.getLocalPart()); + } + + PropertyInfoImpl.propertyDefaultLocalNameVariant = LocalNameVariant.UNCHANGED; + for (int i = 0; i < propertyList.size(); i++) { + QName result = propertyInfoImplList.get(i).calcXmlName((XmlElement) null); + assertEquals(Introspector.decapitalize(propertyList.get(i)), result.getLocalPart()); + } + + PropertyInfoImpl.propertyDefaultLocalNameVariant = LocalNameVariant.UPPER_CASE; + for (int i = 0; i < propertyList.size(); i++) { + QName result = propertyInfoImplList.get(i).calcXmlName((XmlElement) null); + assertEquals(propertyList.get(i).toUpperCase(), result.getLocalPart()); + } + } + + /** + * Auxiliary test classes. + */ + static class TestPropertyInfoImpl extends PropertyInfoImpl { + public TestPropertyInfoImpl(ClassInfoImpl parent, PropertySeed spi) { + super(parent, spi); + } + + @Override + public Collection> ref() { + return null; + } + + @Override + public PropertyKind kind() { + return null; + } + } + + @XmlRootElement + static class TestClass { + String someValue; + OtherClass otherClass; + + public void setOtherClass(OtherClass other) { + this.otherClass = other; + } + + public OtherClass getOtherClass() { + return otherClass; + } + + public void setSomeValue(String value) { + this.someValue = value; + } + + public String getSomeValue() { + return someValue; + } + } + + static class OtherClass { + } +} diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/model/impl/TypeInfoImplTest.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/model/impl/TypeInfoImplTest.java new file mode 100644 index 0000000..1a91d75 --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/model/impl/TypeInfoImplTest.java @@ -0,0 +1,122 @@ +package com.sun.xml.bind.v2.model.impl; + +import static org.junit.Assert.assertEquals; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.HashMap; + +import javax.xml.bind.annotation.XmlRootElement; +import javax.xml.bind.annotation.XmlType; +import javax.xml.namespace.QName; + +import org.junit.Before; +import org.junit.Test; + +import com.sun.xml.bind.v2.model.annotation.Locatable; +import com.sun.xml.bind.v2.model.annotation.RuntimeInlineAnnotationReader; +import com.sun.xml.bind.v2.runtime.Location; + +/** + * Unit Test for abstract TypeInfoImpl class. + * + * @author Przemyslaw Bielicki + */ +@SuppressWarnings("rawtypes") +public class TypeInfoImplTest { + + TypeInfoImpl typeInfoImpl; + + @Before + public void before() { + ModelBuilder builder = + new RuntimeModelBuilder(null, new RuntimeInlineAnnotationReader(), new HashMap(), ""); + + TypeInfoImpl.elementDefaultLocalNameVariant = LocalNameVariant.CLASS_NAME; + TypeInfoImpl.typeDefaultLocalNameVariant = LocalNameVariant.CONSTANT_NAME; + typeInfoImpl = new TestTypeInfoImpl(builder, null); + } + + @Test + public void testParseElementName() { + QName result = typeInfoImpl.parseElementName(TestClass.class); + assertEquals("TestClass", result.getLocalPart()); + + TypeInfoImpl.elementDefaultLocalNameVariant = LocalNameVariant.CONSTANT_NAME; + result = typeInfoImpl.parseElementName(TestClass.class); + assertEquals("TEST_CLASS", result.getLocalPart()); + + TypeInfoImpl.elementDefaultLocalNameVariant = LocalNameVariant.LOWER_CASE; + result = typeInfoImpl.parseElementName(TestClass.class); + assertEquals("testclass", result.getLocalPart()); + + TypeInfoImpl.elementDefaultLocalNameVariant = LocalNameVariant.MIXED_CLASS_NAME; + result = typeInfoImpl.parseElementName(TestClass.class); + assertEquals("testClass", result.getLocalPart()); + + TypeInfoImpl.elementDefaultLocalNameVariant = LocalNameVariant.UPPER_CASE; + result = typeInfoImpl.parseElementName(TestClass.class); + assertEquals("TESTCLASS", result.getLocalPart()); + + result = typeInfoImpl.parseElementName(TestNamedClass.class); + assertEquals("XTestNamedClassX", result.getLocalPart()); + } + + @Test + public void testParseTypeName() { + QName result = typeInfoImpl.parseTypeName(TestClass.class); + assertEquals("TEST_CLASS", result.getLocalPart()); + + TypeInfoImpl.typeDefaultLocalNameVariant = LocalNameVariant.CLASS_NAME; + result = typeInfoImpl.parseTypeName(TestClass.class); + assertEquals("TestClass", result.getLocalPart()); + + TypeInfoImpl.typeDefaultLocalNameVariant = LocalNameVariant.LOWER_CASE; + result = typeInfoImpl.parseTypeName(TestClass.class); + assertEquals("testclass", result.getLocalPart()); + + TypeInfoImpl.typeDefaultLocalNameVariant = LocalNameVariant.MIXED_CLASS_NAME; + result = typeInfoImpl.parseTypeName(TestClass.class); + assertEquals("testClass", result.getLocalPart()); + + TypeInfoImpl.typeDefaultLocalNameVariant = LocalNameVariant.UPPER_CASE; + result = typeInfoImpl.parseTypeName(TestClass.class); + assertEquals("TESTCLASS", result.getLocalPart()); + + result = typeInfoImpl.parseTypeName(TestNamedClass.class); + assertEquals("YTestNamedClassY", result.getLocalPart()); + } + + /** + * Auxiliary test classes. + */ + static class TestTypeInfoImpl extends TypeInfoImpl { + public TestTypeInfoImpl(ModelBuilder builder, Locatable upstream) { + super(builder, upstream); + } + + @Override + public Type getType() { + return null; + } + @Override + public boolean canBeReferencedByIDREF() { + return false; + } + @Override + public Location getLocation() { + return null; + } + } + + @XmlType + @XmlRootElement + static class TestClass { + } + + @XmlType(name = "YTestNamedClassY") + @XmlRootElement(name = "XTestNamedClassX") + static class TestNamedClass { + } +}