下面列出了org.apache.logging.log4j.core.config.plugins.PluginElement#org.apache.logging.log4j.core.util.KeyValuePair 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
private EcsLayout(Configuration config, String serviceName, String eventDataset, boolean includeMarkers, KeyValuePair[] additionalFields, boolean includeOrigin, boolean stackTraceAsArray) {
super(config, UTF_8, null, null);
this.serviceName = serviceName;
this.eventDataset = eventDataset;
this.includeMarkers = includeMarkers;
this.includeOrigin = includeOrigin;
this.stackTraceAsArray = stackTraceAsArray;
this.additionalFields = additionalFields;
fieldValuePatternFormatter = new PatternFormatter[additionalFields.length][];
for (int i = 0; i < additionalFields.length; i++) {
KeyValuePair additionalField = additionalFields[i];
if (additionalField.getValue().contains("%")) {
fieldValuePatternFormatter[i] = PatternLayout.createPatternParser(config)
.parse(additionalField.getValue())
.toArray(new PatternFormatter[0]);
}
}
}
private static ResolvableKeyValuePair[] prepareAdditionalFields(
final Configuration config, final KeyValuePair[] additionalFields) {
if (additionalFields == null || additionalFields.length == 0) {
// No fields set
return new ResolvableKeyValuePair[0];
}
// Convert to specific class which already determines whether values needs lookup during
// serialization
final ResolvableKeyValuePair[] resolvableFields =
new ResolvableKeyValuePair[additionalFields.length];
for (int i = 0; i < additionalFields.length; i++) {
final ResolvableKeyValuePair resolvable =
resolvableFields[i] = new ResolvableKeyValuePair(additionalFields[i]);
// Validate
if (config == null && resolvable.valueNeedsLookup) {
throw new IllegalArgumentException(
"configuration needs to be set when there are additional fields with variables");
}
}
return resolvableFields;
}
protected AbstractJacksonLayout(
final Configuration config,
final ObjectWriter objectWriter,
final Charset charset,
final boolean compact,
final boolean complete,
final boolean eventEol,
final Serializer headerSerializer,
final Serializer footerSerializer,
final boolean includeNullDelimiter,
final KeyValuePair[] additionalFields) {
super(config, charset, headerSerializer, footerSerializer);
this.objectWriter = objectWriter;
this.compact = compact;
this.complete = complete;
this.eol = compact && !eventEol ? COMPACT_EOL : DEFAULT_EOL;
this.includeNullDelimiter = includeNullDelimiter;
this.additionalFields = prepareAdditionalFields(config, additionalFields);
}
@Test
public void testAdditionalFields() throws Exception {
final AbstractJacksonLayout layout = YamlLayout.newBuilder()
.setLocationInfo(false)
.setProperties(false)
.setIncludeStacktrace(false)
.setAdditionalFields(new KeyValuePair[] {
new KeyValuePair("KEY1", "VALUE1"),
new KeyValuePair("KEY2", "${java:runtime}"), })
.setCharset(StandardCharsets.UTF_8)
.setConfiguration(ctx.getConfiguration())
.build();
final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
assertThat(str, containsString("KEY1: \"VALUE1\""));
assertThat(str, containsString("KEY2: \"" + new JavaLookup().getRuntime() + "\""));
}
@Test
public void testMutableLogEvent() throws Exception {
final AbstractJacksonLayout layout = YamlLayout.newBuilder()
.setLocationInfo(false)
.setProperties(false)
.setIncludeStacktrace(false)
.setAdditionalFields(new KeyValuePair[] {
new KeyValuePair("KEY1", "VALUE1"),
new KeyValuePair("KEY2", "${java:runtime}"), })
.setCharset(StandardCharsets.UTF_8)
.setConfiguration(ctx.getConfiguration())
.build();
Log4jLogEvent logEvent = LogEventFixtures.createLogEvent();
final MutableLogEvent mutableEvent = new MutableLogEvent();
mutableEvent.initFrom(logEvent);
final String strLogEvent = layout.toSerializable(logEvent);
final String strMutableEvent = layout.toSerializable(mutableEvent);
assertEquals(strMutableEvent, strLogEvent, strMutableEvent);
}
private static ResolvableKeyValuePair[] prepareAdditionalFields(final Configuration config,
final KeyValuePair[] additionalFields) {
if (additionalFields == null || additionalFields.length == 0) {
// No fields set
return new ResolvableKeyValuePair[0];
}
// Convert to specific class which already determines whether values needs lookup during serialization
final ResolvableKeyValuePair[] resolvableFields = new ResolvableKeyValuePair[additionalFields.length];
for (int i = 0; i < additionalFields.length; i++) {
final ResolvableKeyValuePair resolvable = resolvableFields[i] = new ResolvableKeyValuePair(additionalFields[i]);
// Validate
if (config == null && resolvable.valueNeedsLookup) {
throw new IllegalArgumentException(
"configuration needs to be set when there are additional fields with variables");
}
}
return resolvableFields;
}
private static ResolvableKeyValuePair[] prepareAdditionalFields(final Configuration config,
final KeyValuePair[] additionalFields) {
if (additionalFields == null || additionalFields.length == 0) {
// No fields set
return new ResolvableKeyValuePair[0];
}
// Convert to specific class which already determines whether values needs lookup during serialization
final ResolvableKeyValuePair[] resolvableFields = new ResolvableKeyValuePair[additionalFields.length];
for (int i = 0; i < additionalFields.length; i++) {
final ResolvableKeyValuePair resolvable = resolvableFields[i] = new ResolvableKeyValuePair(additionalFields[i]);
// Validate
if (config == null && resolvable.valueNeedsLookup) {
throw new IllegalArgumentException(
"configuration needs to be set when there are additional fields with variables");
}
}
return resolvableFields;
}
/**
* Creates a DynamicThresholdFilter.
* @param key The name of the key to compare.
* @param pairs An array of value and Level pairs.
* @param defaultThreshold The default Level.
* @param onMatch The action to perform if a match occurs.
* @param onMismatch The action to perform if no match occurs.
* @return The DynamicThresholdFilter.
*/
// TODO Consider refactoring to use AbstractFilter.AbstractFilterBuilder
@PluginFactory
public static DynamicThresholdFilter createFilter(
@PluginAttribute final String key,
@PluginElement final KeyValuePair[] pairs,
@PluginAttribute final Level defaultThreshold,
@PluginAttribute final Result onMatch,
@PluginAttribute final Result onMismatch) {
final Map<String, Level> map = new HashMap<>();
for (final KeyValuePair pair : pairs) {
map.put(pair.getKey(), Level.toLevel(pair.getValue()));
}
final Level level = defaultThreshold == null ? Level.ERROR : defaultThreshold;
return new DynamicThresholdFilter(key, map, level, onMatch, onMismatch);
}
private GelfLayout(final Configuration config, final String host, final KeyValuePair[] additionalFields,
final CompressionType compressionType, final int compressionThreshold, final boolean includeStacktrace,
final boolean includeThreadContext, final boolean includeNullDelimiter, final ListChecker listChecker,
final PatternLayout patternLayout) {
super(config, StandardCharsets.UTF_8, null, null);
this.host = host != null ? host : NetUtils.getLocalHostname();
this.additionalFields = additionalFields != null ? additionalFields : new KeyValuePair[0];
if (config == null) {
for (final KeyValuePair additionalField : this.additionalFields) {
if (valueNeedsLookup(additionalField.getValue())) {
throw new IllegalArgumentException("configuration needs to be set when there are additional fields with variables");
}
}
}
this.compressionType = compressionType;
this.compressionThreshold = compressionThreshold;
this.includeStacktrace = includeStacktrace;
this.includeThreadContext = includeThreadContext;
this.includeNullDelimiter = includeNullDelimiter;
if (includeNullDelimiter && compressionType != CompressionType.OFF) {
throw new IllegalArgumentException("null delimiter cannot be used with compression");
}
this.fieldWriter = new FieldWriter(listChecker);
this.layout = patternLayout;
}
@Test
public void testFilter() {
ThreadContext.put("userid", "testuser");
ThreadContext.put("organization", "apache");
final KeyValuePair[] pairs = new KeyValuePair[] {
new KeyValuePair("testuser", "DEBUG"),
new KeyValuePair("JohnDoe", "warn") };
final DynamicThresholdFilter filter = DynamicThresholdFilter.createFilter("userid", pairs, Level.ERROR, null,
null);
filter.start();
assertTrue(filter.isStarted());
assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.DEBUG, null, (Object) null, (Throwable) null));
assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, (Object) null, (Throwable) null));
ThreadContext.clearMap();
ThreadContext.put("userid", "JohnDoe");
ThreadContext.put("organization", "apache");
LogEvent event = Log4jLogEvent.newBuilder().setLevel(Level.DEBUG).setMessage(new SimpleMessage("Test")).build();
assertSame(Filter.Result.DENY, filter.filter(event));
event = Log4jLogEvent.newBuilder().setLevel(Level.ERROR).setMessage(new SimpleMessage("Test")).build();
assertSame(Filter.Result.NEUTRAL, filter.filter(event));
ThreadContext.clearMap();
}
@Test
public void testFilter() {
final KeyValuePair[] pairs = new KeyValuePair[] { new KeyValuePair("FromAccount", "211000"),
new KeyValuePair("ToAccount", "123456")};
MapFilter filter = MapFilter.createFilter(pairs, "and", null, null);
filter.start();
StringMapMessage msg = new StringMapMessage();
msg.put("ToAccount", "123456");
msg.put("FromAccount", "211000");
msg.put("Amount", "1000.00");
assertTrue(filter.isStarted());
assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.DEBUG, null, msg, null));
msg.put("ToAccount", "111111");
assertSame(Filter.Result.DENY, filter.filter(null, Level.ERROR, null, msg, null));
filter = MapFilter.createFilter(pairs, "or", null, null);
filter.start();
msg = new StringMapMessage();
msg.put("ToAccount", "123456");
msg.put("FromAccount", "211000");
msg.put("Amount", "1000.00");
assertTrue(filter.isStarted());
assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.DEBUG, null, msg, null));
msg.put("ToAccount", "111111");
assertSame(Filter.Result.NEUTRAL, filter.filter(null, Level.ERROR, null, msg, null));
}
@Test
public void testAdditionalFields() throws Exception {
final AbstractJacksonLayout layout = JsonLayout.newBuilder()
.setLocationInfo(false)
.setProperties(false)
.setComplete(false)
.setCompact(true)
.setEventEol(false)
.setIncludeStacktrace(false)
.setAdditionalFields(new KeyValuePair[] {
new KeyValuePair("KEY1", "VALUE1"),
new KeyValuePair("KEY2", "${java:runtime}"), })
.setCharset(StandardCharsets.UTF_8)
.setConfiguration(ctx.getConfiguration())
.build();
final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
assertTrue(str, str.contains("\"KEY1\":\"VALUE1\""));
assertTrue(str, str.contains("\"KEY2\":\"" + new JavaLookup().getRuntime() + "\""));
}
@Test
public void testMutableLogEvent() throws Exception {
final AbstractJacksonLayout layout = JsonLayout.newBuilder()
.setLocationInfo(false)
.setProperties(false)
.setComplete(false)
.setCompact(true)
.setEventEol(false)
.setIncludeStacktrace(false)
.setAdditionalFields(new KeyValuePair[] {
new KeyValuePair("KEY1", "VALUE1"),
new KeyValuePair("KEY2", "${java:runtime}"), })
.setCharset(StandardCharsets.UTF_8)
.setConfiguration(ctx.getConfiguration())
.build();
Log4jLogEvent logEvent = LogEventFixtures.createLogEvent();
final MutableLogEvent mutableEvent = new MutableLogEvent();
mutableEvent.initFrom(logEvent);
final String strLogEvent = layout.toSerializable(logEvent);
final String strMutableEvent = layout.toSerializable(mutableEvent);
assertEquals(strMutableEvent, strLogEvent, strMutableEvent);
}
private void serializeAdditionalFieldsAndMDC(LogEvent event, StringBuilder builder) {
final int length = additionalFields.length;
if (!event.getContextData().isEmpty() || length > 0) {
if (length > 0) {
final StrSubstitutor strSubstitutor = getConfiguration().getStrSubstitutor();
for (int i = 0; i < length; i++) {
KeyValuePair additionalField = additionalFields[i];
PatternFormatter[] formatters = fieldValuePatternFormatter[i];
CharSequence value = null;
if (formatters != null) {
StringBuilder buffer = EcsJsonSerializer.getMessageStringBuilder();
formatPattern(event, formatters, buffer);
if (buffer.length() > 0) {
value = buffer;
}
} else if (valueNeedsLookup(additionalField.getValue())) {
StringBuilder lookupValue = EcsJsonSerializer.getMessageStringBuilder();
lookupValue.append(additionalField.getValue());
if (strSubstitutor.replaceIn(event, lookupValue)) {
value = lookupValue;
}
} else {
value = additionalField.getValue();
}
if (value != null) {
builder.append('\"');
JsonUtils.quoteAsString(additionalField.getKey(), builder);
builder.append("\":\"");
JsonUtils.quoteAsString(EcsJsonSerializer.toNullSafeString(value), builder);
builder.append("\",");
}
}
}
event.getContextData().forEach(WRITE_MDC, builder);
}
}
@BeforeEach
void setUp() {
ctx = new LoggerContext("Test");
ctx.reconfigure();
ctx.getConfiguration().getProperties().put("node.id", "foo");
root = ctx.getRootLogger();
for (final Appender appender : root.getAppenders().values()) {
root.removeAppender(appender);
}
EcsLayout ecsLayout = EcsLayout.newBuilder()
.setConfiguration(ctx.getConfiguration())
.setServiceName("test")
.setIncludeMarkers(true)
.setIncludeOrigin(true)
.setStackTraceAsArray(true)
.setEventDataset("testdataset.log")
.setAdditionalFields(new KeyValuePair[]{
new KeyValuePair("cluster.uuid", "9fe9134b-20b0-465e-acf9-8cc09ac9053b"),
new KeyValuePair("node.id", "${node.id}"),
new KeyValuePair("empty", "${empty}"),
new KeyValuePair("clazz", "%C"),
new KeyValuePair("custom", "%custom"),
new KeyValuePair("emptyPattern", "%notEmpty{%invalidPattern}"),
})
.build();
listAppender = new ListAppender("ecs", null, ecsLayout, false, false);
listAppender.start();
root.addAppender(listAppender);
root.setLevel(Level.DEBUG);
}
protected GelfAppender(final String name,
final Layout<? extends Serializable> layout,
final Filter filter,
final boolean ignoreExceptions,
final GelfConfiguration gelfConfiguration,
final String hostName,
final boolean includeSource,
final boolean includeThreadContext,
final boolean includeStackTrace,
final KeyValuePair[] additionalFields,
final boolean includeExceptionCause) {
super(name, filter, layout, ignoreExceptions);
this.gelfConfiguration = gelfConfiguration;
this.hostName = hostName;
this.includeSource = includeSource;
this.includeThreadContext = includeThreadContext;
this.includeStackTrace = includeStackTrace;
this.includeExceptionCause = includeExceptionCause;
if (null != additionalFields) {
this.additionalFields = new HashMap<>();
for (KeyValuePair pair : additionalFields) {
this.additionalFields.put(pair.getKey(), pair.getValue());
}
} else {
this.additionalFields = Collections.emptyMap();
}
}
private static JsonLayout createCustomJsonLayout() {
return JsonLayout
.newBuilder()
.setConfiguration(CONFIGURATION)
.setCharset(CHARSET)
.setAdditionalFields(new KeyValuePair[]{
new KeyValuePair("@version", "\"1\"")
})
.build();
}
private YamlLayout(final Configuration config, final boolean locationInfo, final boolean properties,
final boolean complete, final boolean compact, final boolean eventEol, final String headerPattern,
final String footerPattern, final Charset charset, final boolean includeStacktrace,
final boolean stacktraceAsString, final boolean includeNullDelimiter, final boolean includeTimeMillis,
final KeyValuePair[] additionalFields) {
super(config,
new YamlJacksonFactory(includeStacktrace, stacktraceAsString).newWriter(locationInfo, properties,
compact, includeTimeMillis),
charset, compact, complete, eventEol,
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(headerPattern)
.setDefaultPattern(DEFAULT_HEADER).build(),
PatternLayout.newSerializerBuilder().setConfiguration(config).setPattern(footerPattern)
.setDefaultPattern(DEFAULT_FOOTER).build(),
includeNullDelimiter, additionalFields);
}
protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset,
final boolean compact, final boolean complete, final boolean eventEol, final Serializer headerSerializer,
final Serializer footerSerializer, final boolean includeNullDelimiter,
final KeyValuePair[] additionalFields) {
this(config, objectWriter, charset, compact, complete, eventEol, null, headerSerializer, footerSerializer,
includeNullDelimiter, additionalFields);
}
protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset,
final boolean compact, final boolean complete, final boolean eventEol, final String endOfLine,
final Serializer headerSerializer, final Serializer footerSerializer, final boolean includeNullDelimiter,
final KeyValuePair[] additionalFields) {
super(config, charset, headerSerializer, footerSerializer);
this.objectWriter = objectWriter;
this.compact = compact;
this.complete = complete;
this.eol = endOfLine != null ? endOfLine : compact && !eventEol ? COMPACT_EOL : DEFAULT_EOL;
this.includeNullDelimiter = includeNullDelimiter;
this.additionalFields = prepareAdditionalFields(config, additionalFields);
}
protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset,
final boolean compact, final boolean complete, final boolean eventEol, final Serializer headerSerializer,
final Serializer footerSerializer, final boolean includeNullDelimiter,
final KeyValuePair[] additionalFields) {
this(config, objectWriter, charset, compact, complete, eventEol, null,
headerSerializer, footerSerializer, includeNullDelimiter, additionalFields);
}
protected AbstractJacksonLayout(final Configuration config, final ObjectWriter objectWriter, final Charset charset,
final boolean compact, final boolean complete, final boolean eventEol, String endOfLine,
final Serializer headerSerializer, final Serializer footerSerializer, final boolean includeNullDelimiter,
final KeyValuePair[] additionalFields) {
super(config, charset, headerSerializer, footerSerializer);
this.objectWriter = objectWriter;
this.compact = compact;
this.complete = complete;
this.eol = endOfLine != null ? endOfLine : compact && !eventEol ? COMPACT_EOL : DEFAULT_EOL;
this.includeNullDelimiter = includeNullDelimiter;
this.additionalFields = prepareAdditionalFields(config, additionalFields);
}
private XmlLayout(final Configuration config, final boolean locationInfo, final boolean properties,
final boolean complete, final boolean compact, final Charset charset, final boolean includeStacktrace,
final boolean stacktraceAsString, final boolean includeNullDelimiter, final boolean includeTimeMillis,
final KeyValuePair[] additionalFields) {
super(config,
new XmlJacksonFactory(includeStacktrace, stacktraceAsString).newWriter(locationInfo, properties,
compact, includeTimeMillis),
charset, compact, complete, false, null, null, includeNullDelimiter, additionalFields);
}
@Test
public void testAdditionalFields() throws Exception {
final AbstractJacksonLayout layout = XmlLayout.newBuilder().setLocationInfo(false).setProperties(false)
.setIncludeStacktrace(false)
.setAdditionalFields(new KeyValuePair[] { new KeyValuePair("KEY1", "VALUE1"),
new KeyValuePair("KEY2", "${java:runtime}"), })
.setCharset(StandardCharsets.UTF_8).setConfiguration(ctx.getConfiguration()).build();
final String str = layout.toSerializable(LogEventFixtures.createLogEvent());
assertTrue(str, str.contains("<KEY1>VALUE1</KEY1>"));
assertTrue(str, str.contains("<KEY2>" + new JavaLookup().getRuntime() + "</KEY2>"));
}
@Test
public void testMutableLogEvent() throws Exception {
final AbstractJacksonLayout layout = XmlLayout.newBuilder().setLocationInfo(false).setProperties(false)
.setIncludeStacktrace(false)
.setAdditionalFields(new KeyValuePair[] { new KeyValuePair("KEY1", "VALUE1"),
new KeyValuePair("KEY2", "${java:runtime}"), })
.setCharset(StandardCharsets.UTF_8).setConfiguration(ctx.getConfiguration()).build();
Log4jLogEvent logEvent = LogEventFixtures.createLogEvent();
final MutableLogEvent mutableEvent = new MutableLogEvent();
mutableEvent.initFrom(logEvent);
final String strLogEvent = layout.toSerializable(logEvent);
final String strMutableEvent = layout.toSerializable(mutableEvent);
assertEquals(strMutableEvent, strLogEvent, strMutableEvent);
}
/**
* Creates a policy to rewrite levels for a given logger name.
*
* @param loggerNamePrefix
* The logger name prefix for events to rewrite; all event logger names that start with this string will be
* rewritten.
* @param levelPairs
* The levels to rewrite, the key is the source level, the value the target level.
* @return a new LoggerNameLevelRewritePolicy
*/
@PluginFactory
public static LoggerNameLevelRewritePolicy createPolicy(
// @formatter:off
@PluginAttribute("logger") final String loggerNamePrefix,
@PluginElement("KeyValuePair") final KeyValuePair[] levelPairs) {
// @formatter:on
final Map<Level, Level> newMap = new HashMap<>(levelPairs.length);
for (final KeyValuePair keyValuePair : levelPairs) {
newMap.put(getLevel(keyValuePair.getKey()), getLevel(keyValuePair.getValue()));
}
return new LoggerNameLevelRewritePolicy(loggerNamePrefix, newMap);
}
/**
* The factory method to create the MapRewritePolicy.
* @param mode The string representation of the Mode.
* @param pairs key/value pairs for the new Map keys and values.
* @return The MapRewritePolicy.
*/
@PluginFactory
public static MapRewritePolicy createPolicy(
@PluginAttribute final String mode,
@PluginElement("KeyValuePair") final KeyValuePair[] pairs) {
Mode op = mode == null ? op = Mode.Add : Mode.valueOf(mode);
if (pairs == null || pairs.length == 0) {
LOGGER.error("keys and values must be specified for the MapRewritePolicy");
return null;
}
final Map<String, Object> map = new HashMap<>();
for (final KeyValuePair pair : pairs) {
final String key = pair.getKey();
if (key == null) {
LOGGER.error("A null key is not valid in MapRewritePolicy");
continue;
}
final String value = pair.getValue();
if (value == null) {
LOGGER.error("A null value for key " + key + " is not allowed in MapRewritePolicy");
continue;
}
map.put(pair.getKey(), pair.getValue());
}
if (map.isEmpty()) {
LOGGER.error("MapRewritePolicy is not configured with any valid key value pairs");
return null;
}
return new MapRewritePolicy(map, op);
}
@PluginFactory
public static ThreadContextMapFilter createFilter(
@PluginElement final KeyValuePair[] pairs,
@PluginAttribute final String operator,
@PluginAttribute final Result onMatch,
@PluginAttribute final Result onMismatch) {
if (pairs == null || pairs.length == 0) {
LOGGER.error("key and value pairs must be specified for the ThreadContextMapFilter");
return null;
}
final Map<String, List<String>> map = new HashMap<>();
for (final KeyValuePair pair : pairs) {
final String key = pair.getKey();
if (key == null) {
LOGGER.error("A null key is not valid in MapFilter");
continue;
}
final String value = pair.getValue();
if (value == null) {
LOGGER.error("A null value for key " + key + " is not allowed in MapFilter");
continue;
}
List<String> list = map.get(pair.getKey());
if (list != null) {
list.add(value);
} else {
list = new ArrayList<>();
list.add(value);
map.put(pair.getKey(), list);
}
}
if (map.isEmpty()) {
LOGGER.error("ThreadContextMapFilter is not configured with any valid key value pairs");
return null;
}
final boolean isAnd = operator == null || !operator.equalsIgnoreCase("or");
return new ThreadContextMapFilter(map, isAnd, onMatch, onMismatch);
}
@PluginFactory
public static MapFilter createFilter(
@PluginElement final KeyValuePair[] pairs,
@PluginAttribute final String operator,
@PluginAttribute final Result onMatch,
@PluginAttribute final Result onMismatch) {
if (pairs == null || pairs.length == 0) {
LOGGER.error("keys and values must be specified for the MapFilter");
return null;
}
final Map<String, List<String>> map = new HashMap<>();
for (final KeyValuePair pair : pairs) {
final String key = pair.getKey();
if (key == null) {
LOGGER.error("A null key is not valid in MapFilter");
continue;
}
final String value = pair.getValue();
if (value == null) {
LOGGER.error("A null value for key " + key + " is not allowed in MapFilter");
continue;
}
List<String> list = map.get(pair.getKey());
if (list != null) {
list.add(value);
} else {
list = new ArrayList<>();
list.add(value);
map.put(pair.getKey(), list);
}
}
if (map.isEmpty()) {
LOGGER.error("MapFilter is not configured with any valid key value pairs");
return null;
}
final boolean isAnd = operator == null || !operator.equalsIgnoreCase("or");
return new MapFilter(map, isAnd, onMatch, onMismatch);
}
/**
* Creates the StructuredDataFilter.
* @param pairs Key and value pairs.
* @param operator The operator to perform. If not "or" the operation will be an "and".
* @param onMatch The action to perform on a match.
* @param onMismatch The action to perform on a mismatch.
* @return The StructuredDataFilter.
*/
// TODO Consider refactoring to use AbstractFilter.AbstractFilterBuilder
@PluginFactory
public static StructuredDataFilter createFilter(
@PluginElement final KeyValuePair[] pairs,
@PluginAttribute final String operator,
@PluginAttribute final Result onMatch,
@PluginAttribute final Result onMismatch) {
if (pairs == null || pairs.length == 0) {
LOGGER.error("keys and values must be specified for the StructuredDataFilter");
return null;
}
final Map<String, List<String>> map = new HashMap<>();
for (final KeyValuePair pair : pairs) {
final String key = pair.getKey();
if (key == null) {
LOGGER.error("A null key is not valid in MapFilter");
continue;
}
final String value = pair.getValue();
if (value == null) {
LOGGER.error("A null value for key " + key + " is not allowed in MapFilter");
continue;
}
List<String> list = map.get(pair.getKey());
if (list != null) {
list.add(value);
} else {
list = new ArrayList<>();
list.add(value);
map.put(pair.getKey(), list);
}
}
if (map.isEmpty()) {
LOGGER.error("StructuredDataFilter is not configured with any valid key value pairs");
return null;
}
final boolean isAnd = operator == null || !operator.equalsIgnoreCase("or");
return new StructuredDataFilter(map, isAnd, onMatch, onMismatch);
}