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

com.datastax.data.dataset.Parser Maven / Gradle / Ivy



package com.datastax.data.dataset;

import com.datastax.data.dataset.event.DataTableEventAdapter;
import net.sf.jga.fn.*;
import net.sf.jga.fn.adaptor.*;
import net.sf.jga.fn.algorithm.Accumulate;
import net.sf.jga.fn.algorithm.Count;
import net.sf.jga.fn.algorithm.TransformUnary;
import net.sf.jga.fn.arithmetic.Average;
import net.sf.jga.fn.arithmetic.Plus;
import net.sf.jga.fn.arithmetic.ValueOf;
import net.sf.jga.fn.comparison.Max;
import net.sf.jga.fn.comparison.Min;
import net.sf.jga.fn.property.*;
import net.sf.jga.parser.*;
import net.sf.jga.util.FilterIterator;

import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;


class Parser extends JFXGParser {

    private DataTable table;

    private boolean inTableContext = false;

    private boolean inUse = false;

    
    private UnaryFunctor getRowsFn =
        new GetProperty(DataTable.class, "Rows");

    
    private UnaryFunctor getRowCountFn =
        new InvokeNoArgMethod(List.class, "size").compose(getRowsFn);

    
    private UnaryFunctor iterateTableFn =
        new InvokeNoArgMethod(List.class, "iterator")
            .compose(getRowsFn);

    
    private UnaryFunctor getValueFn =
        new GetProperty(DataValue.class, "Value");
    
    
    private Class[] filterCtorArgs = new Class[]{Iterator.class,UnaryFunctor.class};
    private BinaryFunctor,? extends Iterator>
        makeFilterFn = new Construct(filterCtorArgs,FilterIterator.class)
            .compose(new ArrayBinary>());

    public Parser(DataSet set) {
        bindThis(set);
        setUndecoratedDecimal(true);
    }
    
    
    
    

    synchronized boolean isInUse() { return inUse; }

    private Object element;
    
    
    synchronized UnaryFunctorRef parseComputedColumn(DataTable table, DataColumn column, String expression)
        throws ParseException
    {
        inUse = true;
        setCurrentTable(table);
        element = column;
        try {
            ReInit (new java.io.StringBufferInputStream(expression));
            return parseUnaryRef(DataRow.class);
        }
        finally {
            setCurrentTable(null);
            inUse = false;
            element =  null;
        }
    }

    
    synchronized GeneratorRef parseDataValue(String expression, DataValue value) throws ParseException {
        inUse = true;
        inTableContext = true;
        element = value;
        try {
            ReInit (new java.io.StringBufferInputStream(expression));
            return parseGeneratorRef();
        }
        finally {
            inTableContext = false;
            inUse = false;
            element = null;
            setCurrentTable(null);
        }
    }

    
    
    

    
    static Set register(Visitable exp, Object element, DataTableEventAdapter listener) {
        if (exp == null) 
            return new HashSet();
        
        Registrar registrar = new Registrar(element, listener);
        exp.accept(registrar);
        return registrar.sources;
    }

 
    
    
    static void unregister(Visitable exp, DataTableEventAdapter listener, Set dependencies)
    {
        if (exp != null)
            exp.accept(new Unregistrar(listener));

        dependencies.clear();
    }

    
    
    
    static private class Registrar extends AdaptorVisitor
            implements ConstantUnary.Visitor, TransformUnary.Visitor
    {
        
        
        
        private Set sources = new HashSet();

        
        
        
        private Object element;
        
        
        private DataTableEventAdapter listener;
        
        public Registrar(Object element, DataTableEventAdapter listener) {
            this.listener = listener;
            this.element = element;
        }
        
        public void visit(ConstantUnary constant) {
            Object value = constant.fn(null);
            if (value instanceof DataColumn) {
                DataColumn column = (DataColumn) value;
                column.getTable().addDataTableListener(listener);
                sources.add(column);
            }
        }
        
        public void visit(TransformUnary xform) {
            xform.getFunction().accept(this);
        }
        
        public void visit(Bind bind) {
            super.visit(bind);
            Object value = bind.getConstant();
            if (value instanceof DataTable) {
                DataTable table = (DataTable) value;
                table.addDataTableListener(listener);
            }
            else if (value instanceof DataValue) {
                DataValue data = (DataValue) value;
                data.addPropertyChangeListener("value", listener);
                data.addPropertyChangeListener("expression", listener);
                sources.add(data);
            }
        }
    }
        

    
    
    static private class Unregistrar extends AdaptorVisitor
            implements ConstantUnary.Visitor, TransformUnary.Visitor
    {
        private DataTableEventAdapter listener;
        
        public Unregistrar(DataTableEventAdapter listener) {
            this.listener = listener;
        }
        
        public void visit(ConstantUnary constant) {
            Object value = constant.fn(null);
            if (value instanceof DataColumn) {
                DataTable table = ((DataColumn) value).getTable();
                if (table != null)
                    table.removeDataTableListener(listener);
            }
        }
        
        public void visit(TransformUnary xform) {
            xform.getFunction().accept(this);
        }
        
        public void visit(Bind bind) {
            super.visit(bind);
            Object value = bind.getConstant();
            if (value instanceof DataTable) {
                DataTable table = (DataTable) value;
                table.removeDataTableListener(listener);
            }
            else if (value instanceof DataValue) {
                DataValue data = (DataValue) value;
                data.removePropertyChangeListener("value", listener);
                data.removePropertyChangeListener("expression", listener);
            }
        }
    }

    
    
    
    

    protected FunctorRef reservedWord(String name) throws ParseException {
        
        
        if (table == null) {
            DataTable maybeTable = ((DataSet) getBoundObject()).getTable(name);
            if (maybeTable != null) {
                setCurrentTable(maybeTable);
                return new GeneratorRef(new Constant(table), DataTable.class);
            }
        }
        
        
        
        
        if (table != null && name.equals(table.getName()))
            return new GeneratorRef(new Constant(table), DataTable.class);

        
        
        
        if (table != null) {
            DataColumn col = table.getColumn(name);
            if (col != null) {
                
                
                
                
                
                
                
                col.getType();
                if (col.dependsOn(element))
                    throw new UncheckedParseException("Circular Reference Exception");
                
                return makeColumnRef(table, col);
            }
        }

        
        DataValue maybeValue = ((DataSet) getBoundObject()).getValue(name);
        if (maybeValue != null) {
            if (maybeValue.dependsOn(element))
                throw new UncheckedParseException("Circular Reference Exception");
            
            return new GeneratorRef(getValueFn.bind(maybeValue), maybeValue.getType());
        }
        
        return null;
    }

    
    protected FunctorRef reservedField(FunctorRef prefix, String name) throws ParseException {
        if (isTableReference(prefix) && getReferencedTable(prefix).equals(table)) {
            DataColumn col = table.getColumn(name);
            if (col == null) {
                String err = "unknown column {0} in table {1}";
                String msg = MessageFormat.format(err, name, table.getName());
                throw new ParseException(msg);
            }

            return makeColumnRef(table, col);
        }                       

        return super.reservedField(prefix, name);
    }

    
    protected FunctorRef reservedFunction(String name, FunctorRef[] args) throws ParseException{
        if (inTableContext) {
            assert table != null;

            
            
            
            FunctorRef lastArgRef = args[args.length - 1];
            boolean hasFilter = (lastArgRef.getReturnType() == Boolean.class);

            UnaryFunctor filter = (hasFilter) ?
                ((UnaryFunctorRef) lastArgRef).getFunctor():
                new ConstantUnary(Boolean.TRUE);
            
            
            
            if ("count".equals(name)) {
                if (hasFilter) {
                    
                    
                    UnaryFunctor countFn =
                        new ValueOf(Integer.class)
                            .compose(new Count(filter))
                            .compose(iterateTableFn); 
                    
                    return new GeneratorRef(countFn.bind(table), Integer.class);
                }
                else {
                    return new GeneratorRef(getRowCountFn.bind(table), Integer.class);
                }
            }

            UnaryFunctor filterTableFn = (hasFilter) ?
                makeFilterFn.bind2nd(filter).compose(iterateTableFn): iterateTableFn;

            Generator iterateRows = filterTableFn.bind(table);

            
            
            
            
            Class type = args[0].getReturnType();
            if (type.isPrimitive())
                type = getBoxedType(type);
            
            TransformUnary xform = new TransformUnary(((UnaryFunctorRef) args[0]).getFunctor());
            
            
            
            if ("avg".equals(name)) {
                validateArgument(Number.class, type, name);

                Average avg = new Average(type);
                return new GeneratorRef(avg.generate(xform.generate(iterateRows)), type);
            }
            
            
            
            
            BinaryFunctor bf = null;
            
            if ("max".equals(name)) {
                validateArgument(Comparable.class, type, name);
                bf = new Max(new net.sf.jga.util.ComparableComparator());
            }
            else if ("min".equals(name)) {
                validateArgument(Comparable.class, type, name);
                bf = new Min(new net.sf.jga.util.ComparableComparator());
            }
            else if ("sum".equals(name)) {
                validateArgument(Number.class, type, name);
                bf = new Plus(type);
            }
            
            
            
            if (bf != null) {
                Generator gen = new Accumulate(bf).generate(xform.generate(iterateRows));
                return new GeneratorRef(gen, type);
            }
        }

        return super.reservedFunction(name, args);
    }


    
    
    

    
    
    private void setCurrentTable(DataTable table) throws ParseException {
        if (this.table != null && table != null)
            throw new ParseException("Parser is currently associated with table " +this.table);

        this.table = table;
    }

    
    private UnaryFunctorRef makeColumnRef(DataTable table, DataColumn column) {
        
        
        ApplyUnary args =
            new ApplyUnary(new UnaryFunctor[]
                { new Identity(),new ConstantUnary(column) });
        
        
        InvokeMethod getValue =
            new InvokeMethod(DataTable.class,"getValue",
                                               new Class[] {DataRow.class, DataColumn.class});
        
        
        
        UnaryFunctor value = getValue.bind1st(table).compose(args);
        
        
        return new UnaryFunctorRef(value, DataRow.class, ARG_NAME[0], column.getType());
    }
    
    
    
    private boolean isTableReference(FunctorRef ref) {
        return ref != null && ref.getReturnType().equals(DataTable.class) &&
               ref.getReferenceType() == FunctorRef.CONSTANT;
    }

    
    
    private DataTable getReferencedTable(FunctorRef ref) {
        return (DataTable)((GeneratorRef) ref).getFunctor().gen();
    }


    
    private void validateArgument(Class reqType, Class foundType, String fnName)
            throws ParseException
    {
        if (reqType.isAssignableFrom(foundType)) {
            return;
        }
        
        String msg = "Unable to compute {0} of type {1}";
        Object[] msgargs = new Object[] { fnName, foundType.getSimpleName() };
        throw new ParseException(MessageFormat.format(msg, msgargs));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy