All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cdc.impex.templates.ColumnTemplate Maven / Gradle / Ivy

The newest version!
package cdc.impex.templates;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.regex.Pattern;

import cdc.issues.IssueSeverity;
import cdc.office.ss.ContentValidation;
import cdc.office.tables.HeaderCell;
import cdc.office.tables.HeaderCell.NameCell;
import cdc.office.tables.HeaderCell.PatternCell;
import cdc.util.lang.Checks;
import cdc.util.strings.StringConversion;
import cdc.validation.checkers.Checker;

/**
 * Description of a column template.
 * 

* A column is described by: *

    *
  • A header (name or pattern).
    * A name column represents a single actual column.
    * A pattern column represents a set of actual columns. *
  • A {@link Usage}. *
  • A data type. *
  • An optional default value. *
  • An optional description.
    * It is used when sample files are generated. *
  • An optional {@link Checker}.
    * It can be used to add more checks to data type, for example, to check the length of string, the domain of a number, ... *
  • The severity of a failed check. *
  • A string to data type converter. *
  • A data type to string converter. *
  • An optional Content Validation type. *
  • An optional Content Validation operator. *
  • An optional list of Content Validation values. *
* WARNING: content validation should be compliant with data type and checker. *

* If data type is a primitive or enum data type, default content validation data are automatically set. * * @author Damien Carbonne * * @param The column data type. */ public final class ColumnTemplate { private final HeaderCell header; private final Usage usage; private final Class dataType; private final T def; private final Primitive primitive; private final String description; private final Checker checker; private final IssueSeverity checkFailureSeverity; private final Function importConverter; private final Function exportConverter; private final ContentValidation.Type cvType; private final ContentValidation.Operator cvOperator; private final List cvValues; private ColumnTemplate(Builder builder) { Checks.isTrue(builder.cvType.accepts(builder.cvOperator), builder.cvType + " is not compliant with " + builder.cvOperator + " operator."); Checks.isTrue(builder.cvOperator.isCompliantWithValues(builder.cvValues.size()), builder.cvOperator + " is not compliant with " + builder.cvValues.size() + " values."); this.header = Checks.isNotNull(builder.header, "header"); this.usage = Checks.isNotNull(builder.usage, "usage"); this.dataType = Checks.isNotNull(builder.dataType, "dataType"); this.def = builder.def; this.primitive = Primitive.getPrimitive(builder.dataType); this.description = builder.description; this.checker = builder.checker; this.checkFailureSeverity = Checks.isNotNull(builder.checkFailureSeverity, "checkFailureSeverity"); this.importConverter = Checks.isNotNull(builder.importConverter, "importConverter"); this.exportConverter = builder.exportConverter == null ? Object::toString : builder.exportConverter; this.cvType = builder.cvType; this.cvOperator = builder.cvOperator; this.cvValues = Collections.unmodifiableList(builder.cvValues); } public HeaderCell getHeader() { return header; } /** * @return {@code true} if the header of the column is a name. */ public boolean isName() { return header instanceof HeaderCell.NameCell; } public void checkIsName() { Checks.isTrue(isName(), "{} is not a name.", this); } /** * @return {@code true} if the header of the column is a pattern. */ public boolean isPattern() { return header instanceof HeaderCell.PatternCell; } public void checkIsPattern() { Checks.isTrue(isPattern(), "{} is not a pattern.", this); } /** * @return The column label (its name or pattern). */ public String getLabel() { return header.getLabel(); } /** * Returns the column name. *

* WARNING: column must have a {@link NameCell name header}. * * @return The column name. * @throws AssertionError When the header of this template is not a name. */ public String getName() { Checks.assertTrue(isName(), "'{}' is not a name column.", this); return ((HeaderCell.NameCell) header).getName(); } /** * Returns the column pattern. *

* WARNING: column must have a {@link PatternCell pattern header}. * * @return The column pattern. * @throws AssertionError When the header of this template is not a pattern. */ public Pattern getPattern() { Checks.assertTrue(isPattern(), "'{}' is not a pattern column.", this); return ((HeaderCell.PatternCell) header).getPattern(); } /** * @return The column usage. */ public Usage getUsage() { return usage; } /** * @return The column data type. */ public Class getDataType() { return dataType; } /** * @return The column default value. */ public T getDef() { return def; } /** * @return The {@link Primitive} type of this column, or {@code null}. */ public Primitive getPrimitive() { return primitive; } /** * @return The column description. */ public String getDescription() { return description; } /** * @return The checker or {@code null}. */ public Checker getCheckerOrNull() { return checker; } public boolean hasChecker() { return checker != null; } /** * @return The severity of a check failure. */ public IssueSeverity getCheckFailureSeverity() { return checkFailureSeverity; } /** * @return the converter used to convert a string to data type. */ public Function getImportConverter() { return importConverter; } /** * @return the converter used to convert a data type to a string. */ public Function getExportConverter() { return exportConverter; } /** * @return The comment that should be used to describe this column. */ public String getComment() { final StringBuilder builder = new StringBuilder(); builder.append("Usage: ") .append(getUsage().getName()) .append('\n') .append("Erasable: ") .append(getUsage().isErasable() ? "Yes" : "No") .append('\n') .append("Type: ") .append(getDataType().getSimpleName()); if (getCheckerOrNull() != null) { builder.append('\n') .append("Check: ") .append(getCheckerOrNull().explain()); } if (getDescription() != null) { builder.append("\n\n") .append(getDescription()); } return builder.toString(); } /** * @return The content validation type. */ public ContentValidation.Type getContentValidationType() { return cvType; } /** * @return The content validation operator. */ public ContentValidation.Operator getContentValidationOperator() { return cvOperator; } /** * @return The content validation values. */ public List getContentValidationValues() { return cvValues; } @Override public String toString() { return "[" + getLabel() + " " + getUsage() + " " + getDataType().getSimpleName() + "]"; } /** * @return A new Builder initialized with data from this Template. */ public Builder newBuilder() { return builder(this); } /** * Creates an empty new Builder. * * @param The data type. * @param dataType The data class. * @return A new Builder typed with {@code dataType}. */ public static Builder builder(Class dataType) { return new Builder<>(dataType); } /** * Creates a new Builder initialized from a Template. * * @param The data type. * @param model The Template model. * @return A new Builder initialized with {@code model}. */ public static Builder builder(ColumnTemplate model) { return new Builder<>(model); } public static final class Builder { private final Class dataType; private HeaderCell header; private Usage usage = Usage.OPTIONAL_RW_ATT; private T def = null; private String description; private Checker checker; private IssueSeverity checkFailureSeverity = IssueSeverity.CRITICAL; private Function importConverter; private Function exportConverter; private ContentValidation.Type cvType = ContentValidation.Type.ANY; private ContentValidation.Operator cvOperator = ContentValidation.Operator.NONE; private final List cvValues = new ArrayList<>(); private static class Bucket { final Function importConverter; final ContentValidation.Type cvType; final ContentValidation.Operator cvOperator; final List cvValues; Bucket(Function importConverter, ContentValidation.Type cvType, ContentValidation.Operator cvOperator, List cvValues) { this.importConverter = importConverter; this.cvType = cvType; this.cvOperator = cvOperator; this.cvValues = cvValues; } } private static final Map, Bucket> BUCKETS = new HashMap<>(); static { BUCKETS.put(Boolean.class, new Bucket(StringConversion::asBoolean, ContentValidation.Type.ANY, ContentValidation.Operator.NONE, Collections.emptyList())); BUCKETS.put(boolean.class, new Bucket(StringConversion::asBoolean, ContentValidation.Type.ANY, ContentValidation.Operator.NONE, Collections.emptyList())); BUCKETS.put(Character.class, new Bucket(StringConversion::asChar, ContentValidation.Type.TEXT_LENGTH, ContentValidation.Operator.EQUAL, List.of("1"))); BUCKETS.put(char.class, new Bucket(StringConversion::asChar, ContentValidation.Type.TEXT_LENGTH, ContentValidation.Operator.EQUAL, List.of("1"))); BUCKETS.put(Byte.class, new Bucket(StringConversion::asByte, ContentValidation.Type.INTEGER, ContentValidation.Operator.BETWEEN, List.of(Byte.toString(Byte.MIN_VALUE), Byte.toString(Byte.MAX_VALUE)))); BUCKETS.put(byte.class, new Bucket(StringConversion::asByte, ContentValidation.Type.INTEGER, ContentValidation.Operator.BETWEEN, List.of(Byte.toString(Byte.MIN_VALUE), Byte.toString(Byte.MAX_VALUE)))); BUCKETS.put(Short.class, new Bucket(StringConversion::asShort, ContentValidation.Type.INTEGER, ContentValidation.Operator.BETWEEN, List.of(Short.toString(Short.MIN_VALUE), Short.toString(Short.MAX_VALUE)))); BUCKETS.put(short.class, new Bucket(StringConversion::asShort, ContentValidation.Type.INTEGER, ContentValidation.Operator.BETWEEN, List.of(Short.toString(Short.MIN_VALUE), Short.toString(Short.MAX_VALUE)))); BUCKETS.put(Integer.class, new Bucket(StringConversion::asInt, ContentValidation.Type.INTEGER, ContentValidation.Operator.BETWEEN, List.of(Integer.toString(Integer.MIN_VALUE), Integer.toString(Integer.MAX_VALUE)))); BUCKETS.put(int.class, new Bucket(StringConversion::asInt, ContentValidation.Type.INTEGER, ContentValidation.Operator.BETWEEN, List.of(Integer.toString(Integer.MIN_VALUE), Integer.toString(Integer.MAX_VALUE)))); BUCKETS.put(Long.class, new Bucket(StringConversion::asLong, ContentValidation.Type.INTEGER, ContentValidation.Operator.BETWEEN, List.of(Long.toString(Long.MIN_VALUE), Long.toString(Long.MAX_VALUE)))); BUCKETS.put(long.class, new Bucket(StringConversion::asLong, ContentValidation.Type.INTEGER, ContentValidation.Operator.BETWEEN, List.of(Long.toString(Long.MIN_VALUE), Long.toString(Long.MAX_VALUE)))); BUCKETS.put(Float.class, new Bucket(StringConversion::asFloat, ContentValidation.Type.DECIMAL, ContentValidation.Operator.BETWEEN, List.of(Float.toString(-Float.MAX_VALUE), Float.toString(Float.MAX_VALUE)))); BUCKETS.put(float.class, new Bucket(StringConversion::asFloat, ContentValidation.Type.DECIMAL, ContentValidation.Operator.BETWEEN, List.of(Float.toString(-Float.MAX_VALUE), Float.toString(Float.MAX_VALUE)))); BUCKETS.put(Double.class, new Bucket(StringConversion::asDouble, ContentValidation.Type.DECIMAL, ContentValidation.Operator.BETWEEN, List.of(Double.toString(-Double.MAX_VALUE), Double.toString(Double.MAX_VALUE)))); BUCKETS.put(double.class, new Bucket(StringConversion::asDouble, ContentValidation.Type.DECIMAL, ContentValidation.Operator.BETWEEN, List.of(Double.toString(-Double.MAX_VALUE), Double.toString(Double.MAX_VALUE)))); BUCKETS.put(String.class, new Bucket(Function.identity(), ContentValidation.Type.ANY, ContentValidation.Operator.NONE, Collections.emptyList())); } private void buildDefaultData() { final Function f; final ContentValidation.Type type; final ContentValidation.Operator operator; final List values; if (this.dataType.isEnum()) { @SuppressWarnings("unchecked") final Class> c = (Class>) dataType; f = s -> StringConversion.asRawEnum(s, c); type = ContentValidation.Type.LIST; operator = ContentValidation.Operator.NONE; values = new ArrayList<>(); for (final Enum e : c.getEnumConstants()) { values.add(e.name()); } } else { final Bucket bucket = BUCKETS.get(dataType); if (bucket == null) { f = null; type = ContentValidation.Type.ANY; operator = ContentValidation.Operator.NONE; values = Collections.emptyList(); } else { f = bucket.importConverter; type = bucket.cvType; operator = bucket.cvOperator; values = bucket.cvValues; } } @SuppressWarnings("unchecked") final Function g = (Function) f; this.importConverter = g; this.cvType = type; this.cvOperator = operator; this.cvValues.addAll(values); } private Builder(Class dataType) { this.dataType = dataType; buildDefaultData(); } private Builder(ColumnTemplate model) { this(model.dataType); header(model.header); usage(model.usage); def(model.def); description(model.description); checker(model.checker); checkFailureSeverity(model.checkFailureSeverity); importConverter(model.importConverter); exportConverter(model.exportConverter); cvType(model.cvType); cvOperator(model.cvOperator); cvValues(model.cvValues); } public Builder header(HeaderCell header) { this.header = header; return this; } public Builder name(String name) { this.header = HeaderCell.name(name); return this; } public Builder pattern(String pattern) { this.header = HeaderCell.pattern(pattern); return this; } public Builder usage(Usage usage) { this.usage = usage; return this; } public Builder def(T def) { this.def = def; return this; } public Builder description(String description) { this.description = description; return this; } public Builder checker(Checker checker) { this.checker = checker; return this; } public Builder checkFailureSeverity(IssueSeverity checkFailureSeverity) { this.checkFailureSeverity = checkFailureSeverity; return this; } public Builder importConverter(Function converter) { this.importConverter = converter; return this; } public Builder exportConverter(Function converter) { this.exportConverter = converter; return this; } public Builder cvType(ContentValidation.Type cvType) { this.cvType = cvType; return this; } public Builder cvOperator(ContentValidation.Operator cvOperator) { this.cvOperator = cvOperator; return this; } public Builder cvValue(String value) { this.cvValues.clear(); this.cvValues.add(value); return this; } public Builder cvValues(String value1, String value2) { this.cvValues.clear(); this.cvValues.add(value1); this.cvValues.add(value2); return this; } public Builder cvValues(String... values) { this.cvValues.clear(); Collections.addAll(this.cvValues, values); return this; } public Builder cvValues(List values) { this.cvValues.clear(); this.cvValues.addAll(values); return this; } public ColumnTemplate build() { return new ColumnTemplate<>(this); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy