    001    /* $Id: MultiVariableExpander.java 729129 2008-12-23 21:27:42Z rahul $
    002     *
    003     * Licensed to the Apache Software Foundation (ASF) under one or more
    004     * contributor license agreements.  See the NOTICE file distributed with
    005     * this work for additional information regarding copyright ownership.
    006     * The ASF licenses this file to You under the Apache License, Version 2.0
    007     * (the "License"); you may not use this file except in compliance with
    008     * the License.  You may obtain a copy of the License at
    009     *
    010     *      http://www.apache.org/licenses/LICENSE-2.0
    011     *
    012     * Unless required by applicable law or agreed to in writing, software
    013     * distributed under the License is distributed on an "AS IS" BASIS,
    014     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    015     * See the License for the specific language governing permissions and
    016     * limitations under the License.
    017     */
    018
    019    package org.apache.commons.digester.substitution;
    020
    021    import java.util.Map;
    022    import java.util.ArrayList;
    023
    024    /**
    025     * <p>Expands variable references from multiple sources.</p>
    026     *
    027     * @since 1.6
    028     */
    029
    030    public class MultiVariableExpander implements VariableExpander {
    031        private int nEntries = 0;
    032        private ArrayList<String> markers = new ArrayList<String>(2);
    033        private ArrayList<Map<String, Object>> sources = new ArrayList<Map<String, Object>>(2);
    034
    035        public MultiVariableExpander() {
    036        }
    037
    038        public void addSource(String marker, Map<String, Object> source) {
    039            ++nEntries;
    040            markers.add(marker);
    041            sources.add(source);
    042        }
    043
    044        /*
    045         * Expands any variable declarations using any of the known
    046         * variable marker strings.
    047         *
    048         * @throws IllegalArgumentException if the input param references
    049         * a variable which is not known to the specified source.
    050         */
    051        public String expand(String param) {
    052            for(int i=0; i<nEntries; ++i) {
    053                param = expand(
    054                    param,
    055                    markers.get(i),
    056                    sources.get(i));
    057            }
    058            return param;
    059        }
    060
    061        /**
    062         * Replace any occurrences within the string of the form
    063         * "marker{key}" with the value from source[key].
    064         * <p>
    065         * Commonly, the variable marker is "$", in which case variables
    066         * are indicated by ${key} in the string.
    067         * <p>
    068         * Returns the string after performing all substitutions.
    069         * <p>
    070         * If no substitutions were made, the input string object is
    071         * returned (not a copy).
    072         *
    073         * @throws IllegalArgumentException if the input param references
    074         * a variable which is not known to the specified source.
    075         */
    076        public String expand(String str, String marker, Map<String, Object> source) {
    077            String startMark = marker + "{";
    078            int markLen = startMark.length();
    079
    080            int index = 0;
    081            for(;;)
    082            {
    083                index = str.indexOf(startMark, index);
    084                if (index == -1)
    085                {
    086                    return str;
    087                }
    088
    089                int startIndex = index + markLen;
    090                if (startIndex > str.length())
    091                {
    092                    throw new IllegalArgumentException(
    093                        "var expression starts at end of string");
    094                }
    095
    096                int endIndex = str.indexOf("}", index + markLen);
    097                if (endIndex == -1)
    098                {
    099                    throw new IllegalArgumentException(
    100                        "var expression starts but does not end");
    101                }
    102
    103                String key = str.substring(index+markLen, endIndex);
    104                Object value =  source.get(key);
    105                if (value == null) {
    106                    throw new IllegalArgumentException(
    107                        "parameter [" + key + "] is not defined.");
    108                }
    109                String varValue = value.toString();
    110
    111                str = str.substring(0, index) + varValue + str.substring(endIndex+1);
    112                index += varValue.length();
    113            }
    114        }
    115
    116    }