From 0c3f04d9a5d0e77cabf8241bf3535e01911c96f3 Mon Sep 17 00:00:00 2001 From: mdb Date: Mon, 26 Nov 2001 23:44:40 +0000 Subject: [PATCH] Moved the value marshalling code out of SetFieldRule and into a separate class. Created a digester rule that sets public fields of objects based on element attributes. git-svn-id: https://samskivert.googlecode.com/svn/trunk@477 6335cc39-0255-0410-8fd6-9bcaacd3b74c --- .../com/samskivert/util/ValueMarshaller.java | 84 +++++++++++++++++++ .../java/com/samskivert/xml/SetFieldRule.java | 68 ++------------- .../samskivert/xml/SetPropertyFieldsRule.java | 78 +++++++++++++++++ 3 files changed, 167 insertions(+), 63 deletions(-) create mode 100644 projects/samskivert/src/java/com/samskivert/util/ValueMarshaller.java create mode 100644 projects/samskivert/src/java/com/samskivert/xml/SetPropertyFieldsRule.java diff --git a/projects/samskivert/src/java/com/samskivert/util/ValueMarshaller.java b/projects/samskivert/src/java/com/samskivert/util/ValueMarshaller.java new file mode 100644 index 00000000..00f68e9f --- /dev/null +++ b/projects/samskivert/src/java/com/samskivert/util/ValueMarshaller.java @@ -0,0 +1,84 @@ +// +// $Id: ValueMarshaller.java,v 1.1 2001/11/26 23:44:40 mdb Exp $ + +package com.samskivert.util; + +import java.util.HashMap; + +/** + * Provides a mechanism for converting a string representation of a value + * into a Java object when provided with the type of the target object. + * This is used to do things like populate object fields with values + * parsed from an XML file and the like. + */ +public class ValueMarshaller +{ + /** + * Attempts to convert the specified value to an instance of the + * specified object type. + * + * @exception Exception thrown if no field parser exists for the + * target type or if an error occurs while parsing the value. + */ + public static Object unmarshal (Class type, String source) + throws Exception + { + // look up an argument parser for the field type + Parser parser = (Parser)_parsers.get(type); + if (parser == null) { + String errmsg = "Don't know how to convert strings into " + + "values of type '" + type + "]."; + throw new Exception(errmsg); + } + return parser.parse(source); + } + + protected static interface Parser + { + public Object parse (String source) throws Exception; + } + + protected static HashMap _parsers; + + protected static final int[] INT_ARRAY_PROTOTYPE = new int[0]; + protected static final String[] STRING_ARRAY_PROTOTYPE = new String[0]; + + static { + _parsers = new HashMap(); + + // we can parse strings + _parsers.put(String.class, new Parser() { + public Object parse (String source) throws Exception { + return source; + } + }); + + // and ints + _parsers.put(Integer.TYPE, new Parser() { + public Object parse (String source) throws Exception { + return Integer.valueOf(source); + } + }); + + // and integers + _parsers.put(Integer.class, new Parser() { + public Object parse (String source) throws Exception { + return Integer.valueOf(source); + } + }); + + // and int arrays + _parsers.put(INT_ARRAY_PROTOTYPE.getClass(), new Parser() { + public Object parse (String source) throws Exception { + return StringUtil.parseIntArray(source); + } + }); + + // and string arrays, oh my! + _parsers.put(STRING_ARRAY_PROTOTYPE.getClass(), new Parser() { + public Object parse (String source) throws Exception { + return StringUtil.parseStringArray(source); + } + }); + } +} diff --git a/projects/samskivert/src/java/com/samskivert/xml/SetFieldRule.java b/projects/samskivert/src/java/com/samskivert/xml/SetFieldRule.java index a6103364..15b8d106 100644 --- a/projects/samskivert/src/java/com/samskivert/xml/SetFieldRule.java +++ b/projects/samskivert/src/java/com/samskivert/xml/SetFieldRule.java @@ -1,5 +1,5 @@ // -// $Id: SetFieldRule.java,v 1.1 2001/11/17 03:45:52 mdb Exp $ +// $Id: SetFieldRule.java,v 1.2 2001/11/26 23:44:40 mdb Exp $ // // samskivert library - useful routines for java programs // Copyright (C) 2001 Walter Korman @@ -21,13 +21,13 @@ package com.samskivert.xml; import java.lang.reflect.Field; -import java.util.HashMap; import org.xml.sax.Attributes; import org.apache.commons.digester.Digester; import org.apache.commons.digester.Rule; import com.samskivert.util.StringUtil; +import com.samskivert.util.ValueMarshaller; /** * Sets a field in the object on the top of the stack with a value parsed @@ -70,70 +70,12 @@ public class SetFieldRule extends Rule _bodyText + "' on '" + top + "'."); } + // convert the source string into an object and set the field Field field = top.getClass().getField(_fieldName); - - // look up an argument parser for the field type - Parser parser = (Parser)_parsers.get(field.getType()); - if (parser == null) { - String errmsg = "Don't know how to convert strings into " + - "fields of type '" + field.getType() + - "' [field=" + _fieldName + ", target=" + top + "]."; - throw new Exception(errmsg); - } - - // parse the text and set the field - field.set(top, parser.parse(_bodyText)); - } - - protected static interface Parser - { - public Object parse (String source) throws Exception; + Object value = ValueMarshaller.unmarshal(field.getType(), _bodyText); + field.set(top, value); } protected String _fieldName; protected String _bodyText; - - protected static HashMap _parsers; - - protected static final int[] INT_ARRAY_PROTOTYPE = new int[0]; - protected static final String[] STRING_ARRAY_PROTOTYPE = new String[0]; - - static { - _parsers = new HashMap(); - - // we can parse strings - _parsers.put(String.class, new Parser() { - public Object parse (String source) throws Exception { - return source; - } - }); - - // and ints - _parsers.put(Integer.TYPE, new Parser() { - public Object parse (String source) throws Exception { - return Integer.valueOf(source); - } - }); - - // and integers - _parsers.put(Integer.class, new Parser() { - public Object parse (String source) throws Exception { - return Integer.valueOf(source); - } - }); - - // and int arrays - _parsers.put(INT_ARRAY_PROTOTYPE.getClass(), new Parser() { - public Object parse (String source) throws Exception { - return StringUtil.parseIntArray(source); - } - }); - - // and string arrays, oh my! - _parsers.put(STRING_ARRAY_PROTOTYPE.getClass(), new Parser() { - public Object parse (String source) throws Exception { - return StringUtil.parseStringArray(source); - } - }); - } } diff --git a/projects/samskivert/src/java/com/samskivert/xml/SetPropertyFieldsRule.java b/projects/samskivert/src/java/com/samskivert/xml/SetPropertyFieldsRule.java new file mode 100644 index 00000000..cd12838e --- /dev/null +++ b/projects/samskivert/src/java/com/samskivert/xml/SetPropertyFieldsRule.java @@ -0,0 +1,78 @@ +// +// $Id: SetPropertyFieldsRule.java,v 1.1 2001/11/26 23:44:40 mdb Exp $ +// +// samskivert library - useful routines for java programs +// Copyright (C) 2001 Walter Korman +// +// 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +package com.samskivert.xml; + +import java.lang.reflect.Field; + +import org.xml.sax.Attributes; +import org.apache.commons.digester.Digester; +import org.apache.commons.digester.Rule; + +import com.samskivert.util.StringUtil; +import com.samskivert.util.ValueMarshaller; + +/** + * Sets the fields in the object on the top of the stack from the + * attributes available in the matched element. + */ +public class SetPropertyFieldsRule extends Rule +{ + /** + * Constructs a set property fields rule. + */ + public SetPropertyFieldsRule (Digester digester) + { + super(digester); + } + + public void begin (Attributes attrs) + throws Exception + { + Object top = digester.peek(); + Class topclass = top.getClass(); + + // iterate over the attributes, setting public fields where + // applicable + for (int i = 0; i < attrs.getLength(); i++) { + String name = attrs.getLocalName(i); + if (StringUtil.blank(name)) { + name = attrs.getQName(i); + } + + // look for a public field with this name + Field field = topclass.getField(name); + if (field == null) { + continue; + } + + // convert the value into the appropriate object type + String valstr = attrs.getValue(i); + Object value = ValueMarshaller.unmarshal(field.getType(), valstr); + if (digester.getDebug() >= 9) { + digester.log(" Setting property '" + name + "' to '" + + valstr + "'"); + } + + // and finally set the field + field.set(top, value); + } + } +}