001    // Copyright 2004, 2005 The Apache Software Foundation
002    //
003    // Licensed under the Apache License, Version 2.0 (the "License");
004    // you may not use this file except in compliance with the License.
005    // You may obtain a copy of the License at
006    //
007    //     http://www.apache.org/licenses/LICENSE-2.0
008    //
009    // Unless required by applicable law or agreed to in writing, software
010    // distributed under the License is distributed on an "AS IS" BASIS,
011    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
012    // See the License for the specific language governing permissions and
013    // limitations under the License.
014    
015    package org.apache.hivemind.schema.rules;
016    
017    import java.util.Collections;
018    import java.util.HashMap;
019    import java.util.Map;
020    
021    import org.apache.commons.logging.Log;
022    import org.apache.commons.logging.LogFactory;
023    import org.apache.hivemind.ApplicationRuntimeException;
024    import org.apache.hivemind.Element;
025    import org.apache.hivemind.ErrorHandler;
026    import org.apache.hivemind.HiveMind;
027    import org.apache.hivemind.internal.Module;
028    import org.apache.hivemind.schema.SchemaProcessor;
029    import org.apache.hivemind.schema.Translator;
030    import org.apache.hivemind.util.PropertyUtils;
031    
032    /**
033     * Static methods useful to {@link org.apache.hivemind.schema.Rule}s and
034     * {@link org.apache.hivemind.schema.Translator}s.
035     * 
036     * @author Howard Lewis Ship
037     */
038    public class RuleUtils
039    {
040        private static final Log LOG = LogFactory.getLog(RuleUtils.class);
041    
042        /**
043         * Used to convert a {@link org.apache.hivemind.schema.Translator} initializer string of the
044         * form: <code><i>key</i>=<i>value</i>[,<i>key</i>=<i>value<i>]*</code> into a Map of
045         * keys and values. The keys and values are Strings.
046         */
047        public static Map convertInitializer(String initializer)
048        {
049            if (HiveMind.isBlank(initializer))
050                return Collections.EMPTY_MAP;
051    
052            Map result = new HashMap();
053    
054            int lastCommax = -1;
055            int inputLength = initializer.length();
056    
057            while (lastCommax < inputLength)
058            {
059                int nextCommax = initializer.indexOf(',', lastCommax + 1);
060    
061                if (nextCommax < 0)
062                    nextCommax = inputLength;
063    
064                String term = initializer.substring(lastCommax + 1, nextCommax);
065    
066                int equalsx = term.indexOf('=');
067    
068                if (equalsx <= 0)
069                    throw new ApplicationRuntimeException(RulesMessages.invalidInitializer(initializer));
070    
071                String key = term.substring(0, equalsx);
072                String value = term.substring(equalsx + 1);
073    
074                result.put(key, value);
075    
076                lastCommax = nextCommax;
077            }
078    
079            return result;
080        }
081    
082        /**
083         * Invoked to process text from an attribute or from an element's content. Performs two jobs:
084         * <ul>
085         * <li>Convert localized message references to localized strings
086         * <li>Expand symbols using
087         * {@link org.apache.hivemind.Registry#expandSymbols(String, Location)}
088         * </ul>
089         * <p>
090         * Note: if the input is a localized message then no symbol expansion takes place. Localized
091         * message references are simply strings that begin with '%'. The remainder of the string is the
092         * message key.
093         * <p>
094         * A null input value passes through unchanged.
095         */
096        public static String processText(SchemaProcessor processor, Element element, String inputValue)
097        {
098            if (inputValue == null)
099                return null;
100    
101            Module contributingModule = processor.getContributingModule();
102    
103            if (inputValue.startsWith("%"))
104            {
105                String key = inputValue.substring(1);
106    
107                return contributingModule.getMessages().getMessage(key);
108            }
109    
110            return contributingModule.expandSymbols(inputValue, element.getLocation());
111        }
112    
113        /**
114         * Sets a property of the target object to the given value. Logs an error if there is a problem.
115         */
116        public static void setProperty(SchemaProcessor processor, Element element, String propertyName,
117                Object target, Object value)
118        {
119            try
120            {
121                PropertyUtils.write(target, propertyName, value);
122            }
123            catch (Exception ex)
124            {
125                // Have to decide if we need to display the location of the rule
126                // or the element.
127    
128                ErrorHandler errorHandler = processor.getContributingModule().getErrorHandler();
129                errorHandler.error(LOG, RulesMessages.unableToSetElementProperty(
130                        propertyName,
131                        target,
132                        processor,
133                        element,
134                        ex), element.getLocation(), ex);
135            }
136        }
137    
138        /**
139         * Convienience for invoking {@link Module#getTranslator(String)}.
140         * 
141         * @param processor
142         *            the processor for the schema being converted
143         * @param translator
144         *            the string identifying the translator to provide (may be null)
145         * @return a translator obtained via the contributing module, or an instance of
146         *         {@link NullTranslator}
147         */
148        public static Translator getTranslator(SchemaProcessor processor, String translator)
149        {
150            if (translator == null)
151                return new NullTranslator();
152    
153            return processor.getContributingModule().getTranslator(translator);
154        }
155    }