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

org.jsimpledb.parse.func.AbstractQueryFunction Maven / Gradle / Ivy

The newest version!

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

package org.jsimpledb.parse.func;

import com.google.common.base.Preconditions;

import org.jsimpledb.JTransaction;
import org.jsimpledb.core.ObjType;
import org.jsimpledb.parse.ObjTypeParser;
import org.jsimpledb.parse.ParseException;
import org.jsimpledb.parse.ParseSession;
import org.jsimpledb.parse.expr.AbstractValue;
import org.jsimpledb.parse.expr.ExprParser;
import org.jsimpledb.parse.expr.LiteralNode;
import org.jsimpledb.parse.expr.Node;
import org.jsimpledb.parse.expr.Value;
import org.jsimpledb.util.ParseContext;

/**
 * Support superclass for index queries (simple or composite). Function parameters take one of these forms:
 * 
    *
  1. {@code function(object-type, name, value-type, ...)} (JSimpleDB mode only)\n" *
  2. {@code function(name)}
  3. *
  4. {@code function(storage-id)}
  5. *
*/ abstract class AbstractQueryFunction extends AbstractFunction { private final int minValueTypes; private final int maxValueTypes; protected AbstractQueryFunction(String name, int minValueTypes, int maxValueTypes) { super(name); Preconditions.checkArgument(minValueTypes >= 1 && maxValueTypes >= minValueTypes, "invalid min/max"); this.minValueTypes = minValueTypes; this.maxValueTypes = maxValueTypes; } /** * Returns one of: {@link Integer}, {@link Node}, or {@link Node}{@code []}. */ @Override public Object parseParams(final ParseSession session, final ParseContext ctx, final boolean complete) { // Check existence of first parameter if (ctx.tryLiteral(")")) throw new ParseException(ctx, "at least one parameter required"); // Attempt to parse second form final int typeStart = ctx.getIndex(); int storageId = -1; try { storageId = this.parseName(session, ctx, complete); } catch (ParseException e) { if (complete && !e.getCompletions().isEmpty()) throw e; } if (storageId != -1) { ctx.skipWhitespace(); if (!ctx.tryLiteral(")")) throw new ParseException(ctx, "expected `)'").addCompletion(") "); return storageId; } ctx.setIndex(typeStart); // Attempt to parse first form with type name (JSimpleDB mode only) Node param1 = null; if (session.getMode().hasJSimpleDB()) { try { final ObjType objType = new ObjTypeParser().parse(session, ctx, complete); final int mark = ctx.getIndex(); ctx.skipWhitespace(); if (!ctx.tryLiteral(",")) // verify this is the first form throw new ParseException(ctx); ctx.setIndex(mark); param1 = new LiteralNode(session.getJSimpleDB().getJClass(objType.getStorageId()).getType()); } catch (ParseException e) { ctx.setIndex(typeStart); } } // Parse first parameter as expression if (param1 == null) param1 = ExprParser.INSTANCE.parse(session, ctx, complete); // Only one parameter? Assume it's the third form. ctx.skipWhitespace(); if (ctx.tryLiteral(")")) return param1; // Multi-parameter form requires JSimpleDB mode if (!session.getMode().hasJSimpleDB()) throw new ParseException(ctx, "expected `)' (JSimpleDB mode required for multiple params)").addCompletion(") "); if (!ctx.tryLiteral(",")) throw new ParseException(ctx, "expected `,' between " + this.getName() + "() function parameters").addCompletion(", "); this.spaceParser.parse(ctx, complete); // Parse value types final Node[] valueTypeNodes = this.parseExpressionParams(session, ctx, complete, 1, 1 + this.minValueTypes, 1 + this.maxValueTypes); // Done final Node[] result = new Node[1 + valueTypeNodes.length]; result[0] = param1; System.arraycopy(valueTypeNodes, 0, result, 1, valueTypeNodes.length); return result; } /** * Attempt to parse an index name. * * @param session parse session * @param ctx parse context * @param complete false if parse is "for real", true if only for tab completion calculation * @return indexed field or composite index storage ID */ protected abstract int parseName(ParseSession session, ParseContext ctx, boolean complete); @Override public Value apply(ParseSession session, Object result) { // Handle second and third forms Integer storageId = null; if (result instanceof Node) storageId = (((Node)result).evaluate(session)).checkIntegral(session, "queryIndex()"); else if (result instanceof Integer) storageId = (Integer)result; if (storageId != null) return this.apply(session, (int)storageId); // Handle first form final Node[] params = (Node[])result; final Class objectType = params[0].evaluate(session).checkType(session, this.getName(), Class.class); final String fieldName = params[1].evaluate(session).checkType(session, this.getName(), String.class); final Class[] valueTypes = new Class[params.length - 2]; for (int i = 0; i < valueTypes.length; i++) valueTypes[i] = params[2 + i].evaluate(session).checkType(session, this.getName(), Class.class); return this.apply(session, objectType, fieldName, valueTypes); } /** * Handle single argument form. * * @param session parse session * @param storageId field or composite index storage ID * @return query return value */ protected Value apply(ParseSession session, final int storageId) { return new AbstractValue() { @Override public Object get(ParseSession session) { if (session.getMode().hasJSimpleDB()) return JTransaction.getCurrent().queryIndex(storageId); else return session.getTransaction().queryIndex(storageId); } }; } /** * Handle multi-argument form. * * @param session parse session * @param objectType target object type * @param name field or composite index name * @param valueTypes index value type(s) * @return query return value */ protected abstract Value apply(ParseSession session, Class objectType, String name, Class[] valueTypes); }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy