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

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

package com.datastax.data.dataset;

import com.datastax.data.dataset.event.DataTableEventAdapter;
import com.datastax.data.dataset.event.RowChangeEvent;
import com.datastax.data.dataset.event.TableChangeEvent;
import net.sf.jga.fn.EvaluationException;
import net.sf.jga.fn.Generator;
import net.sf.jga.fn.adaptor.Constant;
import net.sf.jga.parser.GeneratorRef;
import net.sf.jga.parser.ParseException;
import net.sf.jga.parser.UncheckedParseException;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;


public class DataValue {
    
    
    protected static final String DEFAULT_NAME_PREFIX = "DataValue";
    
    
    private static final NameGenerator NAMEGEN = new NameGenerator(DEFAULT_NAME_PREFIX);
    
    
    private static final Logger LOG = Logger.getLogger(DataValue.class.getName());

    
    
    private PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    
    private DataSet dataSet;
    
    
    private String name;
   
    
    private String expression;
    private Generator exprImpl;

    
    private Class type = Void.TYPE;
    
    
    public DataValue(DataSet ds) {
        assert ds != null;
        this.dataSet = ds;
        name = NAMEGEN.generateName(this);
    }
    
    
    public DataValue(DataSet ds, String name) {
        this(ds);
        if (name != null) {
            setName(name);
        }
    }
    
    
    public void setName(String name) {
        if (this.name != name) {
            assert DataSetUtils.isValidName(name);
            String oldName = this.name;
            this.name = name;
            pcs.firePropertyChange("name", oldName, name);
        }
    }

    
    public String getName() {
        return name;
    }

    
    public DataSet getDataSet() {
        return dataSet;
    }
    
    
    void removeFromDataSet() {
        dataSet = null;
        if (exprImpl != null) {
            Parser.unregister(exprImpl, listener, sources);
        }
    }
    
    
    public String getExpression() {
        return expression;
    }
    
    
    public void setExpression(String expression) {
        if (expression == null) {
            expression = "";
        }
    
        if ( !(expression.equals(this.expression))) {
            if (exprImpl != null) {
                Parser.unregister(exprImpl, listener, sources);
                exprImpl = null;
            }
            
            String oldExpression = this.expression;
            this.expression = expression;
            pcs.firePropertyChange("expression", oldExpression, expression);
        }
    }
    

    
    

    
    
    public Object getValue() {
        assert dataSet != null;
        if (exprImpl == null) {
            parseExpression();
        }
   
        
        try {
            return exprImpl == null ? null : exprImpl.gen();
        } catch (EvaluationException e) {
            LOG.log(Level.WARNING, "Cannot evaluate \""+expression+"\": returning null. {1}",
                    new Object[]{expression, e.getMessage()});
            return null;
        }
    }


    
    public Class getType() {
        if (exprImpl == null) {
            parseExpression();
        }
   
        return type;
    }

    
    private void setType(Class type) {
        if (type == null) {
            String msg = "A DataValue's type may not be null";
            throw new IllegalArgumentException(msg);
        }
        
        if (this.type != type) {
            Class oldType = this.type;
            this.type = type;
            pcs.firePropertyChange("type", oldType, type);
        }
    }


    public String toString() {
        return "Value " +getName()+" == " +getExpression();
    }

    
    Parser getParser() {
        return dataSet.getParser();
    }

    
    
    
    
    
    private boolean isParsing = false;
    
    private void parseExpression() {
        if (exprImpl != null)
            return;
        
        if (expression == null || expression.equals("")) {
            exprImpl = new Constant(null);
            setType(Object.class);
            return;
        } 

        try {
            if (isParsing) {
                throw new UncheckedParseException("Circular Reference Exception");
            }
            
            isParsing = true;
            
            GeneratorRef gen = getParser().parseDataValue(expression, this);
            setType(gen.getReturnType());
         
            exprImpl = gen.getFunctor();
            sources = Parser.register(exprImpl, this, listener);
        }
        catch (ParseException x) {
            if (x.getCause() instanceof UncheckedParseException)
                throw (UncheckedParseException) x.getCause();
            
            x.printStackTrace();
            LOG.log(Level.WARNING, "The expression [{0}] is not valid. {1}",
                    new Object[]{expression, x.getMessage()});
            
            exprImpl = null;
            type = Void.TYPE;

        }
        finally {
            isParsing = false;
        }
    }
    
    
    
    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(listener);
    }
    
   
    public void addPropertyChangeListener(String property, PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(property,  listener);
    }
    
    
    public void removePropertyChangeListener(PropertyChangeListener listener) {
        pcs.removePropertyChangeListener(listener);
    }
    
    
    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        pcs.removePropertyChangeListener(propertyName,  listener);
    }    

    
    
    
    
    
    
    private Set sources = new HashSet();

    

    boolean dependsOn(Object element) {
        if (element == this)
            return true;
        
        for(Object obj : sources) {
            if (obj == element)
                return true;

            if (obj instanceof DataColumn) {
                if (((DataColumn) obj).dependsOn(element))
                    return true;
            }

            if (obj instanceof DataValue) {
                if (((DataValue) obj).dependsOn(element))
                    return true;
            }
        }

        return false;
    }
    
    
    
    

    
    
    

    
    
    

    DataTableEventAdapter listener = new DataTableEventAdapter() {
            public void propertyChange(PropertyChangeEvent evt) {
                super.propertyChange(evt);
                updateValue();
            }

            public void tableLoadComplete(TableChangeEvent evt) { updateValue(); }
            public void tableCleared(TableChangeEvent evt) { updateValue(); }
            public void rowAdded(TableChangeEvent evt) { updateValue(); }
            
            

            public void rowDiscarded(TableChangeEvent evt) { updateValue(); }
            
            public void cellChanged(RowChangeEvent evt) {
                if (sources.contains(evt.getColumnAffected()))
                    updateValue();
            }
            
            public void columnRemoved(TableChangeEvent evt) {
                if (sources.contains(evt.getColumnAffected())) {
                    updateValue();
                }
            }
            
            public void columnChanged(TableChangeEvent evt) {
                if (sources.contains(evt.getColumnAffected()))
                    updateValue();
            }
            
            
            private void updateValue() {
                Object value = getValue();
                pcs.firePropertyChange("value", null, value);
            }
        };
}