summaryrefslogtreecommitdiff
path: root/src/main/java/events/implementations/VSTimestampTriggeredEvent.java
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-06-20 17:18:45 +0300
committerPaul Buetow <paul@buetow.org>2025-06-20 17:18:45 +0300
commit5e16f7f37c984d7ee1d1f0484cf0a8154bbb849d (patch)
treeb163049ab785dcfba3bc46cb159156e1c8566bf1 /src/main/java/events/implementations/VSTimestampTriggeredEvent.java
parent28beef18a728ec4c35e47378c514ad826c2f9a31 (diff)
Improve code quality: Replace instanceof with polymorphism and extract constants
Major improvements: 1. Replace instanceof checks with polymorphic methods in VSAbstractEvent hierarchy - Added isInternalEvent(), isMessageReceiveEvent(), etc. methods - Added getEventPriority() for clean event ordering - Added shouldIncreaseTimestamps() to control timestamp behavior - Refactored VSTask to use these polymorphic methods 2. Extract magic numbers and strings to constants - Created VSConstants class for centralized configuration values - Added event priority constants (PRIORITY_HIGHEST, PRIORITY_HIGH, etc.) - Extracted string constants like CLASS_PREFIX - Moved magic numbers to named constants (PERCENTAGE_RANGE, etc.) 3. Update tests to work with new polymorphic approach - Fixed mocking in VSTaskTest to return correct values - All 132 tests passing These changes improve maintainability, reduce coupling, and make the codebase more self-documenting. The polymorphic approach eliminates type checking and makes it easier to add new event types. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
Diffstat (limited to 'src/main/java/events/implementations/VSTimestampTriggeredEvent.java')
-rw-r--r--src/main/java/events/implementations/VSTimestampTriggeredEvent.java264
1 files changed, 264 insertions, 0 deletions
diff --git a/src/main/java/events/implementations/VSTimestampTriggeredEvent.java b/src/main/java/events/implementations/VSTimestampTriggeredEvent.java
new file mode 100644
index 0000000..16d552d
--- /dev/null
+++ b/src/main/java/events/implementations/VSTimestampTriggeredEvent.java
@@ -0,0 +1,264 @@
+package events.implementations;
+
+import core.VSInternalProcess;
+import core.time.VSLamportTime;
+import core.time.VSVectorTime;
+import events.VSAbstractEvent;
+import events.VSCopyableEvent;
+
+/**
+ * Abstract base class for timestamp-triggered events that fire when specific
+ * Lamport or vector clock conditions are met.
+ *
+ * @author Paul C. Buetow
+ */
+public abstract class VSTimestampTriggeredEvent extends VSAbstractEvent implements VSCopyableEvent {
+
+ public enum TimestampType {
+ LAMPORT,
+ VECTOR
+ }
+
+ public enum ComparisonOperator {
+ EQUAL,
+ GREATER_THAN,
+ LESS_THAN,
+ GREATER_EQUAL,
+ LESS_EQUAL
+ }
+
+ protected TimestampType timestampType;
+ protected ComparisonOperator operator;
+ protected boolean hasTriggered;
+
+ protected long targetLamportTime;
+ protected VSVectorTime targetVectorTime;
+
+ /**
+ * Constructor for Lamport timestamp events
+ */
+ public VSTimestampTriggeredEvent(long targetLamport, ComparisonOperator op) {
+ this.timestampType = TimestampType.LAMPORT;
+ this.targetLamportTime = targetLamport;
+ this.operator = op;
+ this.hasTriggered = false;
+ }
+
+ /**
+ * Constructor for Vector timestamp events
+ */
+ public VSTimestampTriggeredEvent(VSVectorTime targetVector, ComparisonOperator op) {
+ this.timestampType = TimestampType.VECTOR;
+ this.targetVectorTime = targetVector.getCopy();
+ this.operator = op;
+ this.hasTriggered = false;
+ }
+
+ /**
+ * Default constructor for serialization
+ */
+ public VSTimestampTriggeredEvent() {
+ this.hasTriggered = false;
+ }
+
+ @Override
+ public void onInit() {
+ setClassname(getClass().getName());
+ }
+
+ @Override
+ public void onStart() {
+ if (hasTriggered) {
+ return;
+ }
+
+ VSInternalProcess internalProcess = (VSInternalProcess) process;
+ boolean conditionMet = false;
+
+ if (timestampType == TimestampType.LAMPORT) {
+ conditionMet = checkLamportCondition(internalProcess);
+ } else if (timestampType == TimestampType.VECTOR) {
+ conditionMet = checkVectorCondition(internalProcess);
+ }
+
+ if (conditionMet) {
+ hasTriggered = true;
+ onTimestampReached();
+ }
+ }
+
+ /**
+ * Check timestamp condition without triggering the event.
+ * Used by monitoring systems to test conditions.
+ */
+ public boolean checkCondition(VSInternalProcess process) {
+ if (hasTriggered) {
+ return false;
+ }
+
+ if (timestampType == TimestampType.LAMPORT) {
+ return checkLamportCondition(process);
+ } else if (timestampType == TimestampType.VECTOR) {
+ return checkVectorCondition(process);
+ }
+
+ return false;
+ }
+
+ /**
+ * Check if Lamport timestamp condition is met
+ */
+ protected boolean checkLamportCondition(VSInternalProcess process) {
+ long currentLamport = process.getLamportTime();
+
+ switch (operator) {
+ case EQUAL:
+ return currentLamport == targetLamportTime;
+ case GREATER_THAN:
+ return currentLamport > targetLamportTime;
+ case LESS_THAN:
+ return currentLamport < targetLamportTime;
+ case GREATER_EQUAL:
+ return currentLamport >= targetLamportTime;
+ case LESS_EQUAL:
+ return currentLamport <= targetLamportTime;
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Check if Vector timestamp condition is met
+ */
+ protected boolean checkVectorCondition(VSInternalProcess process) {
+ VSVectorTime currentVector = process.getVectorTime();
+
+ if (currentVector == null || targetVectorTime == null) {
+ return false;
+ }
+
+ switch (operator) {
+ case EQUAL:
+ return vectorTimesEqual(currentVector, targetVectorTime);
+ case GREATER_THAN:
+ return vectorTimeGreater(currentVector, targetVectorTime, false);
+ case LESS_THAN:
+ return vectorTimeGreater(targetVectorTime, currentVector, false);
+ case GREATER_EQUAL:
+ return vectorTimeGreater(currentVector, targetVectorTime, true);
+ case LESS_EQUAL:
+ return vectorTimeGreater(targetVectorTime, currentVector, true);
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * Check if two vector times are equal
+ */
+ protected boolean vectorTimesEqual(VSVectorTime v1, VSVectorTime v2) {
+ int maxSize = Math.max(v1.size(), v2.size());
+
+ for (int i = 0; i < maxSize; i++) {
+ long val1 = i < v1.size() ? v1.get(i) : 0;
+ long val2 = i < v2.size() ? v2.get(i) : 0;
+
+ if (val1 != val2) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Check if v1 > v2 (or >= if allowEqual is true) using vector clock ordering
+ */
+ protected boolean vectorTimeGreater(VSVectorTime v1, VSVectorTime v2, boolean allowEqual) {
+ int maxSize = Math.max(v1.size(), v2.size());
+ boolean hasGreater = false;
+
+ for (int i = 0; i < maxSize; i++) {
+ long val1 = i < v1.size() ? v1.get(i) : 0;
+ long val2 = i < v2.size() ? v2.get(i) : 0;
+
+ if (val1 < val2) {
+ return false;
+ } else if (val1 > val2) {
+ hasGreater = true;
+ }
+ }
+
+ return hasGreater || (allowEqual && vectorTimesEqual(v1, v2));
+ }
+
+ /**
+ * This method is called when the timestamp condition is met.
+ * Subclasses should override this to define the actual behavior.
+ */
+ protected abstract void onTimestampReached();
+
+ @Override
+ protected String createShortname(String savedShortname) {
+ return "TimestampTrigger";
+ }
+
+ @Override
+ public void initCopy(VSAbstractEvent copy) {
+ if (copy instanceof VSTimestampTriggeredEvent) {
+ VSTimestampTriggeredEvent copyEvent = (VSTimestampTriggeredEvent) copy;
+ copyEvent.timestampType = this.timestampType;
+ copyEvent.operator = this.operator;
+ copyEvent.targetLamportTime = this.targetLamportTime;
+ copyEvent.hasTriggered = this.hasTriggered;
+
+ if (this.targetVectorTime != null) {
+ copyEvent.targetVectorTime = this.targetVectorTime.getCopy();
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(" [TimestampTrigger: ");
+
+ if (timestampType == TimestampType.LAMPORT) {
+ sb.append("Lamport ").append(operator).append(" ").append(targetLamportTime);
+ } else {
+ sb.append("Vector ").append(operator).append(" ").append(targetVectorTime);
+ }
+
+ if (hasTriggered) {
+ sb.append(" (TRIGGERED)");
+ }
+
+ sb.append("]");
+ return sb.toString();
+ }
+
+ // Getters and setters
+ public TimestampType getTimestampType() {
+ return timestampType;
+ }
+
+ public ComparisonOperator getOperator() {
+ return operator;
+ }
+
+ public long getTargetLamportTime() {
+ return targetLamportTime;
+ }
+
+ public VSVectorTime getTargetVectorTime() {
+ return targetVectorTime != null ? targetVectorTime.getCopy() : null;
+ }
+
+ public boolean hasTriggered() {
+ return hasTriggered;
+ }
+
+ public void reset() {
+ hasTriggered = false;
+ }
+} \ No newline at end of file