001: /*
002: * $Id: TemplateParser.java 8340 2007-09-11 17:06:55Z romikk $
003: * --------------------------------------------------------------------------------------
004: * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com
005: *
006: * The software in this package is published under the terms of the CPAL v1.0
007: * license, a copy of which has been included with this distribution in the
008: * LICENSE.txt file.
009: */
010:
011: package org.mule.util;
012:
013: import java.util.ArrayList;
014: import java.util.HashMap;
015: import java.util.Iterator;
016: import java.util.List;
017: import java.util.Map;
018: import java.util.regex.Matcher;
019: import java.util.regex.Pattern;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023:
024: /**
025: * <code>TemplateParser</code> is a simple string parser that will substitute
026: * tokens in a string with values supplied in a Map.
027: */
028: public final class TemplateParser {
029: public static final String ANT_TEMPLATE_STYLE = "ant";
030: public static final String SQUARE_TEMPLATE_STYLE = "square";
031:
032: /**
033: * logger used by this class
034: */
035: protected static final Log logger = LogFactory
036: .getLog(TemplateParser.class);
037:
038: private final Pattern pattern;
039: private final int pre;
040: private final int post;
041: private final String style;
042:
043: public static TemplateParser createAntStyleParser() {
044: return new TemplateParser(ANT_TEMPLATE_STYLE);
045: }
046:
047: public static TemplateParser createSquareBracesStyleParser() {
048: return new TemplateParser(SQUARE_TEMPLATE_STYLE);
049: }
050:
051: private TemplateParser(String style) {
052: if (ANT_TEMPLATE_STYLE.equals(style)) {
053: pattern = Pattern.compile("\\$\\{[^\\}]+\\}");
054: pre = 2;
055: post = 1;
056: } else if (SQUARE_TEMPLATE_STYLE.equals(style)) {
057: pattern = Pattern.compile("\\[[^\\]]+\\]");
058: pre = 1;
059: post = 1;
060: } else {
061: throw new IllegalArgumentException(
062: "Unknown template style: " + style);
063: }
064: this .style = style;
065: }
066:
067: /**
068: * Matches one or more templates against a Map of key value pairs. If a value for
069: * a template is not found in the map the template is left as is in the return
070: * String
071: *
072: * @param props the key/value pairs to match against
073: * @param template the string containing the template place holders i.e. My name
074: * is ${name}
075: * @return the parsed String
076: */
077: public String parse(Map props, String template) {
078: return parse(props, template, null);
079: }
080:
081: /**
082: * Matches one or more templates against a Map of key value pairs. If a value for
083: * a template is not found in the map the template is left as is in the return
084: * String
085: *
086: * @param callback a callback used to resolve the property name
087: * @param template the string containing the template place holders i.e. My name
088: * is ${name}
089: * @return the parsed String
090: */
091: public String parse(TemplateCallback callback, String template) {
092: return parse(null, template, callback);
093: }
094:
095: protected String parse(Map props, String template,
096: TemplateCallback callback) {
097: String result = template;
098: Matcher m = pattern.matcher(template);
099:
100: while (m.find()) {
101: Object value = null;
102:
103: String match = m.group();
104: String propname = match.substring(pre, match.length()
105: - post);
106:
107: if (callback != null) {
108: value = callback.match(propname);
109: } else if (props != null) {
110: value = props.get(propname);
111: }
112:
113: if (value == null) {
114: if (logger.isDebugEnabled()) {
115: logger.debug("Value " + propname
116: + " not found in context");
117: }
118: } else {
119: String matchRegex = escape(match);
120: String valueString = value.toString();
121:
122: if (valueString.indexOf('\\') != -1) {
123: valueString = valueString.replaceAll("\\\\",
124: "\\\\\\\\");
125: }
126:
127: result = result.replaceAll(matchRegex, valueString);
128: }
129: }
130: return result;
131: }
132:
133: /**
134: * Matches one or more templates against a Map of key value pairs. If a value for
135: * a template is not found in the map the template is left as is in the return
136: * String
137: *
138: * @param props the key/value pairs to match against
139: * @param templates A List of templates
140: * @return the parsed String
141: */
142: public List parse(Map props, List templates) {
143: if (templates == null) {
144: return new ArrayList();
145: }
146: List list = new ArrayList(templates.size());
147: for (Iterator iterator = templates.iterator(); iterator
148: .hasNext();) {
149: list.add(parse(props, iterator.next().toString()));
150: }
151: return list;
152: }
153:
154: /**
155: * Matches one or more templates against a Map of key value pairs. If a value for
156: * a template is not found in the map the template is left as is in the return
157: * String
158: *
159: * @param props the key/value pairs to match against
160: * @param templates A Map of templates. The values for each map entry will be
161: * parsed
162: * @return the parsed String
163: */
164: public Map parse(final Map props, Map templates) {
165: return parse(new TemplateCallback() {
166: public Object match(String token) {
167: return props.get(token);
168: }
169: }, templates);
170: }
171:
172: public Map parse(TemplateCallback callback, Map templates) {
173: if (templates == null) {
174: return new HashMap();
175: }
176: Map map = new HashMap(templates.size());
177: Map.Entry entry;
178: for (Iterator iterator = templates.entrySet().iterator(); iterator
179: .hasNext();) {
180: entry = (Map.Entry) iterator.next();
181: map.put(entry.getKey(), parse(callback, entry.getValue()
182: .toString()));
183: }
184: return map;
185: }
186:
187: private String escape(String string) {
188: int length = string.length();
189: if (length == 0) {
190: // nothing to do
191: return string;
192: } else {
193: StringBuffer buffer = new StringBuffer(length * 2);
194: for (int i = 0; i < length; i++) {
195: char currentCharacter = string.charAt(i);
196: switch (currentCharacter) {
197: case '[':
198: case ']':
199: case '{':
200: case '}':
201: case '$':
202: buffer.append("\\");
203: // fall through to append original character
204: default:
205: buffer.append(currentCharacter);
206: }
207: }
208: return buffer.toString();
209: }
210: }
211:
212: public String getStyle() {
213: return style;
214: }
215:
216: public boolean isContainsTemplate(String value) {
217: if (value == null)
218: return false;
219:
220: Matcher m = pattern.matcher(value);
221: return m.find();
222: }
223:
224: public static interface TemplateCallback {
225: Object match(String token);
226: }
227:
228: }
|