001: package org.conform.format;
002:
003: import java.io.Serializable;
004: import java.util.*;
005:
006: /**
007: * Allows for substitution of variables in a String.
008: * In addition, it's possible, to use a ResourceBundle for translation of
009: * the substituted values. This addresses the special case, when
010: * substitutions are arbitrary Objects, aren't human readable or have to
011: * be localized. For example Locales, MessageIDs, ErrorIds, etc.
012: */
013: public class StringTemplate implements Serializable {
014: private String template = null;
015: private Map map = null;
016: private String defaultValue = "";
017: private boolean upper = false;
018: private ResourceBundle bundle = null;
019:
020: public StringTemplate() {
021: }
022:
023: public StringTemplate(String template) {
024: this .template = template;
025: }
026:
027: public StringTemplate(String template, Map map) {
028: this .template = template;
029: this .map = map;
030: }
031:
032: public void setTemplate(String template) {
033: this .template = template;
034: }
035:
036: public String getTemplate() {
037: return template;
038: }
039:
040: public void setMap(Map map) {
041: this .map = map;
042: }
043:
044: public Map getMap() {
045: return map;
046: }
047:
048: public void setResourceBundle(ResourceBundle bundle) {
049: this .bundle = bundle;
050: }
051:
052: public ResourceBundle getResourceBundle() {
053: return bundle;
054: }
055:
056: public void setDefaultValue(String defaultValue) {
057: this .defaultValue = defaultValue;
058: }
059:
060: public String getDefaultValue() {
061: return defaultValue;
062: }
063:
064: public void setUpperCase(boolean upper) {
065: this .upper = upper;
066: }
067:
068: public boolean isUpperCase() {
069: return upper;
070: }
071:
072: public String toString() {
073: int pos = 0;
074: int end = 0;
075: StringBuffer result = new StringBuffer();
076: boolean has_brace;
077:
078: if (template == null)
079: return "";
080:
081: if (map == null)
082: return template;
083:
084: while ((pos = template.indexOf('$', pos)) >= 0) {
085: if (template.charAt(pos + 1) == '$') {
086: pos++;
087: continue;
088: }
089:
090: // text between last variable and here
091: result.append(template.substring(end, pos));
092:
093: has_brace = (template.charAt(pos + 1) == '{');
094: if (has_brace) {
095: end = template.indexOf('}', pos + 1);
096: handleBrace(result, template.substring(pos + 2, end));
097: pos = ++end;
098: } else {
099: end = pos + 1;
100: if (template.charAt(end) == '#')
101: end++;
102: while (end < template.length()
103: && isVariableChar(template.charAt(end)))
104: end++;
105: handleVariable(result, template.substring(pos + 1, end));
106: pos = end;
107: }
108: }
109:
110: result.append(template.substring(end, template.length()));
111: return result.toString();
112: }
113:
114: private void handleVariable(StringBuffer buffer, String variable) {
115: boolean translate = false;
116: if (variable.charAt(0) == '#') {
117: translate = true;
118: variable = variable.substring(1);
119: }
120:
121: String value = getValue(variable);
122: if (value != null)
123: buffer.append((translate) ? translate(variable, value)
124: : value);
125: else if (defaultValue != null)
126: buffer.append(defaultValue);
127: else
128: buffer.append(variable);
129: }
130:
131: private void handleBrace(StringBuffer buffer, String contents) {
132: List vars = new LinkedList();
133: String delimiter = "";
134:
135: boolean translate = false;
136: if (contents.charAt(0) == '#') {
137: translate = true;
138: contents = contents.substring(1);
139: }
140:
141: StringTokenizer tokenizer = new StringTokenizer(contents, ",");
142: while (tokenizer.hasMoreTokens()) {
143: String token = tokenizer.nextToken();
144: if (token.charAt(0) == '"') {
145: while (!(token.charAt(token.length() - 1) == '"')
146: || token.length() == 1)
147: token = token + "," + tokenizer.nextToken();
148:
149: delimiter = token.substring(1, token.length() - 1);
150: } else {
151: vars.add(token);
152: }
153: }
154:
155: if (vars.size() == 1) {
156: String variable = (String) vars.get(0);
157: String value = getValue(variable);
158: if (value != null) {
159: buffer.append(delimiter).append(
160: (translate) ? translate(variable, value)
161: : value);
162: }
163: } else {
164: boolean first = true;
165: Iterator it = vars.iterator();
166: while (it.hasNext()) {
167: String variable;
168: String value = getValue(variable = (String) it.next());
169: if (value != null) {
170: if (!first)
171: buffer.append(delimiter);
172: buffer.append((translate) ? translate(variable,
173: value) : value);
174: first = false;
175: }
176: }
177: }
178: }
179:
180: private String getValue(String variable) {
181: if (upper)
182: variable = variable.toUpperCase();
183: Object value = map.get(variable);
184: if (value != null)
185: return value.toString();
186: else
187: return null;
188: }
189:
190: public String translate(String name, String value) {
191: String text;
192: try {
193: //logger.finest("translating: " + name + "." + value);
194: text = bundle.getString(name + "." + value);
195: } catch (MissingResourceException e) {
196: text = value;
197: }
198: return text;
199: }
200:
201: /**
202: * gibt zur�ck, ob es sich bei dem Zeichen um ein Zeichen, wie es in
203: * einer Variable vorkommen kann, handelt.
204: *
205: * @param x ein Zeichen, ein Zeichen ..
206: * @result <code>true</code>, wenn Zeichen in Variable vorkommen kann, sonst <code>false</code>
207: */
208: private boolean isVariableChar(char x) {
209: return ((x >= 'A' && x <= 'Z') || (x >= 'a' && x <= 'z')
210: || (x >= '0' && x <= '9') || (x == '.' || x == '_'));
211: }
212: }
|