MATSIM
FingerprintEventHandler.java
Go to the documentation of this file.
1 package org.matsim.utils.eventsfilecomparison;
2 
3 import it.unimi.dsi.fastutil.floats.FloatListIterator;
4 import it.unimi.dsi.fastutil.objects.Object2IntMap;
7 
8 import java.util.*;
9 
13 public final class FingerprintEventHandler implements BasicEventHandler {
14 
19 
23  private static final float EPS = 1e-8f;
24 
28  private final List<String> hashAccumulationList = new ArrayList<>();
29 
34 
35  private FloatListIterator iterator = null;
36 
41  private String comparisonMessage;
42 
44  this.compareFingerprint = null;
45  }
46 
47  public FingerprintEventHandler(EventFingerprint compareFingerprint) {
48  this.compareFingerprint = compareFingerprint;
49  this.comparisonResult = null;
50  }
51 
53  return eventFingerprint;
54  }
55 
57  return comparisonResult;
58  }
59 
60  void setComparisonResult(ComparisonResult comparisonResult) {
61  this.comparisonResult = comparisonResult;
62  }
63 
64  public String getComparisonMessage() {
65  return comparisonMessage;
66  }
67 
68  void setComparisonMessage(String comparisonMessage) {
69  this.comparisonMessage = comparisonMessage;
70  }
71 
72  @Override
73  public void handleEvent(Event event) {
74 
75 
76  String lexicographicSortedString = toLexicographicSortedString(event);
77 
78  if (compareFingerprint != null) {
79  if (iterator == null) {
80  this.iterator = compareFingerprint.timeArray.iterator();
81  }
82 
83  if (this.comparisonResult == null) {
84  if (iterator.hasNext()) {
85  float entry = iterator.nextFloat();
86  //Comparing floats with precision
87  if (Math.abs((float) event.getTime() - entry) >= EPS) {
88  this.comparisonResult = ComparisonResult.DIFFERENT_TIMESTEPS;
89  this.comparisonMessage = "Difference occurred in this event time=" + event.getTime() + lexicographicSortedString;
90  }
91  } else {
92  this.comparisonResult = ComparisonResult.DIFFERENT_TIMESTEPS;
93  this.comparisonMessage = "Additional event time=" + event.getTime() + lexicographicSortedString;
94  }
95  }
96  }
97 
98  eventFingerprint.addEventType(event.getEventType());
99 
100 
101  //First timestep, nothing to accumulate
102  if (eventFingerprint.timeArray.isEmpty()) {
103  hashAccumulationList.add(lexicographicSortedString);
104  } else {
105  float lastTime = eventFingerprint.timeArray.getFloat(eventFingerprint.timeArray.size() - 1);
106  //If new time is the same as previous, add to accumulation list, event hash calculation is not ready
107  if (lastTime == event.getTime()) {
108  hashAccumulationList.add(lexicographicSortedString);
109  }
110  //if new time differs from previous, all hash can be calculated
111  else {
112  accumulateHash();
113  hashAccumulationList.add(lexicographicSortedString);
114  }
115  }
116 
117  eventFingerprint.addTimeStamp(event.getTime());
118 
119  //eventFingerprint.addHashCode(lexicographicSortedString);
120  }
121 
122  private void accumulateHash() {
123 
124  Collections.sort(hashAccumulationList);
125 
126  for (String str : hashAccumulationList) {
127  eventFingerprint.addHashCode(str);
128  }
129 
130  hashAccumulationList.clear();
131  }
132 
138  void finishProcessing() {
139 
140  if (!hashAccumulationList.isEmpty()) {
141  accumulateHash();
142  }
143 
144  byte[] hash = eventFingerprint.computeHash();
145 
146  //hash = eventFingerprint.computeHash();
147 
148  if (compareFingerprint == null)
149  return;
150 
151  //Handling EventTypeCounter differences
152  for (Object2IntMap.Entry<String> entry1 : compareFingerprint.eventTypeCounter.object2IntEntrySet()) {
153  String key = entry1.getKey();
154  int count1 = entry1.getIntValue();
155  int count2 = eventFingerprint.eventTypeCounter.getInt(key);
156  if (count1 != count2) {
157  comparisonMessage = comparisonMessage == null ? "" : comparisonMessage;
158 
159  comparisonResult = (comparisonResult == null ? ComparisonResult.WRONG_EVENT_COUNT : comparisonResult);
160 
161  if (!comparisonMessage.isEmpty())
162  comparisonMessage += "\n";
163 
164  comparisonMessage += "Count for event type '%s' differs: %d (in fingerprint) != %d (in events)".formatted(key, count1, count2);
165  }
166  }
167 
168  // Difference was found in {@link EventFingerprint#eventTypeCounter}
169  if (comparisonResult != null) {
170  return;
171  }
172 
173  // only check hash if there was no difference up until here
174  if (!Arrays.equals(hash, compareFingerprint.hash)) {
175  comparisonResult = ComparisonResult.DIFFERENT_EVENT_ATTRIBUTES;
176  comparisonMessage = "Difference occurred in this hash of 2 files";
177  return;
178  }
179 
180  comparisonResult = ComparisonResult.FILES_ARE_EQUAL;
181  }
182 
183  private String toLexicographicSortedString(Event event) {
184  List<String> strings = new ArrayList<String>();
185  for (Map.Entry<String, String> e : event.getAttributes().entrySet()) {
186  StringBuilder tmp = new StringBuilder();
187  final String key = e.getKey();
188 
189  // don't look at certain attributes
190  switch (key) {
191  case Event.ATTRIBUTE_X:
192  case Event.ATTRIBUTE_Y:
193  case Event.ATTRIBUTE_TIME:
194  continue;
195  }
196 
197  tmp.append(key);
198  tmp.append("=");
199  tmp.append(e.getValue());
200  strings.add(tmp.toString());
201  }
202  Collections.sort(strings);
203  StringBuilder eventStr = new StringBuilder();
204  for (String str : strings) {
205  eventStr.append(" | ");
206  eventStr.append(str);
207  }
208 
209  eventStr.append(" | ");
210  return eventStr.toString();
211  }
212 }
static final String ATTRIBUTE_TIME
Definition: Event.java:33
static final String ATTRIBUTE_X
Definition: Event.java:35
Map< String, String > getAttributes()
Definition: Event.java:44
static final String ATTRIBUTE_Y
Definition: Event.java:36