/** * Recursively parses and breaks down the expression string to build a string ValueSource. * * @param schema The schema to pull fields from. * @param expressionString The expression string to build a ValueSource from. * @return The value source represented by the given expressionString */ private static ValueSource buildStringSource(IndexSchema schema, String expressionString) { int paren = expressionString.indexOf('('); String[] arguments; if (paren < 0) { return buildFieldSource(schema, expressionString, FIELD_TYPE); } else { arguments = ExpressionFactory.getArguments( expressionString.substring(paren + 1, expressionString.lastIndexOf(')')).trim()); } String operands = arguments[0]; String operation = expressionString.substring(0, paren).trim(); if (operation.equals(AnalyticsParams.CONSTANT_STRING)) { operands = expressionString.substring(paren + 1, expressionString.lastIndexOf(')')); return new ConstStringSource(operands); } else if (operation.equals(AnalyticsParams.FILTER)) { return buildFilterSource(schema, operands, FIELD_TYPE); } else if (operation.equals(AnalyticsParams.REVERSE)) { if (arguments.length != 1) { throw new SolrException( ErrorCode.BAD_REQUEST, "\"" + AnalyticsParams.REVERSE + "\" requires exactly one argument. The number of arguments in " + expressionString + " is not 1."); } return new ReverseStringFunction(buildStringSource(schema, operands)); } List<ValueSource> subExpressions = new ArrayList<>(); for (String argument : arguments) { subExpressions.add(buildSourceTree(schema, argument)); } if (operation.equals(AnalyticsParams.CONCATENATE)) { return new ConcatStringFunction(subExpressions.toArray(new ValueSource[0])); } if (AnalyticsParams.NUMERIC_OPERATION_SET.contains(operation)) { return buildNumericSource(schema, expressionString); } else if (AnalyticsParams.DATE_OPERATION_SET.contains(operation)) { return buildDateSource(schema, expressionString); } throw new SolrException( ErrorCode.BAD_REQUEST, "The operation [" + expressionString + "] is not supported."); }
/** * Determines what type of value source the expression represents. * * @param expression The expression representing the desired ValueSource * @return NUMBER_TYPE, DATE_TYPE, STRING_TYPE or -1 */ private static int getSourceType(String expression) { int paren = expression.indexOf('('); if (paren < 0) { return FIELD_TYPE; } String operation = expression.substring(0, paren).trim(); if (AnalyticsParams.NUMERIC_OPERATION_SET.contains(operation)) { return NUMBER_TYPE; } else if (AnalyticsParams.DATE_OPERATION_SET.contains(operation)) { return DATE_TYPE; } else if (AnalyticsParams.STRING_OPERATION_SET.contains(operation)) { return STRING_TYPE; } else if (operation.equals(AnalyticsParams.FILTER)) { return FILTER_TYPE; } throw new SolrException( ErrorCode.BAD_REQUEST, "The operation \"" + operation + "\" in [" + expression + "] is not supported."); }
/** * Recursively parses and breaks down the expression string to build a date ValueSource. * * @param schema The schema to pull fields from. * @param expressionString The expression string to build a ValueSource from. * @return The value source represented by the given expressionString */ @SuppressWarnings("deprecation") private static ValueSource buildDateSource(IndexSchema schema, String expressionString) { int paren = expressionString.indexOf('('); String[] arguments; if (paren < 0) { return buildFieldSource(schema, expressionString, DATE_TYPE); } else { arguments = ExpressionFactory.getArguments( expressionString.substring(paren + 1, expressionString.lastIndexOf(')')).trim()); } String operands = arguments[0]; String operation = expressionString.substring(0, paren).trim(); if (operation.equals(AnalyticsParams.CONSTANT_DATE)) { if (arguments.length != 1) { throw new SolrException( ErrorCode.BAD_REQUEST, "The constant date declaration [" + expressionString + "] does not have exactly 1 argument."); } try { return new ConstDateSource(TrieDateField.parseDate(operands)); } catch (ParseException e) { throw new SolrException( ErrorCode.BAD_REQUEST, "The constant " + operands + " cannot be converted into a date.", e); } } else if (operation.equals(AnalyticsParams.FILTER)) { return buildFilterSource(schema, operands, DATE_TYPE); } if (operation.equals(AnalyticsParams.DATE_MATH)) { List<ValueSource> subExpressions = new ArrayList<>(); boolean first = true; for (String argument : arguments) { ValueSource argSource; if (first) { first = false; argSource = buildDateSource(schema, argument); if (argSource == null) { throw new SolrException( ErrorCode.BAD_REQUEST, "\"" + AnalyticsParams.DATE_MATH + "\" requires the first argument be a date operation or field. [" + argument + "] is not a date operation or field."); } } else { argSource = buildStringSource(schema, argument); if (argSource == null) { throw new SolrException( ErrorCode.BAD_REQUEST, "\"" + AnalyticsParams.DATE_MATH + "\" requires that all arguments except the first be string operations. [" + argument + "] is not a string operation."); } } subExpressions.add(argSource); } return new DateMathFunction(subExpressions.toArray(new ValueSource[0])); } if (AnalyticsParams.NUMERIC_OPERATION_SET.contains(operation) || AnalyticsParams.STRING_OPERATION_SET.contains(operation)) { return null; } throw new SolrException( ErrorCode.BAD_REQUEST, "The operation [" + expressionString + "] is not supported."); }