Package jsynoptic.data

Source Code of jsynoptic.data.ExpressionDataSource

/* ========================
* JSynoptic : a free Synoptic editor
* ========================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Foundation;
* either version 2.1 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* (C) Copyright 2001-2003, by :
*     Corporate:
*         Astrium SAS
*         EADS CRC
*     Individual:
*         Nicolas Brodu
*
* $Id: ExpressionDataSource.java,v 1.9 2007/06/29 16:36:16 ogor Exp $
*
* Changes
* -------
* 14-Jan-2004 : Creation date (NB);
*
*/
package jsynoptic.data;

import java.util.Iterator;
import java.util.Set;

import jsynoptic.parser.ExpressionNode;
import simtools.data.DataException;
import simtools.data.DataInfo;
import simtools.data.DataSource;
import simtools.data.DataSourceListener;
import simtools.data.NoSuchIndex;
import simtools.data.UnsupportedOperation;

/**
* A data source that evaluate a mathematical expression on other sources to compute
* its values
*/
public class ExpressionDataSource extends DataSource implements DataSourceListener {
   
    protected ExpressionNode rootNode;
    protected Set variables;
    protected DataInfo info;
   
    // Intersection of all the variable data sources definition range
    protected long minIndex = 0;
    protected long maxIndex = 0;
   
    /** min max values if computed */
    protected double min;
    protected double max;
    protected boolean minmaxOk;
   
    protected static String EXPRESSION_DATA_SOURCE_MARKER = "ExpressionDataSource:";
   
    /**
     * @return Returns the variables.
     */
    public Set getVariables() {
        return variables;
    }
   
    /* (non-Javadoc)
     * @see simtools.data.DataSource#getInformation()
     */
    public DataInfo getInformation() {
        return info;
    }
   
    public ExpressionDataSource(DataInfo di, ExpressionNode rootNode) {
        info = di;
        info.id = EXPRESSION_DATA_SOURCE_MARKER + info.id;
       
        this.rootNode = rootNode;
        variables = rootNode.getVariables();
       
        // Remove unknown variable types.
        // Use the occasion to compute our index range (intersection of all ranges)
        // If no data source is used, the index range is irrelevant
        minIndex = 0;
        maxIndex = Long.MAX_VALUE;
        for (Iterator it = variables.iterator(); it.hasNext();) {
            Object o = it.next();
            if (!(o instanceof VariableAssociation)) {
                it.remove();
                continue;
            }
            DataSource ds = ((VariableAssociation)o).ds;
            try {
                minIndex = Math.max(minIndex, ds.getStartIndex());
                maxIndex = Math.min(maxIndex, ds.getLastIndex());
            } catch (UnsupportedOperation e) {
            }
            ds.addListener(this);
        }
        if (maxIndex == Long.MAX_VALUE) maxIndex = 0;
        minmaxOk=false;
    }

    /* (non-Javadoc)
     * @see simtools.data.DataSource#computeMin()
     */
    public Object computeMin() throws UnsupportedOperation {
    if (!minmaxOk) {
      computeMinMax();
    }
    return new Double(min);
  }
  /* (non-Javadoc)
   * @see simtools.data.DataSource#computeMax()
   */
  public Object computeMax() throws UnsupportedOperation {
    if (!minmaxOk) {
      computeMinMax();
    }
    return new Double(max);
  }
   
  /* (non-Javadoc)
   * @see simtools.data.DataSource#getMin()
   */
  public Object getMin() throws UnsupportedOperation {
    if (!minmaxOk) {
      computeMinMax();
    }
    return new Double(min);
  }
  /* (non-Javadoc)
   * @see simtools.data.DataSource#getMax()
   */
  public Object getMax() throws UnsupportedOperation {
    if (!minmaxOk) {
      computeMinMax();
    }
    return new Double(max);
  }
   
    /**
   * @throws UnsupportedOperation
   * 
   */
  protected void computeMinMax() throws UnsupportedOperation {
    Object v0;
    try {
      v0 = getValue(minIndex);
    } catch (DataException e) {
      throw new UnsupportedOperation();
    }
    Number n0;
    if(v0 instanceof Number){
      n0=(Number)v0;
    }
    else{
      throw new UnsupportedOperation();
    }
    min=n0.doubleValue();
    max=n0.doubleValue();
    for(long i=minIndex+1;i<=maxIndex;i++){
      double v;
      try {
        v = ((Number)getValue(i)).doubleValue();
      } catch (DataException e1) {
        break;
      }
      if(v<min){
        min=v;
      }
      if(v>max){
        max=v;
      }
    }
    minmaxOk=true;
  }

  /**
     * @param exp
     * @param node
     */
    public synchronized void changeExpression(String exp, ExpressionNode node) {
        cleanup();
        rootNode = node;
        variables = rootNode.getVariables();
        info.comment = exp;
   
        // Remove unknown variable types.
        // Use the occasion to compute our index range (intersection of all ranges)
        // If no data source is used, the index range is irrelevant
        minIndex = Long.MIN_VALUE;
        maxIndex = Long.MAX_VALUE;
        for (Iterator it = variables.iterator(); it.hasNext();) {
            Object o = it.next();
            if (!(o instanceof VariableAssociation)) {
                it.remove();
                continue;
            }
            DataSource ds = ((VariableAssociation)o).ds;
            try {
                minIndex = Math.max(minIndex, ds.getStartIndex());
                maxIndex = Math.min(maxIndex, ds.getLastIndex());
            } catch (UnsupportedOperation e) {
            }
            ds.addListener(this);
            if (minIndex == Long.MIN_VALUE) minIndex = 0;
        }
       
        computeSortedOrder();
        minmaxOk=false;
        notifyListenersForValueChange(minIndex,maxIndex);
        notifyEndNotificationListeners();
    }
   
    /** Remove the listeners */
    public synchronized void cleanup() {
        for (Iterator it = variables.iterator(); it.hasNext();) {
            DataSource ds = ((VariableAssociation)it.next()).ds;
            ds.removeListener(this);
        }
    }
   
      /* (non-Javadoc)
       * @see simtools.data.ValueProvider#getValue(long)
       */
      public Object getValue(long index) throws DataException {
        if(index<0)
          throw new NoSuchIndex(index);
 
          synchronized (this) {
            // Lock the variables index
            for (Iterator it = variables.iterator(); it.hasNext();) {
                ((VariableAssociation)it.next()).lockIndex(index);
            }
           
            Object ret = null;
           
            try {
                // Compute the value at this index
                ret = rootNode.evaluate();
            }
            finally {
                // Release the variables index
                for (Iterator it = variables.iterator(); it.hasNext();) {
                    ((VariableAssociation)it.next()).releaseIndex();
                }
            }
           
            return ret;
          }
      }
   
   
   
   
    /* (non-Javadoc)
     * @see simtools.data.DataSourceListener#DataSourceValueChanged(simtools.data.DataSource, long, long)
     */
    public void DataSourceValueChanged(DataSource ds, long minIndex, long maxIndex) {
        // Only care if it happens in our range
        if ((minIndex>=this.minIndex) && (maxIndex<=this.maxIndex)){
          minmaxOk=false;
            notifyListenersForValueChange(minIndex, maxIndex);
            notifyEndNotificationListeners();
        }
    }
   
    /* (non-Javadoc)
     * @see simtools.data.DataSourceListener#DataSourceIndexRangeChanged(simtools.data.DataSource, long, long)
     */
    public void DataSourceIndexRangeChanged(DataSource ds, long startIndex, long lastIndex) {
        // One of the sources changed its definition interval => recompute the intersection
        long min = startIndex;
        long max = lastIndex;
        for (Iterator it = variables.iterator(); it.hasNext();) {
            DataSource dsv = ((VariableAssociation)it.next()).ds;
            if (dsv==ds) continue; // Same source, and do not need to use equals() here
            try {
                min = Math.max(min, dsv.getStartIndex());
                max = Math.min(max, dsv.getLastIndex());
            } catch (UnsupportedOperation e) {
            }
        }
        // Update our range
        minIndex = min; maxIndex = max;
        minmaxOk=false;
        notifyListenersForIndexRangeChange(minIndex,maxIndex);
        notifyEndNotificationListeners();
    }
   
    /* (non-Javadoc)
     * @see simtools.data.DataSourceListener#DataSourceInfoChanged(simtools.data.DataSource, simtools.data.DataInfo)
     */
    public void DataSourceInfoChanged(DataSource ds, DataInfo newInfo) {
        // Don't care
    }
   
    /* (non-Javadoc)
     * @see simtools.data.DataSourceListener#DataSourceValueRangeChanged(simtools.data.DataSource)
     */
    public void DataSourceValueRangeChanged(DataSource ds) {
        // Don't care
    }
   
    /* (non-Javadoc)
     * @see simtools.data.DataSourceListener#DataSourceOrderChanged(simtools.data.DataSource, int)
     */
    public void DataSourceOrderChanged(DataSource ds, int newOrder) {
        // Don't care
    }
   
  /* (non-Javadoc)
   * @see simtools.data.DataSourceListener#DataSourceReplaced(simtools.data.DataSource, simtools.data.DataSource)
   */
  public void DataSourceReplaced(DataSource oldData, DataSource newData) {
        for (Iterator it = variables.iterator(); it.hasNext();) {
            Object o = it.next();
            if (!(o instanceof VariableAssociation)) {
                it.remove();
                continue;
            }
            DataSource ds = ((VariableAssociation)o).ds;
            if(ds==newData){
              ((VariableAssociation)o).ds=newData;
                try {
                    minIndex = Math.max(minIndex, newData.getStartIndex());
                    maxIndex = Math.min(maxIndex, newData.getLastIndex());
                } catch (UnsupportedOperation e) {
                }
                newData.addListener(this);
            }
        }
  }
 
  /* (non-Javadoc)
     * @see simtools.data.DataSource#computeLastIndex()
     */
    public long computeLastIndex() throws UnsupportedOperation {
        // If no data source is used, the index range is irrelevant
        long max = Long.MAX_VALUE;
        for (Iterator it = variables.iterator(); it.hasNext();) {
            DataSource ds = ((VariableAssociation)it.next()).ds;
            max = Math.min(max, ds.computeLastIndex());
        }
        maxIndex = max;
        if (maxIndex == Long.MAX_VALUE) maxIndex = 0;
        return maxIndex;
    }
   
   
    /* (non-Javadoc)
     * @see simtools.data.DataSource#computeStartIndex()
     */
    public long computeStartIndex() throws UnsupportedOperation {
        // If no data source is used, the index range is irrelevant
        long min = Long.MIN_VALUE;
        for (Iterator it = variables.iterator(); it.hasNext();) {
            DataSource ds = ((VariableAssociation)it.next()).ds;
            min = Math.max(min, ds.computeStartIndex());
        }
        minIndex = min;
        if (minIndex == Long.MIN_VALUE) minIndex = 0;
        return minIndex;
    }
   
    /* (non-Javadoc)
     * @see simtools.data.DataSource#getLastIndex()
     */
    public long getLastIndex() throws UnsupportedOperation {
        return maxIndex;
    }
   
    /* (non-Javadoc)
     * @see simtools.data.DataSource#getStartIndex()
     */
    public long getStartIndex() throws UnsupportedOperation {
        return minIndex;
    }
   
    /* (non-Javadoc)
     * @see simtools.data.DataSource#isComparable()
     */
    public boolean isComparable() {
        return true;
    }
   
    /* (non-Javadoc)
     * @see java.lang.Object#toString()
     */
    public String toString() {
        return info.label + " = " + info.comment;
    }

    /* (non-Javadoc)
     * @see simtools.data.DataSource#getSourceDependencies()
     */
    public DataSource[] getSourceDependencies() {
        // Make it so that the variables will be serialized before this data source
        // And also that they will exist for the parsing at reload (see ExpressionDataSourceProvider)
        int len = variables.size();
        if (len<=0) return null;
        DataSource[] ret = new DataSource[len];
        int i=0;
        for (Iterator it = variables.iterator(); it.hasNext();) {
            ret[i++] = ((VariableAssociation)it.next()).ds;
        }
        return ret;
    }
   
    /* (non-Javadoc)
   * @see simtools.data.DataSource#getDataSourceInformationClass()
   */
  public String getDataSourceInformationClass(){
    return "simtools.ui.DynamicDataSourceInformation";
  }
}
TOP

Related Classes of jsynoptic.data.ExpressionDataSource

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.