1d9be44355d6f0657be3e3c1c6b463ee978f9695
[iot2.git] / iotjava / iotruntime / master / RelationInstrumenter.java
1 package iotruntime.master;
2
3 import iotruntime.slave.IoTRelation;
4
5 import iotinstaller.MySQLInterface;
6 import iotinstaller.TableProperty;
7 import iotinstaller.TableSet;
8 import iotinstaller.TableRelation;
9
10 import java.sql.*;
11 import java.util.Collection;
12 import java.util.Iterator;
13 import java.util.Map;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.Properties;
17
18 import java.lang.Class;
19 import java.lang.Integer;
20 import java.lang.reflect.*;
21
22 /** Class RelationInstrumenter helps instrument the bytecode.
23  *  This class should extract information from the database
24  *  Input is the name of the device/entity extracted from the
25  *  generic Set class in the bytecode,
26  *  e.g. IoTRelation<ProximitySensor, LightBulb>
27  *  Upon extracting information, this class can be used to create
28  *  an IoTRelation object that contains a list of objects from
29  *  the Relation declaration.
30  *
31  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
32  * @version     1.0
33  * @since       2015-12-15
34  */
35 public class RelationInstrumenter {
36
37         /**
38          * RelationInstrumenter class properties
39          */
40         private String[][] arrRelation;
41         private String[][] arrRelOther;
42         private HashMap<String, String> hmEntryTypes;
43         private TableRelation tbl;
44         private int iRows;
45         private int iCols;
46         private int iColsOther;
47         private String strRelationEntityName;
48         private String strRelationOtherName;
49         private boolean bVerbose;
50
51         /**
52          * RelationInstrumenter class constants
53          */
54         private final String STR_PACKAGE_PREFIX = "iotcode.";
55         private final String STR_FIELD_ID_NAME = "ID";
56
57         /**
58          * Class constructor #1
59          *
60          * @param strRelEntName  String that contains the IoTRelation entity name in the DB, e.g. ProximitySensor
61          * @param strRelOthName  String that contains the other IoTRelation entity name in the DB, e.g. LightBulb
62          * @param _bVerbose              Verboseness of runtime output
63          */
64         public RelationInstrumenter(String strRelEntName, String strRelOthName, boolean _bVerbose) {
65
66                 arrRelation = null;
67                 arrRelOther = null;
68                 strRelationEntityName = strRelEntName;
69                 strRelationOtherName = strRelOthName;
70                 tbl = new TableRelation(strRelationEntityName, strRelationOtherName, _bVerbose);
71                 iRows = tbl.getNumOfRows();
72                 iCols = 0;
73                 iColsOther = 0;
74                 bVerbose = _bVerbose;
75                 RuntimeOutput.print("RelationInstrumentation: Creating a Relation for "
76                         + strRelationEntityName + " and " + strRelationOtherName, bVerbose);
77         }
78
79         /**
80          * Class constructor #2
81          *
82          * @param strRelEntName         String that contains the IoTRelation entity name in the DB, e.g. ProximitySensor
83          * @param strRelOthName         String that contains the other IoTRelation entity name in the DB, e.g. LightBulb
84          * @param strQueryFileName  String name for SQL query config file
85          * @param _bVerbose                     Verboseness of runtime output
86          */
87         public RelationInstrumenter(String strRelEntName, String strRelOthName, String strQueryFileName, boolean _bVerbose) {
88
89                 arrRelation = null;
90                 arrRelOther = null;
91                 strRelationEntityName = strRelEntName;
92                 strRelationOtherName = strRelOthName;
93                 tbl = new TableRelation(strRelationEntityName, strRelationOtherName, _bVerbose);
94                 tbl.setTableRelationFromQueryFile(strQueryFileName);
95                 tbl.selectRelationEntry();
96                 iRows = tbl.getNumOfRows();
97                 iCols = 0;
98                 iColsOther = 0;
99                 bVerbose = _bVerbose;
100                 RuntimeOutput.print("RelationInstrumentation: Creating a Relation for "
101                         + strRelationEntityName + " and " + strRelationOtherName, bVerbose);
102         }
103
104
105         /**
106          * A method to give the object/table name of the first set
107          *
108          * @return String
109          */
110         public String firstObjectTableName() {
111
112                 return strRelationEntityName;
113
114         }
115
116         /**
117          * A method to give the object/table name of the first set
118          *
119          * @return String
120          */
121         public String secondObjectTableName() {
122
123                 return strRelationOtherName;
124
125         }
126
127
128         /**
129          * A method to give the number of columns of the first Set
130          *
131          * @param  iIndex  integer index
132          * @return int
133          */
134         public int numberOfFirstCols(int iIndex) {
135
136                 tbl.selectRelationOnFirstTable();
137                 iCols = tbl.getNumOfCols(iIndex);
138                 return iCols;
139         }
140
141         /**
142          * A method to give the number of columns of the second Set
143          *
144          * @param  iIndex  integer index
145          * @return int
146          */
147         public int numberOfSecondCols(int iIndex) {
148
149                 tbl.selectRelationOnOtherTable();
150                 iColsOther = tbl.getNumOfCols(iIndex);
151                 return iColsOther;
152         }
153
154         /**
155          * A method to give the number of rows
156          *
157          * @return int
158          */
159         public int numberOfRows() {
160
161                 return iRows;
162
163         }
164
165         /**
166          * A method to return the entry field TYPE of the first Set based on ID
167          *
168          * @return String
169          */
170         public String firstEntryFieldType(String sID) {
171
172                 tbl.selectRelationOnFirstTable();
173                 hmEntryTypes = tbl.getEntryTypes();
174
175                 // Get the entry type
176                 String strEntryType = hmEntryTypes.get(sID);
177
178                 return strEntryType;
179         }
180
181         /**
182          * A method to return the entry field TYPE of the first Set based on ID
183          *
184          * @return String
185          */
186         public String secondEntryFieldType(String sID) {
187
188                 tbl.selectRelationOnOtherTable();
189                 hmEntryTypes = tbl.getEntryTypes();
190
191                 // Get the entry type
192                 String strEntryType = hmEntryTypes.get(sID);
193
194                 return strEntryType;
195         }
196
197         /**
198          * A method to return the field object ID from the first set entry pointed by certain index
199          *
200          * @param  iIndex  integer index
201          * @return String
202          */
203         public String firstFieldObjectID(int iIndex) {
204
205                 // Select the first table
206                 tbl.selectRelationOnFirstTable();
207
208                 // Get the right entry based on iIndex
209                 String[] arrObjectID = tbl.getFieldObjectIDs();
210                 String strID = arrObjectID[iIndex];
211
212                 RuntimeOutput.print("RelationInstrumentation: Extracting field object ID from value..", bVerbose);
213
214                 return strID;
215         }
216
217         /**
218          * A method to return the field object ID from the second set entry pointed by certain index
219          *
220          * @param  iIndex  integer index
221          * @return String
222          */
223         public String secondFieldObjectID(int iIndex) {
224
225                 // Select the second table
226                 tbl.selectRelationOnOtherTable();
227
228                 // Get the right entry based on iIndex
229                 String[] arrObjectID = tbl.getFieldObjectIDs();
230                 String strID = arrObjectID[iIndex];
231
232                 RuntimeOutput.print("RelationInstrumentation: Extracting field object ID from value..", bVerbose);
233
234                 return strID;
235         }
236
237         /**
238          * A method to return the field values of certain index from the first set
239          *
240          * @param  iIndex  integer index
241          * @return Object[]
242          */
243         public Object[] firstFieldValues(int iIndex) {
244
245                 // Select the first table
246                 tbl.selectRelationOnFirstTable();
247                 arrRelation = tbl.getDBTable();
248                 iCols = tbl.getNumOfCols(iIndex);
249
250                 // Get the right entry based on iIndex
251                 String[] arrRelEntry = arrRelation[iIndex];
252
253                 // Fill in the params array with the Objects needed as parameters
254                 // for the constructor
255                 Object[] arrFirstFieldValues = new Object[iCols];
256
257                 for(int i=0; i<iCols; i++) {
258                         // MySQL column starts from 1, NOT 0
259                         arrFirstFieldValues[i] = getObjectConverted(arrRelEntry[i], getClassName(tbl.getFieldType(i+1, iIndex)).getName());
260                 }
261
262                 RuntimeOutput.print("RelationInstrumentation: Extracting field values..", bVerbose);
263
264                 return arrFirstFieldValues;
265         }
266
267         /**
268          * A method to return the field values of certain index from second Set
269          *
270          * @param  iIndex  integer index
271          * @return Object[]
272          */
273         public Object[] secondFieldValues(int iIndex) {
274
275                 // Select the second table
276                 tbl.selectRelationOnOtherTable();
277                 arrRelOther = tbl.getDBTable();
278                 iColsOther = tbl.getNumOfCols(iIndex);
279
280                 // Get the right entry based on iIndex
281                 String[] arrRelEntry = arrRelOther[iIndex];
282
283                 // Fill in the params array with the Objects needed as parameters
284                 // for the constructor
285                 Object[] arrSecondFieldValues = new Object[iCols];
286
287                 for(int i=0; i<iCols; i++) {
288                         // MySQL column starts from 1, NOT 0
289                         arrSecondFieldValues[i] = getObjectConverted(arrRelEntry[i], getClassName(tbl.getFieldType(i+1, iIndex)).getName());
290                 }
291
292                 RuntimeOutput.print("RelationInstrumentation: Extracting field values..", bVerbose);
293
294                 return arrSecondFieldValues;
295         }
296
297         /**
298          * A method to return the field classes of a certain index
299          *
300          * @param  iIndex  integer index
301          * @return Class[]
302          */
303         public Class[] firstFieldClasses(int iIndex) {
304
305                 // Select the first table
306                 tbl.selectRelationOnFirstTable();
307                 arrRelation = tbl.getDBTable();
308                 iCols = tbl.getNumOfCols(iIndex);
309
310                 RuntimeOutput.print("RelationInstrumentation: Extracting table " + strRelationEntityName + ".", bVerbose);
311
312                 Class[] arrFirstFieldClasses = new Class[iCols];
313
314                 // We start from column 1 and we skip column 0
315                 // Column 0 is for ID
316                 for(int i=0; i<iCols; i++) {
317                         // MySQL column starts from 1, NOT 0
318                         arrFirstFieldClasses[i] = getClassName(tbl.getFieldType(i+1, iIndex));
319                 }
320
321                 RuntimeOutput.print("RelationInstrumentation: Extracting field classes from field types..", bVerbose);
322                 return arrFirstFieldClasses;
323         }
324
325         /**
326          * A method to return the field classes
327          *
328          * @param  iIndex  integer index
329          * @return Class[]
330          */
331         public Class[] secondFieldClasses(int iIndex) {
332
333                 // Select the second table
334                 tbl.selectRelationOnOtherTable();
335                 arrRelOther = tbl.getDBTable();
336                 iCols = tbl.getNumOfCols(iIndex);
337
338                 RuntimeOutput.print("RelationInstrumentation: Extracting table " + strRelationOtherName + ".", bVerbose);
339
340                 Class[] arrSecondFieldClasses = new Class[iCols];
341
342                 // We start from column 1 and we skip column 0
343                 // Column 0 is for ID
344                 for(int i=0; i<iCols; i++) {
345                         // MySQL column starts from 1, NOT 0
346                         arrSecondFieldClasses[i] = getClassName(tbl.getFieldType(i+1, iIndex));
347                 }
348
349                 RuntimeOutput.print("RelationInstrumentation: Extracting field classes from field types..", bVerbose);
350                 return arrSecondFieldClasses;
351         }
352
353         /**
354          * A helper function that gives the Class object of a particular DB data type
355          *
356          * @param  strDataType  String MySQL data type
357          * @return              Class
358          */
359         public Class getClassName(String strDataType) {
360
361                 if (strDataType.equals("VARCHAR")) {
362                         return String.class;
363                 } else if (strDataType.equals("INT")) {
364                         return int.class;
365                 } else {
366                         return null;
367                 }
368         }
369
370         /**
371          * A helper function that returns an Object in the right format
372          * <p>
373          * We give it input from the elements of the HashSet where we
374          * populate all the DB information for a certain Object
375          *
376          * @param  obj           Object to be converted
377          * @param  strClassType  String Java Class type
378          * @return               Object
379          */
380         public Object getObjectConverted(Object obj, String strClassType) {
381
382                 if (strClassType.equals("java.lang.String")) {
383                         return (String) obj;
384                 } else if (strClassType.equals("int")) {
385                         return Integer.parseInt((String) obj);
386                 } else {
387                         return null;
388                 }
389         }
390 }