com.sap.cds.CdsDataProcessor Maven / Gradle / Ivy
/************************************************************************
* © 2021-2022 SAP SE or an SAP affiliate company. All rights reserved. *
************************************************************************/
package com.sap.cds;
import java.util.Map;
import com.google.common.annotations.Beta;
import com.sap.cds.ql.cqn.Path;
import com.sap.cds.reflect.CdsElement;
import com.sap.cds.reflect.CdsStructuredType;
import com.sap.cds.reflect.CdsType;
/**
* The CdsDataProcessor allows to process deeply nested maps of CDS data, by
* executing a sequence of registered handlers of type {@link Generator},
* {@link Converter} or {@link Validator}.
*/
@Beta
public interface CdsDataProcessor {
Factory factory = Cds4jServiceLoader.load(Factory.class);
/**
* Indicates the absence of a value in the data map.
*/
Object ABSENT = new Object();
/**
* The processing mode: {@link #DECLARED}, {@link #CONTAINS}, {@link #NOT_NULL}
* or {@link #NULL}.
*/
enum Mode {
/**
* Include all declared elements. For elements that don't have an associated
* value in the data map, {@link CdsDataProcessor#ABSENT} is used as a
* placeholder value.
*/
DECLARED,
/**
* Include all declared elements for which the data map
* {@link java.util.Map#containsKey contains} a value.
*/
CONTAINS,
/**
* Include all declared elements for which the data map
* {@link java.util.Map#containsKey contains} a non-null value.
*/
NOT_NULL,
/**
* Include all declared elements that are mapped to null, or don't have an
* associated value in the data map, in this case
* {@link CdsDataProcessor#ABSENT} is used as a placeholder value.
*/
NULL
}
/**
* Creates a new DataProcessor instance.
*
* @return a DataProcessor
*/
static CdsDataProcessor create() {
return factory.create();
}
/**
* Adds a function to convert values of elements that match a given filter.
*
* @param filter the filter predicate, see {@link Filter}
* @param valConverter the value converter function, see {@link Converter}
* @return this DataProcessor
*/
CdsDataProcessor addConverter(Filter filter, Converter valConverter);
/**
* Adds a function to generate values for elements that match a given filter and
* are missing in the data or mapped to null.
*
* @param filter the filter predicate, see {@link Filter}
* @param valGenerator the Value {@link Generator} function
* @return this DataProcessor
*/
CdsDataProcessor addGenerator(Filter filter, Generator valGenerator);
/**
* Adds a function to validate values of elements that match a given filter. The
* validator function is only called for elements that have an associated value
* (including null) in the data map, this can be changed by providing a
* processing mode via {@link #addValidator(Filter, Validator, Mode)}
*
* @param filter the filter predicate, see {@link Filter}
* @param validator the validation function, see {@link Validator}
* @return this DataProcessor
*/
default CdsDataProcessor addValidator(Filter filter, Validator validator) {
return addValidator(filter, validator, Mode.CONTAINS);
}
/**
* Adds a function to validate values of elements that match a given filter.
*
* @param filter the filter predicate, see {@link Filter}
* @param validator the validation function, see {@link Validator}
* @param mode the processing {@link Mode}
* @return this DataProcessor
*/
CdsDataProcessor addValidator(Filter filter, Validator validator, Mode mode);
/**
* Runs the CdsDataProcessor on the given data entry.
*
* @param entry the data entry
* @param entryType the CDS type of the data entry
*/
void process(Map entry, CdsStructuredType entryType);
/**
* Runs the CdsDataProcessor on the given data entries.
*
* @param entries the data entries
* @param entryType the CDS type of the data entries
*/
void process(Iterable extends Map> entries, CdsStructuredType entryType);
/**
* Runs the CdsDataProcessor on the given CDS.ql result.
*
* @param result the CDS.ql result
*/
default void process(Result result) {
process(result, result.rowType());
}
/**
* Predicate to filter a CdsElement by the element's CdsType.
*
* This is a functional interface whose functional method is
* {@link #test(Path, CdsElement, CdsType)}.
*/
@Beta
@FunctionalInterface
public interface Filter {
/**
* Evaluates this filter predicate on the given arguments.
*
* @param path the path to the element
* @param element the CDS element
* @param type the element's CdsType, for associations the target type, for
* arrayed elements the item type
* @return {@code true} if the input arguments match the predicate, otherwise
* {@code false}
*/
boolean test(Path path, CdsElement element, CdsType type);
default boolean test(Path path, CdsElement element) {
return test(path, element, element.getType());
}
}
/**
* Function to convert or remove a value for a CdsElement.
*
* This is a functional interface whose functional method is
* {@link #convert(Path, CdsElement, Object)}.
*/
@Beta
@FunctionalInterface
public interface Converter {
/**
* Indicates to remove the value from the data map.
*/
Object REMOVE = new Object();
/**
* Converts the value for the given element.
*
* @param path the path to the element
* @param element the CDS element
* @param value the value, can be null
* @return the converted value, or {@code Converter.REMOVE} to remove the value
*/
Object convert(Path path, CdsElement element, Object value);
}
/**
* Function to compute a value for a CdsElement.
*
* This is a functional interface whose functional method is
* {@link #generate(Path, CdsElement, boolean)}.
*/
@Beta
@FunctionalInterface
public interface Generator {
/**
* Generates a value for the given element.
*
* @param path the path to the element
* @param element the CDS element
* @param isNull {@code true} if the element is mapped to null, {@code false}
* if there is no value mapped to the element
* @return the generated value, or null
*/
Object generate(Path path, CdsElement element, boolean isNull);
}
/**
* Function to validate the value of a CdsElement.
*
* This is a functional interface whose functional method is
* {@link #validate(Path, CdsElement, Object)}.
*/
@Beta
@FunctionalInterface
public interface Validator {
/**
* Validates the value of the given element.
*
* @param path the path to the element
* @param element the CDS element
* @param value the value, can be null
*/
void validate(Path path, CdsElement element, Object value);
}
interface Factory {
CdsDataProcessor create();
}
}