Skip to content

Commit

Permalink
Add Condition.nullMatch
Browse files Browse the repository at this point in the history
  • Loading branch information
wsargent committed Dec 20, 2024
1 parent afdc6b6 commit 1d3bd21
Showing 1 changed file with 182 additions and 174 deletions.
356 changes: 182 additions & 174 deletions logging/src/main/java/echopraxia/logging/api/Condition.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import echopraxia.api.Field;
import echopraxia.api.Value;

import java.util.List;
import java.util.function.Predicate;

import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.NotNull;

Expand All @@ -12,182 +14,188 @@
*/
public interface Condition {

/**
* Tests the condition.
*
* @param level the logging level
* @param context the logging context
* @return true if the conditions are met, false otherwise.
*/
boolean test(Level level, LoggingContext context);

/**
* Returns a condition which does a logical AND on this condition with the given condition.
*
* @param c the given condition.
* @return a condition that renders result of this condition AND given condition.
*/
default Condition and(Condition c) {
return (level, context) -> Condition.this.test(level, context) && c.test(level, context);
}

/**
* Returns a condition which does a logical AND on this condition with the given condition.
*
* @param c the given condition.
* @return a condition that renders result of this condition OR given condition.
*/
default Condition or(Condition c) {
return (level, context) -> Condition.this.test(level, context) || c.test(level, context);
}

/**
* Returns a condition which does a logical XOR on this condition with the given condition.
*
* @param c the given condition.
* @return a condition that renders result of this condition XOR given condition.
*/
default Condition xor(Condition c) {
return (level, context) -> Condition.this.test(level, context) ^ c.test(level, context);
}

/**
* A condition that will always be met.
*
* @return a condition returning true.
*/
static Condition always() {
return Conditions.ALWAYS;
}

/**
* A condition that will never be met.
*
* @return a condition returning false.
*/
static Condition never() {
return Conditions.NEVER;
}

/**
* A condition that returns true if level.isGreaterOrEqual(threshold).
*
* @param threshold the minimum threshold to meet.
* @return a condition that tests for the level to at least meet the threshold.
*/
static Condition threshold(Level threshold) {
return (level, context) -> level.isGreaterOrEqual(threshold);
}

/**
* A condition that returns true if the level is equal to exactLevel.
*
* @param exactLevel the exact level to match.
* @return a condition returning if level.isEqual(exactLevel):
*/
static Condition exactly(Level exactLevel) {
return (level, context) -> level.isEqual(exactLevel);
}

/**
* @return A condition that matches if the level is diagnostic: DEBUG or TRACE.
*/
static Condition diagnostic() {
return (level, context) -> level.isLessOrEqual(Level.DEBUG);
}

/**
* @return A condition that matches if the level is operational: INFO, WARN, or ERROR.
*/
static Condition operational() {
return (level, context) -> level.isGreaterOrEqual(Level.INFO);
}

/**
* Searches through the fields for any match of the predicate.
*
* @param predicate a predicate that the field must satisfy.
* @return true if the predicate is satisfied, false otherwise.
*/
static Condition anyMatch(Predicate<Field> predicate) {
return (level, ctx) -> ctx.getFields().stream().anyMatch(predicate);
}

/**
* Searches through the fields for none match of the predicate.
*
* @param predicate a predicate
* @return true if no elements match the predicate, false otherwise.
*/
static Condition noneMatch(Predicate<Field> predicate) {
return (level, ctx) -> ctx.getFields().stream().noneMatch(predicate);
}

/**
* Searches through the fields for the given field name and value.
*
* @param fieldName The name of the field.
* @param predicate a predicate
* @return true if no elements match the predicate, false otherwise.
*/
@Contract(pure = true)
static @NotNull Condition valueMatch(String fieldName, Predicate<Value<?>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.map(Field::value)
.anyMatch(predicate);
}

static Condition stringMatch(String fieldName, Predicate<Value<String>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.STRING))
.map(f -> (Value.StringValue) f.value())
.anyMatch(predicate);
}

static Condition numberMatch(
String fieldName, Predicate<? super Value.NumberValue<?>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.NUMBER))
.map(f -> (Value.NumberValue<?>) f.value())
.anyMatch(predicate);
}

static Condition booleanMatch(String fieldName, Predicate<Value<Boolean>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.BOOLEAN))
.map(f -> (Value.BooleanValue) f.value())
.anyMatch(predicate);
}

static Condition arrayMatch(String fieldName, Predicate<Value<List<Value<?>>>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.ARRAY))
.map(f -> (Value.ArrayValue) f.value())
.anyMatch(predicate);
}

static Condition objectMatch(String fieldName, Predicate<Value<List<Field>>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.OBJECT))
.map(f -> (Value.ObjectValue) f.value())
.anyMatch(predicate);
}
/**
* Tests the condition.
*
* @param level the logging level
* @param context the logging context
* @return true if the conditions are met, false otherwise.
*/
boolean test(Level level, LoggingContext context);

/**
* Returns a condition which does a logical AND on this condition with the given condition.
*
* @param c the given condition.
* @return a condition that renders result of this condition AND given condition.
*/
default Condition and(Condition c) {
return (level, context) -> Condition.this.test(level, context) && c.test(level, context);
}

/**
* Returns a condition which does a logical AND on this condition with the given condition.
*
* @param c the given condition.
* @return a condition that renders result of this condition OR given condition.
*/
default Condition or(Condition c) {
return (level, context) -> Condition.this.test(level, context) || c.test(level, context);
}

/**
* Returns a condition which does a logical XOR on this condition with the given condition.
*
* @param c the given condition.
* @return a condition that renders result of this condition XOR given condition.
*/
default Condition xor(Condition c) {
return (level, context) -> Condition.this.test(level, context) ^ c.test(level, context);
}

/**
* A condition that will always be met.
*
* @return a condition returning true.
*/
static Condition always() {
return Conditions.ALWAYS;
}

/**
* A condition that will never be met.
*
* @return a condition returning false.
*/
static Condition never() {
return Conditions.NEVER;
}

/**
* A condition that returns true if level.isGreaterOrEqual(threshold).
*
* @param threshold the minimum threshold to meet.
* @return a condition that tests for the level to at least meet the threshold.
*/
static Condition threshold(Level threshold) {
return (level, context) -> level.isGreaterOrEqual(threshold);
}

/**
* A condition that returns true if the level is equal to exactLevel.
*
* @param exactLevel the exact level to match.
* @return a condition returning if level.isEqual(exactLevel):
*/
static Condition exactly(Level exactLevel) {
return (level, context) -> level.isEqual(exactLevel);
}

/**
* @return A condition that matches if the level is diagnostic: DEBUG or TRACE.
*/
static Condition diagnostic() {
return (level, context) -> level.isLessOrEqual(Level.DEBUG);
}

/**
* @return A condition that matches if the level is operational: INFO, WARN, or ERROR.
*/
static Condition operational() {
return (level, context) -> level.isGreaterOrEqual(Level.INFO);
}

/**
* Searches through the fields for any match of the predicate.
*
* @param predicate a predicate that the field must satisfy.
* @return true if the predicate is satisfied, false otherwise.
*/
static Condition anyMatch(Predicate<Field> predicate) {
return (level, ctx) -> ctx.getFields().stream().anyMatch(predicate);
}

/**
* Searches through the fields for none match of the predicate.
*
* @param predicate a predicate
* @return true if no elements match the predicate, false otherwise.
*/
static Condition noneMatch(Predicate<Field> predicate) {
return (level, ctx) -> ctx.getFields().stream().noneMatch(predicate);
}

/**
* Searches through the fields for the given field name and value.
*
* @param fieldName The name of the field.
* @param predicate a predicate
* @return true if no elements match the predicate, false otherwise.
*/
@Contract(pure = true)
static @NotNull Condition valueMatch(String fieldName, Predicate<Value<?>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.map(Field::value)
.anyMatch(predicate);
}

static Condition stringMatch(String fieldName, Predicate<Value<String>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.STRING))
.map(f -> (Value.StringValue) f.value())
.anyMatch(predicate);
}

static Condition numberMatch(
String fieldName, Predicate<? super Value.NumberValue<?>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.NUMBER))
.map(f -> (Value.NumberValue<?>) f.value())
.anyMatch(predicate);
}

static Condition booleanMatch(String fieldName, Predicate<Value<Boolean>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.BOOLEAN))
.map(f -> (Value.BooleanValue) f.value())
.anyMatch(predicate);
}

static Condition arrayMatch(String fieldName, Predicate<Value<List<Value<?>>>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.ARRAY))
.map(f -> (Value.ArrayValue) f.value())
.anyMatch(predicate);
}

static Condition objectMatch(String fieldName, Predicate<Value<List<Field>>> predicate) {
return (level, ctx) ->
ctx.getFields().stream()
.filter(f -> f.name().equals(fieldName))
.filter(f -> (f.value().type() == Value.Type.OBJECT))
.map(f -> (Value.ObjectValue) f.value())
.anyMatch(predicate);
}

static Condition nullMatch(String fieldName) {
return (level, ctx) ->
ctx.getFields().stream()
.anyMatch(f -> f.name().equals(fieldName) && (f.value().type() == Value.Type.NULL));
}
}

class Conditions {
static final Condition NEVER = (level, context) -> false;
static final Condition NEVER = (level, context) -> false;

static final Condition ALWAYS = (level, context) -> true;
static final Condition ALWAYS = (level, context) -> true;
}

0 comments on commit 1d3bd21

Please sign in to comment.