Package fr.upem.query

Source Code of fr.upem.query.QueryParser

package fr.upem.query;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;

import fr.upem.query.Query.With;
import fr.upem.query.Query.With.Operator;

class QueryParser {
    private QueryParser() {
        // no instance
    }

    static Query parse(String query) throws ParseException {
        Iterator<String> it = Arrays.asList(query.split(" ")).iterator();
        if (!it.hasNext()) {
            throw new ParseException("empty query ?");
        }
        String token = it.next();
        String selector = "all".equals(token)? Query.ALL: ensureField(token);
        ArrayList<With> withs = new ArrayList<>();
        if (!it.hasNext()) {
            return new Query(selector, withs, Query.NO_SORT, Query.NO_LIMIT);
        }
        token = it.next();
        while ("with".equals(token)) {
            withs.add(parseWith(it));
            if (!it.hasNext()) {
                return new Query(selector, withs, Query.NO_SORT, Query.NO_LIMIT);
            }
            token = it.next();
        }
        String sortedBy = Query.NO_SORT;
        if ("sorted".equals(token)) {
            ensureToken(it, "by");
            if (!(it.hasNext())) {
                throw new ParseException("query too short, sorted by must be followed by a field");
            }
            sortedBy = ensureField(it.next());
            if (!it.hasNext()) {
                return new Query(selector, withs, sortedBy, Query.NO_LIMIT);
            }
            token = it.next();
        }
        if ("limit".equals(token)) {
            if (!(it.hasNext())) {
                throw new ParseException("query too short, limit must be followed by a value");
            }
            token = it.next();
            int limit;
            try {
                limit = Integer.parseInt(token);
            } catch (NumberFormatException e) {
                throw new ParseException("limit must be followed by an integer value: " + token);
            }
            if (!it.hasNext()) {
                return new Query(selector, withs, sortedBy, limit);
            }
            token = it.next();
        }
        throw new ParseException("invalid token " + token);
    }

    private static With parseWith(Iterator<String> it) throws ParseException {
        if (!it.hasNext()) {
            throw new ParseException("query too short, with must be followed by a field name");
        }
        String field = ensureField(it.next());
        Operator operator;
        if (!it.hasNext()) {
            throw new ParseException("query too short, with /field/ must be followed by an operator");
        }
        String token = it.next();
        switch(token) {
            case "equals":
                ensureToken(it, "to");
                operator = Operator.EQUALS_TO;
                break;
            case "less":
                ensureToken(it, "than");
                operator = Operator.LESS_THAN;
                break;
            case "greater":
                ensureToken(it, "than");
                operator = Operator.GREATER_THAN;
                break;
            default:
                throw new ParseException("invalid with operator " + token);
        }
        if (!it.hasNext()) {
            throw new ParseException("query too short, with /field/ operator must be followed by a constant");
        }
        String constant = it.next();
        return new With(field, operator, constant);
    }

    private static void ensureToken(Iterator<String> it, String expected) throws ParseException {
        if (!(it.hasNext())) {
            throw new ParseException("query too short, expect token " + expected);
        }
        String token = it.next();
        if (!expected.equals(token)) {
            throw new ParseException("expect " + expected + " but found " + token);
        }
    }

    private static String ensureField(String token) throws ParseException {
        switch(token) {
            case "name":
            case "gender":
            case "company":
            case "amount":
                return token;
            default:
                throw new ParseException("unknown field " + token);
        }
    }
}
TOP

Related Classes of fr.upem.query.QueryParser

TOP
Copyright © 2018 www.massapi.com. 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.