001    /**
002     * 
003     */
004    package org.wdssii.core;
005    
006    import java.util.Date;
007    import java.util.HashMap;
008    import java.util.HashSet;
009    import java.util.Map;
010    import java.util.Set;
011    import java.util.SortedMap;
012    import java.util.TreeMap;
013    
014    // import org.apache.commons.logging.Log;
015    // import org.apache.commons.logging.LogFactory;
016    
017    /**
018     * the Index class connects to a data source and provides access to real-time
019     * products as they come in.
020     * 
021     * @author Lakshman
022     * @version $Id: Index.java,v 1.6 2006/12/29 21:15:12 lakshman Exp $
023     * @see IndexRecord
024     */
025    public abstract class Index {
026            // private static Log log = LogFactory.getLog(Index.class);
027    
028            /**
029             * Create a brand-new Index with these listeners attached.
030             */
031            public abstract Index newInstance(String path,
032                            Set<IndexRecordListener> listeners) throws DataUnavailableException;
033    
034            /**
035             * The update() method will be called periodically. The implementation is
036             * allowed to ignore update() calls that happen at inconvenient times.
037             */
038            public abstract void update();
039    
040            /** datatype to TreeMap<time,record> */
041            private HashMap<String, TreeMap<Date, IndexRecord>> timestamps = new HashMap<String, TreeMap<Date, IndexRecord>>();
042    
043            private HashMap<String, IndexRecord> records = new HashMap<String, IndexRecord>();
044    
045            private HashMap<String, HashSet<String>> selections = new HashMap<String, HashSet<String>>();
046    
047            private HashSet<String> datatypes = new HashSet<String>();
048    
049            private Set<IndexRecordListener> listeners = null;
050    
051            private String indexLocation = null;
052    
053            /** the directory in which this index.xml or index.lb is located */
054            public String getIndexLocation() {
055                    return indexLocation;
056            }
057    
058            public Index(String indexLocation, Set<IndexRecordListener> listeners) {
059                    this.indexLocation = indexLocation;
060                    this.listeners = listeners;
061            }
062    
063            /** Register a listener to be notified about new records in this index. */
064            public void addRecordListener(IndexRecordListener listener) {
065                    listeners.add(listener);
066            }
067    
068            public void addRecord(IndexRecord rec) {
069                    // form the selections to create the keys
070                    String[] sels = new String[3];
071                    sels[0] = rec.getDataType(); // dt
072                    sels[1] = rec.getSubType();
073                    sels[2] = rec.getTimeStamp();
074    
075                    addSelection(getKey(sels, 0, 0), sels[1]);
076                    addSelection(getKey(sels, 0, 1), sels[2]);
077                    addRecord(getKey(sels, 0, 2), rec); // everything to record
078    
079                    datatypes.add(sels[0]);
080    
081                    addRecByTypeTime(rec.getTime(), sels[0], rec);
082    
083                    for (IndexRecordListener listener : listeners) {
084                            listener.handleRecord(rec);
085                    }
086            }
087    
088            void addRecByTypeTime(Date time, String dt, IndexRecord rec) {
089                    TreeMap<Date, IndexRecord> tm = timestamps.get(dt);
090                    if (tm == null) {
091                            tm = new TreeMap<Date, IndexRecord>();
092                            timestamps.put(dt, tm);
093                    }
094                    tm.put(time, rec);
095            }
096    
097            private String getKey(String[] sels, int start, int last) {
098                    StringBuilder b = new StringBuilder();
099                    for (int i = start; i <= last; ++i) {
100                            b.append(sels[i]);
101                            b.append(" ");
102                    }
103                    return b.toString();
104            }
105    
106            // note that from is INCLUSIVE and to is EXCLUSIVE
107    
108            public Map<Date, IndexRecord> getRecordsByTypeTime(String dt, Date from,
109                            Date to) {
110                    TreeMap<Date, IndexRecord> tm = timestamps.get(dt);
111                    if (tm == null)
112                            return null;
113    
114                    SortedMap<Date, IndexRecord> sm = null;
115                    if (from != null) {
116                            if (to != null)
117                                    sm = tm.subMap(from, to);
118                            else
119                                    sm = tm.tailMap(from);
120                    } else {
121                            if (to != null)
122                                    sm = tm.headMap(to);
123                            else
124                                    sm = tm;
125                    }
126                    return (sm);
127            }
128    
129            public IndexRecord getFirstRecordByTime(String dt) {
130                    TreeMap<Date, IndexRecord> tm = timestamps.get(dt);
131                    if (tm == null)
132                            return null;
133                    return tm.get(tm.firstKey());
134            }
135    
136            public IndexRecord getLastRecordByTime(String dt) {
137                    TreeMap<Date, IndexRecord> tm = timestamps.get(dt);
138                    if (tm == null)
139                            return null;
140                    return tm.get(tm.lastKey());
141            }
142    
143            public int numRecordsByTime(String dt) {
144                    TreeMap<Date, IndexRecord> tm = timestamps.get(dt);
145                    if (tm == null)
146                            return -1;
147                    return (tm.size());
148            }
149    
150            private void addSelection(String key, String s) {
151                    HashSet<String> inmap = selections.get(key);
152                    if (inmap == null) {
153                            inmap = new HashSet<String>();
154                            selections.put(key, inmap);
155                    }
156                    inmap.add(s);
157            }
158    
159            private void addRecord(String key, IndexRecord rec) {
160                    records.put(key, rec);
161            }
162    
163            public IndexRecord getRecord(String[] selections) {
164                    return getRecord(getKey(selections, 0, 2));
165            }
166    
167            public IndexRecord getRecord(String key) {
168                    return records.get(key);
169            }
170    
171            public Set<String> getDataTypes() {
172                    return datatypes;
173            }
174    
175            public Set<String> getNextSelection(String[] selections) {
176                    return getNextSelection(getKey(selections, 0, selections.length - 1));
177            }
178    
179            public Set<String> getNextSelection(String key) {
180                    return selections.get(key);
181            }
182    
183    }