Package simtools.data

Source Code of simtools.data.DataSourcePool

/* ==============================================
* 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: DataSourcePool.java,v 1.22 2009/02/02 10:34:15 ogor Exp $
*
* Changes
* -------
* 25-Sep-2003 : Initial public release (NB);
*
*/
package simtools.data;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

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

/**
* Pool of data source: holds a certain number of data sources, and can send
* action events to listeners in case the pool is modified.
*
* @author Nicolas Brodu
*
* @version 1.0 2001
*/
public class DataSourcePool implements DataSourceCollectionListener {
    /**
     * A global pool for all to use
     */
    public static final DataSourcePool global = new DataSourcePool();

    protected ListenerManager listeners = new ListenerManager();

    protected Vector providers;

    protected NotifySet sources;

    protected NotifySet collections;

    protected Hashtable translations;

    protected boolean notification;

    protected ArrayList localEmptySources;

    /**
     * A looger to dump error or warning messages in a soket, an output stream,
     * a file...
     */
    static Logger _logger = simtools.util.LogConfigurator.getLogger(DataSourcePool.class.getName());

    public DataSourcePool() {
        providers = new Vector();
        sources = new NotifySet();
        collections = new NotifySet();
        translations = new Hashtable();
        localEmptySources = new ArrayList();
        setNotify(true);
    }

    public void addListener(DataSourcePoolListener l) {
        listeners.add(l);
    }

    public void removeListener(DataSourcePoolListener l) {
        listeners.remove(l);
    }

    /**
     * Adds a datasource provider. Providers are especially used to get
     * datasource references back from ids, during internalization, and to get
     * optional information (if any) about the datasources, during
     * serialization. The new provider takes precedence over the existing ones
     * in case of conflict for an id
     */
    public void addProvider(DataSourceProvider p) {
        providers.add(0, p);
    }

    public DataSourceProvider getProviderFor(DataSource ds, DataSourceCollection dsc) {
        Object option = null;
        for (Iterator it = providers.iterator(); it.hasNext();) {
            DataSourceProvider dsp = (DataSourceProvider) it.next();
            option = dsp.getOptionalInformation(ds, dsc);
            if (option != null) {
                return dsp;
            }
        }
        return null;
    }

    /**
     * Removes a datasource provider
     *
     * @return true if the provider was registered.
     */
    public boolean removeProvider(DataSourceProvider p) {
        return providers.remove(p);
    }

    public void addDataSource(DataSource ds) {
        sources.add(ds);
    }

    public void addDataSourceCollection(DataSourceCollection dsc) {
        collections.add(dsc);
        dsc.addListener(this);
    }

    /**
     * Remove all elements contained inside the pool
     * @return
     */
    public boolean removeAllSources(){
        boolean res = true;

        Set c = (Set)collections.clone();
        Iterator it = c.iterator();
        while(it.hasNext() && res){
            res &=removeDataSourceCollection( ((DataSourceCollection)it.next()));
        }

        Set d = (Set)sources.clone();
        it = d.iterator();
        while(it.hasNext() && res){
            res &=removeDataSourceCollection( ((DataSourceCollection)it.next()));
        }
        return res;
    }
   
    public boolean removeDataSource(DataSource ds) {
        if (ds != null) {
           
         // Notify data sources listeners, that data has been removed
            ds.notifyListenersForDataReplaced(null);
        }
        return sources.remove(ds);
    }

    public boolean removeDataSourceCollection(DataSourceCollection dsc) {
        if (dsc != null) {
            dsc.removeAllElements();
        }
        return collections.remove(dsc);
    }

    /**
     * Data source collections
     */
    public Set dataSourceCollections() {
        return collections;
    }

    /**
     * Data sources
     */
    public Set dataSources() {
        return sources;
    }

    /**
     * Apply a buffer to a datasource. Notify the listeners of the change.
     *
     * @param ds
     *            The datasource to act on
     * @param buffer
     *            The buffer. Its data provider will be set to the datasource
     * @return the bufferized data source if the operation succeded, or null
     */
    public DataSource bufferize(DataSource ds, Buffer buffer) {
        if (ds instanceof BufferedDataSource) {
            return ds;
        }
        buffer.setProvider(ds);
        // temporary stop notification => can remove and add safely
        setNotify(false);
        if (sources.remove(ds)) { // true if it was present
            DataSource ret = new BufferedDataSource(buffer);
            sources.add(ret);
            // reactivate notification and send a 'change' message
            setNotify(true);
            notifyListeners(DataSourcePoolEvent.CHANGE, ret, ds);
            return ret;
        }
        setNotify(true);
        // is in a collection
        for (Iterator it = collections.iterator(); it.hasNext();) {
            DataSourceCollection col = (DataSourceCollection) it.next();
            if (!col.contains(ds)) {
                continue;
            }
            int index = col.indexOf(ds);
            if (index == -1) {
                continue; // ???
            }
            try {
                col.bufferize(index, buffer);
                notifyListeners(DataSourcePoolEvent.CHANGE, col, col);
                return (DataSource) col.get(index);
            } catch (Exception e) {
            }
        }
        // Should not happen if ds is one of our sources
        return null;
    }

    /**
     * Apply a buffer to a datasource collection. Notify the listeners of the
     * change.
     *
     * @param ds
     *            The datasource collection to act on
     * @param buffer
     *            The buffer. See DataSourceCollection.bufferize().
     * @return the bufferized data source collection if the operation succeded,
     *         or null
     */
    public DataSourceCollection bufferize(DataSourceCollection dsc, Buffer buffer) {
        buffer.setProvider(null);
        for (Iterator it = collections.iterator(); it.hasNext();) {
            DataSourceCollection col = (DataSourceCollection) it.next();
            if (col != dsc) {
                continue;
            }
            try {
                col.bufferize(buffer);
                notifyListeners(DataSourcePoolEvent.CHANGE, col, dsc);
                return col;
            } catch (Exception e) {
            }
        }
        // Should not happen if dsc is one of our collections
        return null;
    }

    /**
     * Utility. Look in the datasource and collection sets for the given
     * datasource.
     */
    public boolean contains(DataSource ds) {
        if (sources.contains(ds)) {
            return true;
        }
        for (Iterator it = collections.iterator(); it.hasNext();) {
            if (((DataSourceCollection) it.next()).contains(ds)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Utility. Look in the datasource and collection sets for the given
     * datasource.
     */
    public boolean contains(DataSourceCollection dsc) {
        return collections.contains(dsc);
    }

    /**
     * Utility. Look in the datasource and collection sets for the given
     * datasource id.
     *
     * @return null if this pool doesn't contain a datasource with the given id,
     *         or if multiple source have the same id (for example, in different
     *         collections)
     * @throws DuplicateIdException
     *             when two or more datasource have the given Id
     */
    public DataSource getDataSourceWithId(String id) throws DuplicateIdException {
        if (id == null) {
            return null;
        }
        Vector ret = new Vector();
        try {
            DataSource ds = lookForId(sources, id);
            if (ds != null) {
                ret.add(ds);
            }
        } catch (DuplicateIdException e) {
            ret.addAll(e.conflicts);
        }
        for (Iterator it = collections.iterator(); it.hasNext();) {
            DataSource ds = lookForId((DataSourceCollection) it.next(), id);
            if (ds != null) {
                ret.add(ds);
            }
        }
        if (ret.size() == 0) {
            return null;
        }
        if (ret.size() == 1) {
            return (DataSource) ret.get(0);
        }
        throw new DuplicateIdException(id, ret);
    }

    // avoid code dup
    private DataSource lookForId(Collection c, String id) throws DuplicateIdException {
        if (id == null) {
            return null;
        }
        Vector ret = new Vector();
        for (Iterator it = c.iterator(); it.hasNext();) {
            DataSource ds = (DataSource) it.next();
            if (id.equals(DataInfo.getId(ds))) {
                ret.add(ds);
            }
        }
        if (ret.size() == 0) {
            return null;
        }
        if (ret.size() == 1) {
            return (DataSource) ret.get(0);
        }
        throw new DuplicateIdException(id, ret);
    }

    /**
     * Utility. Look in the datasource and collection sets for the given
     * datasource label.
     *
     * @return null if this pool doesn't contain a datasource with the given
     *         label, or if multiple source have the same label, (for example,
     *         in different collections)
     * @throws DuplicateIdException
     *             when two or more datasource have the given alias
     */
    public DataSource getDataSourceWithLabel(String name) throws DuplicateIdException {
        if (name == null) {
            return null;
        }
        Vector ret = new Vector();
        try {
            DataSource ds = lookForLabel(sources, name);
            if (ds != null) {
                ret.add(ds);
            }
        } catch (DuplicateIdException e) {
            ret.addAll(e.conflicts);
        }
        for (Iterator it = collections.iterator(); it.hasNext();) {
            DataSource ds = lookForLabel((DataSourceCollection) it.next(), name);
            if (ds != null) {
                ret.add(ds);
            }
        }
        if (ret.size() == 0) {
            return null;
        }
        if (ret.size() == 1) {
            return (DataSource) ret.get(0);
        }
        throw new DuplicateIdException(name, ret);
    }

    // avoid code dup
    private DataSource lookForLabel(Collection c, String name) throws DuplicateIdException {
        if (name == null) {
            return null;
        }
        Vector ret = new Vector();
        for (Iterator it = c.iterator(); it.hasNext();) {
            DataSource ds = (DataSource) it.next();
            if (name.equals(DataInfo.getLabel(ds))) {
                ret.add(ds);
            }
        }
        if (ret.size() == 0) {
            return null;
        }
        if (ret.size() == 1) {
            return (DataSource) ret.get(0);
        }
        throw new DuplicateIdException(name, ret);
    }

    /**
     * Utility. Look in the datasource and collection sets for the given
     * datasource alias.
     *
     * @return null if this pool doesn't contain a datasource with the given
     *         alias, or if multiple source have the same alias, (for example,
     *         in different collections)
     * @throws DuplicateIdException
     *             when two or more datasource have the given alias
     */
    public DataSource getDataSourceWithAlias(String name) throws DuplicateIdException {
        if (name == null) {
            return null;
        }
        Vector ret = new Vector();
        try {
            DataSource ds = lookForAlias(sources, name);
            if (ds != null) {
                ret.add(ds);
            }
        } catch (DuplicateIdException e) {
            ret.addAll(e.conflicts);
        }
        for (Iterator it = collections.iterator(); it.hasNext();) {
            DataSource ds = lookForAlias((DataSourceCollection) it.next(), name);
            if (ds != null) {
                ret.add(ds);
            }
        }
        if (ret.size() == 0) {
            return null;
        }
        if (ret.size() == 1) {
            return (DataSource) ret.get(0);
        }
        throw new DuplicateIdException(name, ret);
    }

    // avoid code dup
    private DataSource lookForAlias(Collection c, String name) throws DuplicateIdException {
        if (name == null) {
            return null;
        }
        Vector ret = new Vector();
        for (Iterator it = c.iterator(); it.hasNext();) {
            DataSource ds = (DataSource) it.next();
            if (name.equals(DataInfo.getAlias(ds))) {
                ret.add(ds);
            }
        }
        if (ret.size() == 0) {
            return null;
        }
        if (ret.size() == 1) {
            return (DataSource) ret.get(0);
        }
        throw new DuplicateIdException(name, ret);
    }

    /**
     * Utility. Look in the datasource and collection sets for the given
     * datasource name.
     *
     * @return null if this pool doesn't contain a datasource with the given
     *         alias, or if multiple source have the same alias, (for example,
     *         in different collections)
     * @throws DuplicateIdException
     *             when two or more datasource have the given alias
     */
    public DataSource getDataSourceWithIDOrLabelOrAlias(String name) throws DuplicateIdException {
        DataSource ds = getDataSourceWithId(name);
        if (ds != null) {
            return ds;
        }
        ds = getDataSourceWithLabel(name);
        if (ds != null) {
            return ds;
        }
        ds = getDataSourceWithAlias(name);
        if (ds != null) {
            return ds;
        }
        return null;
    }

    /**
     * Utility. Look in the datasource collection set for the given datasource
     * collection id.
     *
     * @return null if this pool doesn't contain a datasource collection with
     *         the given id
     */
    public DataSourceCollection getDataSourceCollectionWithId(String id) throws DuplicateIdException {
        if (id == null) {
            return null;
        }
        Vector ret = new Vector();
        for (Iterator it = collections.iterator(); it.hasNext();) {
            DataSourceCollection dsc = (DataSourceCollection) it.next();
            if (id.equals(DataInfo.getId(dsc))) {
                ret.add(dsc);
            }
        }
        if (ret.size() == 0) {
            return null;
        }
        if (ret.size() == 1) {
            return (DataSourceCollection) ret.get(0);
        }
        throw new DuplicateIdException(id, ret);
    }

    /**
     * Utility. Look in the datasource collection set for a collection
     * containing the given datasource id.
     *
     * @return null if this pool doesn't contain such a datasource collection
     * @throws DuplicateIdException
     *             when two or more collections contain a datasource with the
     *             given Id
     */
    public DataSourceCollection getCollectionForDataSourceId(String id) throws DuplicateIdException {
        if (id == null) {
            return null;
        }
        Vector ret = new Vector();
        for (Iterator it = collections.iterator(); it.hasNext();) {
            DataSourceCollection dsc = (DataSourceCollection) it.next();
            try {
                if (lookForId(dsc, id) == null) {
                    continue;
                }
            } catch (DuplicateIdException e) {
                // The collection may contain multiple sources with the same ID
            }
            ret.add(dsc);
        }
        if (ret.size() == 0) {
            return null;
        }
        if (ret.size() == 1) {
            return (DataSourceCollection) ret.get(0);
        }
        throw new DuplicateIdException(id, ret);
    }

    /**
     * Asks the providers to resolve a symbolic datasource reference.
     *
     * @param id
     *            The symbolic id of a datasource
     * @param dscId
     *            The symbolic id of a datasourceCollection. May be null
     * @param optionalInformation
     *            Can be set to help the providers. May be null
     * @param add
     *            If set to true, the datasource will be added to the pool if it
     *            could be found, together with its collection if it belongs to
     *            a collection. True by default.
     * @return The desired datasource if it could be found, or null.
     */
    public DataSource provide(String id, String dscId, Object optionalInformation, boolean add) {
        DataSourcePool argPool = add ? this : null;
        for (Iterator it = providers.iterator(); it.hasNext();) {
            DataSource ds = ((DataSourceProvider) it.next()).provide(id, dscId, optionalInformation, argPool);
            if (ds != null) {
                if (ds instanceof EmptyDataSource) {
                    String reason = "Data source cannot be restored with this reference: " + dscId;
                    addLocalEmptySource(id, reason);
                }
                return ds;
            }
        }
        String reason = "This reference cannot be resolved: " + dscId;
        addLocalEmptySource(id, reason);
        return null;
    }

    /**
     * Those are markers we can recognize without any confusion possible for the
     * serialized stream
     */
    protected static final class BufferMarker implements Serializable {
        static final long serialVersionUID = 6047866471365207251L;
    }

    protected static final class DataSourceCollectionMarker implements Serializable {
        static final long serialVersionUID = 8302914329862128731L;
    }

    protected static final class SourceDependenciesMarker implements Serializable {
        static final long serialVersionUID = 4581013092140237821L;
    }

    /**
     * DataSource serialization helper
     */
    public void writeDataSource(ObjectOutputStream out, DataSource ds) throws IOException {
        boolean ourDS = false;
        DataSourceCollection dsc = null;
        if (ds == null) {
            out.writeObject(null);
            return;
        }
        // In case data source is empty: serialize original data source info
        if (ds instanceof EmptyDataSource) {
            String id = ((EmptyDataSource) ds).getDataSourceId();
            out.writeObject(id);
            if (id == null) {
                return; // And that's the end of it, won't be restored.
            }
            if (ds instanceof BufferedEmptyDataSource) {
                out.writeObject(BufferMarker.class);
                out.writeObject(((BufferedEmptyDataSource) ds).getBuffer());
            }
            // Collection ID
            if (((EmptyDataSource) ds).getDataSourceCollectionId() != null) {
                out.writeObject(DataSourceCollectionMarker.class);
                out.writeObject(((EmptyDataSource) ds).getDataSourceCollectionId());
            }
            // optional info
            out.writeObject(((EmptyDataSource) ds).getDataSourceOptionalInformation()); // may
            // be
            // null
        } else {
            if (sources.contains(ds)) {
                ourDS = true;
            } else {
                for (Iterator it = collections.iterator(); it.hasNext();) {
                    dsc = (DataSourceCollection) it.next();
                    if (dsc.contains(ds)) {
                        ourDS = true;
                        break;
                    }
                }
            }
            if (!ourDS) {
                out.writeObject(null);
                return;
            }
            String id = DataInfo.getId(ds);
            out.writeObject(id);
            if (id == null) {
                return; // And that's the end of it, won't be restored.
            }
            // Take care of recursive writing in case of sources depending on
            // other sources
            DataSource[] dependencies = ds.getSourceDependencies();
            if (dependencies != null) {
                out.writeObject(SourceDependenciesMarker.class);
                out.writeInt(dependencies.length);
                for (int i = 0; i < dependencies.length; ++i) {
                    writeDataSource(out, dependencies[i]);
                }
            }
            // Buffered data source => same Id, so save the buffer too
            if (ds instanceof BufferedDataSource) {
                out.writeObject(BufferMarker.class);
                out.writeObject(((BufferedDataSource) ds).getBuffer());
            }
            // If it belongs to a collection, write DataSourceCollection.Class
            // as
            // optional information, so we can recognize it during the read.
            // Don't write the dsc's class itself, in case it could not be
            // found.
            // If a caller really needs it, then it should include the
            // collection
            // class name in the id and use Class.forName. The same is true for
            // the datasource id.
            // Write the dsc's id just after the marker
            if (dsc != null) {
                out.writeObject(DataSourceCollectionMarker.class);
                out.writeObject(DataInfo.getId(dsc));
            }
            // Now run through the providers for one that can provide optional
            // info
            Object option = null;
            for (Iterator it = providers.iterator(); it.hasNext();) {
                option = ((DataSourceProvider) it.next()).getOptionalInformation(ds, dsc);
                if (option != null) {
                    break;
                }
            }
            out.writeObject(option); // may be null
        }
    }

    protected DataSourceCollection getTranslateCollection(String dscId) {
        DataSourceCollection dsc = (DataSourceCollection) translations.get(dscId);
        if (dsc == null) {
            try {
                dsc = getDataSourceCollectionWithId(dscId); // try directly
            } catch (DuplicateIdException e) {
            }
        }
        return dsc;
    }

    protected void setTranslateCollection(String dscId, DataSource ds) {
        if ((dscId == null) || (ds == null)) {
            return;
        }
        DataSourceCollection dsc = null;
        for (Iterator it = collections.iterator(); it.hasNext();) {
            DataSourceCollection col = (DataSourceCollection) it.next();
            if (col.contains(ds)) {
                dsc = col;
                break;
            }
        }
        if (dsc == null) {
            return; // no translation possible
        }
        translations.put(dscId, dsc); // store the new translation
    }

    public DataSource readDataSource(ObjectInputStream in) throws IOException {
        DataSource ds = null;
       
        /// Stream reading ///////////////
        Object o = null;
        try {
            o = in.readObject();
            if (o == null) {
                return null; // OK, no data more written to the stream
            }
        } catch (ClassNotFoundException cnfe1) {
            // continue to read the stream so it is not corrupted
        }
        String id = (String) o;
        // Get optional info
        Object option = null;
        try {
            option = in.readObject();
        } catch (ClassNotFoundException cnfe2) {
            // continue to read the stream so it is not corrupted
        }
        // Take care of recursive reading in case of sources depending on other
        // sources
        if (SourceDependenciesMarker.class.equals(option)) {
            int len = in.readInt();
            for (int i = 0; i < len; ++i) {
                readDataSource(in);
            }
            // Now it is guarantied that the provider can get the sources it
            // needs using
            // getDataSourceWithId => this also handle collection translations
            try {
                option = in.readObject();
            } catch (ClassNotFoundException cnfe2) {
                // continue to read the stream so it is not corrupted
            }
        }
        // If optional info is a buffer marker, take it in account
        Buffer buffer = null;
        if (BufferMarker.class.equals(option)) {
            try {
                buffer = (Buffer) in.readObject();
            } catch (ClassNotFoundException cnfe2) {
                // continue to read the stream so it is not corrupted
            }
            try {
                option = in.readObject();
            } catch (ClassNotFoundException cnfe2) {
                // continue to read the stream so it is not corrupted
            }
        }
        // If optional info is a collection marker, take it in account
        String dscId = null;
        if (DataSourceCollectionMarker.class.equals(option)) {
            try {
                dscId = (String) in.readObject();
            } catch (ClassNotFoundException cnfe2) {
                // continue to read the stream so it is not corrupted
            }
            try {
                option = in.readObject();
            } catch (ClassNotFoundException cnfe2) {
                // continue to read the stream so it is not corrupted
            }
        }
        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine("id=" + id + ", dscId=" + dscId + ", buffer=" + buffer + ", option=" + option);
        }
        /// End of Stream reading ///////////////
      
              
       
        //  No data source collection ID --> Look up in all pool
        if (dscId == null) {
            try {
                ds = getDataSourceWithId(id);
            } catch (DuplicateIdException e) {
            }
     
       
        // Data source collection ID  -> Get the collection related to the data
        } else {
            DataSourceCollection dsc =  getTranslateCollection(dscId);
            if (dsc != null) {    // We have loaded the collection already. Does it contain the source id?
                try {
                    ds = lookForId(dsc, id);
                } catch (DuplicateIdException e) {
                }
            }
        }

        if (ds != null) {
            if ((buffer != null) && !(ds instanceof BufferedDataSource)) {
                ds =  bufferize(ds, buffer);
            }
            if (_logger.isLoggable(Level.FINE)) {
                _logger.fine("DataSource=>" + ( (buffer!=null)? "buffer" : "" ) + ds);
            }

        } else {  

            // No source found in the pool --> ask the providers
            ds = provide(id, dscId, option, true);
           
            if (ds == null) {
                if (_logger.isLoggable(Level.FINE)) {
                    _logger.fine("DataSource=null");
                }
            } else {
               
                // If data source is empty, return it.
                if (ds instanceof EmptyDataSource) {
                    EmptyDataSource eds = (EmptyDataSource) ds;
                   
                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.fine("EmptyDataSource=" + ds);
                    }
                    if (buffer != null) {
                        ds = new BufferedEmptyDataSource(eds.getDataSourceId(), eds.getDataSourceCollectionId(), eds.getDataSourceOptionalInformation(), buffer);
                       
                        // Empty buffer shall be added to the pool of empty sources
                        EmptyDataSourcePool.global.addEmptyDaSource(id, (EmptyDataSource) ds)
                    }
              
                } else {
                   
                    // If we had a collection, apply translation
                    setTranslateCollection(dscId, ds);
                   
                    // Bufferize data source
                    if (buffer != null) {
                        ds =  bufferize(ds, buffer);
                    }
                    if (_logger.isLoggable(Level.FINE)) {
                        _logger.fine("DataSource==>" + ((buffer!=null)? "buffer" : ""+ ds);
                    }
                }
            }
         
        }
     
        return ds;
    }

    /**
     * Notify the listeners a change occured
     *
     * @param action
     *            as defined in DataSourcePoolEvent
     * @param o
     *            the target object. Must be a DataSource or
     *            DataSourceCollection
     */
    protected void notifyListeners(int action, Object o, Object old) {
        if (!notification) {
            return;
        }
        DataSourcePoolEvent e;
        if (o instanceof DataSource) {
            if (old instanceof DataSource) {
                e = new DataSourcePoolEvent(this, action, (DataSource) o, (DataSource) old);
            } else {
                e = new DataSourcePoolEvent(this, action, (DataSource) o);
            }
        } else {
            if (old instanceof DataSourceCollection) {
                e = new DataSourcePoolEvent(this, action, (DataSourceCollection) o, (DataSourceCollection) old);
            } else {
                e = new DataSourcePoolEvent(this, action, (DataSourceCollection) o);
            }
        }
        synchronized (listeners) {
            int n = listeners.size(); // only one call outside loop
            for (int i = 0; i < n; ++i) {
                DataSourcePoolListener dspl = (DataSourcePoolListener) listeners.get(i);
                if (dspl != null) {
                    dspl.dataSourcePoolNotification(e);
                }
            }
        }
    }

    /**
     * Sets the notification on or off
     *
     * @param state
     *            the new state
     */
    protected void setNotify(boolean state) {
        notification = state;
    }

    /**
     * A specific set that notifies the listeners when it changes See HashSet,
     * this implementation is not synchronized.
     */
    protected class NotifySet extends HashSet {
        public boolean add(Object o) {
            boolean ret = super.add(o);
            if (ret) {
                notifyListeners(DataSourcePoolEvent.ADD, o, null);
            }
            return ret;
        }

        public boolean remove(Object o) {
            boolean ret = super.remove(o);
            if (ret) {
                if (o instanceof DataSourceCollection) {
                    translations.remove(DataInfo.getId(o));
                }
                notifyListeners(DataSourcePoolEvent.REMOVE, o, null);
            }
            return ret;
        }
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.data.DataSourceCollectionListener#DataSourceCollectionInfoChanged(simtools.data.DataSourceCollection,
     *      simtools.data.DataInfo)
     */
    public void DataSourceCollectionInfoChanged(DataSourceCollection dsc, DataInfo newInfo) {
        notifyListeners(DataSourcePoolEvent.CHANGE_COLLECTION, dsc, dsc);
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.data.DataSourceCollectionListener#DataSourceCollectionDataSourceAdded(simtools.data.DataSourceCollection,
     *      simtools.data.DataSource)
     */
    public void DataSourceCollectionDataSourceAdded(DataSourceCollection dsc, DataSource ds) {
        notifyListeners(DataSourcePoolEvent.CHANGE_COLLECTION, dsc, dsc);
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.data.DataSourceCollectionListener#DataSourceCollectionDataSourceRemoved(simtools.data.DataSourceCollection,
     *      simtools.data.DataSource)
     */
    public void DataSourceCollectionDataSourceRemoved(DataSourceCollection dsc, DataSource ds) {
        notifyListeners(DataSourcePoolEvent.REMOVE_SOURCE, dsc, dsc);
        dsc.removeListener(this);
    }

    /*
     * (non-Javadoc)
     *
     * @see simtools.data.DataSourceCollectionListener#DataSourceCollectionRemoved(simtools.data.DataSourceCollection)
     */
    public void DataSourceCollectionRemoved(DataSourceCollection dsc) {
        notifyListeners(DataSourcePoolEvent.REMOVE_COLLECTION, dsc, null);
    }

    /**
     * @return true if this pool has no source and no collections in it
     */
    public boolean isEmpty() {
        int size = (sources == null) ? 0 : sources.size();
        size += (collections == null) ? 0 : collections.size();
        return size == 0;
    }

    /**
     * Called after a synoptic loading
     *
     * @return a list of data sources that could'nt be restored during a
     *         synoptic loading.
     */
    public String[][] getEmptySourcesDump() {
        String[][] ret = new String[localEmptySources.size()][2];
        for (int i = 0; i < localEmptySources.size(); i++) {
            ret[i][0] = ((String[]) localEmptySources.get(i))[0];
            ret[i][1] = ((String[]) localEmptySources.get(i))[1];
        }
        return ret;
    }

    /**
     * Called after a synoptic loading.
     *
     * @return the column names of the table that dumps all data sources
     *         restoring problems
     */
    public String[] getEmptySourcesDumpColumnNames() {
        String[] columnNames = { "Data source", "Problem" };
        return columnNames;
    }

    protected void addLocalEmptySource(String source, String reason) {
        String[] emptyElement = new String[2];
        emptyElement[0] = source;
        emptyElement[1] = reason;
        localEmptySources.add(emptyElement);
    }

    /**
     * Called before a synoptic loading.
     */
    public void clearLocalEmptySources() {
        localEmptySources.clear();
    }

    public boolean localEmptySourcesIsEmpty() {
        return localEmptySources.isEmpty();
    }
}
TOP

Related Classes of simtools.data.DataSourcePool

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.