/*******************************************************************************
* Copyright (c) 2004, 2005
* Thomas Hallgren, Kenneth Olwing, Mitch Sonies
* Pontus Rydin, Nils Unden, Peer Torngren
* The code, documentation and other materials contained herein have been
* licensed under the Eclipse Public License - v 1.0 by the individual
* copyright holders listed above, as Initial Contributors under such license.
* The text of such license is available at www.eclipse.org.
*******************************************************************************/
package org.eclipse.buckminster.core.common.model;
import java.util.ArrayList;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.buckminster.sax.AbstractSaxableElement;
import org.eclipse.buckminster.sax.Utils;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
/**
* The Replace class will perform a regular expression based match and replace
* on its source. The pattern can be quoted in order to make the replace
* function as a normal (non expression based) replace.
*
* @author Thomas Hallgren
*/
public class Replace extends ValueHolderFilter {
public static final class Match extends AbstractSaxableElement {
private final Pattern pattern;
private final String patternString;
private final String replacement;
private final boolean quotePattern;
/**
* Create a Replace.Match that will replace every subsequence of the
* value provided by a <code>valueProvider</code> that matches the
* <code>pattern</code> with the given <code>replacement</code> string.
*
* @param pattern
* The pattern that defines the replacement
* @param replacement
* The replacement string
* @param quotePattern
* Set to true if the pattern should be quoted.
* @see java.util.regex.Matcher#replaceAll(String)
* @see java.util.regex.Pattern#quote(String)
*/
public Match(String pattern, String replacement, boolean quotePattern) {
this.patternString = pattern;
this.quotePattern = quotePattern;
this.replacement = replacement;
if (quotePattern)
pattern = Pattern.quote(pattern);
this.pattern = Pattern.compile(pattern);
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Match))
return false;
return quotePattern == ((Match) o).quotePattern && patternString.equals(((Match) o).patternString)
&& replacement.equals(((Match) o).replacement);
}
@Override
public String getDefaultTag() {
return MATCH_TAG;
}
@Override
public int hashCode() {
int hc = patternString.hashCode();
hc = 37 * hc + replacement.hashCode();
hc = 37 * hc + (quotePattern ? 17 : 0);
return hc;
}
@Override
protected void addAttributes(AttributesImpl attrs) throws SAXException {
Utils.addAttribute(attrs, ATTR_PATTERN, patternString);
Utils.addAttribute(attrs, ATTR_REPLACEMENT, replacement);
if (quotePattern)
Utils.addAttribute(attrs, ATTR_QUOTE_PATTERN, "true"); //$NON-NLS-1$
}
String match(String resolved) {
Matcher matcher = pattern.matcher(resolved);
if (matcher.find()) {
StringBuffer sb = new StringBuffer();
do {
matcher.appendReplacement(sb, replacement);
} while (matcher.find());
matcher.appendTail(sb);
return sb.toString();
}
return null;
}
}
public static final String TAG = "replace"; //$NON-NLS-1$
public static final String MATCH_TAG = "match"; //$NON-NLS-1$
public static final String ATTR_PATTERN = "pattern"; //$NON-NLS-1$
public static final String ATTR_REPLACEMENT = "replacement"; //$NON-NLS-1$
public static final String ATTR_QUOTE_PATTERN = "quotePattern"; //$NON-NLS-1$
private final ArrayList<Match> matchers = new ArrayList<Match>();
public void addMatch(Match match) {
matchers.add(match);
}
@Override
public String checkedGetValue(Map<String, ? extends Object> props, int recursionGuard) {
String resolved = this.checkedGetSourceValue(props, recursionGuard);
return (resolved == null || NO_VALUE.equals(resolved)) ? NO_VALUE : replace(resolved);
}
@Override
public boolean equals(Object o) {
return super.equals(o) && matchers.equals(((Replace) o).matchers);
}
@Override
public String getDefaultTag() {
return TAG;
}
@Override
public int hashCode() {
int hc = super.hashCode();
hc = 37 * hc + matchers.hashCode();
return hc;
}
public String replace(String value) {
for (Match match : matchers) {
String result = match.match(value);
if (result != null)
return result;
}
return value;
}
@Override
protected void addAttributes(AttributesImpl attrs) throws SAXException {
// If we have exactly one, then use attributes instead of
// subelements
//
if (matchers.size() == 1)
matchers.get(0).addAttributes(attrs);
}
@Override
protected void emitElements(ContentHandler handler, String namespace, String prefix) throws SAXException {
super.emitElements(handler, namespace, prefix);
int top = matchers.size();
// If there's only one it will be added as an attribute.
//
if (top > 1) {
for (int idx = 0; idx < top; ++idx) {
Match match = matchers.get(idx);
match.toSax(handler, namespace, prefix, match.getDefaultTag());
}
}
}
}