/**
* Copyright (C) 2014 - present by OpenGamma Inc. and the OpenGamma group of companies
*
* Please see distribution for license.
*/
package com.opengamma.sesame.function.scenarios.marketdata;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.commons.lang.StringUtils;
import com.google.common.collect.Sets;
import com.opengamma.id.ExternalId;
import com.opengamma.id.ExternalIdBundle;
import com.opengamma.id.ExternalScheme;
import com.opengamma.util.ArgumentChecker;
import com.opengamma.util.RegexUtils;
/**
* Tests if an {@link ExternalIdBundle} representing a piece of market data matches a rule.
* Used for deciding whether the market data should be affected by a scenario.
* TODO this lot might have to become Joda beans
*/
public abstract class MarketDataMatcher {
/**
* Returns true if any ID in the ID bundle matches this matcher's rule.
*
* @param id an ID bundle
* @return true if any ID in the bundle matches this matcher's rule
*/
public abstract boolean matches(ExternalIdBundle id);
/**
* Creates a matcher that looks for an exact match with an ID.
*
* @param scheme the scheme of the IDs to match
* @param value1 an ID value to match
* @param values the other ID values to match
* @return a matcher that matches if the bundle contains any of the IDs
*/
public static MarketDataMatcher idEquals(String scheme, String value1, String... values) {
ArgumentChecker.notEmpty(scheme, "scheme");
ArgumentChecker.notEmpty(value1, "value1");
Set<ExternalId> ids = new HashSet<>(values.length + 1);
ids.add(ExternalId.of(scheme, value1));
for (String value : values) {
if (StringUtils.isEmpty(value)) {
throw new IllegalArgumentException("External ID values must not be empty");
}
ids.add(ExternalId.of(scheme, value));
}
return new Equals(ids);
}
/**
* Creates a matcher that looks for IDs whose values match a wildcard pattern.
* The special characters recognized in the pattern are ? (match any character), * (match any number of characters)
* and % (same as *). The other characters in the pattern string are escaped before the pattern is created
* so it can safely contain regular expression characters. Escaping is not supported in the pattern string,
* i.e. there's no way to match any of the special characters themselves.
*
* @param scheme the ID scheme to match against
* @param glob the pattern to match values against
* @return a matcher that matches if the ID bundle contains an ID that matches the pattern
*/
public static MarketDataMatcher idLike(String scheme, String glob) {
return new Like(scheme, glob);
}
private static class Equals extends MarketDataMatcher {
private final Set<ExternalId> _ids;
private Equals(Set<ExternalId> ids) {
_ids = ids;
}
@Override
public boolean matches(ExternalIdBundle id) {
Set<ExternalId> intersection = Sets.intersection(id.getExternalIds(), _ids);
return !intersection.isEmpty();
}
}
private static class Like extends MarketDataMatcher {
private final ExternalScheme _scheme;
private final Pattern _pattern;
private Like(String scheme, String glob) {
_scheme = ExternalScheme.of(scheme);
_pattern = RegexUtils.globToPattern(glob);
}
@Override
public boolean matches(ExternalIdBundle id) {
for (ExternalId externalId : id.getExternalIds()) {
if (_scheme.equals(externalId.getScheme()) && _pattern.matcher(externalId.getValue()).matches()) {
return true;
}
}
return false;
}
}
}