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