diff --git a/src/demo/build.gradle b/src/demo/build.gradle index 0bc8048..2ff7f58 100644 --- a/src/demo/build.gradle +++ b/src/demo/build.gradle @@ -42,3 +42,10 @@ task runWithJavaExec(type: JavaExec) { classpath = sourceSets.main.runtimeClasspath main = "com.amplitude.Demo" } + +task runLocalUploadDemo(type: JavaExec) { + group = "Execution" + description = "Run LocalUploadDemo" + classpath = sourceSets.main.runtimeClasspath + main = "com.demo.amplitude.LocalUploadDemo" +} diff --git a/src/demo/java/com/demo/amplitude/LocalUploadDemo.java b/src/demo/java/com/demo/amplitude/LocalUploadDemo.java index 75c592a..5967da8 100644 --- a/src/demo/java/com/demo/amplitude/LocalUploadDemo.java +++ b/src/demo/java/com/demo/amplitude/LocalUploadDemo.java @@ -7,6 +7,7 @@ import org.json.JSONObject; import java.util.concurrent.TimeUnit; +import java.util.HashMap; public class LocalUploadDemo { @@ -42,7 +43,7 @@ public void onLogEventServerResponse(Event event, int status, String message) { }; client.setCallbacks(callback); - // GROUPS AND GROUP PROPERTIES + // GROUPS AND GROUP PROPERTIES - Traditional JSONObject approach JSONObject groups = new JSONObject() .put("org", "engineering") .put("department", "sdk"); @@ -64,25 +65,74 @@ public void onLogEventServerResponse(Event event, int status, String message) { groupIdentifyEvent.groupProperties = groupProps; client.logEvent(groupIdentifyEvent); - // Track an event - client.logEvent(new Event("Test Event 1", userId)); + // GROUPS AND GROUP PROPERTIES - Using new helper methods + java.util.Map groupsMap = new HashMap<>(); + groupsMap.put("new-org", "engineering"); + groupsMap.put("new-department", "sdk"); + + Event groupEventWithHelpers = new Event("$identify", userId) + .setGroups(groupsMap) + .setUserProperties(groupsMap); + client.logEvent(groupEventWithHelpers); + + Event groupIdentifyWithHelpers = new Event("$groupidentify", userId) + .addGroup("new-org", "engineering") + .addGroup("new-department", "sdk") + .addGroupProperty("new-technology", "java") + .addGroupProperty("new-location", "toronto"); + client.logEvent(groupIdentifyWithHelpers); + + // USING NEW HELPER METHODS - Map-based approach + java.util.Map eventPropsMap = new HashMap<>(); + eventPropsMap.put("method", "email"); + eventPropsMap.put("source", "web"); + + java.util.Map userPropsMap = new HashMap<>(); + userPropsMap.put("plan", "premium"); + userPropsMap.put("age", 30); + + Event eventWithMapProps = new Event("User Login - new way", userId) + .setEventProperties(eventPropsMap) + .setUserProperties(userPropsMap); + client.logEvent(eventWithMapProps); + + // event props and user props using old JSONObject approach + Event eventWithJSONObjectProps = new Event("Purchase Complete - old way", userId); + eventWithJSONObjectProps.eventProperties = new JSONObject() + .put("item_id", "SKU-123") + .put("price", 29.99) + .put("currency", "USD"); + eventWithJSONObjectProps.userProperties = new JSONObject() + .put("total_purchases", 5) + .put("last_purchase_date", "2025-11-07"); + client.logEvent(eventWithJSONObjectProps); + // Flush events to the server client.flushEvents(); + int totalEvents = 10; //10000000; - for (int i = 0; i < 10000000; i++) { + for (int i = 0; i < totalEvents; i++) { Event ampEvent = new Event("General" + (i % 20), "Test_UserID_B" + (i % 5000)); while (client.shouldWait(ampEvent)) { System.out.println("Client is busy. Waiting for log event " + ampEvent.eventType); TimeUnit.SECONDS.sleep(60L); } - ampEvent.userProperties = - new JSONObject() - .put("property1", "p" + i) - .put("property2", "p" + i) - .put("property3", "p" + i) - .put("property4", "p" + i) - .put("property5", "p" + i); + // Traditional approach using JSONObject directly + // ampEvent.userProperties = + // new JSONObject() + // .put("property1", "p" + i) + // .put("property2", "p" + i) + // .put("property3", "p" + i) + // .put("property4", "p" + i) + // .put("property5", "p" + i); + + // New approach using helper methods - cleaner and no JSONObject needed + ampEvent.addUserProperty("property1", "p" + i) + .addUserProperty("property2", "p" + i) + .addUserProperty("property3", "p" + i) + .addUserProperty("property4", "p" + i) + .addUserProperty("property5", "p" + i); client.logEvent(ampEvent); } } diff --git a/src/main/java/com/amplitude/Event.java b/src/main/java/com/amplitude/Event.java index 61955c9..63a2a28 100644 --- a/src/main/java/com/amplitude/Event.java +++ b/src/main/java/com/amplitude/Event.java @@ -5,6 +5,7 @@ import org.json.JSONObject; import java.util.Iterator; +import java.util.Map; import java.util.UUID; public class Event { @@ -230,6 +231,130 @@ public Event(String eventType, String userId, String deviceId) { this.deviceId = deviceId; } + /** + * Set event properties from a Map. This replaces any existing event properties. + * + * @param properties Map of key-value pairs for event properties + * @return this Event for method chaining + */ + public Event setEventProperties(Map properties) { + if (properties == null) { + this.eventProperties = null; + } else { + this.eventProperties = new JSONObject(properties); + } + return this; + } + + /** + * Add or update a single event property. If event properties is null, it will be initialized. + * + * @param key Property key + * @param value Property value + * @return this Event for method chaining + */ + public Event addEventProperty(String key, Object value) { + if (this.eventProperties == null) { + this.eventProperties = new JSONObject(); + } + this.eventProperties.put(key, value); + return this; + } + + /** + * Set user properties from a Map. This replaces any existing user properties. + * + * @param properties Map of key-value pairs for user properties + * @return this Event for method chaining + */ + public Event setUserProperties(Map properties) { + if (properties == null) { + this.userProperties = null; + } else { + this.userProperties = new JSONObject(properties); + } + return this; + } + + /** + * Add or update a single user property. If user properties is null, it will be initialized. + * + * @param key Property key + * @param value Property value + * @return this Event for method chaining + */ + public Event addUserProperty(String key, Object value) { + if (this.userProperties == null) { + this.userProperties = new JSONObject(); + } + this.userProperties.put(key, value); + return this; + } + + /** + * Set groups from a Map. This replaces any existing groups. This feature is only available to + * Enterprise customers who have purchased the Accounts add-on. + * + * @param groups Map of key-value pairs representing groups + * @return this Event for method chaining + */ + public Event setGroups(Map groups) { + if (groups == null) { + this.groups = null; + } else { + this.groups = new JSONObject(groups); + } + return this; + } + + /** + * Add or update a single group. If groups is null, it will be initialized. This feature is only + * available to Enterprise customers who have purchased the Accounts add-on. + * + * @param key Group key + * @param value Group value + * @return this Event for method chaining + */ + public Event addGroup(String key, Object value) { + if (this.groups == null) { + this.groups = new JSONObject(); + } + this.groups.put(key, value); + return this; + } + + /** + * Set group properties from a Map. This replaces any existing group properties. This feature is + * only available to Enterprise customers who have purchased the Accounts add-on. + * + * @param properties Map of key-value pairs for group properties + * @return this Event for method chaining + */ + public Event setGroupProperties(Map properties) { + if (properties == null) { + this.groupProperties = null; + } else { + this.groupProperties = new JSONObject(properties); + } + return this; + } + + /** + * Add or update a single group property. If group properties is null, it will be initialized. + * This feature is only available to Enterprise customers who have purchased the Accounts add-on. + * + * @param key Property key + * @param value Property value + * @return this Event for method chaining + */ + public Event addGroupProperty(String key, Object value) { + if (this.groupProperties == null) { + this.groupProperties = new JSONObject(); + } + this.groupProperties.put(key, value); + return this; + } + /** @return the JSONObject that represents the event data of this event */ public JSONObject toJsonObject() { JSONObject event = new JSONObject(); diff --git a/src/test/java/com/amplitude/EventTest.java b/src/test/java/com/amplitude/EventTest.java index 4db2f7f..bec8d50 100644 --- a/src/test/java/com/amplitude/EventTest.java +++ b/src/test/java/com/amplitude/EventTest.java @@ -2,8 +2,12 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.HashMap; +import java.util.Map; import org.json.JSONArray; import org.json.JSONObject; import org.junit.jupiter.api.Test; @@ -104,4 +108,185 @@ public void testLogEventWithoutRevenue() { assertFalse(truncatedEvent.has("productId")); assertFalse(truncatedEvent.has("revenueType")); } + + @Test + public void testSetEventPropertiesWithMap() { + Event event = new Event("test event", "test-user"); + Map properties = new HashMap<>(); + properties.put("key1", "value1"); + properties.put("key2", 123); + properties.put("key3", true); + + event.setEventProperties(properties); + + JSONObject jsonEvent = event.toJsonObject(); + JSONObject eventProps = jsonEvent.getJSONObject("event_properties"); + assertEquals("value1", eventProps.getString("key1")); + assertEquals(123, eventProps.getInt("key2")); + assertTrue(eventProps.getBoolean("key3")); + } + + @Test + public void testSetEventPropertiesWithNull() { + Event event = new Event("test event", "test-user"); + event.eventProperties = new JSONObject().put("existing", "value"); + + event.setEventProperties(null); + + assertNull(event.eventProperties); + } + + @Test + public void testAddEventProperty() { + Event event = new Event("test event", "test-user"); + + event.addEventProperty("prop1", "value1") + .addEventProperty("prop2", 456) + .addEventProperty("prop3", false); + + JSONObject jsonEvent = event.toJsonObject(); + JSONObject eventProps = jsonEvent.getJSONObject("event_properties"); + assertEquals("value1", eventProps.getString("prop1")); + assertEquals(456, eventProps.getInt("prop2")); + assertFalse(eventProps.getBoolean("prop3")); + } + + @Test + public void testSetUserPropertiesWithMap() { + Event event = new Event("test event", "test-user"); + Map properties = new HashMap<>(); + properties.put("name", "John Doe"); + properties.put("age", 30); + properties.put("premium", true); + + event.setUserProperties(properties); + + JSONObject jsonEvent = event.toJsonObject(); + JSONObject userProps = jsonEvent.getJSONObject("user_properties"); + assertEquals("John Doe", userProps.getString("name")); + assertEquals(30, userProps.getInt("age")); + assertTrue(userProps.getBoolean("premium")); + } + + @Test + public void testSetUserPropertiesWithNull() { + Event event = new Event("test event", "test-user"); + event.userProperties = new JSONObject().put("existing", "value"); + + event.setUserProperties(null); + + assertNull(event.userProperties); + } + + @Test + public void testAddUserProperty() { + Event event = new Event("test event", "test-user"); + + event.addUserProperty("city", "San Francisco") + .addUserProperty("visits", 5) + .addUserProperty("subscribed", true); + + JSONObject jsonEvent = event.toJsonObject(); + JSONObject userProps = jsonEvent.getJSONObject("user_properties"); + assertEquals("San Francisco", userProps.getString("city")); + assertEquals(5, userProps.getInt("visits")); + assertTrue(userProps.getBoolean("subscribed")); + } + + @Test + public void testSetGroupsWithMap() { + Event event = new Event("test event", "test-user"); + Map groups = new HashMap<>(); + groups.put("org", "engineering"); + groups.put("department", "sdk"); + + event.setGroups(groups); + + JSONObject jsonEvent = event.toJsonObject(); + JSONObject groupsJson = jsonEvent.getJSONObject("groups"); + assertEquals("engineering", groupsJson.getString("org")); + assertEquals("sdk", groupsJson.getString("department")); + } + + @Test + public void testSetGroupsWithNull() { + Event event = new Event("test event", "test-user"); + event.groups = new JSONObject().put("existing", "value"); + + event.setGroups(null); + + assertNull(event.groups); + } + + @Test + public void testAddGroup() { + Event event = new Event("test event", "test-user"); + + event.addGroup("company", "Amplitude") + .addGroup("team", "SDK"); + + JSONObject jsonEvent = event.toJsonObject(); + JSONObject groupsJson = jsonEvent.getJSONObject("groups"); + assertEquals("Amplitude", groupsJson.getString("company")); + assertEquals("SDK", groupsJson.getString("team")); + } + + @Test + public void testSetGroupPropertiesWithMap() { + Event event = new Event("test event", "test-user"); + Map groupProps = new HashMap<>(); + groupProps.put("technology", "java"); + groupProps.put("location", "toronto"); + + event.setGroupProperties(groupProps); + + JSONObject jsonEvent = event.toJsonObject(); + JSONObject groupPropsJson = jsonEvent.getJSONObject("group_properties"); + assertEquals("java", groupPropsJson.getString("technology")); + assertEquals("toronto", groupPropsJson.getString("location")); + } + + @Test + public void testSetGroupPropertiesWithNull() { + Event event = new Event("test event", "test-user"); + event.groupProperties = new JSONObject().put("existing", "value"); + + event.setGroupProperties(null); + + assertNull(event.groupProperties); + } + + @Test + public void testAddGroupProperty() { + Event event = new Event("test event", "test-user"); + + event.addGroupProperty("size", 100) + .addGroupProperty("region", "us-west"); + + JSONObject jsonEvent = event.toJsonObject(); + JSONObject groupPropsJson = jsonEvent.getJSONObject("group_properties"); + assertEquals(100, groupPropsJson.getInt("size")); + assertEquals("us-west", groupPropsJson.getString("region")); + } + + @Test + public void testMethodChaining() { + Map eventProps = new HashMap<>(); + eventProps.put("event_key", "event_value"); + + Map userProps = new HashMap<>(); + userProps.put("user_key", "user_value"); + + Event event = new Event("test event", "test-user") + .setEventProperties(eventProps) + .setUserProperties(userProps) + .addEventProperty("additional_event", "value") + .addUserProperty("additional_user", "value"); + + JSONObject jsonEvent = event.toJsonObject(); + assertEquals("event_value", jsonEvent.getJSONObject("event_properties").getString("event_key")); + assertEquals("value", jsonEvent.getJSONObject("event_properties").getString("additional_event")); + assertEquals("user_value", jsonEvent.getJSONObject("user_properties").getString("user_key")); + assertEquals("value", jsonEvent.getJSONObject("user_properties").getString("additional_user")); + } }