From 8dc22b41f30a962f467cea42fd802c196d5f95a5 Mon Sep 17 00:00:00 2001
From: Andrea Burattin <andrea.burattin@gmail.com>
Date: Sat, 26 Mar 2022 19:56:14 +0100
Subject: [PATCH] Refactored constructors of BEvent and added documentation

---
 src/main/java/beamline/events/BEvent.java     | 154 ++++++++++++++----
 .../java/beamline/sources/CSVLogSource.java   |   2 +-
 .../java/beamline/sources/MQTTXesSource.java  |   2 +-
 .../beamline/sources/StringTestSource.java    |   2 +-
 .../java/beamline/sources/XesLogSource.java   |   2 +-
 .../java/beamline/tests/AlgorithmTest.java    |   8 +-
 src/test/java/beamline/tests/EventTest.java   |  24 +--
 src/test/java/beamline/tests/FiltersTest.java |  16 +-
 src/test/java/beamline/tests/MapperTest.java  |  16 +-
 .../java/beamline/tests/ResponsesTest.java    |  22 +--
 10 files changed, 170 insertions(+), 78 deletions(-)

diff --git a/src/main/java/beamline/events/BEvent.java b/src/main/java/beamline/events/BEvent.java
index 6cf55bb..df75b87 100644
--- a/src/main/java/beamline/events/BEvent.java
+++ b/src/main/java/beamline/events/BEvent.java
@@ -17,11 +17,26 @@ import org.deckfour.xes.model.XAttributeContinuous;
 import org.deckfour.xes.model.XAttributeDiscrete;
 import org.deckfour.xes.model.XAttributeLiteral;
 import org.deckfour.xes.model.XAttributeTimestamp;
-import org.deckfour.xes.model.XTrace;
 
 import beamline.exceptions.EventException;
 
 /**
+ * This class describes an event for the Beamline framework. An event is the
+ * minimal observable unit in the context of streaming process mining. Each
+ * event is expected to belong to a process instance which, in turn, belongs to
+ * a process. For this reason, when an event is created (for example using the
+ * {@link #BEvent(String, String, String)} constructor).
+ * 
+ * <p>
+ * Some level of compatibility with the OpenXES library is guaranteed by:
+ * <ul>
+ * 	<li>using the same attribute names for internally storing the name of the
+ * attributes;</li>
+ * 	<li>having the capability of setting attributes using the
+ * 	{@link #setTraceAttribute(String, XAttribute)} and
+ * 	{@link #setEventAttribute(String, XAttribute)} which take an
+ * 	{@link XAttribute} as parameter.</li>
+ * </ul>
  * 
  * @author Andrea Burattin
  */
@@ -33,18 +48,6 @@ public class BEvent implements Serializable, Comparable<BEvent> {
 	private Map<String, Serializable> traceAttributes;
 	private Map<String, Serializable> processAttributes;
 
-	/**
-	 * Constructor of a new event
-	 */
-	public BEvent() {
-		this.eventAttributes = new HashMap<>();
-		this.traceAttributes = new HashMap<>();
-		this.processAttributes = new HashMap<>();
-	}
-	
-	//
-	// Factories
-	//
 	/**
 	 * Creates a new {@link BEvent} referring to one event
 	 *
@@ -53,11 +56,10 @@ public class BEvent implements Serializable, Comparable<BEvent> {
 	 * @param caseId the identifier of the process instance
 	 * @param time the time when the event has happened
 	 * @param eventAttributes a collection of string attributes for the event
-	 * @return the new event
 	 * @throws EventException this exception is thrown is incomplete information
 	 * is provided
 	 */
-	public static BEvent create(
+	public BEvent(
 			String processName,
 			String caseId,
 			String activityName,
@@ -67,22 +69,24 @@ public class BEvent implements Serializable, Comparable<BEvent> {
 			throw new EventException("Activity name or case id missing");
 		}
 		
-		BEvent event = new BEvent();
-		event.setProcessName(processName);
-		event.setTraceName(caseId);
-		event.setEventName(activityName);
+		this.eventAttributes = new HashMap<>();
+		this.traceAttributes = new HashMap<>();
+		this.processAttributes = new HashMap<>();
+		
+		setProcessName(processName);
+		setTraceName(caseId);
+		setEventName(activityName);
 		if (time == null) {
-			event.setTimestamp(new Date());
+			setTimestamp(new Date());
 		} else {
-			event.setTimestamp(time);
+			setTimestamp(time);
 		}
 		
 		if (eventAttributes != null) {
 			for(Pair<String, String> a : eventAttributes) {
-				event.setEventAttribute(a.getLeft(), a.getRight());
+				setEventAttribute(a.getLeft(), a.getRight());
 			}
 		}
-		return event;
 	}
 	
 	/**
@@ -92,17 +96,15 @@ public class BEvent implements Serializable, Comparable<BEvent> {
 	 * @param activityName the name of the activity
 	 * @param caseId the identifier of the process instance
 	 * @param time the time when the event has happened
-	 * @return the new event
 	 * @throws EventException this exception is thrown is incomplete information
 	 * is provided
 	 */
-	public static BEvent create(String processName, String caseId, String activityName, Date time) throws EventException {
-		return create(processName, caseId, activityName, time, null);
+	public BEvent(String processName, String caseId, String activityName, Date time) throws EventException {
+		this(processName, caseId, activityName, time, null);
 	}
 	
 	/**
-	 * Creates a new {@link XTrace} referring to one event. The time of the
-	 * event is set to the current time
+	 * Creates a new {@link BEvent} referring to one event
 	 * 
 	 * @param processName the name of the process
 	 * @param activityName the name of the activity
@@ -111,41 +113,81 @@ public class BEvent implements Serializable, Comparable<BEvent> {
 	 * @throws EventException this exception is thrown is incomplete information
 	 * is provided
 	 */
-	public static BEvent create(String processName, String caseId, String activityName) throws EventException {
-		return create(processName, caseId, activityName, null, null);
+	public BEvent(String processName, String caseId, String activityName) throws EventException {
+		this(processName, caseId, activityName, null, null);
 	}
 	
 	//
 	// Specific methods
 	//
+	/**
+	 * Sets the process name
+	 * 
+	 * @param name the process name
+	 */
 	public void setProcessName(String name) {
 		setProcessAttribute(XConceptExtension.KEY_NAME, name);
 	}
 	
+	/**
+	 * Gets the process name
+	 * 
+	 * @return the process name
+	 */
 	public String getProcessName() {
 		return (String) processAttributes.get(XConceptExtension.KEY_NAME);
 	}
 	
+	/**
+	 * Sets the trace name (a.k.a. case id)
+	 * 
+	 * @param name the trace name
+	 */
 	public void setTraceName(String name) {
 		setTraceAttribute(XConceptExtension.KEY_NAME, name);
 	}
 	
+	/**
+	 * Gets the trace name (a.k.a. case id)
+	 * 
+	 * @return the trace name
+	 */
 	public String getTraceName() {
 		return (String) traceAttributes.get(XConceptExtension.KEY_NAME);
 	}
 	
+	/**
+	 * Sets the event name (a.k.a. activity name)
+	 * 
+	 * @param name the event name
+	 */
 	public void setEventName(String name) {
 		setEventAttribute(XConceptExtension.KEY_NAME, name);
 	}
 	
+	/**
+	 * Gets the event name (a.k.a. activity name)
+	 * 
+	 * @return the event name
+	 */
 	public String getEventName() {
 		return (String) eventAttributes.get(XConceptExtension.KEY_NAME);
 	}
 	
+	/**
+	 * Sets the event time
+	 * 
+	 * @param timestamp the event time
+	 */
 	public void setTimestamp(Date timestamp) {
 		setEventAttribute(XTimeExtension.KEY_TIMESTAMP, timestamp);
 	}
 	
+	/**
+	 * Gets the event time
+	 * 
+	 * @return the event time
+	 */
 	public Date getEventTime() {
 		return (Date) eventAttributes.get(XTimeExtension.KEY_TIMESTAMP);
 	}
@@ -153,39 +195,89 @@ public class BEvent implements Serializable, Comparable<BEvent> {
 	//
 	// General methods
 	//
-	
+	/**
+	 * Gets all event level attributes
+	 * 
+	 * @return the attributes
+	 */
 	public Map<String, Serializable> getEventAttributes() {
 		return eventAttributes;
 	}
 	
+	/**
+	 * Gets all trace level attributes
+	 * 
+	 * @return the attributes
+	 */
 	public Map<String, Serializable> getTraceAttributes() {
 		return traceAttributes;
 	}
 	
+	/**
+	 * Gets all process level attributes
+	 * 
+	 * @return the attributes
+	 */
 	public Map<String, Serializable> getProcessAttributes() {
 		return processAttributes;
 	}
 	
+	/**
+	 * Sets a event level attribute
+	 * 
+	 * @param name the attribute name
+	 * @param value the attribute value
+	 */
 	public void setEventAttribute(String name, Serializable value) {
 		eventAttributes.put(name, value);
 	}
 	
+	/**
+	 * Sets a event level attribute
+	 * 
+	 * @param name the attribute name
+	 * @param value the attribute value
+	 */
 	public void setEventAttribute(String name, XAttribute value) {
 		setAttributeFromXAttribute(eventAttributes, name, value);
 	}
 	
+	/**
+	 * Sets a trace level attribute
+	 * 
+	 * @param name the attribute name
+	 * @param value the attribute value
+	 */
 	public void setTraceAttribute(String name, Serializable value) {
 		traceAttributes.put(name, value);
 	}
 	
+	/**
+	 * Sets a trace level attribute
+	 * 
+	 * @param name the attribute name
+	 * @param value the attribute value
+	 */
 	public void setTraceAttribute(String name, XAttribute value) {
 		setAttributeFromXAttribute(traceAttributes, name, value);
 	}
 	
+	/**
+	 * Sets a process level attribute
+	 * 
+	 * @param name the attribute name
+	 * @param value the attribute value
+	 */
 	public void setProcessAttribute(String name, Serializable value) {
 		processAttributes.put(name, value);
 	}
 	
+	/**
+	 * Sets a process level attribute
+	 * 
+	 * @param name the attribute name
+	 * @param value the attribute value
+	 */
 	public void setProcessAttribute(String name, XAttribute value) {
 		setAttributeFromXAttribute(processAttributes, name, value);
 	}
diff --git a/src/main/java/beamline/sources/CSVLogSource.java b/src/main/java/beamline/sources/CSVLogSource.java
index 4cfb0d7..050045f 100644
--- a/src/main/java/beamline/sources/CSVLogSource.java
+++ b/src/main/java/beamline/sources/CSVLogSource.java
@@ -84,7 +84,7 @@ public class CSVLogSource extends BeamlineAbstractSource {
 					attributes.add(Pair.of("attribute_" + i, line[i]));
 				}
 				synchronized (ctx.getCheckpointLock()) {
-					ctx.collect(BEvent.create(filename, line[caseIdColumn], line[activityNameColumn], null, attributes));
+					ctx.collect(new BEvent(filename, line[caseIdColumn], line[activityNameColumn], null, attributes));
 				}
 			}
 		} catch (IOException e) {
diff --git a/src/main/java/beamline/sources/MQTTXesSource.java b/src/main/java/beamline/sources/MQTTXesSource.java
index 6a89e8b..d81fdb8 100644
--- a/src/main/java/beamline/sources/MQTTXesSource.java
+++ b/src/main/java/beamline/sources/MQTTXesSource.java
@@ -69,7 +69,7 @@ public class MQTTXesSource extends BeamlineAbstractSource {
 					String partBeforeActName = topic.substring(0, posLastSlash);
 					String activityName = topic.substring(posLastSlash + 1);
 					String caseId = partBeforeActName.substring(partBeforeActName.lastIndexOf("/") + 1);
-					BEvent b = BEvent.create(processName, caseId, activityName);
+					BEvent b = new BEvent(processName, caseId, activityName);
 					buffer.add(b);
 				}
 				
diff --git a/src/main/java/beamline/sources/StringTestSource.java b/src/main/java/beamline/sources/StringTestSource.java
index 7188161..65c317d 100644
--- a/src/main/java/beamline/sources/StringTestSource.java
+++ b/src/main/java/beamline/sources/StringTestSource.java
@@ -15,7 +15,7 @@ public class StringTestSource extends BeamlineAbstractSource {
 	public void run(SourceContext<BEvent> ctx) throws Exception {
 		for (int j = 0; j < traces.length; j++) {
 			for (int i = 0; i < traces[j].length(); i++) {
-				ctx.collect(BEvent.create("test-process", "case-"+j, traces[j].substring(i, i+1)));
+				ctx.collect(new BEvent("test-process", "case-"+j, traces[j].substring(i, i+1)));
 			}
 		}
 	}
diff --git a/src/main/java/beamline/sources/XesLogSource.java b/src/main/java/beamline/sources/XesLogSource.java
index 792f347..c6e99f9 100644
--- a/src/main/java/beamline/sources/XesLogSource.java
+++ b/src/main/java/beamline/sources/XesLogSource.java
@@ -126,7 +126,7 @@ public class XesLogSource extends BeamlineAbstractSource {
 		events = new LinkedList<>();
 		for (XTrace t : log) {
 			for (XEvent e : t) {
-				BEvent be = BEvent.create(
+				BEvent be = new BEvent(
 					processName,
 					XConceptExtension.instance().extractName(t),
 					XConceptExtension.instance().extractName(e),
diff --git a/src/test/java/beamline/tests/AlgorithmTest.java b/src/test/java/beamline/tests/AlgorithmTest.java
index a104135..fdb5f82 100644
--- a/src/test/java/beamline/tests/AlgorithmTest.java
+++ b/src/test/java/beamline/tests/AlgorithmTest.java
@@ -31,10 +31,10 @@ public class AlgorithmTest {
 		StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
 		env
 			.fromElements(
-				BEvent.create("p", "c1", "3"),
-				BEvent.create("p", "c1", "7"),
-				BEvent.create("p", "c1", "11"),
-				BEvent.create("p", "c1", "13"))
+				new BEvent("p", "c1", "3"),
+				new BEvent("p", "c1", "7"),
+				new BEvent("p", "c1", "11"),
+				new BEvent("p", "c1", "13"))
 			.keyBy(BEvent::getProcessName)
 			.flatMap(m)
 			.executeAndCollect().forEachRemaining((StringResponse e) -> {
diff --git a/src/test/java/beamline/tests/EventTest.java b/src/test/java/beamline/tests/EventTest.java
index 77c71bd..89991ad 100644
--- a/src/test/java/beamline/tests/EventTest.java
+++ b/src/test/java/beamline/tests/EventTest.java
@@ -28,32 +28,32 @@ public class EventTest {
 	
 	@Test
 	public void event_creation() throws EventException {
-		assertThrows(EventException.class, () -> BEvent.create("", "", null));
-		assertThrows(EventException.class, () -> BEvent.create("", null, ""));
-		assertThrows(EventException.class, () -> BEvent.create(null, "", ""));
+		assertThrows(EventException.class, () -> new BEvent("", "", null));
+		assertThrows(EventException.class, () -> new BEvent("", null, ""));
+		assertThrows(EventException.class, () -> new BEvent(null, "", ""));
 		
-		BEvent e = BEvent.create(processName, traceName, eventName, eventDate, Set.of(Pair.of("a1", "v1")));
+		BEvent e = new BEvent(processName, traceName, eventName, eventDate, Set.of(Pair.of("a1", "v1")));
 		assertEquals("v1", e.getEventAttributes().get("a1"));
 	}
 	
 	@Test
 	public void event_names() throws EventException {
-		BEvent e = BEvent.create(processName, traceName, eventName);
+		BEvent e = new BEvent(processName, traceName, eventName);
 		assertEquals(processName, e.getProcessName());
 		assertEquals(traceName, e.getTraceName());
 		assertEquals(eventName, e.getEventName());
 		
 		Date eventDate = new Date();
-		BEvent e2 = BEvent.create(processName, traceName, eventName, eventDate);
+		BEvent e2 = new BEvent(processName, traceName, eventName, eventDate);
 		assertEquals(eventDate, e2.getEventTime());
 	}
 	
 	@Test
 	public void test_equals() throws EventException {
-		BEvent e = BEvent.create(processName, traceName, eventName);
+		BEvent e = new BEvent(processName, traceName, eventName);
 		e.setTimestamp(null);
-		BEvent e2 = BEvent.create(processName, traceName, eventName, eventDate);
-		BEvent e3 = BEvent.create(processName, traceName, eventName, eventDate);
+		BEvent e2 = new BEvent(processName, traceName, eventName, eventDate);
+		BEvent e3 = new BEvent(processName, traceName, eventName, eventDate);
 
 		assertEquals(e2, e3);
 		assertThat(e2).hasSameHashCodeAs(e3);
@@ -66,7 +66,7 @@ public class EventTest {
 	
 	@Test
 	public void event_attributes() throws EventException {
-		BEvent e = BEvent.create(processName, traceName, eventName);
+		BEvent e = new BEvent(processName, traceName, eventName);
 		e.setProcessAttribute("pa", "v1");
 		e.setTraceAttribute("ta", "v2");
 		e.setEventAttribute("ea", "v3");
@@ -79,7 +79,7 @@ public class EventTest {
 	@Test
 	public void event_attributes_xattributable() throws EventException {
 		Date date = new Date();
-		BEvent e = BEvent.create(processName, traceName, eventName);
+		BEvent e = new BEvent(processName, traceName, eventName);
 		e.setProcessAttribute("pa", new XAttributeLiteralImpl("pa", "v1"));
 		e.setTraceAttribute("ta", new XAttributeBooleanImpl("ta", false));
 		e.setEventAttribute("ea", new XAttributeDiscreteImpl("ea", 42));
@@ -95,7 +95,7 @@ public class EventTest {
 	
 	@Test
 	public void event_to_string() throws EventException {
-		BEvent e = BEvent.create(processName, traceName, eventName, eventDate);
+		BEvent e = new BEvent(processName, traceName, eventName, eventDate);
 		assertEquals(
 			"{concept:name=" + processName +"} - " +
 			"{concept:name=" + traceName + "} - " +
diff --git a/src/test/java/beamline/tests/FiltersTest.java b/src/test/java/beamline/tests/FiltersTest.java
index 87a3d14..b52a1e9 100644
--- a/src/test/java/beamline/tests/FiltersTest.java
+++ b/src/test/java/beamline/tests/FiltersTest.java
@@ -18,22 +18,22 @@ public class FiltersTest {
 	public void test_exclude_activities_on_name_filter() throws EventException, Exception {
 		ExcludeActivitiesFilter f = new ExcludeActivitiesFilter("A");
 		
-		assertTrue(f.filter(BEvent.create("", "", "B")));
-		assertFalse(f.filter(BEvent.create("", "", "A")));
+		assertTrue(f.filter(new BEvent("", "", "B")));
+		assertFalse(f.filter(new BEvent("", "", "A")));
 	}
 	
 	@Test
 	public void test_retain_activities_on_name_filter() throws EventException {
 		RetainActivitiesFilter f = new RetainActivitiesFilter("A");
 
-		assertTrue(f.filter(BEvent.create("", "", "A")));
-		assertFalse(f.filter(BEvent.create("", "", "B")));
+		assertTrue(f.filter(new BEvent("", "", "A")));
+		assertFalse(f.filter(new BEvent("", "", "B")));
 	}
 	
 	@Test
 	public void test_retain_activities_on_case_attribute_filter() throws EventException {
-		BEvent e1 = BEvent.create("", "", "");
-		BEvent e2 = BEvent.create("", "", "");
+		BEvent e1 = new BEvent("", "", "");
+		BEvent e2 = new BEvent("", "", "");
 		
 		e1.getTraceAttributes().put("a", "v1");
 		e2.getTraceAttributes().put("a", "v2");
@@ -46,8 +46,8 @@ public class FiltersTest {
 	
 	@Test
 	public void test_exclude_activities_on_case_attribute_filter() throws EventException {
-		BEvent e1 = BEvent.create("", "", "");
-		BEvent e2 = BEvent.create("", "", "");
+		BEvent e1 = new BEvent("", "", "");
+		BEvent e2 = new BEvent("", "", "");
 		
 		e1.getTraceAttributes().put("a", "v1");
 		e2.getTraceAttributes().put("a", "v2");
diff --git a/src/test/java/beamline/tests/MapperTest.java b/src/test/java/beamline/tests/MapperTest.java
index 1e7ddeb..a41e8a0 100644
--- a/src/test/java/beamline/tests/MapperTest.java
+++ b/src/test/java/beamline/tests/MapperTest.java
@@ -23,14 +23,14 @@ public class MapperTest {
 		StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
 		env
 			.fromElements(
-				BEvent.create("p", "c", "K"),
-				BEvent.create("p", "c2", "A"),
-				BEvent.create("p", "c", "A"),
-				BEvent.create("p", "c", "B"),
-				BEvent.create("p", "c2", "B"),
-				BEvent.create("p", "c", "A"),
-				BEvent.create("p", "c2", "A"),
-				BEvent.create("p", "c", "C"))
+				new BEvent("p", "c", "K"),
+				new BEvent("p", "c2", "A"),
+				new BEvent("p", "c", "A"),
+				new BEvent("p", "c", "B"),
+				new BEvent("p", "c2", "B"),
+				new BEvent("p", "c", "A"),
+				new BEvent("p", "c2", "A"),
+				new BEvent("p", "c", "C"))
 			.keyBy(BEvent::getProcessName)
 			.flatMap(new InfiniteSizeDirectlyFollowsMapper())
 			.executeAndCollect().forEachRemaining((DirectlyFollowsRelation e) -> {
diff --git a/src/test/java/beamline/tests/ResponsesTest.java b/src/test/java/beamline/tests/ResponsesTest.java
index 4c377e8..4deca87 100644
--- a/src/test/java/beamline/tests/ResponsesTest.java
+++ b/src/test/java/beamline/tests/ResponsesTest.java
@@ -29,16 +29,16 @@ public class ResponsesTest {
 	
 	@Test
 	public void directly_follow_tests() throws EventException {
-		BEvent e1 = BEvent.create("p", "c1", "a");
-		BEvent e2 = BEvent.create("p", "c2", "a");
+		BEvent e1 = new BEvent("p", "c1", "a");
+		BEvent e2 = new BEvent("p", "c2", "a");
 		
 		assertThrows(IllegalArgumentException.class, () -> new DirectlyFollowsRelation(e1, e2));
 		
-		BEvent e21 = BEvent.create("p", "c1", "a");
-		BEvent e22 = BEvent.create("p", "c1", "b");
-		BEvent e23 = BEvent.create("p", "c2", "a");
-		BEvent e24 = BEvent.create("p", "c2", "b");
-		BEvent e25 = BEvent.create("p", "c1", "d");
+		BEvent e21 = new BEvent("p", "c1", "a");
+		BEvent e22 = new BEvent("p", "c1", "b");
+		BEvent e23 = new BEvent("p", "c2", "a");
+		BEvent e24 = new BEvent("p", "c2", "b");
+		BEvent e25 = new BEvent("p", "c1", "d");
 
 		DirectlyFollowsRelation df = new DirectlyFollowsRelation(e21, e22);
 		DirectlyFollowsRelation df2 = new DirectlyFollowsRelation(e23, e24);
@@ -53,10 +53,10 @@ public class ResponsesTest {
 	
 	@Test
 	public void test_equals() throws EventException {
-		BEvent e21 = BEvent.create("p", "c1", "a");
-		BEvent e22 = BEvent.create("p", "c1", "b");
-		BEvent e23 = BEvent.create("p", "c2", "a");
-		BEvent e24 = BEvent.create("p", "c2", "b");
+		BEvent e21 = new BEvent("p", "c1", "a");
+		BEvent e22 = new BEvent("p", "c1", "b");
+		BEvent e23 = new BEvent("p", "c2", "a");
+		BEvent e24 = new BEvent("p", "c2", "b");
 		
 		DirectlyFollowsRelation df = new DirectlyFollowsRelation(e21, e22);
 		DirectlyFollowsRelation df2 = new DirectlyFollowsRelation(e23, e24);
-- 
GitLab