package com.revolsys.spring; import java.io.Serializable; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.springframework.util.Assert; import com.revolsys.logging.Logs; import com.revolsys.util.Property; public class StringTemplate implements Serializable { /** * Static inner class to parse URI template strings into a matching regular * expression. */ private static class Parser { private final StringBuilder patternBuilder = new StringBuilder(); private final List<String> variableNames = new LinkedList<>(); private Parser(final String uriTemplate) { Assert.hasText(uriTemplate, "'template' must not be null"); final Matcher m = NAMES_PATTERN.matcher(uriTemplate); int end = 0; while (m.find()) { this.patternBuilder.append(quote(uriTemplate, end, m.start())); this.patternBuilder.append(VALUE_REGEX); this.variableNames.add(m.group(1)); end = m.end(); } this.patternBuilder.append(quote(uriTemplate, end, uriTemplate.length())); final int lastIdx = this.patternBuilder.length() - 1; if (lastIdx >= 0 && this.patternBuilder.charAt(lastIdx) == '/') { this.patternBuilder.deleteCharAt(lastIdx); } } private List<String> getVariableNames() { return Collections.unmodifiableList(this.variableNames); } private String quote(final String fullPath, final int start, final int end) { if (start == end) { return ""; } return Pattern.quote(fullPath.substring(start, end)); } } private static final Pattern NAMES_PATTERN = Pattern.compile("\\{([^/]+?)\\}"); private static final long serialVersionUID = 1L; private static final String VALUE_REGEX = "(.*)"; private final String template; private List<String> variableNames; public StringTemplate(final String template) { this.template = template; if (Property.hasValue(template)) { try { final Parser parser = new Parser(template); this.variableNames = parser.getVariableNames(); } catch (final Throwable e) { Logs.error(this, "Invalid Template:" + template, e); } } } public String expand(Map<String, ?> uriVariables) { if (this.variableNames == null) { return this.template; } else { if (uriVariables == null) { uriVariables = Collections.emptyMap(); } final Object[] values = new Object[this.variableNames.size()]; if (uriVariables != null) { for (int i = 0; i < this.variableNames.size(); i++) { final String name = this.variableNames.get(i); if (uriVariables.containsKey(name)) { values[i] = uriVariables.get(name); } } } return expand(values); } } private String expand(final Object... uriVariableValues) { final Matcher matcher = NAMES_PATTERN.matcher(this.template); final StringBuffer buffer = new StringBuffer(); int i = 0; while (matcher.find()) { final Object uriVariable = uriVariableValues[i++]; String replacement; if (uriVariable == null) { replacement = Matcher.quoteReplacement("null"); } else { replacement = Matcher.quoteReplacement(uriVariable.toString()); } matcher.appendReplacement(buffer, replacement); } matcher.appendTail(buffer); return buffer.toString(); } public List<String> getVariableNames() { return this.variableNames; } @Override public String toString() { return this.template; } }