Code Examples
A repository of 155 code examples for BeepBeep
IteratorDemo.java
1 /*
2  BeepBeep, an event stream processor
3  Copyright (C) 2008-2023 Sylvain HallĂ©
4 
5  This program is free software: you can redistribute it and/or modify
6  it under the terms of the GNU Lesser General Public License as published
7  by the Free Software Foundation, either version 3 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU Lesser General Public License for more details.
14 
15  You should have received a copy of the GNU Lesser General Public License
16  along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 package complex;
19 
20 import java.util.Set;
21 
22 import ca.uqac.lif.cep.Connector;
23 import ca.uqac.lif.cep.Context;
24 import ca.uqac.lif.cep.EventTracker;
25 import ca.uqac.lif.cep.GroupProcessor;
26 import ca.uqac.lif.cep.Processor;
27 import ca.uqac.lif.cep.Pushable;
28 import ca.uqac.lif.cep.complex.RangeCep;
29 import ca.uqac.lif.cep.functions.ApplyFunction;
30 import ca.uqac.lif.cep.functions.Constant;
31 import ca.uqac.lif.cep.functions.Cumulate;
32 import ca.uqac.lif.cep.functions.CumulativeFunction;
33 import ca.uqac.lif.cep.functions.Function;
34 import ca.uqac.lif.cep.functions.FunctionTree;
35 import ca.uqac.lif.cep.functions.IfThenElse;
36 import ca.uqac.lif.cep.functions.StreamVariable;
37 import ca.uqac.lif.cep.io.Print.Println;
38 import ca.uqac.lif.cep.tmf.SliceLast;
39 import ca.uqac.lif.cep.util.Booleans;
40 import ca.uqac.lif.cep.util.Equals;
41 import ca.uqac.lif.cep.util.Lists;
42 import ca.uqac.lif.cep.util.NthElement;
43 import ca.uqac.lif.cep.util.Numbers;
44 
45 /**
46  * Creates complex events out of low-level events occurring to Java iterators.
47  * Each basic event represents a method call done on a Java iterator. It is
48  * an array made of two elements:
49  * <ul>
50  * <li>The object's hashcode (an integer)</li>
51  * <li>The name of the method being called on this object (a String)</li>
52  * </ul>
53  * The goal is to produce a high-level stream where each event summarizes the
54  * "lifecycle" of an iterator, from its instantiation to its disposal. When an
55  * iterator is destroyed, a "complex" {@link IteratorLifecycle} event should be
56  * produced, summarizing the operations done on this iterator during its
57  * lifespan: its hashcode, and the number of times some methods have been
58  * called on it.
59  * @author Sylvain HallĂ©
60  */
61 public class IteratorDemo
62 {
63  public static void main(String[] args)
64  {
65  /* Create a RangeCep processor that will aggregate information about a
66  * single instance of iterator. */
67  RangeCep cep = new RangeCep(
68  /* The range processor returns true until the "dispose" event is seen,
69  * triggering the creation of the complex output event. */
70  new ApplyFunction(new FunctionTree(Booleans.not, new FunctionTree(Equals.instance, new FunctionTree(new NthElement(1), StreamVariable.X), new Constant("dispose")))),
71  /* Four processors respectively output... */
72  new Processor[] {
73  /* The iterator's hashcode (same value in each event) */
74  new ApplyFunction(new NthElement(0)),
75  /* The cumulative number of "next" calls seen so far */
76  new CountIf("next"),
77  /* The cumulative number of "hasNext" calls seen so far */
78  new CountIf("hasNext"),
79  /* The cumulative number of "remove" calls seen so far */
80  new CountIf("remove")},
81  /* The function called to create the complex event when the end of the
82  * range (i.e. the "dispose" event) is reached. */
83  new CreateIteratorLifecycle()).allowRestarts(true);
84 
85  /* Create a slice processor associating one instance of the RangeCep
86  * processor to each individual instance of iterator in circulation. */
87  SliceLast slice = new SliceLast(new NthElement(0), cep);
88 
89  /* Connect to a printer and push some events. */
90  Connector.connect(slice, new Lists.Unpack(), new Println());
91  Pushable p = slice.getPushableInput();
92  Object i1 = new Object();
93  Object i2 = new Object();
94  p.push(new Object[]{i1, "next"});
95  p.push(new Object[]{i2, "hasNext"});
96  p.push(new Object[]{i1, "hasNext"});
97  p.push(new Object[]{i2, "dispose"});
98  p.push(new Object[]{i1, "dispose"});
99  p.push(new Object[]{i1, "next"});
100  p.push(new Object[]{i1, "dispose"});
101  }
102 
103  /**
104  * Processor that accumulates the number of events where the method name
105  * (i.e. second element of the array) is equal to a specific string.
106  */
107  protected static class CountIf extends GroupProcessor
108  {
109  public CountIf(String name)
110  {
111  super(1, 1);
112  ApplyFunction nth = new ApplyFunction(new NthElement(1));
113  ApplyFunction ite = new ApplyFunction(
114  new FunctionTree(IfThenElse.instance,
115  new FunctionTree(Equals.instance, StreamVariable.X, new Constant(name)),
116  new Constant(1),
117  new Constant(0)));
118  Cumulate sum = new Cumulate(new CumulativeFunction<Number>(Numbers.addition));
119  Connector.connect(nth, ite, sum);
120  addProcessors(nth, ite, sum).associateInput(nth).associateOutput(sum);
121  }
122  }
123 
124  /**
125  * Definition of the complex event "iterator lifecycle". For each iterator
126  * reaching its disposal state, the complex event contains the following
127  * elements:
128  * <ul>
129  * <li>Hash code of the iterator in question</li>
130  * <li>Number of calls to {@code next()} on this iterator</li>
131  * <li>Number of calls to {@code hasNext()} on this iterator</li>
132  * <li>Number of calls to {@code remove()} on this iterator</li>
133  * </ul>
134  */
135  protected static class IteratorLifecycle
136  {
137  /**
138  * Hash code of the iterator.
139  */
140  protected final int m_hash;
141 
142  /**
143  * Number of calls to {@code next()} on this iterator.
144  */
145  protected final int m_numNext;
146 
147  /**
148  * Number of calls to {@code hasNext()} on this iterator.
149  */
150  protected final int m_numHasNext;
151 
152  /**
153  * Number of calls to {@code remove()} on this iterator.
154  */
155  protected final int m_numRemove;
156 
157  /**
158  * Creates a new iterator lifecycle complex event.
159  * @param hash Hash code of the iterator
160  * @param num_next Number of calls to {@code next()} on this iterator
161  * @param num_hasNext Number of calls to {@code hasNext()} on this iterator
162  * @param num_remove Number of calls to {@code remove()} on this iterator
163  */
164  public IteratorLifecycle(int hash, int num_next, int num_hasNext, int num_remove)
165  {
166  super();
167  m_hash = hash;
168  m_numNext = num_next;
169  m_numHasNext = num_hasNext;
170  m_numRemove = num_remove;
171  }
172 
173  @Override
174  public String toString()
175  {
176  StringBuilder out = new StringBuilder();
177  out.append("subject: ").append(m_hash).append(",");
178  out.append("next: ").append(m_numNext).append(",");
179  out.append("hasNext: ").append(m_numHasNext).append(",");
180  out.append("remove: ").append(m_numRemove);
181  return out.toString();
182  }
183  }
184 
185  /**
186  * Function that creates an {@link IteratorLifecycle} complex event out of
187  * four input arguments.
188  */
189  protected static class CreateIteratorLifecycle extends Function
190  {
191  @Override
192  public void evaluate(Object[] inputs, Object[] outputs, Context context, EventTracker tracker)
193  {
194  outputs[0] = new IteratorLifecycle(inputs[0].hashCode(), ((Number) inputs[1]).intValue(), ((Number) inputs[2]).intValue(), ((Number) inputs[3]).intValue());
195  }
196 
197  @Override
198  public int getInputArity()
199  {
200  return 4;
201  }
202 
203  @Override
204  public int getOutputArity()
205  {
206  return 1;
207  }
208 
209  @Override
210  public void getInputTypesFor(Set<Class<?>> classes, int index)
211  {
212  classes.add(Number.class);
213  }
214 
215  @Override
216  public Class<?> getOutputTypeFor(int index)
217  {
218  return Number.class;
219  }
220 
221  @Override
222  public Function duplicate(boolean with_state)
223  {
224  return this;
225  }
226  }
227 }
Creates complex events out of low-level events occurring to Java iterators.