Package simtools.data

Source Code of simtools.data.DataSourceCollection$Container

/* ==============================================
* Simtools : The tools library used in JSynoptic
* ==============================================
*
* Project Info:  http://jsynoptic.sourceforge.net/index.html
*
* This library 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 library 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
* library; 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: DataSourceCollection.java,v 1.15 2008/09/08 10:12:57 ogor Exp $
*
* Changes
* -------
* 25-Sep-2003 : Initial public release (NB);
*
*/
package simtools.data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Vector;

import simtools.data.buffer.Buffer;
import simtools.data.buffer.BufferedDataSource;
import simtools.data.buffer.ResizeableBuffer;
import simtools.util.ListenerManager;
import simtools.util.NumberStringComparator;

/**
* A data source collection gathers data sources with strong interdependancy For
* example, all the data source values may be read from the same file.
*
* This strong inter-dependancy is highlighted by: - The delegation of
* CollectiveDataSource methods here - The same indexing system for all
* CollectiveDataSource - A common update mechanism.
*
* This is an abstract class. Default implementation handles indexing and update
* mechanism, but subclasses are responsible for handling values together with
* setting the index corresponding to those values.
*
* Two sets of methods are provided: one uses CollectiveDataSource parameters
* and the other uses integer = position in the vector of the corresponding
* CollectiveDataSource. They are of course equivalent and the first calls the
* second. Thus, subclasses should only implement methods with the vector-like
* API, not the ones with the CollectiveDataSource parameters.
*/
public abstract class DataSourceCollection extends Vector {
    // listener helpers to avoid code dup
    protected ListenerManager listeners = new ListenerManager();

    protected ListenerManager endNotificationListeners = new ListenerManager();

    // Index
    protected long startIndex, lastIndex;

    protected Buffer[] buffers;

    /**
     * to get quickly the StreamingDataSource in the vector according to its
     * name
     */
    protected HashMap map = null;

    public DataSourceCollection() {
        super();
        startIndex = lastIndex = -1;
        // initialize cached index with negative value => not cached
        buffers = null;
    }

    /**
     * Common indexation system for all members of this collection
     */
    public long getStartIndex() throws UnsupportedOperation {
        if (startIndex >= 0) {
            return startIndex;
        }
        throw new UnsupportedOperation();
    }

    public long getLastIndex() throws UnsupportedOperation {
        if (lastIndex >= 0) {
            return lastIndex;
        }
        throw new UnsupportedOperation();
    }

    public long computeStartIndex() throws UnsupportedOperation {
        if (startIndex >= 0) {
            return startIndex;
        }
        throw new UnsupportedOperation();
    }

    public long computeLastIndex() throws UnsupportedOperation {
        if (lastIndex >= 0) {
            return lastIndex;
        }
        throw new UnsupportedOperation();
    }

    // Same, but for individual Sources => default is that index is common
    public long getStartIndex(int i) throws UnsupportedOperation {
        return getStartIndex();
    }

    public long getLastIndex(int i) throws UnsupportedOperation {
        return getLastIndex();
    }

    public long computeStartIndex(int i) throws UnsupportedOperation {
        return computeStartIndex();
    }

    public long computeLastIndex(int i) throws UnsupportedOperation {
        return computeLastIndex();
    }

    public void setSlice(long min, long max) {
        // propagate info to buffers
        if (buffers != null) {
            for (int i = 0; i < size(); i++) {
                if (buffers[i] != null) {
                    buffers[i].setSlice(min, max);
                    // Do nothing else by default, subclass to decide what to do
                }
            }
        }
    }

    // Our own information
    public DataInfo getInformation() {
        return null;
    }

    /**
     * Kind of the data source at position i, Object by default
     *
     * @return the i-th data source kind
     */
    public int getKind(int i) {
        return ValueProvider.ObjectProvider;
    }

    /**
     * Returns the more specialized superclass of all objects returned by the
     * i-th data source. Returns Object by default in the base implementation,
     * subclass should specialize if possible.
     */
    public Class valueClass(int i) {
        return Object.class;
    }

    /**
     * @param id
     * @return data source related to a string id
     */
    public DataSource get(String id) {
        if (map != null) {
            // Should be the fastest way to get a DataSource from a string id
           return (DataSource) map.get(id);
           
        } else {
            if (id == null) {
                return null;
            }
            for (int j = 0; j < size(); j++) {
                DataSource ds = (DataSource) get(j);
                if (id.equals(DataInfo.getId(ds))) {
                    return ds;
                }
            }
            return null;
        }
    }

    /**
     * Buffer methods
     */
    /**
     * Internal method for the buffer package only, could lead to
     * inconsistencies if misused. User classes should use bufferize instead.
     */
    public void attachBuffer(int i, Buffer b) {
        if (buffers == null) {
            buffers = new Buffer[size()];
        }
        buffers[i] = b;
    }

    /**
     * Public method to put a buffer on a data source. This function uses the
     * default buffer for this collection.
     *
     * @param i
     *            The position of the datasource to bufferize
     */
    public void bufferize(int i) throws UnsupportedOperation {
        bufferize(i, new ResizeableBuffer());
    }

    /**
     * Public method to put a buffer on a data source
     *
     * @param i
     *            The position of the datasource to bufferize
     * @param b
     *            The buffer to use. It must have been created using the
     *            datasource at position i, or a null provider (in which case,
     *            the datasource at position i will be used automatically). An
     *            UnsupportedOperation exception is thrown otherwise.
     */
    public void bufferize(int i, Buffer b) throws UnsupportedOperation {
        if (get(i) instanceof BufferedDataSource) {
            return; // done already
        }
        if ((b.getProvider() != null) && (!b.getProvider().equals(get(i)))) {
            throw new UnsupportedOperation();
        }
        b.setProvider((ValueProvider) get(i));
        // this will in turn call back attachBuffer
        set(i, new BufferedDataSource(b));
    }

    /**
     * Public method to put a buffer on a data source
     *
     * @param b
     *            The buffer to use. It must have been created using a null
     *            provider. The buffer will then be cloned and applied to all
     *            datasources using the bufferize(int,Buffer) function.
     */
    public void bufferize(Buffer b) throws UnsupportedOperation {
        if (b.getProvider() != null) {
            throw new UnsupportedOperation();
        }
        for (int i = 0; i < size(); i++) {
            bufferize(i, (Buffer) b.clone());
        }
    }

    /**
     * Methods for subclasses to specialize
     */
    public abstract Object getValue(int i, long index) throws DataException;

    // / /** Optimized accessor for type values. Works the same way as provider
    // functions.
    // / */
    // / public type getTypeValue(int i, long index) throws DataException {
    // / Object o = getValue(i, index);
    // / if (o == null) return 0;
    // / if (o instanceof String) o =
    // NumberStringComparator.stringToNumber((String)o);
    // / if (o == null) return 0;
    // / if (o instanceof Number) return ((Number)o).typeValue();
    // / return 0;
    // / }
    // /
    // ------ START of perl-generated corresponding code --------
    /**
     * Optimized accessor for byte values. Works the same way as provider
     * functions.
     */
    public byte getByteValue(int i, long index) throws DataException {
        Object o = getValue(i, index);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).byteValue();
        }
        return 0;
    }

    /**
     * Optimized accessor for short values. Works the same way as provider
     * functions.
     */
    public short getShortValue(int i, long index) throws DataException {
        Object o = getValue(i, index);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).shortValue();
        }
        return 0;
    }

    /**
     * Optimized accessor for int values. Works the same way as provider
     * functions.
     */
    public int getIntegerValue(int i, long index) throws DataException {
        Object o = getValue(i, index);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).intValue();
        }
        return 0;
    }

    /**
     * Optimized accessor for long values. Works the same way as provider
     * functions.
     */
    public long getLongValue(int i, long index) throws DataException {
        Object o = getValue(i, index);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).longValue();
        }
        return 0;
    }

    /**
     * Optimized accessor for float values. Works the same way as provider
     * functions.
     */
    public float getFloatValue(int i, long index) throws DataException {
        Object o = getValue(i, index);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).floatValue();
        }
        return 0;
    }

    /**
     * Optimized accessor for double values. Works the same way as provider
     * functions.
     */
    public double getDoubleValue(int i, long index) throws DataException {
        Object o = getValue(i, index);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).doubleValue();
        }
        return 0;
    }

    // -------- END of perl-generated corresponding code --------
    public DataInfo getInformation(int i) {
        return null;
    }

    public Object getMin(int i) throws UnsupportedOperation {
        throw new UnsupportedOperation();
    }

    public Object getMax(int i) throws UnsupportedOperation {
        throw new UnsupportedOperation();
    }

    // / public type getTypeMin(int i) throws DataException {
    // / Object o = getMin(i);
    // / if (o == null) return 0;
    // / if (o instanceof String) o =
    // NumberStringComparator.stringToNumber((String)o);
    // / if (o == null) return 0;
    // / if (o instanceof Number) return ((Number)o).typeValue();
    // / return 0;
    // / }
    // /
    // / public type getTypeMax(int i) throws DataException {
    // / Object o = getMax(i);
    // / if (o == null) return 0;
    // / if (o instanceof String) o =
    // NumberStringComparator.stringToNumber((String)o);
    // / if (o == null) return 0;
    // / if (o instanceof Number) return ((Number)o).typeValue();
    // / return 0;
    // / }
    // /
    // ------ START of perl-generated corresponding code --------
    public byte getByteMin(int i) throws DataException {
        Object o = getMin(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).byteValue();
        }
        return 0;
    }

    public byte getByteMax(int i) throws DataException {
        Object o = getMax(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).byteValue();
        }
        return 0;
    }

    public short getShortMin(int i) throws DataException {
        Object o = getMin(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).shortValue();
        }
        return 0;
    }

    public short getShortMax(int i) throws DataException {
        Object o = getMax(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).shortValue();
        }
        return 0;
    }

    public int getIntegerMin(int i) throws DataException {
        Object o = getMin(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).intValue();
        }
        return 0;
    }

    public int getIntegerMax(int i) throws DataException {
        Object o = getMax(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).intValue();
        }
        return 0;
    }

    public long getLongMin(int i) throws DataException {
        Object o = getMin(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).longValue();
        }
        return 0;
    }

    public long getLongMax(int i) throws DataException {
        Object o = getMax(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).longValue();
        }
        return 0;
    }

    public float getFloatMin(int i) throws DataException {
        Object o = getMin(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).floatValue();
        }
        return 0;
    }

    public float getFloatMax(int i) throws DataException {
        Object o = getMax(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).floatValue();
        }
        return 0;
    }

    public double getDoubleMin(int i) throws DataException {
        Object o = getMin(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).doubleValue();
        }
        return 0;
    }

    public double getDoubleMax(int i) throws DataException {
        Object o = getMax(i);
        if (o == null) {
            return 0;
        }
        if (o instanceof String) {
            o = NumberStringComparator.stringToNumber((String) o);
        }
        if (o == null) {
            return 0;
        }
        if (o instanceof Number) {
            return ((Number) o).doubleValue();
        }
        return 0;
    }

    // -------- END of perl-generated corresponding code --------
    public Object computeMin(int i) throws UnsupportedOperation {
        throw new UnsupportedOperation();
    }

    public Object computeMax(int i) throws UnsupportedOperation {
        throw new UnsupportedOperation();
    }

    public int sortedOrder(int i) {
        DataSource ds = (DataSource) get(i);
        if (ds.getSortedOrder() == -2) {
            ds.computeSortedOrder();
        }
        return ds.getSortedOrder();
    }

    public boolean isComparable(int i) {
        return false; // not comparable by default
    }

    // Listeners related functions
    public void addListener(DataSourceCollectionListener dscl) {
        listeners.add(dscl);
    }

    public void removeListener(DataSourceCollectionListener dscl) {
        listeners.remove(dscl);
    }

    public void addEndNotificationListener(EndNotificationListener enl) {
        endNotificationListeners.add(enl);
    }

    public void removeEndNotificationListener(EndNotificationListener enl) {
        endNotificationListeners.remove(enl);
    }

    // Listeners related functions : helpers for child classes
    public void notifyListenersForInfoChange(DataInfo newInfo) {
        synchronized (listeners) {
            int n = listeners.size(); // only one call outside loop
            for (int i = 0; i < n; ++i) {
                DataSourceCollectionListener dscl = (DataSourceCollectionListener) listeners.get(i);
                if (dscl != null) {
                    dscl.DataSourceCollectionInfoChanged(this, newInfo);
                }
            }
        }
    }

    protected void notifyListenersForDataSourceAdded(DataSource ds) {
        synchronized (listeners) {
            int n = listeners.size(); // only one call outside loop
            for (int i = 0; i < n; ++i) {
                DataSourceCollectionListener dscl = (DataSourceCollectionListener) listeners.get(i);
                if (dscl != null) {
                    dscl.DataSourceCollectionDataSourceAdded(this, ds);
                }
            }
        }
    }

    protected void notifyListenersForDataSourceRemoved(DataSource ds) {
        synchronized (listeners) {
            int n = listeners.size(); // only one call outside loop
            for (int i = 0; i < n; ++i) {
                DataSourceCollectionListener dscl = (DataSourceCollectionListener) listeners.get(i);
                if (dscl != null) {
                    dscl.DataSourceCollectionDataSourceRemoved(this, ds);
                }
            }
        }
    }

    protected void notifyListenersForCollectionRemoved() {
        synchronized (listeners) {
            int n = listeners.size(); // only one call outside loop
            for (int i = 0; i < n; ++i) {
                DataSourceCollectionListener dscl = (DataSourceCollectionListener) listeners.get(i);
                if (dscl != null) {
                    dscl.DataSourceCollectionRemoved(this);
                }
            }
        }
    }

    public void removeAllElements() {
        // Notify data sources listeners, that data has been removed
        for (int i = 0; i < size(); i++) {
            DataSource dsToRemove = (DataSource) get(i);
            dsToRemove.notifyListenersForDataReplaced(null);   
        }
        // Notify collection listener that collection has been removed
        notifyListenersForCollectionRemoved();
       
        // Delete collection contents
        super.removeAllElements();
    }

    // Note: "listeners are called only once" is guaranteed by implementation :
    // by using a reference
    // counter in add/remove methods, and by delegating from the collective
    // sources to this collection.
    // So, there is nothing special to do at this point, which is what we want
    // to keep the notification
    // fast
    /**
     * Use this method only when this data source collection is the referer. See
     * class comments for EndNotificationListener. Listeners for data sources in
     * this collection will also be notified, but only once (if a listener
     * listens to more than one data source in this collection, it is notified
     * once).
     */
    public void notifyEndNotificationListeners() {
        synchronized (endNotificationListeners) {
            int n = endNotificationListeners.size(); // only one call outside
            // loop
            for (int i = 0; i < n; ++i) {
                EndNotificationListener enl = (EndNotificationListener) endNotificationListeners.get(i);
                if (enl != null) {
                    enl.notificationEnd(this);
                }
            }
        }
    }

    private final Object hashCode = new Object();

    /**
     * Overrides Vector/AbstractList implementation to get a fix hashcode and be
     * able to put and remove a collection from a HashSet for instance
     */
    public synchronized int hashCode() {
        return hashCode.hashCode();
    }

    /**
     * Checks if a data source collection is compound, i.e. if it provides
     * containers to organize the data source hierarchically
     *
     * @return true if it is compound
     */
    public boolean isCompound() {
        return false;
    }

    /**
     * If the data source collection is compound return the first level
     * collection of containers used to organize the data sources
     *
     * @return the first level collection of containers or null
     */
    public Collection getCollectionContainers() {
        return null;
    }

    //

    public class Container {
        protected final String value;

        protected Collection children;
       
        /**
         * If true, this container does not reflect the data name
         * and shall be squizzed when filtering the data source collection tree
         * with a data source ID
         */
        protected boolean isVirtual;
       

        /**
         * Create a new container with the given value
         */
        public Container(String value) {
           this(value, false);
        }

        /**
         * Create a new container with the given value
         */
        public Container(String value, boolean isVirtual) {
            this.value = value;
            this.isVirtual = isVirtual;
        }

        public void addDataSource(DataSource ds) {
            if (children == null) {
                children = new ArrayList();
            }
            children.add(ds);
        }

        public void addContainer(Container c) {
            if (children == null) {
                children = new ArrayList();
            }
            children.add(c);
        }

        public void setChildren(Collection c) {
            children = c;
        }

        public Collection getChildren() {
            return children;
        }

        /*
         * (non-Javadoc)
         *
         * @see java.lang.Object#toString()
         */
        public String toString() {
            return value;
        }
       
        public boolean isVirtual() {
            return isVirtual;
        }
    }
}
TOP

Related Classes of simtools.data.DataSourceCollection$Container

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.