Search in sources :

Example 96 with IntegerType

use of org.hl7.fhir.r4.model.IntegerType in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method parseExpression.

private ExpressionNode parseExpression(FHIRLexer lexer, boolean proximal) throws FHIRLexerException {
    ExpressionNode result = new ExpressionNode(lexer.nextId());
    ExpressionNode wrapper = null;
    SourceLocation c = lexer.getCurrentStartLocation();
    result.setStart(lexer.getCurrentLocation());
    // so we back correct for both +/- and as part of a numeric constant below.
    if (Utilities.existsInList(lexer.getCurrent(), "-", "+")) {
        wrapper = new ExpressionNode(lexer.nextId());
        wrapper.setKind(Kind.Unary);
        wrapper.setOperation(ExpressionNode.Operation.fromCode(lexer.take()));
        wrapper.setStart(lexer.getCurrentLocation());
        wrapper.setProximal(proximal);
    }
    if (lexer.getCurrent() == null) {
        throw lexer.error("Expression terminated unexpectedly");
    } else if (lexer.isConstant()) {
        boolean isString = lexer.isStringConstant();
        if (!isString && (lexer.getCurrent().startsWith("-") || lexer.getCurrent().startsWith("+"))) {
            // the grammar says that this is a unary operation; it affects the correct processing order of the inner operations
            wrapper = new ExpressionNode(lexer.nextId());
            wrapper.setKind(Kind.Unary);
            wrapper.setOperation(ExpressionNode.Operation.fromCode(lexer.getCurrent().substring(0, 1)));
            wrapper.setProximal(proximal);
            wrapper.setStart(lexer.getCurrentLocation());
            lexer.setCurrent(lexer.getCurrent().substring(1));
        }
        result.setConstant(processConstant(lexer));
        result.setKind(Kind.Constant);
        if (!isString && !lexer.done() && (result.getConstant() instanceof IntegerType || result.getConstant() instanceof DecimalType) && (lexer.isStringConstant() || lexer.hasToken("year", "years", "month", "months", "week", "weeks", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds", "millisecond", "milliseconds"))) {
            // it's a quantity
            String ucum = null;
            String unit = null;
            if (lexer.hasToken("year", "years", "month", "months", "week", "weeks", "day", "days", "hour", "hours", "minute", "minutes", "second", "seconds", "millisecond", "milliseconds")) {
                String s = lexer.take();
                unit = s;
                if (s.equals("year") || s.equals("years")) {
                // this is not the UCUM year
                } else if (s.equals("month") || s.equals("months")) {
                // this is not the UCUM month
                } else if (s.equals("week") || s.equals("weeks")) {
                    ucum = "wk";
                } else if (s.equals("day") || s.equals("days")) {
                    ucum = "d";
                } else if (s.equals("hour") || s.equals("hours")) {
                    ucum = "h";
                } else if (s.equals("minute") || s.equals("minutes")) {
                    ucum = "min";
                } else if (s.equals("second") || s.equals("seconds")) {
                    ucum = "s";
                } else {
                    // (s.equals("millisecond") || s.equals("milliseconds"))
                    ucum = "ms";
                }
            } else {
                ucum = lexer.readConstant("units");
            }
            result.setConstant(new Quantity().setValue(new BigDecimal(result.getConstant().primitiveValue())).setUnit(unit).setSystem(ucum == null ? null : "http://unitsofmeasure.org").setCode(ucum));
        }
        result.setEnd(lexer.getCurrentLocation());
    } else if ("(".equals(lexer.getCurrent())) {
        lexer.next();
        result.setKind(Kind.Group);
        result.setGroup(parseExpression(lexer, true));
        if (!")".equals(lexer.getCurrent())) {
            throw lexer.error("Found " + lexer.getCurrent() + " expecting a \")\"");
        }
        result.setEnd(lexer.getCurrentLocation());
        lexer.next();
    } else {
        if (!lexer.isToken() && !lexer.getCurrent().startsWith("`")) {
            throw lexer.error("Found " + lexer.getCurrent() + " expecting a token name");
        }
        if (lexer.isFixedName()) {
            result.setName(lexer.readFixedName("Path Name"));
        } else {
            result.setName(lexer.take());
        }
        result.setEnd(lexer.getCurrentLocation());
        if (!result.checkName()) {
            throw lexer.error("Found " + result.getName() + " expecting a valid token name");
        }
        if ("(".equals(lexer.getCurrent())) {
            Function f = Function.fromCode(result.getName());
            FunctionDetails details = null;
            if (f == null) {
                if (hostServices != null) {
                    details = hostServices.resolveFunction(result.getName());
                }
                if (details == null) {
                    throw lexer.error("The name " + result.getName() + " is not a valid function name");
                }
                f = Function.Custom;
            }
            result.setKind(Kind.Function);
            result.setFunction(f);
            lexer.next();
            while (!")".equals(lexer.getCurrent())) {
                result.getParameters().add(parseExpression(lexer, true));
                if (",".equals(lexer.getCurrent())) {
                    lexer.next();
                } else if (!")".equals(lexer.getCurrent())) {
                    throw lexer.error("The token " + lexer.getCurrent() + " is not expected here - either a \",\" or a \")\" expected");
                }
            }
            result.setEnd(lexer.getCurrentLocation());
            lexer.next();
            checkParameters(lexer, c, result, details);
        } else {
            result.setKind(Kind.Name);
        }
    }
    ExpressionNode focus = result;
    if ("[".equals(lexer.getCurrent())) {
        lexer.next();
        ExpressionNode item = new ExpressionNode(lexer.nextId());
        item.setKind(Kind.Function);
        item.setFunction(ExpressionNode.Function.Item);
        item.getParameters().add(parseExpression(lexer, true));
        if (!lexer.getCurrent().equals("]")) {
            throw lexer.error("The token " + lexer.getCurrent() + " is not expected here - a \"]\" expected");
        }
        lexer.next();
        result.setInner(item);
        focus = item;
    }
    if (".".equals(lexer.getCurrent())) {
        lexer.next();
        focus.setInner(parseExpression(lexer, false));
    }
    result.setProximal(proximal);
    if (proximal) {
        while (lexer.isOp()) {
            focus.setOperation(ExpressionNode.Operation.fromCode(lexer.getCurrent()));
            focus.setOpStart(lexer.getCurrentStartLocation());
            focus.setOpEnd(lexer.getCurrentLocation());
            lexer.next();
            focus.setOpNext(parseExpression(lexer, false));
            focus = focus.getOpNext();
        }
        result = organisePrecedence(lexer, result);
    }
    if (wrapper != null) {
        wrapper.setOpNext(result);
        result.setProximal(false);
        result = wrapper;
    }
    return result;
}
Also used : SourceLocation(org.hl7.fhir.utilities.SourceLocation) IntegerType(org.hl7.fhir.r5.model.IntegerType) Function(org.hl7.fhir.r5.model.ExpressionNode.Function) FunctionDetails(org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails) ExpressionNode(org.hl7.fhir.r5.model.ExpressionNode) DecimalType(org.hl7.fhir.r5.model.DecimalType) Quantity(org.hl7.fhir.r5.model.Quantity) BigDecimal(java.math.BigDecimal)

Example 97 with IntegerType

use of org.hl7.fhir.r4.model.IntegerType in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method opMinus.

private List<Base> opMinus(List<Base> left, List<Base> right, ExpressionNode expr) throws PathEngineException {
    if (left.size() == 0 || right.size() == 0) {
        return new ArrayList<Base>();
    }
    if (left.size() > 1) {
        throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "-");
    }
    if (!left.get(0).isPrimitive() && !left.get(0).hasType("Quantity")) {
        throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "-", left.get(0).fhirType());
    }
    if (right.size() > 1) {
        throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "-");
    }
    if (!right.get(0).isPrimitive() && !((left.get(0).isDateTime() || "0".equals(left.get(0).primitiveValue()) || left.get(0).hasType("Quantity")) && right.get(0).hasType("Quantity"))) {
        throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "-", right.get(0).fhirType());
    }
    List<Base> result = new ArrayList<Base>();
    Base l = left.get(0);
    Base r = right.get(0);
    if (l.hasType("integer") && r.hasType("integer")) {
        result.add(new IntegerType(Integer.parseInt(l.primitiveValue()) - Integer.parseInt(r.primitiveValue())));
    } else if (l.hasType("decimal", "integer") && r.hasType("decimal", "integer")) {
        result.add(new DecimalType(new BigDecimal(l.primitiveValue()).subtract(new BigDecimal(r.primitiveValue()))));
    } else if (l.hasType("decimal", "integer", "Quantity") && r.hasType("Quantity")) {
        String s = l.primitiveValue();
        if ("0".equals(s)) {
            Quantity qty = (Quantity) r;
            result.add(qty.copy().setValue(qty.getValue().abs()));
        }
    } else if (l.isDateTime() && r.hasType("Quantity")) {
        result.add(dateAdd((BaseDateTimeType) l, (Quantity) r, true, expr));
    } else {
        throw makeException(expr, I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "-", left.get(0).fhirType(), right.get(0).fhirType());
    }
    return result;
}
Also used : IntegerType(org.hl7.fhir.r5.model.IntegerType) ArrayList(java.util.ArrayList) DecimalType(org.hl7.fhir.r5.model.DecimalType) Quantity(org.hl7.fhir.r5.model.Quantity) Base(org.hl7.fhir.r5.model.Base) BigDecimal(java.math.BigDecimal)

Example 98 with IntegerType

use of org.hl7.fhir.r4.model.IntegerType in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method opTimes.

private List<Base> opTimes(List<Base> left, List<Base> right, ExpressionNode expr) throws PathEngineException {
    if (left.size() == 0 || right.size() == 0) {
        return new ArrayList<Base>();
    }
    if (left.size() > 1) {
        throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_PLURAL, "*");
    }
    if (!left.get(0).isPrimitive() && !(left.get(0) instanceof Quantity)) {
        throw makeException(expr, I18nConstants.FHIRPATH_LEFT_VALUE_WRONG_TYPE, "*", left.get(0).fhirType());
    }
    if (right.size() > 1) {
        throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_PLURAL, "*");
    }
    if (!right.get(0).isPrimitive() && !(right.get(0) instanceof Quantity)) {
        throw makeException(expr, I18nConstants.FHIRPATH_RIGHT_VALUE_WRONG_TYPE, "*", right.get(0).fhirType());
    }
    List<Base> result = new ArrayList<Base>();
    Base l = left.get(0);
    Base r = right.get(0);
    if (l.hasType("integer") && r.hasType("integer")) {
        result.add(new IntegerType(Integer.parseInt(l.primitiveValue()) * Integer.parseInt(r.primitiveValue())));
    } else if (l.hasType("decimal", "integer") && r.hasType("decimal", "integer")) {
        result.add(new DecimalType(new BigDecimal(l.primitiveValue()).multiply(new BigDecimal(r.primitiveValue()))));
    } else if (l instanceof Quantity && r instanceof Quantity && worker.getUcumService() != null) {
        Pair pl = qtyToPair((Quantity) l);
        Pair pr = qtyToPair((Quantity) r);
        Pair p;
        try {
            p = worker.getUcumService().multiply(pl, pr);
            result.add(pairToQty(p));
        } catch (UcumException e) {
            throw new PathEngineException(e.getMessage(), expr.getOpStart(), expr.toString(), e);
        }
    } else {
        throw makeException(expr, I18nConstants.FHIRPATH_OP_INCOMPATIBLE, "*", left.get(0).fhirType(), right.get(0).fhirType());
    }
    return result;
}
Also used : IntegerType(org.hl7.fhir.r5.model.IntegerType) ArrayList(java.util.ArrayList) Quantity(org.hl7.fhir.r5.model.Quantity) DecimalType(org.hl7.fhir.r5.model.DecimalType) UcumException(org.fhir.ucum.UcumException) PathEngineException(org.hl7.fhir.exceptions.PathEngineException) Base(org.hl7.fhir.r5.model.Base) BigDecimal(java.math.BigDecimal) Pair(org.fhir.ucum.Pair)

Example 99 with IntegerType

use of org.hl7.fhir.r4.model.IntegerType in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method funcCeiling.

private List<Base> funcCeiling(ExecutionContext context, List<Base> focus, ExpressionNode expr) {
    if (focus.size() != 1) {
        throw makeException(expr, I18nConstants.FHIRPATH_FOCUS_PLURAL, "ceiling", focus.size());
    }
    Base base = focus.get(0);
    List<Base> result = new ArrayList<Base>();
    if (base.hasType("integer", "decimal", "unsignedInt", "positiveInt")) {
        Double d = Double.parseDouble(base.primitiveValue());
        try {
            result.add(new IntegerType((int) Math.ceil(d)));
        } catch (Exception e) {
        // just return nothing
        }
    } else {
        makeException(expr, I18nConstants.FHIRPATH_WRONG_PARAM_TYPE, "ceiling", "(focus)", base.fhirType(), "integer or decimal");
    }
    return result;
}
Also used : IntegerType(org.hl7.fhir.r5.model.IntegerType) ArrayList(java.util.ArrayList) Base(org.hl7.fhir.r5.model.Base) UcumException(org.fhir.ucum.UcumException) NotImplementedException(org.apache.commons.lang3.NotImplementedException) DefinitionException(org.hl7.fhir.exceptions.DefinitionException) PathEngineException(org.hl7.fhir.exceptions.PathEngineException) FHIRException(org.hl7.fhir.exceptions.FHIRException) FHIRLexerException(org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException)

Example 100 with IntegerType

use of org.hl7.fhir.r4.model.IntegerType in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method opDiv.

private List<Base> opDiv(List<Base> left, List<Base> right) throws PathEngineException {
    if (left.size() == 0)
        throw new PathEngineException("Error performing div: left operand has no value");
    if (left.size() > 1)
        throw new PathEngineException("Error performing div: left operand has more than one value");
    if (!left.get(0).isPrimitive())
        throw new PathEngineException(String.format("Error performing div: left operand has the wrong type (%s)", left.get(0).fhirType()));
    if (right.size() == 0)
        throw new PathEngineException("Error performing div: right operand has no value");
    if (right.size() > 1)
        throw new PathEngineException("Error performing div: right operand has more than one value");
    if (!right.get(0).isPrimitive())
        throw new PathEngineException(String.format("Error performing div: right operand has the wrong type (%s)", right.get(0).fhirType()));
    List<Base> result = new ArrayList<Base>();
    Base l = left.get(0);
    Base r = right.get(0);
    if (l.hasType("integer") && r.hasType("integer"))
        result.add(new IntegerType(Integer.parseInt(l.primitiveValue()) / Integer.parseInt(r.primitiveValue())));
    else if (l.hasType("decimal", "integer") && r.hasType("decimal", "integer")) {
        Decimal d1;
        try {
            d1 = new Decimal(l.primitiveValue());
            Decimal d2 = new Decimal(r.primitiveValue());
            result.add(new IntegerType(d1.divInt(d2).asDecimal()));
        } catch (UcumException e) {
            throw new PathEngineException(e);
        }
    } else
        throw new PathEngineException(String.format("Error performing div: left and right operand have incompatible or illegal types (%s, %s)", left.get(0).fhirType(), right.get(0).fhirType()));
    return result;
}
Also used : IntegerType(org.hl7.fhir.dstu2016may.model.IntegerType) BigDecimal(java.math.BigDecimal) Decimal(org.fhir.ucum.Decimal) ArrayList(java.util.ArrayList) UcumException(org.fhir.ucum.UcumException) PathEngineException(org.hl7.fhir.exceptions.PathEngineException) ParserBase(org.hl7.fhir.dstu2016may.metamodel.ParserBase) Base(org.hl7.fhir.dstu2016may.model.Base)

Aggregations

ArrayList (java.util.ArrayList)51 BigDecimal (java.math.BigDecimal)34 PathEngineException (org.hl7.fhir.exceptions.PathEngineException)28 IntegerType (org.hl7.fhir.r5.model.IntegerType)26 IntegerType (org.hl7.fhir.r4.model.IntegerType)23 IntegerType (org.hl7.fhir.r4b.model.IntegerType)23 UcumException (org.fhir.ucum.UcumException)19 Test (org.junit.jupiter.api.Test)13 Decimal (org.fhir.ucum.Decimal)12 FHIRException (org.hl7.fhir.exceptions.FHIRException)12 Base (org.hl7.fhir.r4b.model.Base)11 Base (org.hl7.fhir.r5.model.Base)11 IntegerType (org.hl7.fhir.dstu2.model.IntegerType)10 IntegerType (org.hl7.fhir.dstu2016may.model.IntegerType)10 StringType (org.hl7.fhir.r4.model.StringType)10 Patient (org.hl7.fhir.r4.model.Patient)9 Map (java.util.Map)7 ParserBase (org.hl7.fhir.dstu2016may.metamodel.ParserBase)7 DecimalType (org.hl7.fhir.r5.model.DecimalType)7 List (java.util.List)6