Search in sources :

Example 31 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method parse.

/**
 * Parse a path that is part of some other syntax
 *
 * @return
 * @throws PathEngineException
 * @throws Exception
 */
public ExpressionNode parse(FHIRLexer lexer) throws FHIRLexerException {
    ExpressionNode result = parseExpression(lexer, true);
    result.check();
    return result;
}
Also used : ExpressionNode(org.hl7.fhir.dstu2016may.model.ExpressionNode)

Example 32 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method parse.

// --- public API -------------------------------------------------------
/**
 * Parse a path for later use using execute
 *
 * @param path
 * @return
 * @throws PathEngineException
 * @throws Exception
 */
public ExpressionNode parse(String path) throws FHIRLexerException {
    FHIRLexer lexer = new FHIRLexer(path);
    if (lexer.done())
        throw lexer.error("Path cannot be empty");
    ExpressionNode result = parseExpression(lexer, true);
    if (!lexer.done())
        throw lexer.error("Premature ExpressionNode termination at unexpected token \"" + lexer.getCurrent() + "\"");
    result.check();
    return result;
}
Also used : ExpressionNode(org.hl7.fhir.dstu2016may.model.ExpressionNode)

Example 33 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method check.

/**
 * check that paths referred to in the ExpressionNode are valid
 *
 * xPathStartsWithValueRef is a hack work around for the fact that FHIR Path sometimes needs a different starting point than the xpath
 *
 * returns a list of the possible types that might be returned by executing the ExpressionNode against a particular context
 *
 * @param context - the logical type against which this path is applied
 * @throws DefinitionException
 * @throws PathEngineException
 * @if the path is not valid
 */
public TypeDetails check(Object appContext, String resourceType, String context, ExpressionNode expr) throws FHIRLexerException, PathEngineException, DefinitionException {
    // if context is a path that refers to a type, do that conversion now
    TypeDetails types;
    if (!context.contains("."))
        types = new TypeDetails(CollectionStatus.SINGLETON, context);
    else {
        StructureDefinition sd = worker.fetchTypeDefinition(context.substring(0, context.indexOf('.')));
        if (sd == null)
            throw new PathEngineException("Unknown context " + context);
        ElementDefinitionMatch ed = getElementDefinition(sd, context, true);
        if (ed == null)
            throw new PathEngineException("Unknown context element " + context);
        if (ed.fixedType != null)
            types = new TypeDetails(CollectionStatus.SINGLETON, ed.fixedType);
        else if (ed.getDefinition().getType().isEmpty() || isAbstractType(ed.getDefinition().getType()))
            types = new TypeDetails(CollectionStatus.SINGLETON, context);
        else {
            types = new TypeDetails(CollectionStatus.SINGLETON);
            for (TypeRefComponent t : ed.getDefinition().getType()) types.addType(t.getCode());
        }
    }
    return executeType(new ExecutionTypeContext(appContext, resourceType, types), types, expr, true);
}
Also used : TypeDetails(org.hl7.fhir.dstu2016may.model.ExpressionNode.TypeDetails) StructureDefinition(org.hl7.fhir.dstu2016may.model.StructureDefinition) TypeRefComponent(org.hl7.fhir.dstu2016may.model.ElementDefinition.TypeRefComponent) PathEngineException(org.hl7.fhir.exceptions.PathEngineException)

Example 34 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException in project org.hl7.fhir.core by hapifhir.

the class FHIRPathEngine method parsePartial.

/**
 * Parse a path for later use using execute
 *
 * @param path
 * @return
 * @throws PathEngineException
 * @throws Exception
 */
public ExpressionNodeWithOffset parsePartial(String path, int i) throws FHIRLexerException {
    FHIRLexer lexer = new FHIRLexer(path, i);
    if (lexer.done()) {
        throw lexer.error("Path cannot be empty");
    }
    ExpressionNode result = parseExpression(lexer, true);
    result.check();
    return new ExpressionNodeWithOffset(lexer.getCurrentStart(), result);
}
Also used : ExpressionNode(org.hl7.fhir.r4b.model.ExpressionNode)

Example 35 with FHIRLexerException

use of org.hl7.fhir.r5.utils.FHIRLexer.FHIRLexerException 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.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.r4b.model.IntegerType) Function(org.hl7.fhir.r4b.model.ExpressionNode.Function) FunctionDetails(org.hl7.fhir.r4b.utils.FHIRPathEngine.IEvaluationContext.FunctionDetails) ExpressionNode(org.hl7.fhir.r4b.model.ExpressionNode) DecimalType(org.hl7.fhir.r4b.model.DecimalType) Quantity(org.hl7.fhir.r4b.model.Quantity) BigDecimal(java.math.BigDecimal)

Aggregations

CommaSeparatedStringBuilder (org.hl7.fhir.utilities.CommaSeparatedStringBuilder)9 ExpressionNode (org.hl7.fhir.r5.model.ExpressionNode)6 ExpressionNode (org.hl7.fhir.dstu2.model.ExpressionNode)5 ExpressionNode (org.hl7.fhir.r4.model.ExpressionNode)4 ExpressionNode (org.hl7.fhir.r4b.model.ExpressionNode)4 BigDecimal (java.math.BigDecimal)3 ArrayList (java.util.ArrayList)3 HashMap (java.util.HashMap)3 ExpressionNode (org.hl7.fhir.dstu2016may.model.ExpressionNode)3 ExpressionNode (org.hl7.fhir.dstu3.model.ExpressionNode)3 PathEngineException (org.hl7.fhir.exceptions.PathEngineException)3 SourceLocation (org.hl7.fhir.utilities.SourceLocation)3 Base (org.hl7.fhir.dstu2.model.Base)2 DefinitionException (org.hl7.fhir.exceptions.DefinitionException)2 FHIRException (org.hl7.fhir.exceptions.FHIRException)2 IOException (java.io.IOException)1 HashSet (java.util.HashSet)1 List (java.util.List)1 NotImplementedException (org.apache.commons.lang3.NotImplementedException)1 TypeRefComponent (org.hl7.fhir.dstu2.model.ElementDefinition.TypeRefComponent)1