/* * JFugue, an Application Programming Interface (API) for Music Programming * http://www.jfugue.org * * Copyright (C) 2003-2014 David Koelle * * 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.staccato; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; public class ReplacementMapPreprocessor implements Preprocessor { private static ReplacementMapPreprocessor instance; private ReplacementMapPreprocessor() { } public static ReplacementMapPreprocessor getInstance() { if (instance == null) { instance = new ReplacementMapPreprocessor(); } return instance; } private static Pattern replacementPatternWithBrackets = Pattern.compile("<\\S+>"); private static Pattern replacementPatternWithoutBrackets = Pattern.compile("\\S+"); private Map<String, String> map; private boolean requiresAngleBrackets = true; private boolean caseSensitive = false; private int iterations = 1; public ReplacementMapPreprocessor setRequireAngleBrackets(boolean require) { this.requiresAngleBrackets = require; return this; } public boolean requiresAngleBrackets() { return this.requiresAngleBrackets; } /** * NOTE: This might seem a little backwards, but if your ReplacementMap is not case sensitive, then you need * to use only upper-case letters as keys in your map! * */ public ReplacementMapPreprocessor setCaseSensitive(boolean caseSensitive) { this.caseSensitive = caseSensitive; return this; } public boolean isCaseSensitive() { return this.caseSensitive; } public ReplacementMapPreprocessor setReplacementMap(Map<String, String> map) { this.map = map; return this; } public ReplacementMapPreprocessor setIterations(int iterations) { this.iterations = iterations; return this; } public int getIterations() { return this.iterations; } private Pattern getReplacementPattern() { return requiresAngleBrackets() ? replacementPatternWithBrackets : replacementPatternWithoutBrackets; } @Override public String preprocess(String s, StaccatoParserContext context) { String iteratingString = s; for (int i=0; i < iterations; i++) { StringBuilder buddy = new StringBuilder(); int posPrev = 0; Matcher m = getReplacementPattern().matcher(iteratingString); while (m.find()) { String foundKey = requiresAngleBrackets() ? m.group().substring(1, m.group().length()-1) : m.group(); buddy.append(iteratingString.substring(posPrev, m.start())); String lookupKey = isCaseSensitive() ? foundKey : foundKey.toUpperCase(); String replacementValue = map.get(lookupKey); if (replacementValue != null) { buddy.append(map.get(lookupKey)); } else { buddy.append(foundKey); // If the key doesn't have a value, just put the key back - it might be intended for another parser or purpose } posPrev = m.end(); } buddy.append(iteratingString.substring(posPrev, iteratingString.length())); iteratingString = buddy.toString(); } return iteratingString; } }