Package org.rhq.core.domain.resource.group

Examples of org.rhq.core.domain.resource.group.InvalidExpressionException


            // allow empty lines, by simply ignoring them
            return;
        }

        if (expression.contains("<"))
            throw new InvalidExpressionException("Expressions must not contain the '<' character");

        String condition;
        String value = null;

        /*
         * instead of building '= value' parsing into the below algorithm, let's chop this off early and store it; this
         * makes the rest of the parsing a bit simpler because some ParseContexts need the value immediately in order to
         * properly build up internal maps / constructs to be used in generating the requisite JPQL statement
         *
         * however, since '=' can occur in the names of configuration properties and trait names, we need
         * to process from the end of the word skipping over all characters that are inside brackets
         */
        int equalsIndex = -1;
        boolean insideBrackets = false;
        for (int i = expression.length() - 1; i >= 0; i--) {
            char next = expression.charAt(i);
            if (insideBrackets) {
                if (next == '[') {
                    insideBrackets = false;
                }
            } else {
                if (next == ']') {
                    insideBrackets = true;
                } else if (next == '=') {
                    equalsIndex = i;
                    break;
                }
            }
        }

        if (equalsIndex == -1) {
            condition = expression;
        } else {
            condition = expression.substring(0, equalsIndex);
            value = expression.substring(equalsIndex + 1).trim();
            if (value.equals("")) {
                throw new InvalidExpressionException(INVALID_EXPRESSION_FORM_MSG);
            }
        }

        /*
         * the remainder of the passed expression should be in the form of '[groupBy] condition', so let's tokenize on
         * '.' and ' ' and continue the parse
         */
        List<String> originalTokens = tokenizeCondition(condition);

        String[] tokens = new String[originalTokens.size()];
        for (int i = 0; i < tokens.length; i++) {
            tokens[i] = originalTokens.get(i).toLowerCase();
        }
        log.debug("TOKENS: " + Arrays.asList(tokens));

        /*
         * build the normalized expression outside of the parse, to keep the parse code as clean as possible;
         * however, this string will be used to determine if the expression being added to this evaluator, based
         * on whether it's grouped or not, compared against all expressions seen so far, is valid
         */
        StringBuilder normalizedSubExpressionBuilder = new StringBuilder();
        for (String subExpressionToken : tokens) {
            // do not add modifiers to the normalized expression
            if (subExpressionToken.equals("groupby")) {
                continue;
            } else if (subExpressionToken.equals("memberof")) {
                continue;
            } else if (subExpressionToken.equals("not")) {
                continue;
            } else if (subExpressionToken.equals("empty")) {
                continue;
            }
            normalizedSubExpressionBuilder.append(subExpressionToken);
        }
        String normalizedSubExpression = normalizedSubExpressionBuilder.toString();

        /*
         * it's easier to code a quick solution when each ParseContext can ignore additional whitespace from the
         * original expression
         */
        for (int i = 0; i < tokens.length; i++) {
            tokens[i] = tokens[i].trim();
        }

        // setup some instance-level context data to be manipulated and leveraged during the parse
        context = ParseContext.BEGIN;
        subcontext = null;
        parseIndex = 0;
        isGroupBy = false; // this needs to be reset each time a new expression is added
        isMemberOf = false; // this needs to be reset each time a new expression is added
        comparisonType = ComparisonType.EQUALS; // assume equals, unless "(not) empty" found during the parse

        deepestResourceContext = null;
        expressionType = String.class;

        for (; parseIndex < tokens.length; parseIndex++) {
            String nextToken = tokens[parseIndex];

            if (context == ParseContext.BEGIN) {
                if (nextToken.equals("resource")) {
                    context = ParseContext.Resource;
                    deepestResourceContext = context;

                } else if (nextToken.equals("memberof")) {
                    context = ParseContext.Membership; // ensure proper expression termination
                    String groupName = value;

                    if (null == groupName || groupName.isEmpty() || "=".equals(groupName)) {
                        throw new InvalidExpressionException(INVALID_EXPRESSION_FORM_MSG);
                    }

                    validateSubExpressionAgainstPreviouslySeen(groupName, false, true);
                    isMemberOf = true;
                    populatePredicateCollections(null, groupName);

                } else if (nextToken.equals("groupby")) {
                    context = ParseContext.Modifier;
                    subcontext = ParseSubContext.Pivot;

                } else if (nextToken.equals("not")) {

                    context = ParseContext.Modifier;
                    subcontext = ParseSubContext.Negated;
                    // 'not' must be followed by 'empty' today, but we won't know until next parse iteration
                    // furthermore, we may support other forms of negated expressions in the future

                } else if (nextToken.equals("empty")) {
                    context = ParseContext.Modifier;
                    subcontext = ParseSubContext.Empty;

                } else {
                    throw new InvalidExpressionException(
                        "Expression must either start with 'resource', 'groupby', 'empty', or 'not empty' tokens");
                }
            } else if (context == ParseContext.Modifier) {
                if (subcontext == ParseSubContext.Negated) {
                    if (nextToken.equals("empty")) {
                        subcontext = ParseSubContext.NotEmpty;
                    } else {
                        throw new InvalidExpressionException(
                            "Expression starting with 'not' must be followed by the 'empty' token");
                    }
                } else {
                    // first check for valid forms given the subcontext
                    if (subcontext == ParseSubContext.Pivot || subcontext == ParseSubContext.Empty
                        || subcontext == ParseSubContext.NotEmpty) {
                        if (value != null) {
                            // these specific types of 'modified' expressions must NOT HAVE "= <value>" part
                            throw new InvalidExpressionException(INVALID_EXPRESSION_FORM_MSG);
                        }
                    }

                    // then perform individual processing based on current subcontext
                    if (subcontext == ParseSubContext.Pivot) {
                        // validates the uniqueness of the subexpression after checking for INVALID_EXPRESSION_FORM_MSG
                        validateSubExpressionAgainstPreviouslySeen(normalizedSubExpression, true, false);
                        isGroupBy = true;
                        comparisonType = ComparisonType.NONE;
                    } else if (subcontext == ParseSubContext.NotEmpty) {
                        comparisonType = ComparisonType.NOT_EMPTY;
                    } else if (subcontext == ParseSubContext.Empty) {
                        comparisonType = ComparisonType.EMPTY;
                    } else {
                        throw new InvalidExpressionException("Unknown or unsupported ParseSubContext[" + subcontext
                            + "] for ParseContext[" + context + "]");
                    }

                    if (nextToken.equals("resource")) {
                        context = ParseContext.Resource;
                        deepestResourceContext = context;
                    } else {
                        throw new InvalidExpressionException(
                            "Grouped expressions must be followed by the 'resource' token");
                    }
                }
            } else if (context == ParseContext.Resource) {
                if (comparisonType == ComparisonType.EQUALS) {
                    if (value == null) {
                        // EQUALS filter expressions must HAVE "= <value>" part
                        throw new InvalidExpressionException(INVALID_EXPRESSION_FORM_MSG);
                    }
                    validateSubExpressionAgainstPreviouslySeen(normalizedSubExpression, false, false);
                }

                if (nextToken.equals("parent")) {
                    context = ParseContext.ResourceParent;
                    deepestResourceContext = context;
                } else if (nextToken.equals("grandparent")) {
                    context = ParseContext.ResourceGrandParent;
                    deepestResourceContext = context;
                } else if (nextToken.equals("greatgrandparent")) {
                    context = ParseContext.ResourceGreatGrandParent;
                    deepestResourceContext = context;
                } else if (nextToken.equals("greatgreatgrandparent")) {
                    context = ParseContext.ResourceGreatGreatGrandParent;
                    deepestResourceContext = context;
                } else if (nextToken.equals("child")) {
                    context = ParseContext.ResourceChild;
                    deepestResourceContext = context;
                } else {
                    parseExpression_resourceContext(value, tokens, nextToken);
                }
            } else if ((context == ParseContext.ResourceParent) || (context == ParseContext.ResourceGrandParent)
                || (context == ParseContext.ResourceGreatGrandParent)
                || (context == ParseContext.ResourceGreatGreatGrandParent) || (context == ParseContext.ResourceChild)) {
                // since a parent or child *is* a resource, support the exact same processing
                parseExpression_resourceContext(value, tokens, nextToken);
            } else if (context == ParseContext.ResourceType) {
                if (nextToken.equals("plugin")) {
                    populatePredicateCollections(getResourceRelativeContextToken() + ".resourceType.plugin", value);
                } else if (nextToken.equals("name")) {
                    populatePredicateCollections(getResourceRelativeContextToken() + ".resourceType.name", value);
                } else if (nextToken.equals("category")) {
                    populatePredicateCollections(getResourceRelativeContextToken() + ".resourceType.category",
                        (value == null) ? null : ResourceCategory.valueOf(value.toUpperCase()));
                } else {
                    throw new InvalidExpressionException("Invalid 'type' subexpression: "
                        + PrintUtils.getDelimitedString(tokens, parseIndex, "."));
                }
            } else if (context == ParseContext.Availability) {
                AvailabilityType type = null;
                if (isGroupBy == false) {
                    if (value == null) {
                        // pass through, NULL elements now supported
                    } else if ("up".equalsIgnoreCase(value)) {
                        type = AvailabilityType.UP;
                    } else if ("down".equalsIgnoreCase(value)) {
                        type = AvailabilityType.DOWN;
                    } else if ("disabled".equalsIgnoreCase(value)) {
                        type = AvailabilityType.DISABLED;
                    } else if ("unknown".equalsIgnoreCase(value)) {
                        type = AvailabilityType.UNKNOWN;
                    } else {
                        throw new InvalidExpressionException("Invalid 'resource.availability' comparision value, "
                            + "only 'UP''DOWN''DISABLED''UNKNOWN' are valid values");
                    }
                }
                addJoinCondition(JoinCondition.AVAILABILITY);
                populatePredicateCollections(JoinCondition.AVAILABILITY.alias + ".availabilityType", type);
            } else if (context == ParseContext.Trait) {
                // SELECT res.id FROM Resource res JOIN res.schedules sched, sched.definition def, MeasurementDataTrait trait
                // WHERE def.name = :arg1 AND trait.value = :arg2 AND trait.schedule = sched AND trait.id.timestamp =
                // (SELECT max(mdt.id.timestamp) FROM MeasurementDataTrait mdt WHERE sched.id = mdt.schedule.id)
                String traitName = parseTraitName(originalTokens);
                addJoinCondition(JoinCondition.SCHEDULES);
                populatePredicateCollections(METRIC_DEF_ALIAS + ".name", "%" + traitName + "%", false, false);
                populatePredicateCollections(TRAIT_ALIAS + ".value", value);
                whereStatics.add(TRAIT_ALIAS + ".schedule = " + JoinCondition.SCHEDULES.alias);
                whereStatics.add(TRAIT_ALIAS
                    + ".id.timestamp = (SELECT max(mdt.id.timestamp) FROM MeasurementDataTrait mdt WHERE "
                    + JoinCondition.SCHEDULES.alias + ".id = mdt.schedule.id)");
            } else if (context == ParseContext.Configuration) {
                String prefix;
                JoinCondition joinCondition;
                JoinCondition definitionJoinCondition;

                if (subcontext == ParseSubContext.PluginConfiguration) {
                    prefix = "pluginconfiguration";
                    joinCondition = JoinCondition.PLUGIN_CONFIGURATION;
                    definitionJoinCondition = JoinCondition.PLUGIN_CONFIGURATION_DEFINITION;
                } else if (subcontext == ParseSubContext.ResourceConfiguration) {
                    prefix = "resourceconfiguration";
                    joinCondition = JoinCondition.RESOURCE_CONFIGURATION;
                    definitionJoinCondition = JoinCondition.RESOURCE_CONFIGURATION_DEFINITION;
                } else {
                    throw new InvalidExpressionException("Invalid 'configuration' subexpression: " + subcontext);
                }

                String suffix = originalTokens.get(parseIndex).substring(prefix.length());
                if (suffix.length() < 3) {
                    throw new InvalidExpressionException("Unrecognized connection property '" + suffix + "'");
                }

                if ((suffix.charAt(0) != '[') || (suffix.charAt(suffix.length() - 1) != ']')) {
                    throw new InvalidExpressionException("Property '" + suffix
                        + "' must be contained within '[' and ']' characters");
                }

                String propertyName = suffix.substring(1, suffix.length() - 1);

                addJoinCondition(joinCondition);
                addJoinCondition(definitionJoinCondition);

                populatePredicateCollections(PROP_SIMPLE_ALIAS + ".name", propertyName, false, false);
                populatePredicateCollections(PROP_SIMPLE_ALIAS + ".stringValue", value);

                whereStatics.add(PROP_SIMPLE_ALIAS + ".configuration = " + joinCondition.alias);
                whereStatics.add(PROP_SIMPLE_DEF_ALIAS + ".configurationDefinition = " + definitionJoinCondition.alias);
                whereStatics.add(PROP_SIMPLE_ALIAS + ".name = " + PROP_SIMPLE_DEF_ALIAS + ".name");
                whereStatics.add(PROP_SIMPLE_DEF_ALIAS + ".type != 'PASSWORD'");

            } else if (context == ParseContext.StringMatch) {
                if (expressionType != String.class) {
                    throw new InvalidExpressionException(
                        "Can not apply a string function to an expression that resolves to "
                            + expressionType.getSimpleName());
                }

                String lastArgumentName = getLastArgumentName();
                String argumentValue = (String) whereReplacements.get(lastArgumentName);

                if (nextToken.equals("startswith")) {
                    argumentValue = QueryUtility.escapeSearchParameter(argumentValue) + "%";
                } else if (nextToken.equals("endswith")) {
                    argumentValue = "%" + QueryUtility.escapeSearchParameter(argumentValue);
                } else if (nextToken.equals("contains")) {
                    argumentValue = "%" + QueryUtility.escapeSearchParameter(argumentValue) + "%";
                } else {
                    throw new InvalidExpressionException("Unrecognized string function '" + nextToken
                        + "' at end of condition");
                }

                // fix the value replacement with the JPQL fragment that maps to the specified string function
                whereReplacements.put(lastArgumentName, argumentValue);

                context = ParseContext.END;
            } else if (context == ParseContext.END) {
                throw new InvalidExpressionException("Unrecognized tokens at end of expression");
            } else {
                throw new InvalidExpressionException("Unknown parse context: " + context);
            }
        }

        if (context.isExpressionTerminator() == false) {
            throw new InvalidExpressionException("Unexpected termination of expression");
        }
    }
View Full Code Here


        } else if (nextToken.startsWith("resourceconfiguration")) {
            context = ParseContext.Configuration;
            subcontext = ParseSubContext.ResourceConfiguration;
            parseIndex--; // undo auto-inc, since this context requires element re-parse
        } else {
            throw new InvalidExpressionException("Invalid 'resource' subexpression: "
                + PrintUtils.getDelimitedString(tokens, parseIndex, "."));
        }
    }
View Full Code Here

                    value = Literal.NOTNULL;
                }
            } else if (comparisonType == ComparisonType.EQUALS || comparisonType == ComparisonType.NONE) {
                // pass through
            } else {
                throw new InvalidExpressionException("Unknown or unsupported ComparisonType[" + comparisonType
                    + "] for predicate population");
            }

            if (resourceExpressions.containsKey(predicateName) && whereConditions.containsKey(predicateName)) {
                throw new DuplicateExpressionTypeException(resourceExpressions.get(predicateName));
View Full Code Here

    private String parseTraitName(List<String> originalTokens) throws InvalidExpressionException {
        String prefix = "trait";
        String suffix = originalTokens.get(parseIndex).substring(prefix.length());
        if (suffix.length() < 3) {
            throw new InvalidExpressionException("Unrecognized trait name '" + suffix + "'");
        }
        if ((suffix.charAt(0) != '[') || (suffix.charAt(suffix.length() - 1) != ']')) {
            throw new InvalidExpressionException("Trait name '" + suffix
                + "' must be contained within '[' and ']' characters");
        }
        return suffix.substring(1, suffix.length() - 1);
    }
View Full Code Here

    private void validateSubExpressionAgainstPreviouslySeen(String normalizedSubExpression, boolean grouped,
        boolean membership) throws InvalidExpressionException {
        normalizedSubExpression = stripFunctionSuffix(normalizedSubExpression);
        if (grouped) {
            if (groupedSubExpressions.contains(normalizedSubExpression)) {
                throw new InvalidExpressionException("Redundant 'groupby' expression[" + normalizedSubExpression
                    + "] - these expressions must be unique");
            }
            if (simpleSubExpressions.contains(normalizedSubExpression)) {
                throw new InvalidExpressionException(
                    "Can not group by the same condition you are filtering on, expression[" + normalizedSubExpression
                        + "]");
            }
            groupedSubExpressions.add(normalizedSubExpression);

        } else if (membership) {
            if (memberSubExpressions.contains(normalizedSubExpression)) {
                throw new InvalidExpressionException("Redundant 'memberof' expression[" + normalizedSubExpression
                    + "] - these expressions must be unique");
            }
            memberSubExpressions.add(normalizedSubExpression);
        } else {
            if (groupedSubExpressions.contains(normalizedSubExpression)) {
                throw new InvalidExpressionException(
                    "Can not group by the same condition you are filtering on, expression[" + normalizedSubExpression
                        + "]");
            }
            simpleSubExpressions.add(normalizedSubExpression);
        }
View Full Code Here

TOP

Related Classes of org.rhq.core.domain.resource.group.InvalidExpressionException

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.