![JAR search and dependency download from the Maven repository](/logo.png)
main.java.de.k3b.util.StringTemplateEngine Maven / Gradle / Ivy
/*
* Copyright (c) 2015-2016 by k3b.
*
* This file is part of k3b-geoHelper library.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.k3b.util;
import java.util.ListIterator;
import java.util.Stack;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Engine that replaces all occurences of ${name} with corresponding values from callback defined in {@link IValueResolver}.
*
*
* new StringTemplate(valueResolver).format("hello ${first.name}!")
*
*
* will produce "hello world!" if valueResolver.get("first","name") returns "world"
*
* Created by k3b on 01.04.2015.
*/
public class StringTemplateEngine {
/**
* callback for {@link StringTemplateEngine} to resolve the values for names.
*
*
* new StringTemplate(valueResolver).format("hello ${first.name}!")
*
*
* will produce "hello world!" if valueResolver.get("first","name") returns "world"
*
* Created by k3b on 01.04.2015.
*/
public interface IValueResolver {
String get(String className, String propertyName, String templateParameter);
}
/** used to convert ${name} to corresponding value */
protected IValueResolver valueResolver = null;
/** if {@link StringTemplateEngine#sedDebugEnabled(boolean)} is set to true.
* this stack will contain debugbessages as callstack */
protected Stack debugStack = null; // new Stack();
/** contain last processing error or null if there is no (new) error */
private StringBuilder errors = null;
// matches ${a.b}
private static final Pattern pattern = Pattern.compile("\\$\\{([^ \\.\\}]+)\\.([^ }]+)\\}");
/** creates the engine with {@link IValueResolver}. */
public StringTemplateEngine(IValueResolver valueResolver) {
this.valueResolver = valueResolver;
}
/** return strue, if value contains tempate parameters */
protected boolean hasParameters(String value) {
return ((value != null) && (value.contains("${")));
}
/** translates tmeplate to string. */
public String format(String template) {
if (template == null) {
return null;
}
final StringBuffer buffer = new StringBuffer();
final Matcher match = pattern.matcher(template);
while (match.find()) {
final String templateParameter = match.group(0);
final String className = match.group(1);
final String propertyName = match.group(2);
debugPush(templateParameter);
String resolverResult = valueResolver.get(className, propertyName, templateParameter);
resolverResult = onResolverResult(templateParameter, resolverResult);
if (resolverResult != null) {
match.appendReplacement(buffer, resolverResult);
} else {
match.appendReplacement(buffer, "");
}
debugPop();
}
match.appendTail(buffer);
return buffer.toString();
}
/** called for every parameter match. Is used to collect debug infos. */
protected String onResolverResult(String templateParameter, String resolverResult) {
// log error if resolve failed
if ((errors != null) && (resolverResult == null)) {
this.errors
.append(templateParameter)
.append(" not found in ")
.append(getDebugStackTrace())
.append("\n");
}
return resolverResult;
}
/** en- or disables debugging mode. */
public StringTemplateEngine sedDebugEnabled(boolean enabled) {
if (enabled) {
this.debugStack = new Stack();
errors = new StringBuilder();
} else {
this.debugStack = null;
errors = null;
}
return this;
}
/** debug implementation: push to stack. */
protected void debugPush(String parameter) {
if (debugStack != null) {
if (debugStack.contains(parameter)) {
final String errorMessage = this.getClass().toString() +
".format() : " + parameter +
" - endless recursion detected " + getDebugStackTrace();
if (errors != null) {
this.errors
.append(errorMessage)
.append("\n");
}
throw new StackOverflowError(errorMessage);
}
debugStack.push(parameter);
}
}
/** debug implementation: pop from stack: forget last {@link #debugPush(String)}. */
protected void debugPop() {
if (debugStack != null) {
debugStack.pop();
}
}
/** show debug stacktrace, if {@link StringTemplateEngine#sedDebugEnabled(boolean)} is set to true. */
protected String getDebugStackTrace() {
StringBuilder result = new StringBuilder();
if (debugStack != null) {
ListIterator iter = debugStack.listIterator();
if (iter.hasNext()) {
result.append(" > ").append(iter.next());
}
}
return result.toString();
}
/** get last error message. Error is cleared after reading message. */
public String getErrors() {
if (errors == null) return null;
final String result = errors.toString();
errors.setLength(0);
return result;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy