blob: 0e396448c469028d18b738400a420ff9c3a05bf5 [file] [log] [blame]
// Copyright (C) 2009 The Android Open Source Project
//
// 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 com.google.gerrit.server;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/** Performs replacements on strings such as <code>Hello ${user}</code>. */
public class ParamertizedString {
/** Obtain a string which has no parameters and always produces the value. */
public static ParamertizedString asis(final String constant) {
return new ParamertizedString(new Constant(constant));
}
private final String pattern;
private final String rawPattern;
private final List<Format> patternOps;
private final List<String> patternArgs;
private ParamertizedString(final Constant c) {
pattern = c.text;
rawPattern = c.text;
patternOps = Collections.<Format> singletonList(c);
patternArgs = Collections.emptyList();
}
public ParamertizedString(final String pattern) {
final StringBuilder raw = new StringBuilder();
final List<String> args = new ArrayList<String>(4);
final List<Format> ops = new ArrayList<Format>(4);
int i = 0;
while (i < pattern.length()) {
final int b = pattern.indexOf("${", i);
if (b < 0) {
break;
}
final int e = pattern.indexOf("}", b + 2);
if (e < 0) {
break;
}
raw.append(pattern.substring(i, b));
ops.add(new Constant(pattern.substring(i, b)));
raw.append("{" + args.size() + "}");
args.add(pattern.substring(b + 2, e));
ops.add(new Parameter(pattern.substring(b + 2, e)));
i = e + 1;
}
if (i < pattern.length()) {
raw.append(pattern.substring(i));
ops.add(new Constant(pattern.substring(i)));
}
this.pattern = pattern;
this.rawPattern = raw.toString();
this.patternOps = Collections.unmodifiableList(ops);
this.patternArgs = Collections.unmodifiableList(args);
}
/** Get the original pattern given to the constructor. */
public String getPattern() {
return pattern;
}
/** Get the pattern with variables replaced with {0}, {1}, ... */
public String getRawPattern() {
return rawPattern;
}
/** Get the list of parameter names, ordered by appearance in the pattern. */
public List<String> getParameterNames() {
return patternArgs;
}
/** Convert a map of parameters into a value array for binding. */
public String[] bind(final Map<String, String> params) {
final String[] r = new String[patternArgs.size()];
for (int i = 0; i < r.length; i++) {
r[i] = params.get(patternArgs.get(i));
if (r[i] == null) {
r[i] = "";
}
}
return r;
}
/** Format this string by performing the variable replacements. */
public String replace(final Map<String, String> params) {
final StringBuilder r = new StringBuilder();
for (final Format f : patternOps) {
f.format(r, params);
}
return r.toString();
}
public Builder replace(final String name, final String value) {
return new Builder().replace(name, value);
}
public Builder replace() {
return new Builder();
}
@Override
public String toString() {
return getPattern();
}
public final class Builder {
private final Map<String, String> params = new HashMap<String, String>();
public Builder replace(final String name, final String value) {
params.put(name, value);
return this;
}
@Override
public String toString() {
return ParamertizedString.this.replace(params);
}
}
private static abstract class Format {
abstract void format(StringBuilder b, Map<String, String> p);
}
private static class Constant extends Format {
private final String text;
Constant(final String text) {
this.text = text;
}
@Override
void format(StringBuilder b, Map<String, String> p) {
b.append(text);
}
}
private static class Parameter extends Format {
private final String name;
Parameter(final String name) {
this.name = name;
}
@Override
void format(StringBuilder b, Map<String, String> p) {
String v = p.get(name);
if (v != null) {
b.append(v);
}
}
}
}