diff --git a/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/algorithms/iLCDAlgorithm.java b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/algorithms/iLCDAlgorithm.java index 3c62e961..e5c46ad7 100644 --- a/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/algorithms/iLCDAlgorithm.java +++ b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/algorithms/iLCDAlgorithm.java @@ -215,9 +215,10 @@ public Cover detectOverlappingCommunities(CustomGraph graph) throws OcdAlgorithm - HashSet fusionCandidates = new HashSet(); + //Foreach modified community for(iLCDCommunityAgent community: modifiedCommunitiesSorted) { + HashSet fusionCandidates = new HashSet(); //Get all communities "community"'s agents are part of for(iLCDNodeAgent node: community.getNodes()) { fusionCandidates.addAll(node.getCommunities()); diff --git a/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/CommunityEvent.java b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/CommunityEvent.java new file mode 100644 index 00000000..7fa3ff4d --- /dev/null +++ b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/CommunityEvent.java @@ -0,0 +1,140 @@ +package i5.las2peer.services.ocd.utils; + +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDatabase; +import com.arangodb.entity.BaseDocument; +import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.model.DocumentReadOptions; +import com.fasterxml.jackson.databind.ObjectMapper; +import i5.las2peer.services.ocd.graphs.Community; + +import java.util.ArrayList; +import java.util.List; + +/** + * The class corresponding to community events in the community life cycle. + */ +public class CommunityEvent { + public static final String clcKeyColumnName = "CLC_KEY"; + public static final String collectionName = "communityEvent"; + public static final String dateColumnName = "date"; + public static final String eventTypeColumnName = "eventType"; + public static final String communitiesColumnName = "communitiesInvolved"; + public static final String nodesColumnName = "nodesInvolved"; + /** + * System generated persistence key + */ + private String key; + /** + * The date of the event + */ + private String date; + /** + * The event type by id + */ + private int eventType; + /** + * The list of communities involved in the event + */ + private List communitiesInvolved = new ArrayList<>(); + /** + * The list of nodes involved in the event + */ + private List nodesInvolved = new ArrayList<>(); + /** + * The community life cycle the event is part of + */ + private CommunityLifeCycle clc; + public CommunityEvent(CommunityLifeCycle clc, String date, List communitiesInvolved, List nodesInvolved) { + this.clc = clc; + this.date = date; + this.communitiesInvolved = communitiesInvolved; + this.nodesInvolved = nodesInvolved; + } + + public CommunityEvent(CommunityLifeCycle clc, String date, List communitiesInvolved) { + this.clc = clc; + this.date = date; + this.communitiesInvolved = communitiesInvolved; + } + + public CommunityEvent() { + } + + public int getEventType() { + return eventType; + } + + public String getKey() { + return key; + } + + public String getDate() { + return date; + } + public int getDateAsInt() { + return Integer.parseInt(date); + } + + public List getCommunitiesInvolved() { + return communitiesInvolved; + } + + public List getNodesInvolved() { + return nodesInvolved; + } + + /** + * Adds an event type to the event as the id of the type. + * @param type + */ + public void addEventType(CommunityEventType type){ + this.eventType = type.getId(); + } + + public void persist(ArangoDatabase db, DocumentCreateOptions opt){ + ArangoCollection collection = db.collection(collectionName); + BaseDocument bd = new BaseDocument(); + bd.addAttribute(dateColumnName, this.date); + bd.addAttribute(eventTypeColumnName, this.eventType); + bd.addAttribute(communitiesColumnName, this.communitiesInvolved); + bd.addAttribute(nodesColumnName, this.nodesInvolved); + bd.addAttribute(clcKeyColumnName, this.clc.getKey()); + collection.insertDocument(bd, opt); + this.key = bd.getKey(); + } + + public static CommunityEvent load(String key, CommunityLifeCycle clc, ArangoDatabase db, DocumentReadOptions opt){ + CommunityEvent ce = new CommunityEvent(); + + ArangoCollection collection = db.collection(collectionName); + + BaseDocument bd = collection.getDocument(key, BaseDocument.class, opt); + if(bd != null){ + ObjectMapper om = new ObjectMapper(); + String eventTypeString = bd.getAttribute(eventTypeColumnName).toString(); + Object objCommunities = bd.getAttribute(communitiesColumnName); + Object objNodes = bd.getAttribute(nodesColumnName); + + ce.key = key; + ce.clc = clc; + ce.date = bd.getAttribute(dateColumnName).toString(); + ce.eventType = Integer.parseInt(eventTypeString); + ce.communitiesInvolved = om.convertValue(objCommunities, List.class); + ce.nodesInvolved = om.convertValue(objNodes, List.class); + }else{ + System.out.println("empty event document"); + } + return ce; + } + + @Override + public String toString() { + return "CommunityEvent{" + + "date='" + date + '\'' + + ", eventType=" + CommunityEventType.lookupType(eventType) + + ", communitiesInvolved=" + communitiesInvolved + + ", nodesInvolved=" + nodesInvolved + + '}'; + } +} diff --git a/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/CommunityEventType.java b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/CommunityEventType.java new file mode 100644 index 00000000..78866d72 --- /dev/null +++ b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/CommunityEventType.java @@ -0,0 +1,84 @@ +package i5.las2peer.services.ocd.utils; + +import java.util.Locale; + +import i5.las2peer.services.ocd.utils.EnumDisplayNames; + +/** + * Used to indicate the type of event. + */ +public enum CommunityEventType implements EnumDisplayNames { + //event types, can be expanded + GROWTH("Growth", 0), + + BIRTH("Birth", 1), + + CONTRACTION("Contraction", 2), + + DEATH("Death", 3), + + FUSION("Fusion", 4), + + SPLIT("Split", 5); + + + /** + * For persistence and other purposes. + */ + private int id; + + /** + * A display name for web frontends and more + */ + private final String displayName; + + /** + * Creates a new instance. + * @param id Defines the id attribute. + */ + private CommunityEventType(String displayName, int id) { + this.displayName = displayName; + this.id = id; + } + + /** + * Getter for the id. + * @return The id. + */ + public int getId() { + return id; + } + + /** + * Returns the display name of the type. + * @return The name. + */ + public String getDisplayName() { + return displayName; + } + + /** + * Returns the type corresponding to an id. + * @param id The id. + * @return The type. + */ + public static CommunityEventType lookupType(int id) { + for (CommunityEventType type : CommunityEventType.values()) { + if (id == type.getId()) { + return type; + } + } + return null; + } + + /** + * Returns the name of the type written in lower case letters and with any underscores replaced by space characters. + */ + @Override + public String toString() { + String name = name(); + name = name.replace('_', ' '); + name = name.toLowerCase(Locale.ROOT); + return name; + } +} diff --git a/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/CommunityLifeCycle.java b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/CommunityLifeCycle.java new file mode 100644 index 00000000..05145aa1 --- /dev/null +++ b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/CommunityLifeCycle.java @@ -0,0 +1,297 @@ +package i5.las2peer.services.ocd.utils; + +import com.arangodb.ArangoCollection; +import com.arangodb.ArangoDatabase; +import com.arangodb.entity.BaseDocument; +import com.arangodb.model.DocumentCreateOptions; +import com.arangodb.model.DocumentReadOptions; +import com.arangodb.model.DocumentUpdateOptions; +import com.fasterxml.jackson.databind.ObjectMapper; +import i5.las2peer.services.ocd.graphs.*; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; + +/** + * This class represents the Community Life Cycle as described in "Quantifying social group evolution" by Palla et al. + * [doi:10.1038/nature05670] + * It handles the 6 types of events presented GROWTH, BIRTH, CONTRACTION, DEATH, FUSION and SPLIT. + * The handle methods are to be integrated into dynamic algorithms. + */ +public class CommunityLifeCycle { + ////////////////////////////// DATABASE COLUMN NAMES ////////////////////////////////// + public static final String nameColumnName = "NAME"; + + public static final String collectionName = "clc"; + + public static final String graphKeyColumnName = "GRAPH_KEY"; + + public static final String creationMethodKeyColumnName = "CREATION_METHOD_KEY"; + + public static final String coverKeyColumnName = "COVER_KEY"; + + public static final String eventKeysColumnName = "EVENT_KEYS"; + + /////////////////////////// ATTRIBUTES //////////////////////////// + /** + * System generated persistence key + */ + private String key = ""; + /** + * The graph the community life cycle is based on + */ + private DynamicGraph graph = new DynamicGraph(); + /** + * The cover the community life cycle is based on + */ + private Cover cover = new Cover(this.graph); + /** + * Logged data about the algorithm that created the clc + */ + private CoverCreationLog creationMethod = new CoverCreationLog(CoverCreationType.UNDEFINED, new HashMap(), new HashSet()); + /** + * The name of the clc + */ + private String name = ""; + /** + * The list of events + */ + private List events = new ArrayList<>(); + + public CommunityLifeCycle() { + } + + public CommunityLifeCycle(Cover c, DynamicGraph g){ + this.graph = g; + this.cover = c; + } + + public String getKey() { + return key; + } + + public List getEvents() { + return events; + } + + public void setCreationMethod(CoverCreationLog creationMethod) { + if(creationMethod != null) { + this.creationMethod = creationMethod; + } else{ + this.creationMethod = new CoverCreationLog(CoverCreationType.UNDEFINED, new HashMap(), + new HashSet()); + } + + } + + public void setName(String name) { + this.name = name; + } + + /** + * Handles an incoming growth event from the dynamic algorithm + * @param current_timestamp the timestamp the event is taking place + * @param community_id the involved community + * @param node_name the node added to the community + */ + public void handleGrowth(String current_timestamp, int community_id, String node_name){ + // If the community has already had a growth event at this timestep, only add the node to the event + boolean added = false; + for(CommunityEvent event: events){ + if(event.getEventType() == CommunityEventType.GROWTH.getId() && event.getDate() == current_timestamp && event.getCommunitiesInvolved().get(0) == community_id){ + event.getNodesInvolved().add(node_name); + added = true; + } + } + // if new growth event add new event + if(!added) { + List communitiesInvolved = new ArrayList<>(); + List nodesInvolved = new ArrayList<>(); + + communitiesInvolved.add(community_id); + nodesInvolved.add(node_name); + + CommunityEvent new_event = new CommunityEvent(this, current_timestamp, communitiesInvolved, nodesInvolved); + new_event.addEventType(CommunityEventType.GROWTH); + + + events.add(new_event); + } + } + + /** + * Handles an incoming birth event from the algorithm + * @param current_timestamp the timestamp the event is taking place + * @param community_id the involved community + * @param node_names the nodes in the birthed community + */ + public void handleBirth(String current_timestamp, int community_id, List node_names) { + List communitiesInvolved = new ArrayList<>(); + + communitiesInvolved.add(community_id); + + CommunityEvent new_event = new CommunityEvent(this, current_timestamp, communitiesInvolved, node_names); + new_event.addEventType(CommunityEventType.BIRTH); + events.add(new_event); + } + + /** + * Handles an incoming contraction event from the algorithm + * @param current_timestamp the timestamp the event is taking place + * @param community_id the involved community + * @param node_name the node removed from the community + */ + public void handleContraction(String current_timestamp, int community_id, String node_name) { + // If the community has already had a contraction event at this timestep, only add the node to the event + boolean added = false; + for(CommunityEvent event: events) { + if(event.getEventType() == CommunityEventType.CONTRACTION.getId() && event.getDate() == current_timestamp && event.getCommunitiesInvolved().get(0) == community_id){ + event.getNodesInvolved().add(node_name); + added = true; + } + } + // if new contraction event add new event + if(!added) { + List communitiesInvolved = new ArrayList<>(); + List nodesInvolved = new ArrayList<>(); + + communitiesInvolved.add(community_id); + nodesInvolved.add(node_name); + + CommunityEvent new_event = new CommunityEvent(this, current_timestamp, communitiesInvolved, nodesInvolved); + new_event.addEventType(CommunityEventType.CONTRACTION); + events.add(new_event); + } + } + + /** + * Handles an incoming death event from the dynamic algorithm + * @param current_timestamp the timestamp the event is taking place + * @param community_id the involved community + */ + public void handleDeath(String current_timestamp, int community_id) { + // If the community was born in this timestamp delete the birth event + boolean born = false; + List eventCopy = new ArrayList<>(this.events); + for(CommunityEvent event: eventCopy){ + if(event.getDate() == current_timestamp && event.getCommunitiesInvolved().get(0) == community_id && event.getEventType() == CommunityEventType.BIRTH.getId()){ + born = true; + events.remove(event); + } + } + //if not add new death event to events + if(!born) { + List communitiesInvolved = new ArrayList<>(); + + communitiesInvolved.add(community_id); + + CommunityEvent new_event = new CommunityEvent(this, current_timestamp, communitiesInvolved); + new_event.addEventType(CommunityEventType.DEATH); + events.add(new_event); + } + } + + /** + * Handles an incoming fusion event from the dynamic algorithm + * @param current_timestamp the timestamp the event is taking place + * @param communitiesInvolved the communities involved sorted by age + */ + public void handleFusion(String current_timestamp, List communitiesInvolved){ + CommunityEvent new_event = new CommunityEvent(this, current_timestamp, communitiesInvolved); + new_event.addEventType(CommunityEventType.FUSION); + events.add(new_event); + } + + /** + * Handles an incoming split event from the dynamic algorithm + * @param current_timestamp the timestamp the event is taking place + * @param communitiesInvolved the communities involved sorted by age + */ + public void handleSplit(String current_timestamp, List communitiesInvolved) { + CommunityEvent new_event = new CommunityEvent(this, current_timestamp, communitiesInvolved); + new_event.addEventType((CommunityEventType.SPLIT)); + events.add(new_event); + } + + ///////////////////////// DATABASE FUNCTIONS ///////////////////////////// + public void persist(ArangoDatabase db, String transId){ + ArangoCollection collection = db.collection(collectionName); + BaseDocument bd = new BaseDocument(); + DocumentCreateOptions createOptions = new DocumentCreateOptions().streamTransactionId(transId); + DocumentUpdateOptions updateOptions = new DocumentUpdateOptions().streamTransactionId(transId); + if(this.graph == null){ + throw new IllegalArgumentException("graph attribute of the clc to be persisted does not exist"); + }else if(this.graph.getKey().equals("")){ + throw new IllegalArgumentException("the graph of the clc is not persisted yet"); + } else if (this.cover.getKey().equals("")) { + throw new IllegalArgumentException("the cover of the clc is not persisted yet"); + } + bd.addAttribute(graphKeyColumnName, this.graph.getKey()); + bd.addAttribute(coverKeyColumnName, this.cover.getKey()); + bd.addAttribute(nameColumnName, this.name); + bd.addAttribute(creationMethodKeyColumnName, this.cover.getCreationMethod().getKey()); + collection.insertDocument(bd, createOptions); + this.key = bd.getKey(); + + bd = new BaseDocument(); + List eventKeyList = new ArrayList<>(); + for(CommunityEvent event: this.events){ + event.persist(db, createOptions); + eventKeyList.add(event.getKey()); + } + bd.addAttribute(eventKeysColumnName, eventKeyList); + collection.updateDocument(this.key, bd, updateOptions); + } + + public static CommunityLifeCycle load(String key, Cover c, DynamicGraph g, ArangoDatabase db, String transId){ + CommunityLifeCycle clc = null; + ArangoCollection collection = db.collection(collectionName); + DocumentReadOptions readOpt = new DocumentReadOptions().streamTransactionId(transId); + BaseDocument bd = collection.getDocument(key, BaseDocument.class, readOpt); + + if(bd != null) { + clc = new CommunityLifeCycle(c, g); + ObjectMapper om = new ObjectMapper(); + + String graphKey = bd.getAttribute(graphKeyColumnName).toString(); + String coverKey = bd.getAttribute(coverKeyColumnName).toString(); + if(!graphKey.equals(g.getKey())){ + System.out.println("graph with key: " + g.getKey() + " does not fit to cover with GraphKey: " + graphKey); + return null; + } + if(!coverKey.equals(c.getKey())){ + System.out.println("cover with key: " + c.getKey() + " does not fit to cover with coverKey: " + coverKey); + return null; + } + String creationMethodKey = bd.getAttribute(creationMethodKeyColumnName).toString(); + Object objEventKeys = bd.getAttribute(eventKeysColumnName); + List eventKeys = om.convertValue(objEventKeys, List.class); + + clc.key = key; + clc.name = bd.getAttribute(nameColumnName).toString(); + clc.creationMethod = CoverCreationLog.load(creationMethodKey, db, readOpt); + for(String eventKey: eventKeys){ + CommunityEvent event = CommunityEvent.load(eventKey, clc, db, readOpt); + clc.events.add(event); + } + + }else{ + System.out.println("empty clc document"); + } + return clc; + } + + @Override + public String toString() { + return "CommunityLifeCycle{" + + "key='" + key + '\'' + + ", graph=" + graph + + ", cover=" + cover + + ", creationMethod=" + creationMethod + + ", name='" + name + '\'' + + ", events=" + events + + '}'; + } +} diff --git a/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/Database.java b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/Database.java index 9d69d217..64f9edb5 100644 --- a/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/Database.java +++ b/rest_ocd_services/src/main/java/i5/las2peer/services/ocd/utils/Database.java @@ -189,6 +189,16 @@ public void createCollections() { if(!collection.exists()) { collection.create(); } + collectionNames.add(CommunityLifeCycle.collectionName); //14 + collection = db.collection(CommunityLifeCycle.collectionName); + if(!collection.exists()) { + collection.create(); + } + collectionNames.add(CommunityEvent.collectionName); //15 + collection = db.collection(CommunityEvent.collectionName); + if(!collection.exists()) { + collection.create(); + } } @@ -996,6 +1006,45 @@ public void deleteCover(String username, String graphKey, String coverKey, Threa } } + /////////////////////////////////////////////// COMMUNTIY LIFE CYCLE ////////////////////////////////////////////////////////// + public String storeCLC(CommunityLifeCycle clc){ + String transId = this.getTransactionId(CommunityLifeCycle.class, true); + try{ + clc.persist(db, transId); + db.commitStreamTransaction(transId); + }catch(Exception e){ + db.abortStreamTransaction(transId); + throw e; + } + return clc.getKey(); + } + + public CommunityLifeCycle getCLC(String key, Cover c, DynamicGraph g){ + String transId = this.getTransactionId(CommunityLifeCycle.class, false); + CommunityLifeCycle clc; + try { + clc = CommunityLifeCycle.load(key, c, g, db, transId); + }catch(Exception e){ + db.abortStreamTransaction(transId); + throw e; + } + return clc; + } + + public CommunityLifeCycle getCLC(String username, String clcKey, String graphKey, String coverKey){ + DynamicGraph graph = (DynamicGraph) getGraph(graphKey); + Cover cover = getCover(coverKey, graph); + CommunityLifeCycle clc = null; + if(!(graph == null) && !(cover==null)){ + clc = getCLC(clcKey, cover, graph); + } + if(cover == null){ + logger.log(Level.WARNING, "user: " + username + ", " + "CLC does not exist: cover id " + clcKey + ", graph id " + graphKey + ", cover id " + coverKey); + } + return clc; + } + + ////////////////////////////////////////////////// CENTRALITY MAPS //////////////////////////////////////////////////////////// @@ -1810,7 +1859,7 @@ else if(c == SimulationSeriesGroup.class){ collections = collectionNames.subList(12,14).toArray(new String[1]); } else { - collections = collectionNames.subList(0, 14).toArray(new String[10]); + collections = collectionNames.subList(0, 16).toArray(new String[16]); } StreamTransactionEntity tx; if(write) { diff --git a/rest_ocd_services/src/test/java/i5/las2peer/services/ocd/utils/CommunityLifeCycleDatabaseTest.java b/rest_ocd_services/src/test/java/i5/las2peer/services/ocd/utils/CommunityLifeCycleDatabaseTest.java new file mode 100644 index 00000000..7d8cb4d8 --- /dev/null +++ b/rest_ocd_services/src/test/java/i5/las2peer/services/ocd/utils/CommunityLifeCycleDatabaseTest.java @@ -0,0 +1,98 @@ +package i5.las2peer.services.ocd.utils; + +import i5.las2peer.services.ocd.graphs.*; +import i5.las2peer.services.ocd.metrics.OcdMetricLog; +import i5.las2peer.services.ocd.metrics.OcdMetricType; +import org.graphstream.graph.Edge; +import org.graphstream.graph.Node; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.la4j.matrix.Matrix; +import org.la4j.matrix.sparse.CCSMatrix; + +import java.awt.*; +import java.util.*; +import java.util.List; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNotNull; + +public class CommunityLifeCycleDatabaseTest { + private static final String userName = "clcPersistenceUser"; + + private static final String graphName = "clcPersistenceGraph"; + + private static final String coverName = "clcPersistenceCover"; + + private static final String clcName = "clcPersistenceCLC"; + + private static Database database; + + @BeforeClass + public static void clearDatabase() {database = new Database(true);} + + @AfterClass + public static void deleteDatabase() {database.deleteDatabase();} + + @Test + public void testPersist() { + DynamicGraph graph = new DynamicGraph(); + graph.setUserName(userName); + graph.setName(graphName); + + Node nodeA = graph.addNode("nodeA"); + Node nodeB = graph.addNode("nodeB"); + Node nodeC = graph.addNode("nodeC"); + graph.setNodeName(nodeA, "A"); + graph.setNodeName(nodeB, "B"); + graph.setNodeName(nodeC, "C"); + Edge edgeAB = graph.addEdge(UUID.randomUUID().toString(), nodeA, nodeB); + graph.addDynamicInteraction(edgeAB,"0","+"); + graph.setEdgeWeight(edgeAB, 5); + Edge edgeBC = graph.addEdge(UUID.randomUUID().toString(), nodeB, nodeC); + graph.addDynamicInteraction(edgeBC, "1","-"); + graph.setEdgeWeight(edgeBC, 2.5); + + String gkey = database.storeGraph(graph); + System.out.println("graph key:" + graph.getKey()); + + Matrix memberships = new CCSMatrix(3, 2); + memberships.set(0, 0, 1); + memberships.set(1, 0, 0.5); + memberships.set(1, 1, 0.5); + memberships.set(2, 1, 1); + HashMap params = new HashMap(); + params.put("param1", "val1"); + params.put("param2", "val2"); + CoverCreationLog algo = new CoverCreationLog(CoverCreationType.UNDEFINED, params, new HashSet()); + Cover cover = new Cover(graph, memberships); + cover.setCreationMethod(algo); + cover.setName(coverName); + cover.setCommunityColor(1, Color.BLUE); + cover.setCommunityName(1, "Community1"); + OcdMetricLog metric = new OcdMetricLog(OcdMetricType.EXECUTION_TIME, 3.55, params, cover); + cover.addMetric(metric); + + String cKey = database.storeCover(cover); + System.out.println("cover key: " + cKey); + List birth_nodes = new ArrayList<>(); + birth_nodes.add("A"); + birth_nodes.add("B"); + birth_nodes.add("C"); + CommunityLifeCycle clc = new CommunityLifeCycle(cover, graph); + clc.setName(clcName); + clc.handleBirth("0", 1, birth_nodes); + clc.handleBirth("1", 2, birth_nodes); + clc.handleGrowth("3", 1, "D"); + + String clcKey = database.storeCLC(clc); + System.out.println("clcKey: " + clcKey); + + CommunityLifeCycle result = database.getCLC(userName, clcKey, gkey, cKey); + + assertNotNull(result); + + System.out.println(result.toString()); + } +} diff --git a/rest_ocd_services/src/test/java/i5/las2peer/services/ocd/utils/CommunityLifeCycleTest.java b/rest_ocd_services/src/test/java/i5/las2peer/services/ocd/utils/CommunityLifeCycleTest.java new file mode 100644 index 00000000..501774a5 --- /dev/null +++ b/rest_ocd_services/src/test/java/i5/las2peer/services/ocd/utils/CommunityLifeCycleTest.java @@ -0,0 +1,42 @@ +package i5.las2peer.services.ocd.utils; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.TestCase.assertEquals; + +public class CommunityLifeCycleTest { + + @Test + public void testClcCleanUp(){ + CommunityLifeCycle clc = new CommunityLifeCycle(); + + List birth_nodes = new ArrayList<>(); + birth_nodes.add("A"); + birth_nodes.add("B"); + birth_nodes.add("C"); + + clc.handleBirth("0", 0, birth_nodes); + clc.handleBirth("1", 1, birth_nodes); + clc.handleDeath("1", 1); + + assertEquals(1, clc.getEvents().size()); + System.out.println(clc.getEvents().toString()); + + clc.handleBirth("2", 2, birth_nodes); + clc.handleGrowth("2", 2, "D"); + clc.handleGrowth("2", 2, "E"); + clc.handleGrowth("2", 2, "F"); + + assertEquals(3, clc.getEvents().size()); + System.out.println(clc.getEvents().toString()); + + clc.handleContraction("3", 2, "D"); + clc.handleContraction("3", 2, "B"); + + assertEquals(4, clc.getEvents().size()); + System.out.println(clc.getEvents().toString()); + } +} diff --git a/time_seed.dat b/time_seed.dat index cb71624a..efd3d6cb 100644 --- a/time_seed.dat +++ b/time_seed.dat @@ -1 +1 @@ -21112134 \ No newline at end of file +21112154 \ No newline at end of file