KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > scriptella > expression > PropertiesSubstitutor


1 /*
2  * Copyright 2006-2007 The Scriptella Project Team.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package scriptella.expression;
17
18 import scriptella.spi.ParametersCallback;
19
20 import java.util.regex.Matcher JavaDoc;
21 import java.util.regex.Pattern JavaDoc;
22
23
24 /**
25  * Substitutes properties(or expressions) in strings.
26  * <p>$ symbol indicate property or expression to evaluate and substitute.
27  * <p>The following properties/expression syntax is used:
28  * <h3>Property reference</h3>
29  * References named property.
30  * <br>Examples:
31  * <pre><code>
32  * $foo
33  * </code></pre>
34  * <h3>Expression</h3>.
35  * Expression is wrapped by braces and evaluated by {@link Expression} engine.
36  * Examples:
37  * <pre><code>
38  * ${name+' '+surname} etc.
39  * </code></pre>
40  * </ul>
41  * <p>This class is not thread safe
42  *
43  * @author Fyodor Kupolov
44  * @version 1.0
45  */

46 public class PropertiesSubstitutor {
47     /**
48      * Simple property patterns, e.g. $property
49      */

50     public static final Pattern JavaDoc PROP_PTR = Pattern.compile("([a-zA-Z_0-9\\.]+)");
51
52     /**
53      * Expression pattern, e.g. ${property} etc.
54      */

55     public static final Pattern JavaDoc EXPR_PTR = Pattern.compile("\\{([^\\}]+)\\}");
56
57     final Matcher JavaDoc m1 = PROP_PTR.matcher("");
58     final Matcher JavaDoc m2 = EXPR_PTR.matcher("");
59
60     /**
61      * Creates a properties substitutor.
62      * <p>This constructor is used for performance critical places where multiple instantiation
63      * via {@link #PropertiesSubstitutor(scriptella.spi.ParametersCallback)} is expensive.
64      * <p><b>Note:</b> {@link #setParameters(scriptella.spi.ParametersCallback)} must be called before
65      * {@link #substitute(String)}.
66      */

67     public PropertiesSubstitutor() {
68     }
69
70     /**
71      * Creates a properties substitutor.
72      *
73      * @param parameters parameters callback to use for substitution.
74      */

75     public PropertiesSubstitutor(ParametersCallback parameters) {
76         this.parameters = parameters;
77     }
78
79     private ParametersCallback parameters;
80
81     /**
82      * Substitutes properties/expressions in s and returns the result string.
83      * <p>If result of evaluation is null or the property being substitued doesn't have value in callback - the whole
84      * expressions is copied into result string as is.
85      *
86      * @param s string to substitute. Null strings allowed.
87      * @return substituted string.
88      */

89     public String JavaDoc substitute(final String JavaDoc s) {
90         if (s == null) {
91             return null;
92         }
93         if (parameters == null) {
94             throw new IllegalStateException JavaDoc("setParameters must be called before calling substitute");
95         }
96
97         final int len = s.length() - 1; //Last character is not checked - optimization
98
if (len <= 0 || s.indexOf('$') < 0) { //skip empty strings, single characters or other strings without $ char
99
return s;
100         }
101         StringBuilder JavaDoc res = null;
102         final char[] sChars = s.toCharArray();
103         int lastPos = 0;
104         m1.reset(s);
105         m2.reset(s);
106         for (int i = 0; i < len; i++) {
107             if (sChars[i]=='$') {
108                 //Start of expression
109
Matcher JavaDoc m;
110                 if (m1.find(i + 1) && m1.start() == i + 1) {
111                     m = m1;
112                 } else if (m2.find(i + 1) && m2.start() == i + 1) {
113                     m = m2;
114                 } else { //not an expression
115
m = null;
116                 }
117                 if (m != null) {
118                     if (res == null) {
119                         res = new StringBuilder JavaDoc(s.length());
120                     }
121                     if (i > lastPos) { //if we have unflushed character
122
res.append(sChars, lastPos, i - lastPos);
123                     }
124                     final String JavaDoc name = m.group(1);
125                     String JavaDoc v;
126
127                     if (m == m1) {
128                         v = toString(parameters.getParameter(name));
129                     } else {
130                         v = toString(Expression.compile(name).evaluate(parameters));
131                     }
132
133                     lastPos = m.end();
134                     if (v != null) {
135                         res.append(v);
136                     } else { //appends the original string
137
res.append(sChars, i, lastPos - i);
138                     }
139
140                 }
141             }
142         }
143         if (res == null) {
144             return s;
145         }
146         if (lastPos <= len) {
147             res.append(sChars, lastPos, s.length() - lastPos);
148         }
149
150
151         return res.toString();
152     }
153
154     /**
155      * @return parameter callback used for substitution.
156      */

157     public ParametersCallback getParameters() {
158         return parameters;
159     }
160
161     /**
162      * Sets parameters callback used for substitution.
163      *
164      * @param parameters not null parameters callback.
165      */

166     public void setParameters(ParametersCallback parameters) {
167         this.parameters = parameters;
168     }
169
170     /**
171      * Converts specified object to string.
172      * <p>Subclasses may provide custom conversion strategy here.
173      *
174      * @param o object to convert to String.
175      * @return string representation of object.
176      */

177     protected String JavaDoc toString(final Object JavaDoc o) {
178         return o == null ? null : o.toString();
179     }
180
181 }
182
Popular Tags