io.github.linuxforhealth.hl7.expression.AbstractExpression Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hl7v2-fhir-converter Show documentation
Show all versions of hl7v2-fhir-converter Show documentation
FHIR converter is a Java based library that enables converting Hl7v2 messages to FHIR resources
/*
* (C) Copyright IBM Corp. 2020
*
* SPDX-License-Identifier: Apache-2.0
*/
package io.github.linuxforhealth.hl7.expression;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.text.StringTokenizer;
import org.apache.commons.text.matcher.StringMatcherFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableMap;
import io.github.linuxforhealth.api.Condition;
import io.github.linuxforhealth.api.EvaluationResult;
import io.github.linuxforhealth.api.Expression;
import io.github.linuxforhealth.api.InputDataExtractor;
import io.github.linuxforhealth.api.ResourceValue;
import io.github.linuxforhealth.api.Specification;
import io.github.linuxforhealth.api.Variable;
import io.github.linuxforhealth.core.Constants;
import io.github.linuxforhealth.core.data.DataTypeUtil;
import io.github.linuxforhealth.core.exception.DataExtractionException;
import io.github.linuxforhealth.core.exception.RequiredConstraintFailureException;
import io.github.linuxforhealth.core.expression.EmptyEvaluationResult;
import io.github.linuxforhealth.core.expression.EvaluationResultFactory;
import io.github.linuxforhealth.core.expression.VariableUtils;
import io.github.linuxforhealth.core.expression.condition.ConditionUtil;
import io.github.linuxforhealth.hl7.expression.specification.SpecificationParser;
import io.github.linuxforhealth.hl7.expression.specification.SpecificationUtil;
import io.github.linuxforhealth.hl7.expression.variable.VariableGenerator;
public abstract class AbstractExpression implements Expression {
private static final Logger LOGGER = LoggerFactory.getLogger(AbstractExpression.class);
public static final String OBJECT_TYPE = Object.class.getSimpleName();
protected static final Pattern HL7_SPEC_SPLITTER = Pattern.compile(".");
private final String type;
private final EvaluationResult defaultValue;
private final boolean required;
private final List hl7specs;
private List variables;
private Condition condition;
private Map constants;
private boolean useGroup;
public AbstractExpression(String type, String defaultValue, boolean required, String specs,
Map rawvariables, String condition, Map constants,
boolean useGroup) {
if (type == null) {
this.type = OBJECT_TYPE;
} else {
this.type = type;
}
if (defaultValue != null) {
this.defaultValue = EvaluationResultFactory.getEvaluationResult(defaultValue);
} else {
this.defaultValue = null;
}
this.useGroup = useGroup;
this.required = required;
this.hl7specs = getSpecList(specs, useGroup);
if (StringUtils.isNotBlank(condition)) {
this.condition = ConditionUtil.createCondition(condition);
}
this.constants = new HashMap<>();
if (constants != null && !constants.isEmpty()) {
this.constants.putAll(constants);
}
initVariables(rawvariables);
}
private void initVariables(Map rawvariables) {
this.variables = new ArrayList<>();
if (rawvariables != null) {
for (Entry e : rawvariables.entrySet()) {
this.variables.add(VariableGenerator.parse(e.getKey(), e.getValue()));
}
}
}
@Override
public String getType() {
return type;
}
@Override
public EvaluationResult getDefaultValue() {
return defaultValue;
}
public boolean isRequired() {
return required;
}
@Override
public List getspecs() {
return new ArrayList<>(this.hl7specs);
}
@Override
public List getVariables() {
return new ArrayList<>(variables);
}
/**
* Evaluates the expression and generated single or multiple resources based on the expression
* values. If expression (reference and resource) ends with * then for that expression a the
* Generic result includes list of values.
*
* @see io.github.linuxforhealth.api.Expression#evaluate(io.github.linuxforhealth.api.InputDataExtractor,
* java.util.Map, EvaluationResult)
*/
@Override
public EvaluationResult evaluate(InputDataExtractor dataSource,
Map contextValues, EvaluationResult baseValue) {
Preconditions.checkArgument(dataSource != null, "dataSource cannot be null");
Preconditions.checkArgument(contextValues != null, "contextValues cannot be null");
Preconditions.checkArgument(baseValue != null, "baseValue cannot be null");
EvaluationResult result;
try {
LOGGER.debug("Started Evaluating expression {} ", this);
Map localContextValues = new HashMap<>(contextValues);
if (!baseValue.isEmpty()) {
localContextValues.put(baseValue.getIdentifier(), baseValue);
}
this.constants.entrySet().forEach(e -> localContextValues.put(e.getKey(),
EvaluationResultFactory.getEvaluationResult(e.getValue())));
if (this.isMultiple()) {
result = evaluateMultiple(dataSource, localContextValues, baseValue);
} else {
result = evaluateSingle(dataSource, localContextValues, baseValue);
}
LOGGER.debug("Completed Evaluating the expression {} returned result {}", this, result);
if (this.isRequired() && (result == null || result.isEmpty())) {
String stringRep = this.toString();
RuntimeException e = new RequiredConstraintFailureException(
"Failure in Evaluating expression :" + stringRep);
LOGGER.warn("Failure encountered during evaluation of expression {} , exception {}", this,
e);
throw e;
} else {
return result;
}
} catch (DataExtractionException | IllegalArgumentException e) {
LOGGER.warn("Failure encountered during evaluation of expression {} , exception {}", this,
e);
return null;
}
}
private EvaluationResult evaluateSingle(InputDataExtractor dataSource,
Map contextValues, EvaluationResult baseInputValue) {
EvaluationResult baseValue;
if (this.getspecs() == null || this.getspecs().isEmpty()) {
baseValue = baseInputValue;
} else {
baseValue = SpecificationUtil.extractValueForSpec(this.getspecs(), dataSource,
ImmutableMap.copyOf(contextValues));
}
LOGGER.debug("Evaluating Single value for expression {} returned hl7 value {} ", this,
baseValue);
return generateValue(dataSource, contextValues, baseValue);
}
private EvaluationResult evaluateMultiple(InputDataExtractor dataSource,
Map contextValues, EvaluationResult baseinputValue) {
List