
package org.openspml.browser;

import java.util.*;

import org.openspml.util.*;
import org.openspml.message.*;


/**
 * Very simple parser for filter expressions.
 * Not supporting much yet, but enough for demos.
 */
public class Parser {

    Lexer _lex;

    public Parser() {
    }

    /**
     * Parse a query entered as text into a Filter object.
     * Not handling everything.
     *
     *   accountId = "jlarson" and email = "jlarson@waveset.com"
     *
     * Should try to (shudder) support LDAP filter syntax, but
     * SQL would be nicer
     * 
     * Once this gets working move to the Filter class.
     */
    public Filter parseFilter(String src) throws Exception {

        Filter filter = null;
        _lex = new Lexer(src);

        FilterTerm root = parseTerm();
        if (root != null) {
            String tok = _lex.nextToken();
            while (tok != null) {
                String op = getLogicalOperator(tok);
                if (op != null) {
                    FilterTerm log = new FilterTerm();
                    log.addOperand(root);
                    log.setOperation(op);
                    root = log;
                }
                else {
                    // must be the start of another term
                    FilterTerm term = parseTerm(tok);
                    root.addOperand(term);
                }
                tok = _lex.nextToken();
            }
        }

        if (root != null) {
            filter = new Filter();
            filter.addTerm(root);
        }
        
        return filter;
    }

    private String getLogicalOperator(String tok) {
        
        String op = null;

        // these turn out to have the same names, but
        // allow for variants

        if ("and".equals(tok))
            op = FilterTerm.OP_AND;

        else if (",".equals(tok))
            op = FilterTerm.OP_AND;

        else if ("or".equals(tok))
            op = FilterTerm.OP_OR;

        else if ("not".equals(tok))
            op = FilterTerm.OP_NOT;

        return op;
    }

    private FilterTerm parseTerm() 
        throws Exception {

        FilterTerm term = null;
        String tok = _lex.nextToken();
        if (tok != null)
            term = parseTerm(tok);

        return term;
    }

    private FilterTerm parseTerm(String name) 
        throws Exception {

        FilterTerm term = new FilterTerm();
        term.setName(name);

        String tok = _lex.nextToken();
        if (tok == null)
            throw new Exception("No operator for term " + term.getName());

            // only equals for now
        if (!tok.equals("="))
            throw new Exception("Operator " + tok + " not supported");

        term.setOperation(FilterTerm.OP_EQUAL);
        tok = _lex.nextToken();
        if (tok == null)
            throw new Exception("No value for term " + term.getName());
            
            // complete, support csv lists?
        term.setValue(tok);

        return term;
    }

    public void dumpFilter(Filter f) {
        if (f != null) {
            SpmlBuffer b = new SpmlBuffer();
            f.toXml(b);
            println(b.toString());
        }
    }

    public static void println(String msg) {
        System.out.println(msg);
    }

    public static void main(String[] args) {

        if (args.length < 1) {
            println("Parser: <string>");
        }
        else {
            try {
                String s = args[0];
                println("Parsing \"" + s + "\"");

                Parser p = new Parser();
                Filter f = p.parseFilter(s);
                if (f == null)
                    println("Empty filter");
                else
                    p.dumpFilter(f);
            }
            catch (Throwable t) {
                println(t.toString());
            }
        }
    }

}    





