Issue 84: JavaBeanLoader does not use regular expressions for implicit types
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index bf5cc46..0b41f05 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -7,6 +7,10 @@
</properties>
<body>
<release version="1.8-SNAPSHOT" date="in Mercurial" description="Performance improvement">
+ <action dev="py4fun" type="update" issue="84">
+ JavaBeanLoader does not use regular expressions for implicit types. It is possible
+ to keep the implicit types when it is required. (2010-09-06)
+ </action>
<action dev="py4fun" type="update" issue="79">
Introduce LoaderOptions to be able to specify configuration while loading (2010-09-03)
</action>
diff --git a/src/main/java/org/yaml/snakeyaml/JavaBeanLoader.java b/src/main/java/org/yaml/snakeyaml/JavaBeanLoader.java
index 46b327f..e5f0a83 100644
--- a/src/main/java/org/yaml/snakeyaml/JavaBeanLoader.java
+++ b/src/main/java/org/yaml/snakeyaml/JavaBeanLoader.java
@@ -23,6 +23,8 @@
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.introspector.BeanAccess;
import org.yaml.snakeyaml.reader.UnicodeReader;
+import org.yaml.snakeyaml.representer.Representer;
+import org.yaml.snakeyaml.resolver.Resolver;
/**
* Convenience utility to parse JavaBeans. When the YAML document contains a
@@ -38,14 +40,25 @@
this(typeDescription, BeanAccess.DEFAULT);
}
+ // TODO should BeanAccess be inside LoaderOptions ???
public JavaBeanLoader(TypeDescription typeDescription, BeanAccess beanAccess) {
- if (typeDescription == null) {
+ this(new LoaderOptions(typeDescription), beanAccess);
+ }
+
+ public JavaBeanLoader(LoaderOptions options, BeanAccess beanAccess) {
+ if (options.getRootTypeDescription() == null) {
throw new NullPointerException("TypeDescription must be provided.");
}
- Constructor constructor = new Constructor(typeDescription.getType());
- typeDescription.setRoot(true);
- constructor.addTypeDescription(typeDescription);
- loader = new Yaml(constructor);
+ Constructor constructor = new Constructor(options.getRootTypeDescription().getType());
+ options.getRootTypeDescription().setRoot(true);
+ Resolver resolver;
+ if (options.useImplicitTypes()) {
+ resolver = new Resolver(Resolver.Mode.STANDARD);
+ } else {
+ resolver = new Resolver(Resolver.Mode.JAVABEAN);
+ }
+ constructor.addTypeDescription(options.getRootTypeDescription());
+ loader = new Yaml(constructor, options, new Representer(), new DumperOptions(), resolver);
loader.setBeanAccess(beanAccess);
}
diff --git a/src/main/java/org/yaml/snakeyaml/LoaderOptions.java b/src/main/java/org/yaml/snakeyaml/LoaderOptions.java
index edf2ce7..9f7e24f 100644
--- a/src/main/java/org/yaml/snakeyaml/LoaderOptions.java
+++ b/src/main/java/org/yaml/snakeyaml/LoaderOptions.java
@@ -22,7 +22,16 @@
* 40% slower and it consumes much more memory (default=false)
*/
private boolean withMarkContext = false;
- private ImplicitMode implicitMode = ImplicitMode.ALWAYS_IMPLICIT_TYPES;
+ private ImplicitMode implicitMode = ImplicitMode.DYNAMIC_IMPLICIT_TYPES;
+ private TypeDescription rootTypeDescription;
+
+ public LoaderOptions() {
+ this(new TypeDescription(Object.class));
+ }
+
+ public LoaderOptions(TypeDescription rootTypeDescription) {
+ this.rootTypeDescription = rootTypeDescription;
+ }
public enum ImplicitMode {
/**
@@ -55,4 +64,21 @@
public void setImplicitMode(ImplicitMode implicitMode) {
this.implicitMode = implicitMode;
}
+
+ public TypeDescription getRootTypeDescription() {
+ return rootTypeDescription;
+ }
+
+ public void setRootTypeDescription(TypeDescription rootTypeDescription) {
+ this.rootTypeDescription = rootTypeDescription;
+ }
+
+ public boolean useImplicitTypes() {
+ if (implicitMode == ImplicitMode.DYNAMIC_IMPLICIT_TYPES) {
+ Class<?> t = rootTypeDescription.getType();
+ return Object.class.equals(t);
+ } else {
+ return implicitMode == ImplicitMode.ALWAYS_IMPLICIT_TYPES;
+ }
+ }
}
diff --git a/src/main/java/org/yaml/snakeyaml/resolver/Resolver.java b/src/main/java/org/yaml/snakeyaml/resolver/Resolver.java
index ecc2fa9..98aaba0 100644
--- a/src/main/java/org/yaml/snakeyaml/resolver/Resolver.java
+++ b/src/main/java/org/yaml/snakeyaml/resolver/Resolver.java
@@ -48,6 +48,10 @@
protected Map<Character, List<ResolverTuple>> yamlImplicitResolvers = new HashMap<Character, List<ResolverTuple>>();
+ public enum Mode {
+ STANDARD, JAVABEAN;
+ }
+
/**
* Create Resolver
*
@@ -78,7 +82,16 @@
}
public Resolver() {
- this(true);
+ this(Mode.STANDARD);
+ }
+
+ public Resolver(Mode mode) {
+ if (mode == Mode.STANDARD) {
+ addImplicitResolvers();
+ } else {
+ addImplicitResolver(Tag.NULL, NULL, "~nN\0");
+ addImplicitResolver(Tag.NULL, EMPTY, null);
+ }
}
public void addImplicitResolver(Tag tag, Pattern regexp, String first) {
diff --git a/src/test/java/examples/collections/TypeSafeMapTest.java b/src/test/java/examples/collections/TypeSafeMapTest.java
index 83d9d59..440a798 100644
--- a/src/test/java/examples/collections/TypeSafeMapTest.java
+++ b/src/test/java/examples/collections/TypeSafeMapTest.java
@@ -23,7 +23,11 @@
import org.yaml.snakeyaml.JavaBeanDumper;
import org.yaml.snakeyaml.JavaBeanLoader;
+import org.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Util;
+import org.yaml.snakeyaml.LoaderOptions.ImplicitMode;
+import org.yaml.snakeyaml.introspector.BeanAccess;
/**
* Test MapBean->Map<String, Developer> developers <br/>
@@ -166,8 +170,10 @@
public void testLoadMapWithObject() {
String output = Util.getLocalResource("examples/map-bean-10.yaml");
// System.out.println(output);
+ LoaderOptions options = new LoaderOptions(new TypeDescription(MapBeanNoGenerics.class));
+ options.setImplicitMode(ImplicitMode.ALWAYS_IMPLICIT_TYPES);
JavaBeanLoader<MapBeanNoGenerics> beanLoader = new JavaBeanLoader<MapBeanNoGenerics>(
- MapBeanNoGenerics.class);
+ options, BeanAccess.DEFAULT);
MapBeanNoGenerics parsed = beanLoader.load(output);
assertNotNull(parsed);
Map<String, Integer> data = parsed.getData();
diff --git a/src/test/java/org/yaml/snakeyaml/JavaBeanLoaderTest.java b/src/test/java/org/yaml/snakeyaml/JavaBeanLoaderTest.java
index 0b13cd4..654c2d5 100644
--- a/src/test/java/org/yaml/snakeyaml/JavaBeanLoaderTest.java
+++ b/src/test/java/org/yaml/snakeyaml/JavaBeanLoaderTest.java
@@ -152,6 +152,23 @@
assertEquals("Name123", parsed.getName());
}
+ public void testTypeDescription1111() {
+ Bean3 bean3 = new Bean3();
+ bean3.setName("Name123");
+ Bean bean = new Bean();
+ bean.setId(3);
+ bean.setName("Test me.");
+ bean3.setBean(bean);
+ JavaBeanDumper dumper = new JavaBeanDumper();
+ String output = dumper.dump(bean3);
+ assertEquals("bean:\n id: 3\n name: Test me.\nlist: null\nname: Name123\n", output);
+ TypeDescription td = new TypeDescription(Bean3.class);
+ td.putListPropertyType("list", Integer.class);
+ JavaBeanLoader<Bean3> loader = new JavaBeanLoader<Bean3>(td);
+ Bean3 parsed = loader.load("bean:\n id: 3\n name: Test me.\n\nname: Name123\n");
+ assertEquals("Name123", parsed.getName());
+ }
+
public void testTypeDescription2() {
Bean3 bean3 = new Bean3();
bean3.setName("Name123");
diff --git a/src/test/java/org/yaml/snakeyaml/LoaderOptionsTest.java b/src/test/java/org/yaml/snakeyaml/LoaderOptionsTest.java
index f722395..4d902a3 100644
--- a/src/test/java/org/yaml/snakeyaml/LoaderOptionsTest.java
+++ b/src/test/java/org/yaml/snakeyaml/LoaderOptionsTest.java
@@ -18,12 +18,38 @@
import junit.framework.TestCase;
+import org.yaml.snakeyaml.LoaderOptions.ImplicitMode;
+
public class LoaderOptionsTest extends TestCase {
public void testGetMode() {
LoaderOptions defaultOptions = new LoaderOptions();
assertFalse(defaultOptions.isWithMarkContext());
- assertEquals(LoaderOptions.ImplicitMode.ALWAYS_IMPLICIT_TYPES, defaultOptions
+ assertEquals(LoaderOptions.ImplicitMode.DYNAMIC_IMPLICIT_TYPES, defaultOptions
.getImplicitMode());
}
+
+ public void testUseImplicitTypes1() {
+ LoaderOptions options = new LoaderOptions();
+ assertTrue(options.useImplicitTypes());
+
+ }
+
+ public void testUseImplicitTypes2() {
+ LoaderOptions options = new LoaderOptions(new TypeDescription(Object.class));
+ assertTrue(options.useImplicitTypes());
+ }
+
+ public void testUseImplicitTypes3() {
+ LoaderOptions options = new LoaderOptions(new TypeDescription(LoaderOptionsTest.class));
+ assertFalse(options.useImplicitTypes());
+ }
+
+ public void testMoImplicitTypes() {
+ LoaderOptions options = new LoaderOptions();
+ options.setImplicitMode(ImplicitMode.NEVER_IMPLICIT_TYPES);
+ Yaml yaml = new Yaml(options);
+ // String number = (String) yaml.load("11");
+ // TODO assertEquals("Integer must not be recognised.", "11", number);
+ }
}
diff --git a/src/test/java/org/yaml/snakeyaml/constructor/BeanConstructorTest.java b/src/test/java/org/yaml/snakeyaml/constructor/BeanConstructorTest.java
index ce18cf3..d42539d 100644
--- a/src/test/java/org/yaml/snakeyaml/constructor/BeanConstructorTest.java
+++ b/src/test/java/org/yaml/snakeyaml/constructor/BeanConstructorTest.java
@@ -209,7 +209,20 @@
yaml.load(document);
fail("ExceptionParent should not be created.");
} catch (Exception e) {
- assertTrue(e.getMessage().contains(
+ assertTrue(e.getMessage(), e.getMessage().contains(
+ "Can't construct a java object for scalar tag:yaml.org,2002:int"));
+ }
+ }
+
+ public void testScalarContructorExceptionNoRegExpMode() throws IOException {
+ //TODO ???
+ Yaml yaml = new Yaml(new Constructor(ExceptionParent.class));
+ String document = "id: 123\nchild: 25";
+ try {
+ yaml.load(document);
+ fail("ExceptionParent should not be created.");
+ } catch (Exception e) {
+ assertTrue(e.getMessage(), e.getMessage().contains(
"Can't construct a java object for scalar tag:yaml.org,2002:int"));
}
}
diff --git a/src/test/java/org/yaml/snakeyaml/constructor/TypeSafeCollectionsTest.java b/src/test/java/org/yaml/snakeyaml/constructor/TypeSafeCollectionsTest.java
index 071db15..9dc3fe6 100644
--- a/src/test/java/org/yaml/snakeyaml/constructor/TypeSafeCollectionsTest.java
+++ b/src/test/java/org/yaml/snakeyaml/constructor/TypeSafeCollectionsTest.java
@@ -69,6 +69,26 @@
}
}
+ public void testTypeSafeMapNoRegularExpressionsMode() throws IOException {
+ Constructor constructor = new Constructor(MyCar.class);
+ TypeDescription carDescription = new TypeDescription(MyCar.class);
+ carDescription.putMapPropertyType("wheels", MyWheel.class, Object.class);
+ constructor.addTypeDescription(carDescription);
+ Yaml yaml = new Yaml(constructor);
+ MyCar car = (MyCar) yaml.load(Util
+ .getLocalResource("constructor/car-no-root-class-map.yaml"));
+ assertEquals("00-FF-Q2", car.getPlate());
+ Map<MyWheel, Date> wheels = car.getWheels();
+ assertNotNull(wheels);
+ assertEquals(5, wheels.size());
+ for (MyWheel wheel : wheels.keySet()) {
+ assertTrue(wheel.getId() > 0);
+ Date date = wheels.get(wheel);
+ long time = date.getTime();
+ assertTrue("It must be midnight.", time % 10000 == 0);
+ }
+ }
+
public void testWithGlobalTag() throws IOException {
Map<MyWheel, Date> wheels = new TreeMap<MyWheel, Date>();
long time = 1248212168084L;
diff --git a/src/test/java/org/yaml/snakeyaml/generics/ObjectValuesTest.java b/src/test/java/org/yaml/snakeyaml/generics/ObjectValuesTest.java
index 9360322..c2f805c 100644
--- a/src/test/java/org/yaml/snakeyaml/generics/ObjectValuesTest.java
+++ b/src/test/java/org/yaml/snakeyaml/generics/ObjectValuesTest.java
@@ -25,6 +25,10 @@
import org.yaml.snakeyaml.JavaBeanDumper;
import org.yaml.snakeyaml.JavaBeanLoader;
+import org.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.TypeDescription;
+import org.yaml.snakeyaml.LoaderOptions.ImplicitMode;
+import org.yaml.snakeyaml.introspector.BeanAccess;
public class ObjectValuesTest extends TestCase {
@@ -48,8 +52,10 @@
JavaBeanDumper dumper = new JavaBeanDumper();
String dumpedStr = dumper.dump(ov);
-
- JavaBeanLoader<ObjectValues> loader = new JavaBeanLoader<ObjectValues>(ObjectValues.class);
+ LoaderOptions options = new LoaderOptions(new TypeDescription(ObjectValues.class));
+ options.setImplicitMode(ImplicitMode.ALWAYS_IMPLICIT_TYPES);
+ JavaBeanLoader<ObjectValues> loader = new JavaBeanLoader<ObjectValues>(options,
+ BeanAccess.DEFAULT);
ObjectValues ov2 = loader.load(dumpedStr);
assertEquals(ov.getObject(), ov2.getObject());
@@ -58,7 +64,6 @@
ov.getPossible()[0] = ov2.getPossible()[0];
}
- @SuppressWarnings("unchecked")
public void testObjectValuesWithParam() {
ObjectValuesWithParam<String, Integer> ov = new ObjectValuesWithParam<String, Integer>();
Integer obj = new Integer(131313);
@@ -80,8 +85,11 @@
JavaBeanDumper dumper = new JavaBeanDumper();
String dumpedStr = dumper.dump(ov);
+ LoaderOptions options = new LoaderOptions(new TypeDescription(
+ new ObjectValuesWithParam<String, Integer>().getClass()));
+ options.setImplicitMode(ImplicitMode.ALWAYS_IMPLICIT_TYPES);
JavaBeanLoader<ObjectValuesWithParam<String, Integer>> loader = new JavaBeanLoader<ObjectValuesWithParam<String, Integer>>(
- new ObjectValuesWithParam<String, Integer>().getClass());
+ options, BeanAccess.DEFAULT);
ObjectValuesWithParam<String, Integer> ov2 = loader.load(dumpedStr);
assertEquals(ov.getObject(), ov2.getObject());
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue61/GenericMapBeanTest.java b/src/test/java/org/yaml/snakeyaml/issues/issue61/GenericMapBeanTest.java
index dc7343b..3a68b84 100644
--- a/src/test/java/org/yaml/snakeyaml/issues/issue61/GenericMapBeanTest.java
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue61/GenericMapBeanTest.java
@@ -23,7 +23,11 @@
import org.yaml.snakeyaml.JavaBeanDumper;
import org.yaml.snakeyaml.JavaBeanLoader;
+import org.yaml.snakeyaml.LoaderOptions;
+import org.yaml.snakeyaml.TypeDescription;
import org.yaml.snakeyaml.Util;
+import org.yaml.snakeyaml.LoaderOptions.ImplicitMode;
+import org.yaml.snakeyaml.introspector.BeanAccess;
public class GenericMapBeanTest extends TestCase {
@SuppressWarnings("unchecked")
@@ -36,7 +40,11 @@
// System.out.println(s);
assertEquals("map:\n foo: 17\n bar: 19\n", s);
// parse
- JavaBeanLoader<MapProvider> loader = new JavaBeanLoader<MapProvider>(MapProvider.class);
+ LoaderOptions options = new LoaderOptions();
+ options.setRootTypeDescription(new TypeDescription(MapProvider.class));
+ options.setImplicitMode(ImplicitMode.ALWAYS_IMPLICIT_TYPES);
+ JavaBeanLoader<MapProvider> loader = new JavaBeanLoader<MapProvider>(options,
+ BeanAccess.DEFAULT);
MapProvider<String, Integer> listProvider2 = loader.load(s);
assertEquals(new Integer(17), listProvider2.getMap().get("foo"));
assertEquals(new Integer(19), listProvider2.getMap().get("bar"));
@@ -44,6 +52,27 @@
}
@SuppressWarnings("unchecked")
+ public void testGenericMapNoImplicitTypes() throws Exception {
+ JavaBeanDumper beanDumper = new JavaBeanDumper();
+ MapProvider<String, Integer> listProvider = new MapProvider<String, Integer>();
+ listProvider.getMap().put("foo", 17);
+ listProvider.getMap().put("bar", 19);
+ String s = beanDumper.dump(listProvider);
+ // System.out.println(s);
+ assertEquals("map:\n foo: 17\n bar: 19\n", s);
+ // parse
+ LoaderOptions options = new LoaderOptions();
+ options.setRootTypeDescription(new TypeDescription(MapProvider.class));
+ options.setImplicitMode(ImplicitMode.NEVER_IMPLICIT_TYPES);
+ JavaBeanLoader<MapProvider> loader = new JavaBeanLoader<MapProvider>(options,
+ BeanAccess.DEFAULT);
+ MapProvider<String, Integer> listProvider2 = loader.load(s);
+ assertEquals("17", listProvider2.getMap().get("foo"));
+ assertEquals("19", listProvider2.getMap().get("bar"));
+ assertFalse(listProvider.equals(listProvider2));
+ }
+
+ @SuppressWarnings("unchecked")
public void testGenericBean() throws Exception {
JavaBeanDumper beanDumper = new JavaBeanDumper();
MapProvider<String, Bean> listProvider = new MapProvider<String, Bean>();
diff --git a/src/test/java/org/yaml/snakeyaml/issues/issue82/PropOrderInfluenceWhenAliasedInGenericCollectionTest.java b/src/test/java/org/yaml/snakeyaml/issues/issue82/PropOrderInfluenceWhenAliasedInGenericCollectionTest.java
index e1a913f..65b8635 100644
--- a/src/test/java/org/yaml/snakeyaml/issues/issue82/PropOrderInfluenceWhenAliasedInGenericCollectionTest.java
+++ b/src/test/java/org/yaml/snakeyaml/issues/issue82/PropOrderInfluenceWhenAliasedInGenericCollectionTest.java
@@ -81,7 +81,7 @@
CustomerAB parsed = (CustomerAB) yaml.load(dump);
} catch (Exception e) {
// TODO fix issue 82
- e.printStackTrace();
+ // e.printStackTrace();
}
}
@@ -108,7 +108,7 @@
CustomerAB parsed = loader.load(dump2);
} catch (Exception e) {
// TODO fix issue 82
- e.printStackTrace();
+ // e.printStackTrace();
}
}