Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save sebge2emasphere/1b09af1695c23f4ceebabf51ef3b5049 to your computer and use it in GitHub Desktop.
Save sebge2emasphere/1b09af1695c23f4ceebabf51ef3b5049 to your computer and use it in GitHub Desktop.
package com.emasphere.operation.query.model.definition.matrix.dimension;
import com.emasphere.operation.injection.model.CodeLabel;
import com.emasphere.operation.query.model.SimpleRegexUtils;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import static java.util.Arrays.*;
import static java.util.Collections.*;
/**
* The {@link MatrixDimensionDefinition dimension} is based on hard-coded range of text values.
*
* @author Sebastien Gerard
*/
@JsonDeserialize(builder = MatrixTextRangeValuesDimensionDefinition.Builder.class)
public class MatrixTextRangeValuesDimensionDefinition implements MatrixDimensionDefinition {
/**
* Returns a new empty {@link Builder builder}.
*/
public static MatrixTextRangeValuesDimensionDefinition.Builder matrixTextRangeValuesDimensionDefinition() {
return new Builder();
}
/**
* Returns a new {@link Group text group}.
*/
public static Group textGroup(String name, List<String> entries) {
return textGroup(Type.STRICT_MATCH, name, entries);
}
/**
* Returns a new {@link Group text group}.
*/
public static Group textGroup(String name, String... entries) {
return textGroup(name, asList(entries));
}
/**
* Returns a new {@link Group text group}.
*/
public static Group textGroup(Type type, String name, List<String> entries) {
return new Group(entries, type, name);
}
/**
* Returns a new {@link Group text group}.
*/
public static Group textGroup(Type type, String name, String... entries) {
return textGroup(type, name, asList(entries));
}
private final CodeLabel valueReference;
private final List<Group> textGroups;
private MatrixTextRangeValuesDimensionDefinition(Builder builder) {
valueReference = builder.valueReference;
textGroups = unmodifiableList(builder.textGroups);
}
@Override
public CodeLabel getValueReference() {
return valueReference;
}
@Override
public DimensionType getType() {
return DimensionType.TEXT_RANGE_VALUES;
}
@Override
public <T> T accept(MatrixDimensionDefinition.Visitor<T> visitor) {
if (visitor instanceof Visitor) {
return ((Visitor<T>) visitor).visitMatrixTextRangeValuesDimension(this);
} else {
return visitor.visitMatrixDimension(this);
}
}
/**
* Returns {@link Group groups} of this dimension. Dimension values are grouped by range and associated to a name.
*/
public List<Group> getTextGroups() {
return textGroups;
}
/**
* Group of text values.
*/
public static final class Group implements Serializable {
private final List<String> values;
private final Type type;
private final String name;
@JsonCreator
public Group(@JsonProperty("entries") List<String> values,
@JsonProperty("type") Type type,
@JsonProperty("name") String name) {
this.values = values;
this.type = type;
this.name = name;
}
/**
* Returns all the group values.
*/
public List<String> getValues() {
return values;
}
/**
* Returns the {@link Type group type}.
*/
public Type getType() {
return type;
}
/**
* Returns the name of this range displayed to the end-user.
*/
public String getName() {
return name;
}
/**
* Returns whether the specified value is contained within this group.
*/
public boolean isInGroup(String value) {
return getValues()
.stream()
.anyMatch(groupEntry -> getType().matches(groupEntry, value));
}
@Override
public String toString() {
return "Group{" +
"name='" + name + '\'' +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
final Group group = (Group) o;
return Objects.equals(name, group.name);
}
@Override
public int hashCode() {
return Objects.hash(name);
}
}
/**
* Type of group entry.
*/
public enum Type {
/**
* Group entries must exactly match flow entry values.
*/
STRICT_MATCH(Object::equals, x -> {
}),
/**
* Group entries are expressions that must match flow entry values.
*/
SIMPLE_EXPRESSION(
(groupEntry, value) -> (value != null) && SimpleRegexUtils.buildPattern(groupEntry).matcher(value).matches(),
groupEntry -> {
try {
SimpleRegexUtils.buildPattern(groupEntry);
} catch (PatternSyntaxException e) {
throw new IllegalArgumentException("Error while validating the group entry.", e);
}
}
),
@SuppressWarnings("ResultOfMethodCallIgnored")
REGULAR_EXPRESSION(
(groupEntry, value) -> (value != null) && Pattern.matches(groupEntry, value),
groupEntry -> {
try {
Pattern.compile(groupEntry);
} catch (PatternSyntaxException e) {
throw new IllegalArgumentException("Error while validating the group entry.", e);
}
}
);
/**
* @deprecated to be removed once the migration has been performed
*/
@JsonCreator
public static Type forValue(String value) {
if ("EXPRESSION".equals(value)) {
return SIMPLE_EXPRESSION;
}
return Type.valueOf(value);
}
private final BiFunction<String, String, Boolean> matcher;
private final Consumer<String> validator;
Type(BiFunction<String, String, Boolean> matcher,
Consumer<String> validator) {
this.matcher = matcher;
this.validator = validator;
}
/**
* Returns whether the specified group entry matches the current value.
*/
public boolean matches(String groupEntry, String value) {
return matcher.apply(groupEntry, value); // TODO operational build the pattern only once and not when matching
}
/**
* Validates that the specified group entry is valid.
*/
public void validate(String groupEntry) throws IllegalArgumentException {
validator.accept(groupEntry);
}
}
/**
* Visitor pattern for {@link MatrixTextRangeValuesDimensionDefinition}.
*
* @param <T> type of object returned when visiting
*/
public interface Visitor<T> extends MatrixDimensionDefinition.Visitor<T> {
/**
* Visits the specified definition.
*/
T visitMatrixTextRangeValuesDimension(MatrixTextRangeValuesDimensionDefinition definition);
}
/**
* Builder of {@link MatrixTextRangeValuesDimensionDefinition}.
*/
@JsonPOJOBuilder(withPrefix = "")
@JsonIgnoreProperties(ignoreUnknown = true)
public static final class Builder {
private CodeLabel valueReference;
private final List<Group> textGroups = new ArrayList<>();
private Builder() {
}
public Builder valueReference(CodeLabel valueReference) {
this.valueReference = valueReference;
return this;
}
@JsonProperty("textGroups")
public Builder textGroups(List<Group> textGroups) {
this.textGroups.addAll(textGroups);
return this;
}
@JsonIgnore
public Builder textGroups(Group... textGroups) {
return textGroups(asList(textGroups));
}
public MatrixTextRangeValuesDimensionDefinition build() {
return new MatrixTextRangeValuesDimensionDefinition(this);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment