hlship 2003/08/04 07:21:57 Modified: hivemind/src/test/hivemind/test/config TestExtensionPoint.java hivemind/src/java/org/apache/commons/hivemind/schema SchemaProcessor.java Translator.java hivemind/src/java/org/apache/commons/hivemind/parse DescriptorParser.java AbstractServiceDescriptor.java hivemind/src/test/hivemind/test HiveMindSuite.java hivemind/src/java/org/apache/commons/hivemind/schema/rules ReadContentRule.java BooleanTranslator.java SetParentRule.java BaseRule.java IntTranslator.java ReadAttributeRule.java hivemind/src/java/org/apache/commons/hivemind HiveMindMessages.properties HiveMind.java hivemind/xdocs rules.xml hivemind/src/java/org/apache/commons/hivemind/impl RegistryBuilder.java Added: hivemind/src/test/hivemind/test/config IntTranslator.xml hivemind/src/java/org/apache/commons/hivemind/schema/rules RuleUtils.java hivemind/src/test/hivemind/test/rules TestConvertInitializer.java hivemind/src/test/hivemind/test/config/impl IntHolder.java Log: Add support for initializers for Translators. Initializers are strings used to configure a Translator. Revision Changes Path 1.4 +41 -0 jakarta-commons-sandbox/hivemind/src/test/hivemind/test/config/TestExtensionPoint.java Index: TestExtensionPoint.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/test/hivemind/test/config/TestExtensionPoint.java,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- TestExtensionPoint.java 1 Aug 2003 14:41:29 -0000 1.3 +++ TestExtensionPoint.java 4 Aug 2003 14:21:56 -0000 1.4 @@ -63,6 +63,7 @@ import hivemind.test.config.impl.Datum; import hivemind.test.config.impl.DatumHolder; import hivemind.test.config.impl.FrobableHolder; +import hivemind.test.config.impl.IntHolder; import hivemind.test.config.impl.Parent; import java.util.List; @@ -213,6 +214,46 @@ h = (BooleanHolder) l.get(2); assertEquals(false, h.getValue()); + } + + public void testIntTranslator() throws Exception + { + interceptLogging(); + + Registry r = buildRegistry("IntTranslator.xml"); + + List l = r.getExtensionPointElements("hivemind.test.config.IntTranslator"); + + List events = getInterceptedLogEvents(); + + checkLoggingEvent(null, "Value 2 \\(at .*\\) is less than minimum value 5\\.", events); + checkLoggingEvent(null, "Value 12 \\(at .*\\) is greater than maximum value 10\\.", events); + checkLoggingEvent( + null, + "'fred' \\(in element int at .*\\) is not an integer value\\.", + events); + + assertEquals(4, l.size()); + + IntHolder h = (IntHolder) l.get(0); + + assertEquals(7, h.getValue()); + + h = (IntHolder) l.get(1); + assertEquals(5, h.getValue()); + + h = (IntHolder) l.get(2); + + assertEquals(10, h.getValue()); + + h = (IntHolder)l.get(3); + + assertEquals(6, h.getValue()); + + h = (IntHolder)l.get(3); + + assertEquals(6, h.getValue()); + } public void testClassTranslator() throws Exception 1.1 jakarta-commons-sandbox/hivemind/src/test/hivemind/test/config/IntTranslator.xml Index: IntTranslator.xml =================================================================== <?xml version="1.0" encoding="UTF-8"?> <!-- $Id: IntTranslator.xml,v 1.1 2003/08/04 14:21:56 hlship Exp $ --> <module id="hivemind.test.config" version="1.0.0"> <extension-point id="IntTranslator"> <schema> <element name="int"> <attribute name="value" required="true"/> <rules> <create-object class="hivemind.test.config.impl.IntHolder"/> <read-attribute property="value" attribute="value" translator="int,min=5,max=10,default=6"/> <invoke-parent method="addElement"/> </rules> </element> </schema> </extension-point> <extension point-id="IntTranslator"> <int value="7"/> <int value="2"/> <int value="12"/> <int value="fred"/> <int/> </extension> </module> 1.2 +2 -2 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/SchemaProcessor.java Index: SchemaProcessor.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/SchemaProcessor.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SchemaProcessor.java 29 Jul 2003 22:20:36 -0000 1.1 +++ SchemaProcessor.java 4 Aug 2003 14:21:56 -0000 1.2 @@ -71,7 +71,7 @@ /** * The SchemaProcessor is always the bottom (deepest) object on the stack. * Top level objects (contained by a schema, not another element) - * can use an [EMAIL PROTECTED] org.apache.commons.hivemind.schema.rules.AddToParentRule} + * can use an [EMAIL PROTECTED] org.apache.commons.hivemind.schema.rules.InvokeParentRule} * to add themselves to the list of elements for the * [EMAIL PROTECTED] org.apache.commons.hivemind.ExtensionPoint} being constructed. */ 1.2 +17 -1 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/Translator.java Index: Translator.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/Translator.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- Translator.java 29 Jul 2003 22:20:36 -0000 1.1 +++ Translator.java 4 Aug 2003 14:21:56 -0000 1.2 @@ -64,6 +64,22 @@ * translate attribute values (or element content) from strings into * numbers, booleans or other constructs before assigning the final value * to a propery. Translation occurs after symbol substitution. + * + * <p> + * Translator classes should have a public constructor that takes no + * arguments. They may optionally have a second constructor + * that takes a single string as a parameter. When the + * [EMAIL PROTECTED] org.apache.commons.hivemind.parse.DescriptorParser} encounters + * a <code>translator</code> of the form + * "<code><i>translator-id</i>,<i>initializataion-string</i></code>" + * (example: "int,min=0") it will use the second constructor, passing + * the initialization string. + * + * <p> + * Generally, initializion strings are of the form + * <code><i>key</i>=<i>value</i>[,<i>key</i>=<i>value</i>]*</code>. + * Each initializer has a set of keys it recognizes, other keys are simply + * ignored. * * @author Howard Lewis Ship * @version $Id$ 1.18 +61 -11 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/parse/DescriptorParser.java Index: DescriptorParser.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/parse/DescriptorParser.java,v retrieving revision 1.17 retrieving revision 1.18 diff -u -r1.17 -r1.18 --- DescriptorParser.java 1 Aug 2003 19:05:24 -0000 1.17 +++ DescriptorParser.java 4 Aug 2003 14:21:56 -0000 1.18 @@ -57,6 +57,7 @@ package org.apache.commons.hivemind.parse; +import java.lang.reflect.Constructor; import java.net.URL; import java.util.ArrayList; import java.util.Collections; @@ -298,16 +299,17 @@ OCCURS_MAP.put("0..n", Occurances.UNBOUNDED); } + private final Map _builtinTranslators = new HashMap(); private final Map _translatorMap = new HashMap(); // Seed the translator map with shared instances of built-in // translators. { - _translatorMap.put("boolean", new BooleanTranslator()); - _translatorMap.put("class", new ClassTranslator()); - _translatorMap.put("int", new IntTranslator()); - _translatorMap.put("service", new ServiceTranslator()); + _builtinTranslators.put("boolean", BooleanTranslator.class); + _builtinTranslators.put("class", ClassTranslator.class); + _builtinTranslators.put("int", IntTranslator.class); + _builtinTranslators.put("service", ServiceTranslator.class); } /** @@ -1285,34 +1287,82 @@ return getTranslator(name); } + /** + * The name may be a class name or a builtin id. In addition, + * an initializer may follow the name or id (separated by a comma). + */ private Translator getTranslator(String name) { Translator result = (Translator) _translatorMap.get(name); - if (result == null) + if (result != null) + return result; + + String className = name; + String initializer = null; + + int commax = name.indexOf(','); + + if (commax > 0) { - result = createTranslator(name); + className = name.substring(0, commax); + initializer = name.substring(commax + 1); + } + + Class translatorClass = findTranslatorClass(className); + result = createTranslator(translatorClass, initializer); + + if (result != null) _translatorMap.put(name, result); + + return result; + + } + + /** + * Finds the class for a translator based on class name. In addition, + * certain builtin ids are recognized. + */ + private Class findTranslatorClass(String className) + { + Class result = (Class) _builtinTranslators.get(className); + + if (result == null) + { + result = _resolver.findClass(className); + _builtinTranslators.put(className, result); } return result; } - private Translator createTranslator(String name) + private Translator createTranslator(Class translatorClass, String initializer) { try { - Class translatorClass = _resolver.findClass(name); - return (Translator) translatorClass.newInstance(); + if (initializer == null) + return (Translator) translatorClass.newInstance(); + + Constructor c = translatorClass.getConstructor(new Class[] { String.class }); + + return (Translator) c.newInstance(new Object[] { initializer }); + } + catch (NoSuchMethodException ex) + { + LOG.error( + HiveMind.format( + "DescriptorParser.missing-translator", + translatorClass.getName(), + getLocation())); } catch (Exception ex) { LOG.error( HiveMind.format( "DescriptorParser.bad-translator", - name, + translatorClass.getName(), getLocation(), ex.getMessage()), ex); 1.9 +2 -2 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/parse/AbstractServiceDescriptor.java Index: AbstractServiceDescriptor.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/parse/AbstractServiceDescriptor.java,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- AbstractServiceDescriptor.java 29 Jul 2003 22:20:38 -0000 1.8 +++ AbstractServiceDescriptor.java 4 Aug 2003 14:21:56 -0000 1.9 @@ -65,7 +65,7 @@ /** * Base class for [EMAIL PROTECTED] org.apache.commons.hivemind.parse.ServiceDescriptor} and - * [EMAIL PROTECTED] org.apache.commons.hivemind.parse.ServiceExtensionDescriptor}. + * [EMAIL PROTECTED] org.apache.commons.hivemind.parse.ExtendServiceDescriptor}. * * * @author Howard Lewis Ship 1.10 +4 -1 jakarta-commons-sandbox/hivemind/src/test/hivemind/test/HiveMindSuite.java Index: HiveMindSuite.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/test/hivemind/test/HiveMindSuite.java,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- HiveMindSuite.java 29 Jul 2003 22:20:32 -0000 1.9 +++ HiveMindSuite.java 4 Aug 2003 14:21:56 -0000 1.10 @@ -62,6 +62,7 @@ import hivemind.test.config.TestExtensionPoint; import hivemind.test.parse.TestDescriptorParser; import hivemind.test.parse.TestToString; +import hivemind.test.rules.*; import hivemind.test.services.TestServices; import junit.framework.Test; import junit.framework.TestSuite; @@ -78,6 +79,8 @@ public static Test suite() { TestSuite suite = new TestSuite("Master HiveMind Test Suite"); + + suite.addTestSuite(TestConvertInitializer.class); suite.addTestSuite(TestMessagesImpl.class); 1.3 +3 -3 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/ReadContentRule.java Index: ReadContentRule.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/ReadContentRule.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- ReadContentRule.java 1 Aug 2003 14:41:30 -0000 1.2 +++ ReadContentRule.java 4 Aug 2003 14:21:56 -0000 1.3 @@ -81,12 +81,12 @@ public void begin(SchemaProcessor processor, Element element) { - String value = processText(processor, element, element.getContent()); + String value = RuleUtils.processText(processor, element, element.getContent()); Object finalValue = _translator == null ? value : _translator.translate(processor, element, value); - setProperty(processor, element, _propertyName, processor.peek(), finalValue); + RuleUtils.setProperty(processor, element, _propertyName, processor.peek(), finalValue); } public String getPropertyName() 1.2 +28 -4 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/BooleanTranslator.java Index: BooleanTranslator.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/BooleanTranslator.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- BooleanTranslator.java 29 Jul 2003 22:20:48 -0000 1.1 +++ BooleanTranslator.java 4 Aug 2003 14:21:56 -0000 1.2 @@ -57,6 +57,8 @@ package org.apache.commons.hivemind.schema.rules; +import java.util.Map; + import org.apache.commons.hivemind.Element; import org.apache.commons.hivemind.HiveMind; import org.apache.commons.hivemind.schema.SchemaProcessor; @@ -76,10 +78,32 @@ { private static final Log LOG = LogFactory.getLog(BooleanTranslator.class); + private Boolean _defaultValue = Boolean.FALSE; + + public BooleanTranslator() + { + } + + /** + * Initializes the translator, recognizing key "default" as the + * default value for the translator when the input is null or + * can't be converted. + */ + + public BooleanTranslator(String initializer) + { + Map m = RuleUtils.convertInitializer(initializer); + + String defaultInit = (String) m.get("default"); + + if (defaultInit != null) + _defaultValue = Boolean.valueOf(defaultInit); + } + public Object translate(SchemaProcessor processor, Element element, String inputValue) { if (StringUtils.isEmpty(inputValue)) - return Boolean.FALSE; + return _defaultValue; if (inputValue.equals("true")) return Boolean.TRUE; @@ -93,8 +117,8 @@ inputValue, processor.getElementPath(), element.getLocation())); - - return Boolean.FALSE; + + return _defaultValue; } } 1.2 +2 -2 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/SetParentRule.java Index: SetParentRule.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/SetParentRule.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- SetParentRule.java 29 Jul 2003 22:20:48 -0000 1.1 +++ SetParentRule.java 4 Aug 2003 14:21:56 -0000 1.2 @@ -88,7 +88,7 @@ Object child = processor.peek(); Object parent = processor.peek(1); - setProperty(processor, element, _propertyName, child, parent); + RuleUtils.setProperty(processor, element, _propertyName, child, parent); } } 1.3 +1 -74 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/BaseRule.java Index: BaseRule.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/BaseRule.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- BaseRule.java 1 Aug 2003 14:41:30 -0000 1.2 +++ BaseRule.java 4 Aug 2003 14:21:56 -0000 1.3 @@ -57,14 +57,9 @@ package org.apache.commons.hivemind.schema.rules; -import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.hivemind.Element; -import org.apache.commons.hivemind.HiveMind; -import org.apache.commons.hivemind.Registry; import org.apache.commons.hivemind.schema.Rule; import org.apache.commons.hivemind.schema.SchemaProcessor; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.tapestry.spec.BaseLocatable; /** @@ -75,74 +70,6 @@ */ public abstract class BaseRule extends BaseLocatable implements Rule { - private static final Log LOG = LogFactory.getLog(BaseRule.class); - - /** - * Invoked to process text from an attribute or from an element's content. Performs - * two jobs: - * <ul> - * <li>Convert localized message references to localized strings - * <li>Expand symbols using [EMAIL PROTECTED] Registry#expandSymbols(String, ILocation)} - * </ul> - * - * <p> - * Note: if the input is a localized message then no symbol expansion takes place. - * Localized message references are simply strings that begin with '%'. The remainder - * of the string is the message key. - * - * <p> - * A null input value passes through unchanged. - */ - protected String processText(SchemaProcessor processor, Element element, String inputValue) - { - if (inputValue == null) - return null; - - if (inputValue.startsWith("%")) - { - String key = inputValue.substring(1); - - return processor.getContributingModule().getMessages().getMessage(key); - } - - Registry registry = processor.getContributingModule().getRegistry(); - - return registry.expandSymbols(inputValue, element.getLocation()); - } - - /** - * Sets a property of the target object to the given value. - * Logs an error if there is a problem. - */ - protected void setProperty( - SchemaProcessor processor, - Element element, - String propertyName, - Object target, - Object value) - { - try - { - BeanUtils.setProperty(target, propertyName, value); - } - catch (Exception ex) - { - // Have to decide if we need to display the location of the rule - // or the element. - - LOG.error( - HiveMind.format( - "BaseRule.set-property-error", - new Object[] { - propertyName, - target, - value, - processor.getElementPath(), - element.getLocation(), - ex.getMessage()})); - } - } - /** * Does nothing; subclasses may override. */ 1.2 +74 -4 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/IntTranslator.java Index: IntTranslator.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/IntTranslator.java,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- IntTranslator.java 29 Jul 2003 22:20:48 -0000 1.1 +++ IntTranslator.java 4 Aug 2003 14:21:56 -0000 1.2 @@ -57,6 +57,8 @@ package org.apache.commons.hivemind.schema.rules; +import java.util.Map; + import org.apache.commons.hivemind.Element; import org.apache.commons.hivemind.HiveMind; import org.apache.commons.hivemind.schema.SchemaProcessor; @@ -75,6 +77,47 @@ { private static final Log LOG = LogFactory.getLog(IntTranslator.class); + private int _minValue; + private boolean _isMinValue; + private int _maxValue; + private boolean _isMaxValue; + private int _defaultValue = 0; + + public IntTranslator() + { + } + + /** + * Initializers: + * <ul> + * <li>default: default value for empty or invalid input + * <li>min: minimum acceptible value + * <li>max: maximum acceptible value + */ + public IntTranslator(String initializer) + { + Map m = RuleUtils.convertInitializer(initializer); + + String defaultInit = (String) m.get("default"); + + if (defaultInit != null) + _defaultValue = Integer.parseInt(defaultInit); + + String minInit = (String) m.get("min"); + if (minInit != null) + { + _isMinValue = true; + _minValue = Integer.parseInt(minInit); + } + + String maxInit = (String) m.get("max"); + if (maxInit != null) + { + _isMaxValue = true; + _maxValue = Integer.parseInt(maxInit); + } + } + /** * Converts the string to an Integer. The empty string is returned as zero. * On failure, an error is logged and the method returns zero. @@ -82,11 +125,37 @@ public Object translate(SchemaProcessor processor, Element element, String inputValue) { if (StringUtils.isEmpty(inputValue)) - return new Integer(0); + return new Integer(_defaultValue); + + int value; try { - return new Integer(inputValue); + value = Integer.parseInt(inputValue); + + if (_isMinValue && value < _minValue) + { + LOG.error( + HiveMind.format( + "IntTranslator.min-value", + inputValue, + element.getLocation(), + Integer.toString(_minValue))); + + value = _minValue; + } + + if (_isMaxValue && value > _maxValue) + { + LOG.error( + HiveMind.format( + "IntTranslator.max-value", + inputValue, + element.getLocation(), + Integer.toString(_maxValue))); + + value = _maxValue; + } } catch (Exception ex) { @@ -96,9 +165,10 @@ inputValue, processor.getElementPath(), element.getLocation())); + value = _defaultValue; } - return new Integer(0); + return new Integer(value); } } 1.3 +3 -3 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/ReadAttributeRule.java Index: ReadAttributeRule.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/ReadAttributeRule.java,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- ReadAttributeRule.java 1 Aug 2003 14:41:30 -0000 1.2 +++ ReadAttributeRule.java 4 Aug 2003 14:21:56 -0000 1.3 @@ -84,12 +84,12 @@ if (rawValue == null && _skipIfNull) return; - String value = processText(processor, element, rawValue); + String value = RuleUtils.processText(processor, element, rawValue); Object finalValue = _translator == null ? value : _translator.translate(processor, element, value); - setProperty(processor, element, _propertyName, processor.peek(), finalValue); + RuleUtils.setProperty(processor, element, _propertyName, processor.peek(), finalValue); } public Translator getTranslator() 1.1 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/schema/rules/RuleUtils.java Index: RuleUtils.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package org.apache.commons.hivemind.schema.rules; import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.hivemind.Element; import org.apache.commons.hivemind.HiveMind; import org.apache.commons.hivemind.Registry; import org.apache.commons.hivemind.schema.SchemaProcessor; import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tapestry.ApplicationRuntimeException; /** * Static methods useful to [EMAIL PROTECTED] org.apache.commons.hivemind.schema.Rule}s and * [EMAIL PROTECTED] org.apache.commons.hivemind.schema.Translator}s. * * @author Howard Lewis Ship * @version $Id: RuleUtils.java,v 1.1 2003/08/04 14:21:56 hlship Exp $ */ public class RuleUtils { private static final Log LOG = LogFactory.getLog(RuleUtils.class); /** * Used to convert a [EMAIL PROTECTED] org.apache.commons.hivemind.schema.Translator} * initializer string of the form: * <code><i>key</i>=<i>value</i>[,<i>key</i>=<i>value<i>]*</code> * into a Map of keys and values. The keys and values are Strings. */ public static Map convertInitializer(String initializer) { if (StringUtils.isEmpty(initializer)) return Collections.EMPTY_MAP; Map result = new HashMap(); int lastCommax = -1; int inputLength = initializer.length(); while (lastCommax < inputLength) { int nextCommax = initializer.indexOf(',', lastCommax + 1); if (nextCommax < 0) nextCommax = inputLength; String term = initializer.substring(lastCommax + 1, nextCommax); int equalsx = term.indexOf('='); if (equalsx <= 0) throw new ApplicationRuntimeException( HiveMind.format("RuleUtils.invalid-initializer", initializer)); String key = term.substring(0, equalsx); String value = term.substring(equalsx + 1); result.put(key, value); lastCommax = nextCommax; } return result; } /** * Invoked to process text from an attribute or from an element's content. Performs * two jobs: * <ul> * <li>Convert localized message references to localized strings * <li>Expand symbols using [EMAIL PROTECTED] Registry#expandSymbols(String, ILocation)} * </ul> * * <p> * Note: if the input is a localized message then no symbol expansion takes place. * Localized message references are simply strings that begin with '%'. The remainder * of the string is the message key. * * <p> * A null input value passes through unchanged. */ public static String processText(SchemaProcessor processor, Element element, String inputValue) { if (inputValue == null) return null; if (inputValue.startsWith("%")) { String key = inputValue.substring(1); return processor.getContributingModule().getMessages().getMessage(key); } Registry registry = processor.getContributingModule().getRegistry(); return registry.expandSymbols(inputValue, element.getLocation()); } /** * Sets a property of the target object to the given value. * Logs an error if there is a problem. */ public static void setProperty( SchemaProcessor processor, Element element, String propertyName, Object target, Object value) { try { BeanUtils.setProperty(target, propertyName, value); } catch (Exception ex) { // Have to decide if we need to display the location of the rule // or the element. LOG.error( HiveMind.format( "BaseRule.set-property-error", new Object[] { propertyName, target, value, processor.getElementPath(), element.getLocation(), ex.getMessage()})); } } } 1.17 +6 -2 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/HiveMindMessages.properties Index: HiveMindMessages.properties =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/HiveMindMessages.properties,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- HiveMindMessages.properties 1 Aug 2003 19:05:23 -0000 1.16 +++ HiveMindMessages.properties 4 Aug 2003 14:21:56 -0000 1.17 @@ -40,6 +40,7 @@ DescriptorParser.invalid-numeric-value=''{0}'' (attribute ''{1}'' of {2}, at {3}) can not be converted to a numeric value. DescriptorParser.bad-translator=Unable to create translator ''{0}'' (at {1}): {2} DescriptorParser.unknown-schema-id=Element {0} (at {1}) references unknown schema ''{2}''. +DescriptorParser.missing-translator-constructor=Translator class {0} does not contain an appropriate constructor (at {1}). ExternalParser.missing-resource=Unable to locate {0}. @@ -107,10 +108,13 @@ BooleanTranslator.invalid-value=''{0}'' (in element {1} at {2}) is not a boolean value (which should be either ''true'' or ''false''). -IntegerTransaltor.invalid-value=''{0}'' (in element {1} at {2}) is not an integer value. +IntTranslator.invalid-value=''{0}'' (in element {1} at {2}) is not an integer value. +IntTranslator.min-value=Value {0} (at {1}) is less than minimum value {2}. +IntTranslator.max-value=Value {0} (at {1}) is greater than maximum value {2}. ServiceTranslator.invalid-value=Error resolving service {0} (in element {1} at {2}): {3} +RuleUtils.invalid-initializer=Initializer string (''{0}'') is not in proper format (key=value[,key=value]*). # service.impl package 1.12 +13 -4 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/HiveMind.java Index: HiveMind.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/HiveMind.java,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- HiveMind.java 1 Aug 2003 18:26:02 -0000 1.11 +++ HiveMind.java 4 Aug 2003 14:21:56 -0000 1.12 @@ -59,11 +59,11 @@ import java.text.MessageFormat; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.MissingResourceException; import java.util.ResourceBundle; import org.apache.commons.logging.Log; @@ -136,7 +136,7 @@ return _registry; } - + /** * Returns true if the shared registry is not null. */ @@ -167,7 +167,16 @@ public static String format(String key, Object[] args) { - String pattern = _bundle.getString(key); + String pattern = null; + + try + { + pattern = _bundle.getString(key); + } + catch (MissingResourceException ex) + { + pattern = "[" + key.toUpperCase() + "]"; + } if (args == null) return pattern; 1.2 +87 -53 jakarta-commons-sandbox/hivemind/xdocs/rules.xml Index: rules.xml =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/xdocs/rules.xml,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- rules.xml 31 Jul 2003 21:06:24 -0000 1.1 +++ rules.xml 4 Aug 2003 14:21:56 -0000 1.2 @@ -55,6 +55,7 @@ are useful for creating hierarchies of objects. </p> + <p> The available rules are: <ul> @@ -66,50 +67,7 @@ </ul> </p> -</section> - -<section name="Translators"> - -<p> -Commonly, it is necessary to perform some translation or transformation of string attribute value to convert the -value into some other type, such as boolean, integer or date. This can be accomplished by specifying a <i>translator</i> -in the &read-attribute; rule (it also applies to element content, and the &read-content; rule). -</p> - -<p> -A translator is an object implementing the -<a href="apidocs/org/apache/commons/hivemind/schema/Translator.html">Translator</a> interface. The -<code>translator</code> value specified in a rule may be either the complete class name of a class implementing -the interface, or one of a number of builtin values: -</p> - -<table> -<tr> - <th>translator</th> - <th>Description</th> - <th>Null/empty handled as</th> -</tr> -<tr> -<td>boolean</td> -<td>Expects the input to be either "true" or "false".</td> -<td>false</td> -</tr> -<tr> -<td>int</td> -<td>Converts to integer value</td> -<td>0</td> -</tr> -<tr> -<td>service</td> -<td>Looks up the named service in the registry, using a fully-qualified id</td> -<td>null</td> -</tr> -</table> - - -</section> - -<section name="create-object"> +<subsection name="create-object"> <p> The &_create-object; rule is used to create a new object, which is pushed onto the stack at <code>begin()</code>. @@ -133,9 +91,9 @@ </tr> </table> -</section> +</subsection> -<section name="invoke-parent"> +<subsection name="invoke-parent"> <p> The &_invoke-parent; rule is used to connect the child (top object on the stack) to its parent @@ -167,9 +125,9 @@ (or for service factories, adds the object as a parameter). </p> -</section> +</subsection> -<section name="read-attribute"> +<subsection name="read-attribute"> <p> The @@ -211,9 +169,9 @@ </tr> </table> -</section> +</subsection> -<section name="read-content"> +<subsection name="read-content"> <p> The &_read-content; rule is similar to &read-attribute;, except it concerns the content of the current element @@ -240,9 +198,9 @@ <td>See <a href="#Translators">Translators</a></td> </tr> </table> -</section> +</subsection> -<section name="set-parent"> +<subsection name="set-parent"> <p> The &set-parent; rule is used to set a property of the child object to parent object. This allows @@ -264,7 +222,83 @@ </tr> </table> +</subsection> + </section> + +<section name="Translators"> + +<p> +Commonly, it is necessary to perform some translation or transformation of string attribute value to convert the +value into some other type, such as boolean, integer or date. This can be accomplished by specifying a <i>translator</i> +in the &read-attribute; rule (it also applies to element content, and the &read-content; rule). +</p> + +<p> +A translator is an object implementing the +<a href="apidocs/org/apache/commons/hivemind/schema/Translator.html">Translator</a> interface. The +<code>translator</code> value specified in a rule may be either the complete class name of a class implementing +the interface, or one of a number of builtin values. +</p> + +<p> +Translators can be configured using <i>initializer strings</i>. The initializer string is separated from the +translator id (or translator class name) by a comma, ex: <code>int,min=0</code>. Initializer +strings are <i>generally</i> in the format of +<code><i>key</i>=<i>value</i>[,<i>key</i>=<i>value</i>]*</code> ... but each Translator +is free to interpret the initializer string its own way. +</p> + +<subsection name="boolean"> + +<p> +The boolean translator converts an input string into a boolean value. "true" is translated to true, and "false" to false. +</p> + +<p> +A default value is used when the input is null or invalid. Normally, this default is false, but the "default" key in the initializer +can override this (i.e., <code>boolean,default=true</code>). + </p> + +</subsection> + +<subsection name="class"> + +<p> + The class translator converts a fully qualified class name into an object instance. The class must implement +a public no-arguments constructor. +</p> + +</subsection> + +<subsection name="int"> + +<p> +The int translator converts the input into an integer value. It recognizes three initializer values: +<ul> +<li>default: the default value (normally 0) to use when the input is null or invavlid</li> +<li>min: a minimum acceptible value</li> +<li>max: a maximum acceptible value</li> +</ul> +</p> + +<p> +If the value is outside of the range defined by the min and max initializer keys, it is constrained into the range. +</p> + +</subsection> + +<subsection name="service"> + +<p> +The service translator is used to lookup a service in the registry. The input value is either a local service id +from the contributing module, or a fully qualified service id. +</p> + +</subsection> + + </section> + </body> </document> 1.1 jakarta-commons-sandbox/hivemind/src/test/hivemind/test/rules/TestConvertInitializer.java Index: TestConvertInitializer.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package hivemind.test.rules; import hivemind.test.HiveMindTestCase; import java.util.Map; import org.apache.commons.hivemind.schema.rules.RuleUtils; import org.apache.tapestry.ApplicationRuntimeException; /** * Tests for [EMAIL PROTECTED] org.apache.commons.hivemind.HiveMind#convertTranslatorInitializer(String)}. * * @author Howard Lewis Ship * @version $Id: TestConvertInitializer.java,v 1.1 2003/08/04 14:21:56 hlship Exp $ */ public class TestConvertInitializer extends HiveMindTestCase { public TestConvertInitializer(String name) { super(name); } public void testEmpty() { Map m = RuleUtils.convertInitializer(null); assertEquals(true, m.isEmpty()); m = RuleUtils.convertInitializer(""); assertEquals(true, m.isEmpty()); } public void testSimple() { Map m = RuleUtils.convertInitializer("alpha=bravo"); assertEquals(1, m.size()); assertEquals("bravo", m.get("alpha")); } public void testComplex() { Map m = RuleUtils.convertInitializer("alpha=bravo,fred=barney,gromit=greyhound"); assertEquals(3, m.size()); assertEquals("bravo", m.get("alpha")); assertEquals("barney", m.get("fred")); assertEquals("greyhound", m.get("gromit")); } public void testFailure() { try { RuleUtils.convertInitializer("bad"); unreachable(); } catch (ApplicationRuntimeException ex) { checkException( ex, "Initializer string ('bad') is not in proper format (key=value[,key=value]*)."); } } } 1.1 jakarta-commons-sandbox/hivemind/src/test/hivemind/test/config/impl/IntHolder.java Index: IntHolder.java =================================================================== /* * ==================================================================== * * The Apache Software License, Version 1.1 * * Copyright (c) 1999-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, if * any, must include the following acknowlegement: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * * 4. The names "The Jakarta Project", "Commons", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] * * 5. Products derived from this software may not be called "Apache" * nor may "Apache" appear in their names without prior written * permission of the Apache Group. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * */ package hivemind.test.config.impl; /** * Used for testing [EMAIL PROTECTED] org.apache.commons.hivemind.schema.rules.IntTranslator}. * * @author Howard Lewis Ship * @version $Id: IntHolder.java,v 1.1 2003/08/04 14:21:56 hlship Exp $ */ public class IntHolder { private int _value; public int getValue() { return _value; } public void setValue(int i) { _value = i; } } 1.17 +4 -4 jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/impl/RegistryBuilder.java Index: RegistryBuilder.java =================================================================== RCS file: /home/cvs/jakarta-commons-sandbox/hivemind/src/java/org/apache/commons/hivemind/impl/RegistryBuilder.java,v retrieving revision 1.16 retrieving revision 1.17 diff -u -r1.16 -r1.17 --- RegistryBuilder.java 1 Aug 2003 14:21:38 -0000 1.16 +++ RegistryBuilder.java 4 Aug 2003 14:21:56 -0000 1.17 @@ -100,8 +100,8 @@ * here and in many of the related classes is divided into construction-time logic * and runtime logic. Runtime logic is synchronized and threadsafe. Construction-time logic * is not threadsafe. Methods such as [EMAIL PROTECTED] org.apache.commons.hivemind.impl.RegistryImpl#addModule(Module)}, - * [EMAIL PROTECTED] org.apache.commons.hivemind.impl.ModuleImpl#addConfigurationExtensionPoint(ConfigurationExtensionPoint)}, - * [EMAIL PROTECTED] org.apache.commons.hivemind.impl.ConfigurationExtensionPointImpl#addConfigurationContribution(ConfigurationContribution)} + * [EMAIL PROTECTED] org.apache.commons.hivemind.impl.ModuleImpl#addExtensionPoint(ExtensionPoint))}, + * [EMAIL PROTECTED] org.apache.commons.hivemind.impl.ExtensionPointImpl#addExtension(Extension)} * and the like are construction-time. Once the registry is fully constructed, it is not * allowed to invoke those methods (though, at this time, no checks occur). * @@ -494,7 +494,7 @@ } /** - * Adds an [EMAIL PROTECTED] org.apache.commons.hivemind.parse.AbstractInstanceBuilderDescriptor} + * Adds an [EMAIL PROTECTED] InstanceBuilder} * to a service extension point. * *
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]