@@ -138,136 +138,144 @@ private String interpolate( String input, RecursionInterceptor recursionIntercep
138138 // return empty String to prevent NPE too
139139 return "" ;
140140 }
141- StringBuilder result = new StringBuilder ( input .length () * 2 );
142141
143142 int startIdx ;
144143 int endIdx = -1 ;
145- while ( ( startIdx = input .indexOf ( startExpr , endIdx + 1 ) ) > -1 )
144+ if ( ( startIdx = input .indexOf ( startExpr , endIdx + 1 ) ) > -1 )
146145 {
147- result .append ( input , endIdx + 1 , startIdx );
148-
149- endIdx = input .indexOf ( endExpr , startIdx + 1 );
150- if ( endIdx < 0 )
151- {
152- break ;
153- }
154-
155- final String wholeExpr = input .substring ( startIdx , endIdx + endExpr .length () );
156- String realExpr = wholeExpr .substring ( startExpr .length (), wholeExpr .length () - endExpr .length () );
157-
158- if ( startIdx >= 0 && escapeString != null && escapeString .length () > 0 )
159- {
160- int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString .length ();
161- if ( startEscapeIdx >= 0 )
146+ StringBuilder result = new StringBuilder ( input .length () * 2 );
147+ do
162148 {
163- String escape = input .substring ( startEscapeIdx , startIdx );
164- if ( escapeString .equals ( escape ) )
165- {
166- result .append ( wholeExpr );
167- result .replace ( startEscapeIdx , startEscapeIdx + escapeString .length (), "" );
168- continue ;
169- }
170- }
171- }
149+ result .append ( input , endIdx + 1 , startIdx );
172150
173- boolean resolved = false ;
174- if ( !unresolvable .contains ( wholeExpr ) )
175- {
176- if ( realExpr .startsWith ( "." ) )
151+ endIdx = input .indexOf ( endExpr , startIdx + 1 );
152+ if ( endIdx < 0 )
177153 {
178- realExpr = realExpr . substring ( 1 ) ;
154+ break ;
179155 }
180156
181- if ( recursionInterceptor .hasRecursiveExpression ( realExpr ) )
182- {
183- throw new InterpolationCycleException ( recursionInterceptor , realExpr , wholeExpr );
184- }
157+ final String wholeExpr = input .substring ( startIdx , endIdx + endExpr .length () );
158+ String realExpr = wholeExpr .substring ( startExpr .length (), wholeExpr .length () - endExpr .length () );
185159
186- recursionInterceptor .expressionResolutionStarted ( realExpr );
187- try
160+ if ( startIdx >= 0 && escapeString != null && escapeString .length () > 0 )
188161 {
189- Object value = existingAnswers .get ( realExpr );
190- Object bestAnswer = null ;
191-
192- for ( ValueSource valueSource : valueSources )
162+ int startEscapeIdx = startIdx == 0 ? 0 : startIdx - escapeString .length ();
163+ if ( startEscapeIdx >= 0 )
193164 {
194- if ( value != null )
165+ String escape = input .substring ( startEscapeIdx , startIdx );
166+ if ( escapeString .equals ( escape ) )
195167 {
196- break ;
168+ result .append (wholeExpr );
169+ result .replace (startEscapeIdx , startEscapeIdx + escapeString .length (), "" );
170+ continue ;
197171 }
198- value = valueSource .getValue ( realExpr );
172+ }
173+ }
199174
200- if ( value != null && value .toString ().contains ( wholeExpr ) )
201- {
202- bestAnswer = value ;
203- value = null ;
204- }
175+ boolean resolved = false ;
176+ if ( !unresolvable .contains ( wholeExpr ) )
177+ {
178+ if ( realExpr .startsWith ( "." ) )
179+ {
180+ realExpr = realExpr .substring (1 );
205181 }
206182
207- // this is the simplest recursion check to catch exact recursion
208- // (non synonym), and avoid the extra effort of more string
209- // searching.
210- if ( value == null && bestAnswer != null )
183+ if ( recursionInterceptor .hasRecursiveExpression ( realExpr ) )
211184 {
212185 throw new InterpolationCycleException ( recursionInterceptor , realExpr , wholeExpr );
213186 }
214187
215- if ( value != null )
188+ recursionInterceptor .expressionResolutionStarted ( realExpr );
189+ try
216190 {
217- value = interpolate ( String .valueOf ( value ), recursionInterceptor , unresolvable );
191+ Object value = existingAnswers .get ( realExpr );
192+ Object bestAnswer = null ;
193+
194+ for ( ValueSource valueSource : valueSources )
195+ {
196+ if ( value != null )
197+ {
198+ break ;
199+ }
200+ value = valueSource .getValue ( realExpr );
201+
202+ if ( value != null && value .toString ().contains ( wholeExpr ) )
203+ {
204+ bestAnswer = value ;
205+ value = null ;
206+ }
207+ }
218208
219- if ( postProcessors != null && !postProcessors .isEmpty () )
209+ // this is the simplest recursion check to catch exact recursion
210+ // (non synonym), and avoid the extra effort of more string
211+ // searching.
212+ if ( value == null && bestAnswer != null )
220213 {
221- for ( InterpolationPostProcessor postProcessor : postProcessors )
214+ throw new InterpolationCycleException ( recursionInterceptor , realExpr , wholeExpr );
215+ }
216+
217+ if ( value != null )
218+ {
219+ value = interpolate ( String .valueOf (value ), recursionInterceptor , unresolvable );
220+
221+ if ( postProcessors != null && !postProcessors .isEmpty () )
222222 {
223- Object newVal = postProcessor .execute ( realExpr , value );
224- if ( newVal != null )
223+ for ( InterpolationPostProcessor postProcessor : postProcessors )
225224 {
226- value = newVal ;
227- break ;
225+ Object newVal = postProcessor .execute ( realExpr , value );
226+ if ( newVal != null )
227+ {
228+ value = newVal ;
229+ break ;
230+ }
228231 }
229232 }
230- }
231233
232- // could use:
233- // result = matcher.replaceFirst( stringValue );
234- // but this could result in multiple lookups of stringValue, and replaceAll is not correct
235- // behaviour
236- result .append ( String .valueOf ( value ) );
237- resolved = true ;
234+ // could use:
235+ // result = matcher.replaceFirst( stringValue );
236+ // but this could result in multiple lookups of stringValue, and replaceAll is not correct
237+ // behaviour
238+ result .append ( String .valueOf ( value ) );
239+ resolved = true ;
240+ }
241+ else
242+ {
243+ unresolvable .add ( wholeExpr );
244+ }
238245 }
239- else
246+ finally
240247 {
241- unresolvable . add ( wholeExpr );
248+ recursionInterceptor . expressionResolutionFinished ( realExpr );
242249 }
243250 }
244- finally
251+
252+ if (!resolved )
245253 {
246- recursionInterceptor .expressionResolutionFinished ( realExpr );
254+ result .append ( wholeExpr );
255+ }
256+
257+ if ( endIdx > -1 )
258+ {
259+ endIdx += endExpr .length () - 1 ;
247260 }
248261 }
262+ while ( ( startIdx = input .indexOf ( startExpr , endIdx + 1 ) ) > -1 );
249263
250- if ( ! resolved )
264+ if ( endIdx == - 1 && startIdx > - 1 )
251265 {
252- result .append ( wholeExpr );
266+ result .append ( input , startIdx , input . length () );
253267 }
254-
255- if ( endIdx > -1 )
268+ else if ( endIdx < input .length () )
256269 {
257- endIdx += endExpr .length () - 1 ;
270+ result . append ( input , endIdx + 1 , input .length () ) ;
258271 }
259- }
260272
261- if ( endIdx == -1 && startIdx > -1 )
262- {
263- result .append ( input , startIdx , input .length ());
273+ return result .toString ();
264274 }
265- else if ( endIdx < input . length () )
275+ else
266276 {
267- result . append ( input , endIdx + 1 , input . length () ) ;
277+ return input ;
268278 }
269-
270- return result .toString ();
271279 }
272280
273281 /**
0 commit comments