source: src/main/java/weka/gui/streams/InstanceJoiner.java @ 4

Last change on this file since 4 was 4, checked in by gnappo, 14 years ago

Import di weka.

File size: 9.0 KB
Line 
1/*
2 *    This program is free software; you can redistribute it and/or modify
3 *    it under the terms of the GNU General Public License as published by
4 *    the Free Software Foundation; either version 2 of the License, or
5 *    (at your option) any later version.
6 *
7 *    This program is distributed in the hope that it will be useful,
8 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
9 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 *    GNU General Public License for more details.
11 *
12 *    You should have received a copy of the GNU General Public License
13 *    along with this program; if not, write to the Free Software
14 *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
15 */
16
17/*
18 *    InstanceJoiner.java
19 *    Copyright (C) 1999 University of Waikato, Hamilton, New Zealand
20 *
21 */
22
23package weka.gui.streams;
24
25import weka.core.Instance;
26import weka.core.Instances;
27
28import java.io.Serializable;
29import java.util.Vector;
30
31/**
32 * A bean that joins two streams of instances into one.
33 *
34 * @author Len Trigg (trigg@cs.waikato.ac.nz)
35 * @version $Revision: 4997 $
36 */
37public class InstanceJoiner
38  implements Serializable, InstanceProducer, SerialInstanceListener {
39
40  /** for serialization */
41  private static final long serialVersionUID = -6529972700291329656L;
42
43  /** The listeners */
44  private Vector listeners;
45
46  /** Debugging mode */
47  private boolean b_Debug;
48
49  /** The input format for instances */
50  protected Instances m_InputFormat;
51
52  /** The current output instance */
53  private Instance m_OutputInstance;
54
55
56  /** Whether the first input batch has finished */
57  private boolean b_FirstInputFinished;
58  private boolean b_SecondInputFinished;
59
60
61  /** Setup the initial states of the member variables */
62  public InstanceJoiner() {
63   
64    listeners = new Vector();
65    m_InputFormat = null;
66    m_OutputInstance = null;
67    b_Debug = false;
68    b_FirstInputFinished = false;
69    b_SecondInputFinished = false;
70  }
71
72
73  /**
74   * Sets the format of the input instances. If the filter is able to determine
75   * the output format before seeing any input instances, it does so here. This
76   * default implementation assumes the output format is determined when
77   * batchFinished() is called.
78   *
79   * @param instanceInfo an Instances object containing the input instance
80   * structure (any instances contained in the object are ignored - only the
81   * structure is required).
82   * @return true if the outputFormat may be collected immediately
83   */
84  public boolean inputFormat(Instances instanceInfo) {
85   
86    m_InputFormat = new Instances(instanceInfo,0);
87    notifyInstanceProduced(new InstanceEvent(this, InstanceEvent.FORMAT_AVAILABLE));
88    b_FirstInputFinished = false;
89    b_SecondInputFinished = false;
90    return true;
91  }
92
93  /**
94   * Gets the format of the output instances. This should only be called
95   * after input() or batchFinished() has returned true.
96   *
97   * @return an Instances object containing the output instance
98   * structure only.
99   * @throws Exception if no input structure has been defined (or the output
100   * format hasn't been determined yet)
101   */
102  public Instances outputFormat() throws Exception {
103   
104    if (m_InputFormat == null) {
105      throw new Exception("No output format defined.");
106    }
107    return new Instances(m_InputFormat,0);
108  }
109 
110  public boolean input(Instance instance) throws Exception {
111   
112    if (m_InputFormat == null) {
113      throw new Exception("No input instance format defined");
114    }
115    if (instance != null) {
116      m_OutputInstance = (Instance)instance.copy();
117      notifyInstanceProduced(new InstanceEvent(this,
118                                InstanceEvent.INSTANCE_AVAILABLE));
119      return true;
120    }
121    return false;
122  }
123
124  /**
125   * Signify that this batch of input to the filter is finished. If the filter
126   * requires all instances prior to filtering, output() may now be called
127   * to retrieve the filtered instances. Any subsequent instances filtered
128   * should be filtered based on setting obtained from the first batch
129   * (unless the inputFormat has been re-assigned or new options have been
130   * set). This default implementation assumes all instance processing occurs
131   * during inputFormat() and input().
132   *
133   * @throws Exception if no input structure has been defined
134   */
135  public void batchFinished() throws Exception {
136   
137    if (m_InputFormat == null) {
138      throw new Exception("No input instance format defined");
139    }
140    notifyInstanceProduced(new InstanceEvent(this,
141                                             InstanceEvent.BATCH_FINISHED));
142  }
143
144
145  /**
146   * Output an instance after filtering but do not remove from the output
147   * queue.
148   *
149   * @return the instance that has most recently been filtered (or null if
150   * the queue is empty).
151   * @throws Exception if no input structure has been defined
152   */
153  public Instance outputPeek() throws Exception {
154   
155    if (m_InputFormat == null) {
156      throw new Exception("No output instance format defined");
157    }
158    if (m_OutputInstance == null) {
159      return null;
160    }
161    return (Instance)m_OutputInstance.copy();
162  }
163
164
165  public void setDebug(boolean debug) {
166   
167    b_Debug = debug;
168  }
169 
170  public boolean getDebug() {
171   
172    return b_Debug;
173  }
174
175  public synchronized void addInstanceListener(InstanceListener ipl) {
176   
177    listeners.addElement(ipl);
178  }
179 
180  public synchronized void removeInstanceListener(InstanceListener ipl) {
181   
182    listeners.removeElement(ipl);
183  }
184 
185  protected void notifyInstanceProduced(InstanceEvent e) {
186   
187    if (listeners.size() > 0) {
188      if (b_Debug) {
189        System.err.println(this.getClass().getName()
190                           + "::notifyInstanceProduced()");
191      }
192      Vector l;
193      synchronized (this) {
194        l = (Vector)listeners.clone();
195      }
196      for(int i = 0; i < l.size(); i++) {
197        ((InstanceListener)l.elementAt(i)).instanceProduced(e);
198      }
199      // If there are any listeners, and the event is an INSTANCE_AVAILABLE,
200      // they should have retrieved the instance with outputPeek();
201      try {
202        if (e.getID() == InstanceEvent.INSTANCE_AVAILABLE) {
203          m_OutputInstance = null;
204        }
205      } catch (Exception ex) {
206        System.err.println("Problem: notifyInstanceProduced() was\n"
207                           + "called with INSTANCE_AVAILABLE, but output()\n"
208                           + "threw an exception: " + ex.getMessage());
209      }
210    }
211  }
212
213  public void instanceProduced(InstanceEvent e) {
214   
215    Object source = e.getSource();
216    if (source instanceof InstanceProducer) { 
217      try {
218        InstanceProducer a = (InstanceProducer) source;
219        switch (e.getID()) {
220        case InstanceEvent.FORMAT_AVAILABLE:
221          if (b_Debug) {
222            System.err.println(this.getClass().getName()
223                        + "::firstInstanceProduced() - Format available");
224          }
225          inputFormat(a.outputFormat());
226          break;
227        case InstanceEvent.INSTANCE_AVAILABLE:
228          if (b_Debug) {
229            System.err.println(this.getClass().getName()
230                        + "::firstInstanceProduced() - Instance available");
231          }
232          input(a.outputPeek());
233          break;
234        case InstanceEvent.BATCH_FINISHED:
235          if (b_Debug) {
236            System.err.println(this.getClass().getName()
237                        + "::firstInstanceProduced() - End of instance batch");
238          }
239          batchFinished();
240          b_FirstInputFinished = true;
241          break;
242        default:
243          System.err.println(this.getClass().getName()
244               + "::firstInstanceProduced() - unknown event type");
245          break;
246        }
247      } catch (Exception ex) {
248        System.err.println(ex.getMessage());
249      }
250    } else {
251      System.err.println(this.getClass().getName()
252             + "::firstInstanceProduced() - Unknown source object type");
253    }
254  }
255
256  public void secondInstanceProduced(InstanceEvent e) {
257   
258    Object source = e.getSource();
259    if (source instanceof InstanceProducer) { 
260      try {
261        if (!b_FirstInputFinished) {
262          throw new Exception(this.getClass().getName()
263          + "::secondInstanceProduced() - Input received from"
264          + " second stream before first stream finished");
265        }
266        InstanceProducer a = (InstanceProducer) source;
267        switch (e.getID()) {
268        case InstanceEvent.FORMAT_AVAILABLE:
269          if (b_Debug) {
270            System.err.println(this.getClass().getName()
271            + "::secondInstanceProduced() - Format available");
272          }
273          // Check the formats are compatible
274          if (!(a.outputFormat()).equalHeaders(outputFormat())) {
275            throw new Exception(this.getClass().getName()
276            + "::secondInstanceProduced() - incompatible instance streams\n" + (a.outputFormat()).equalHeadersMsg(outputFormat()));
277          }
278          break;
279        case InstanceEvent.INSTANCE_AVAILABLE:
280          if (b_Debug) {
281            System.err.println(this.getClass().getName()
282            + "::secondInstanceProduced() - Instance available");
283          }
284          input(a.outputPeek());
285          break;
286        case InstanceEvent.BATCH_FINISHED:
287          if (b_Debug) {
288            System.err.println(this.getClass().getName()
289            + "::secondInstanceProduced() - End of instance batch");
290          }
291          batchFinished();
292          break;
293        default:
294          System.err.println(this.getClass().getName()
295                + "::secondInstanceProduced() - unknown event type");
296          break;
297        }
298      } catch (Exception ex) {
299        System.err.println(ex.getMessage());
300      }
301    } else {
302      System.err.println(this.getClass().getName()
303          + "::secondInstanceProduced() - Unknown source object type");
304    }
305  }
306}
307
308
309
310
311
312
313
314
Note: See TracBrowser for help on using the repository browser.