66import java .sql .Connection ;
77import java .sql .PreparedStatement ;
88import java .sql .ResultSet ;
9+ import java .util .Arrays ;
10+ import java .util .List ;
11+
12+ import app .MeetingQueryConfig .Comparison ;
13+ import app .MeetingQueryConfig .LocationFilter ;
914
1015/**
16+ * Generates Edge-list files from the meeting database.
17+ *
18+ * <p>Connects to the PostgreSQL meeting database and produces an Edge-list
19+ * file for each relationship type (friends, classmates, study-groups,
20+ * strangers, familiar strangers) based on configurable duration and
21+ * frequency thresholds.</p>
1122 *
23+ * <p>The output path is validated to prevent directory traversal —
24+ * it must resolve to a location within the current working directory.</p>
1225 *
1326 * @author zalenix
1427 */
1528public class Network {
1629
1730 /**
31+ * Generates the edge-list file from the meeting database.
1832 *
19- * Connects to database and writes out the Edge-list from the meeting DB table, forming edges of kind:
20- * friends, classmates, study-groups, strangers and familiar strangers (depending upon parameters).
21- *
22- * <p>The output path is validated to prevent directory traversal —
23- * it must resolve to a location within the current working directory.</p>
33+ * <p>Replaces the previous 13-parameter signature with a structured
34+ * parameter object approach. Each relationship type is described by
35+ * a {@link MeetingQueryConfig} that encapsulates the SQL pattern
36+ * differences (location filter, comparison direction, thresholds).</p>
2437 *
25- * @param path output file path (must be within the working directory)
26- * @param Month
27- * @param Date
28- * @param dThresF
29- * @param CThresF
30- * @param dThresFS
31- * @param CThresFS
32- * @param dThresC
33- * @param CThresC
34- * @param dThresS
35- * @param CThresS
36- * @param dThresSg
37- * @param CThresSg
38- * @throws Exception
38+ * @param path output file path (must be within the working directory)
39+ * @param month month filter (e.g. "03")
40+ * @param date date filter (e.g. "15")
41+ * @param configs list of relationship query configurations
42+ * @throws Exception if database access or file I/O fails
3943 */
40- public static void generateFile (String path , String Month , String Date , int dThresF , int CThresF , int dThresFS , int CThresFS , int dThresC , int CThresC , int dThresS , int CThresS , int dThresSg , int CThresSg ) throws Exception {
41-
44+ public static void generateFile (String path , String month , String date ,
45+ List < MeetingQueryConfig > configs ) throws Exception {
4246 // Validate output path — prevent directory traversal attacks
4347 File outputFile = new File (path ).getCanonicalFile ();
4448 File workingDir = new File ("." ).getCanonicalFile ();
@@ -50,67 +54,14 @@ public static void generateFile(String path, String Month, String Date, int dThr
5054
5155 System .out .println ("connecting..." );
5256
53- // Parameterized query template for location-based meeting queries.
54- // Parameters: month, date, location, duration threshold, count threshold.
55-
56- // --- Friends query ---
57- String friendSql = " SELECT x.id , y.id , C , d "
58- + " FROM ( SELECT imei1 , imei2, count(*) as C,avg(duration) as d"
59- + " FROM ( SELECT imei1, imei2, duration"
60- + " FROM meeting"
61- + " WHERE month = ? AND date = ? AND location= 'public' AND duration > ?) as b"
62- + " GROUP BY imei1, imei2) as a, deviceID as x, deviceID as y"
63- + " WHERE C >= ? AND a.imei1= x.imei AND a.imei2 = y.imei" ;
64-
65- // --- Study groups query ---
66- String studygSql = " SELECT x.id , y.id , C , d "
67- + " FROM ( SELECT imei1, imei2, count(*) as C,avg(duration) as d"
68- + " FROM ( SELECT imei1, imei2, duration"
69- + " FROM meeting"
70- + " WHERE month = ? AND date = ? AND location= 'class' AND duration > ?) as b"
71- + " GROUP BY imei1, imei2) as a, deviceID as x, deviceID as y"
72- + " WHERE C <= ? AND a.imei1= x.imei AND a.imei2 = y.imei" ;
73-
74- // --- Classmates query ---
75- String cmateSql = " SELECT x.id , y.id, C , d "
76- + " FROM ( SELECT imei1, imei2, count(*) as C, avg(duration) as d"
77- + " FROM ( SELECT imei1, imei2, duration"
78- + " FROM meeting"
79- + " WHERE month = ? AND date = ? AND location= 'class' AND duration > ?) as b"
80- + " GROUP BY imei1, imei2) as a, deviceID as x, deviceID as y"
81- + " WHERE C >= ? AND a.imei1= x.imei AND a.imei2 = y.imei" ;
82-
83- // --- Strangers query ---
84- // Exclude both 'class' and 'unknown' locations so only meetings with
85- // a resolved location (e.g. 'public', 'path') are considered.
86- String strangerSql = " SELECT x.id , y.id , C , d "
87- + " FROM ( SELECT imei1, imei2, count(*) as C,avg(duration) as d"
88- + " FROM ( SELECT imei1, imei2, duration"
89- + " FROM meeting"
90- + " WHERE month = ? AND date = ? AND location NOT IN ('class', 'unknown', '') AND duration < ?) as b"
91- + " GROUP BY imei1, imei2) as a, deviceID as x, deviceID as y"
92- + " WHERE C < ? AND a.imei1= x.imei AND a.imei2 = y.imei" ;
93-
94- // --- Familiar strangers query ---
95- String famstrangerSql = " SELECT x.id , y.id , C , d "
96- + " FROM ( SELECT imei1, imei2, count(*) as C, avg(duration) as d"
97- + " FROM ( SELECT imei1, imei2, duration"
98- + " FROM meeting"
99- + " WHERE month = ? AND date = ? AND location NOT IN ('class', 'unknown', '') AND duration < ?) as b"
100- + " GROUP BY imei1, imei2) as a , deviceID as x, deviceID as y"
101- + " WHERE C > ? AND a.imei1= x.imei AND a.imei2 = y.imei" ;
102-
10357 try (Connection conn = Util .getAppConnection ()) {
104-
105- // Use StringBuilder instead of String concatenation for performance
10658 StringBuilder sb = new StringBuilder ("edges" );
10759
108- // Execute each relationship query using the shared helper
109- appendEdges (conn , sb , friendSql , "f" , Month , Date , dThresF , CThresF );
110- appendEdges (conn , sb , studygSql , "sg" , Month , Date , dThresSg , CThresSg );
111- appendEdges (conn , sb , cmateSql , "c" , Month , Date , dThresC , CThresC );
112- appendEdges (conn , sb , strangerSql , "s" , Month , Date , dThresS , CThresS );
113- appendEdges (conn , sb , famstrangerSql , "fs" , Month , Date , dThresFS , CThresFS );
60+ for (MeetingQueryConfig config : configs ) {
61+ appendEdges (conn , sb , config .buildSql (), config .getEdgePrefix (),
62+ month , date , config .getDurationThreshold (),
63+ config .getCountThreshold ());
64+ }
11465
11566 // Write output file — use validated outputFile, not raw path
11667 if (outputFile .exists ()) {
@@ -122,6 +73,45 @@ public static void generateFile(String path, String Month, String Date, int dThr
12273 }
12374 }
12475
76+ /**
77+ * Backward-compatible overload preserving the original 13-parameter signature.
78+ *
79+ * <p>Delegates to {@link #generateFile(String, String, String, List)} by
80+ * constructing {@link MeetingQueryConfig} instances from the raw threshold
81+ * parameters.</p>
82+ *
83+ * @deprecated Use {@link #generateFile(String, String, String, List)} with
84+ * explicit {@link MeetingQueryConfig} objects instead.
85+ */
86+ @ Deprecated
87+ public static void generateFile (String path , String Month , String Date ,
88+ int dThresF , int CThresF , int dThresFS , int CThresFS ,
89+ int dThresC , int CThresC , int dThresS , int CThresS ,
90+ int dThresSg , int CThresSg ) throws Exception {
91+
92+ String [] excludedLocations = {"class" , "unknown" , "" };
93+
94+ List <MeetingQueryConfig > configs = Arrays .asList (
95+ new MeetingQueryConfig ("f" , LocationFilter .EXACT ,
96+ new String []{"public" }, Comparison .GT , Comparison .GTE ,
97+ dThresF , CThresF ),
98+ new MeetingQueryConfig ("sg" , LocationFilter .EXACT ,
99+ new String []{"class" }, Comparison .GT , Comparison .LTE ,
100+ dThresSg , CThresSg ),
101+ new MeetingQueryConfig ("c" , LocationFilter .EXACT ,
102+ new String []{"class" }, Comparison .GT , Comparison .GTE ,
103+ dThresC , CThresC ),
104+ new MeetingQueryConfig ("s" , LocationFilter .EXCLUDE ,
105+ excludedLocations , Comparison .LT , Comparison .LT ,
106+ dThresS , CThresS ),
107+ new MeetingQueryConfig ("fs" , LocationFilter .EXCLUDE ,
108+ excludedLocations , Comparison .LT , Comparison .GT ,
109+ dThresFS , CThresFS )
110+ );
111+
112+ generateFile (path , Month , Date , configs );
113+ }
114+
125115 /**
126116 * Executes a parameterized meeting query and appends edges to the output buffer.
127117 *
0 commit comments