All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jsimpledb.parse.IndexedFieldParser Maven / Gradle / Ivy

The newest version!

/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package org.jsimpledb.parse;

import java.util.function.Predicate;
import java.util.regex.Matcher;

import org.jsimpledb.core.ComplexField;
import org.jsimpledb.core.Field;
import org.jsimpledb.core.FieldSwitchAdapter;
import org.jsimpledb.core.ObjType;
import org.jsimpledb.core.SimpleField;
import org.jsimpledb.util.ParseContext;

/**
 * Parses the name of an indexed field.
 *
 * 

* Syntax examples: *

    *
  • Person.lastName
  • *
  • Person.friends.element
  • *
  • Person.grades.key
  • *
*/ public class IndexedFieldParser implements Parser { private final SpaceParser spaceParser = new SpaceParser(); private final Predicate> hasIndexedPredicate; @SuppressWarnings("rawtypes") // https://bugs.openjdk.java.net/browse/JDK-8012685 public IndexedFieldParser() { this.hasIndexedPredicate = field -> field instanceof SimpleField ? ((SimpleField)field).isIndexed() : field instanceof ComplexField ? ((ComplexField)field).getSubFields().stream().anyMatch(SimpleField::isIndexed) : false; } @Override @SuppressWarnings("rawtypes") // https://bugs.openjdk.java.net/browse/JDK-8012685 public Result parse(final ParseSession session, final ParseContext ctx, final boolean complete) { // Get object type final ObjType objType = new ObjTypeParser().parse(session, ctx, complete); // Get indexed field name ctx.skipWhitespace(); if (!ctx.tryLiteral(".")) throw new ParseException(ctx, "expected field name").addCompletion("."); ctx.skipWhitespace(); final Matcher fieldMatcher = ctx.tryPattern("\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*"); if (fieldMatcher == null) { throw new ParseException(ctx, "expected field name").addCompletions( objType.getFields().values().stream().filter(this.hasIndexedPredicate).map(Field::getName)); } final String fieldName = fieldMatcher.group(); // Get indexed field final Field field = objType.getFields().values().stream() .filter(f -> f.getName().equals(fieldName)) .filter(this.getFieldFilter()) .findAny().orElseThrow(() -> new ParseException(ctx, "error accessing field `" + fieldName + "': there is no such indexed field in " + objType) .addCompletions(ParseUtil.complete( objType.getFields().values().stream() .filter(this.getFieldFilter()) .filter(this.hasIndexedPredicate) .map(Field::getName), fieldName))); // Get sub-field if field is a complex field return field.visit(new FieldSwitchAdapter() { @Override protected Result caseComplexField(ComplexField field) { // Get sub-field name ctx.skipWhitespace(); if (!ctx.tryLiteral(".")) { throw new ParseException(ctx, "expected sub-field name").addCompletion("."); } final Matcher subfieldMatcher = ctx.tryPattern("\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*"); if (subfieldMatcher == null) { throw new ParseException(ctx, "expected sub-field name").addCompletions(field.getSubFields().stream() .filter(SimpleField::isIndexed) .map(Field::getName)); } final String subFieldName = subfieldMatcher.group(); // Get sub-field final SimpleField subField = field.getSubFields().stream() .filter(f -> f.getName().equals(subFieldName)) .filter(IndexedFieldParser.this.getSubFieldFilter()) .findAny().orElseThrow(() -> new ParseException(ctx, "unknown sub-field `" + subFieldName + "' of complex field `" + fieldName + "'") .addCompletions(ParseUtil.complete( field.getSubFields().stream() .filter(IndexedFieldParser.this.getSubFieldFilter()) .filter(SimpleField::isIndexed) .map(Field::getName), fieldName))); // Done return new Result(fieldName + "." + subFieldName, this.verifyIndexedSimple(subField), field); } @Override protected Result caseField(Field field) { return new Result(fieldName, this.verifyIndexedSimple(field)); } private SimpleField verifyIndexedSimple(Field field) { if (!(field instanceof SimpleField) || !((SimpleField)field).isIndexed()) throw new ParseException(ctx, "expected indexed field"); return (SimpleField)field; } }); } protected Predicate> getFieldFilter() { return field -> true; } protected Predicate> getSubFieldFilter() { return subField -> true; } // Return type /** * Result returned from an {@link IndexedFieldParser} parse. */ public static class Result { private final String fieldName; private final SimpleField field; private final ComplexField parentField; Result(String fieldName, SimpleField field) { this(fieldName, field, null); } Result(String fieldName, SimpleField field, ComplexField parentField) { this.fieldName = fieldName; this.field = field; this.parentField = parentField; } /** * Get the field's name. * * @return field name */ public String getFieldName() { return this.fieldName; } /** * Get the indexed field. * * @return indexed field */ public SimpleField getField() { return this.field; } /** * Get the indexed field's parent field, if any. * * @return indexed field's parent field, or null if the indexed field is not a sub-field */ public ComplexField getParentField() { return this.parentField; } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy