/*
* Copyright 2016 Martin Kouba
*
* 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 org.trimou.util;
import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.trimou.annotations.Internal;
import org.trimou.exception.MustacheException;
import org.trimou.exception.MustacheProblem;
/**
* Escapes the characters using a map of replacements.
*
* @author Martin Kouba
*/
@Internal
public class Escaper {
private final Map<Character, String> replacements;
/**
*
* @param replacements
*/
private Escaper(Map<Character, String> replacements) {
this.replacements = replacements.isEmpty() ? Collections.emptyMap()
: new HashMap<>(replacements);
}
/**
*
* @param value
* @return an escaped value
*/
public String escape(String value) {
Checker.checkArgumentNotNull(value);
if (value.isEmpty()) {
return value;
}
for (int i = 0; i < value.length(); i++) {
String replacement = replacements.get(value.charAt(i));
if (replacement != null) {
StringBuilder result = new StringBuilder();
result.append(value.substring(0, i));
result.append(replacement);
try {
escapeNext(value, i, result);
} catch (IOException e) {
throw new MustacheException(MustacheProblem.RENDER_IO_ERROR,
e);
}
return result.toString();
}
}
return value;
}
/**
*
* @param value
* @param appendable
* @throws IOException
*/
public void escape(String value, Appendable appendable) throws IOException {
Checker.checkArgumentsNotNull(value, appendable);
if (value.isEmpty()) {
return;
}
for (int i = 0; i < value.length(); i++) {
String replacement = replacements.get(value.charAt(i));
if (replacement != null) {
appendable.append(value.substring(0, i));
appendable.append(replacement);
escapeNext(value, i, appendable);
return;
}
}
appendable.append(value);
}
private void escapeNext(String value, int index, Appendable appendable)
throws IOException {
int length = value.length();
while (++index < length) {
char c = value.charAt(index);
String replacement = replacements.get(c);
if (replacement != null) {
appendable.append(replacement);
} else {
appendable.append(c);
}
}
}
/**
*
* @return a new builder instance
*/
public static Builder builder() {
return new Builder();
}
public static class Builder {
private final Map<Character, String> replacements;
private Builder() {
this.replacements = new HashMap<>();
}
public Builder add(char c, String replacement) {
replacements.put(c, replacement);
return this;
}
public Escaper build() {
return new Escaper(replacements);
}
}
}