001    /* $Id: MultiVariableExpander.java 471661 2006-11-06 08:09:25Z skitching $
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 markers = new ArrayList(2);
033        private ArrayList sources = new ArrayList(2);
034        
035        public MultiVariableExpander() {
036        }
037        
038        public void addSource(String marker, Map 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                    (String) markers.get(i), 
056                    (Map) 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 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    }