public static XpathAnalysis analyze()

in drools-drl/drools-drl-parser/src/main/java/org/drools/drl/parser/lang/XpathAnalysis.java [132:286]


    public static XpathAnalysis analyze(String xpath) {
        List<XpathPart> parts = new ArrayList<>();
        boolean lazyPath = false;
        int i = 0;
        if (xpath.length() >= 1 && xpath.charAt(0) == '/') {
            i = 1;
        } else if (xpath.length() >= 2 && xpath.charAt(0) == '?' && xpath.charAt(1) == '/') {
            lazyPath = true;
            i = 2;
        } else {
            return new XpathAnalysis(parts, "An oopath expression has to start with '/' or '?/'");
        }

        List<String> constraints = new ArrayList<>();

        String inlineCast = null;
        int index = -1;
        int lastStart = i;
        int nestedParam = 0;
        int nestedSquare = 0;

        boolean iterate = true;
        boolean isQuoted = false;
        boolean isDoubleQuoted = false;
        boolean isInlineCast = false;

        String field = null;
        String error = null;
        int partStart = 0;

        for (; i < xpath.length() && error == null; i++) {
            switch (xpath.charAt(i)) {
                case '/':
                case '.':
                    if (!isQuoted && nestedParam == 0 && nestedSquare == 0) {
                        if (field == null) {
                            field = xpath.substring(lastStart, xpath.charAt(i-1) == '?' ? i-1 : i).trim();
                        } else if (isInlineCast) {
                            inlineCast = xpath.substring(lastStart, xpath.charAt(i-1) == '?' ? i-1 : i).trim();
                            isInlineCast = false;
                        }
                        parts.add(new XpathPart(field, iterate, lazyPath, constraints, inlineCast, index, partStart));
                        partStart = i;

                        iterate = xpath.charAt(i) == '/';
                        if (xpath.charAt(i-1) == '?') {
                            if (lazyPath) {
                                error = "It is not possible to have 2 non-reactive parts in the same oopath";
                                break;
                            } else {
                                lazyPath = true;
                            }
                        }
                        constraints = new ArrayList<>();
                        inlineCast = null;
                        index = -1;
                        lastStart = i + 1;
                        field = null;
                    }
                    break;
                case '(':
                    if (!isQuoted) {
                        nestedParam++;
                    }
                    break;
                case ')':
                    if (!isQuoted) {
                        nestedParam--;
                        if (nestedParam < 0) {
                            error = "Unbalanced parenthesis";
                        }
                    }
                    break;
                case '#':
                    if (!isQuoted && nestedParam == 0 && nestedSquare == 0) {
                        if (field == null) {
                            field = xpath.substring( lastStart, i ).trim();
                        }
                        lastStart = i+1;
                        isInlineCast = true;
                    }
                    break;
                case '[':
                    if (!isQuoted && nestedParam == 0) {
                        if (nestedSquare == 0) {
                            if (field == null) {
                                field = xpath.substring( lastStart, i ).trim();
                            } else if (isInlineCast) {
                                inlineCast = xpath.substring( lastStart, i ).trim();
                                isInlineCast = false;
                            }
                            lastStart = i+1;
                        }
                        nestedSquare++;
                    }
                    break;
                case ']':
                    if (!isQuoted && nestedParam == 0) {
                        nestedSquare--;
                        if (nestedSquare == 0) {
                            String constraint = xpath.substring( lastStart, i ).trim();
                            if ( Character.isDigit(constraint.charAt( 0 )) ) {
                                try {
                                    index = Integer.parseInt( constraint );
                                } catch (Exception e) {
                                    constraints.add( constraint );
                                }
                            } else {
                                constraints.add( constraint );
                            }
                        } else if (nestedSquare < 0) {
                            error = "Unbalanced square brackets";
                        }
                    }
                    break;
                case ',':
                    if (!isQuoted && nestedParam == 0 && nestedSquare == 1) {
                        String constraint = xpath.substring(lastStart, i).trim();
                        constraints.add(constraint);
                        lastStart = i+1;
                    }
                    break;
                case '"':
                    if (isQuoted) {
                        if (isDoubleQuoted) {
                            isQuoted = false;
                            isDoubleQuoted = false;
                        }
                    } else {
                        isQuoted = true;
                        isDoubleQuoted = true;
                    }
                    break;
                case '\'':
                    if (isQuoted) {
                        if (!isDoubleQuoted) {
                            isQuoted = false;
                        }
                    } else {
                        isQuoted = true;
                    }
                    break;
            }
        }

        if (field == null) {
            field = xpath.substring(lastStart).trim();
        } else if (isInlineCast) {
            inlineCast = xpath.substring(lastStart).trim();
            isInlineCast = false;
        }
        parts.add(new XpathPart(field, iterate, lazyPath, constraints, inlineCast, index, partStart));

        return new XpathAnalysis(parts, error);
    }