79e838cb97b0a59f78e1bf318beac6100355c881
[iot2.git] / iotjava / iotpolicy / IoTCompiler.java
1 package iotpolicy;
2
3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
5 import java.io.*;
6 import java.util.Arrays;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.Collections;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16
17 import iotpolicy.parser.Lexer;
18 import iotpolicy.parser.Parser;
19 import iotpolicy.tree.ParseNode;
20 import iotpolicy.tree.ParseNodeVector;
21 import iotpolicy.tree.ParseTreeHandler;
22 import iotpolicy.tree.Declaration;
23 import iotpolicy.tree.DeclarationHandler;
24 import iotpolicy.tree.CapabilityDecl;
25 import iotpolicy.tree.InterfaceDecl;
26 import iotpolicy.tree.RequiresDecl;
27 import iotpolicy.tree.EnumDecl;
28 import iotpolicy.tree.StructDecl;
29
30 import iotrmi.Java.IoTRMITypes;
31
32
33 /** Class IoTCompiler is the main interface/stub compiler for
34  *  files generation. This class calls helper classes
35  *  such as Parser, Lexer, InterfaceDecl, CapabilityDecl,
36  *  RequiresDecl, ParseTreeHandler, etc.
37  *
38  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
39  * @version     1.0
40  * @since       2016-09-22
41  */
42 public class IoTCompiler {
43
44         /**
45          * Class properties
46          */
47         // Maps multiple interfaces to multiple objects of ParseTreeHandler
48         private Map<String,ParseTreeHandler> mapIntfacePTH;
49         private Map<String,DeclarationHandler> mapIntDeclHand;
50         private Map<String,Map<String,Set<String>>> mapInt2NewInts;
51         private Map<String,String> mapInt2NewIntName;
52         private Map<String,List<String>> mapInt2Drv;
53         // Data structure to store our types (primitives and non-primitives) for compilation
54         private Map<String,String> mapPrimitives;
55         private Map<String,String> mapNonPrimitivesJava;
56         private Map<String,String> mapNonPrimitivesCplus;
57         // Other data structures
58         private Map<String,Integer> mapIntfaceObjId;            // Maps interface name to object Id
59         private Map<String,Integer> mapNewIntfaceObjId;         // Maps new interface name to its object Id (keep track of stubs)
60         private PrintWriter pw;
61         private String dir;
62         private String subdir;
63         private Map<String,Integer> mapPortCount;       // Counter for ports
64         private static int portCount = 0;
65         private static int countObjId = 1;                      // Always increment object Id for a new stub/skeleton
66         private String mainClass;
67         private String controllerClass;
68
69
70         /**
71          * Class constants
72          */
73         private final static String OUTPUT_DIRECTORY = "output_files";
74         private final static String INTERFACES_DIRECTORY = "interfaces";
75         private final static String VIRTUALS_DIRECTORY = "virtuals";
76         private final static String CODE_PREFIX = "iotcode";
77         private final static String INTERFACE_PACKAGE = "iotcode.interfaces";
78
79
80         private enum ParamCategory {
81
82                 PRIMITIVES,             // All the primitive types, e.g. byte, short, int, long, etc.
83                 NONPRIMITIVES,  // Non-primitive types, e.g. Set, Map, List, etc.
84                 ENUM,                   // Enum type
85                 STRUCT,                 // Struct type
86                 USERDEFINED             // Assumed as driver classes
87         }
88
89
90         /**
91          * Class constructors
92          */
93         public IoTCompiler() {
94
95                 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
96                 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
97                 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
98                 mapInt2NewIntName = new HashMap<String,String>();
99                 mapInt2Drv = new HashMap<String,List<String>>();
100                 mapIntfaceObjId = new HashMap<String,Integer>();
101                 mapNewIntfaceObjId = new HashMap<String,Integer>();
102                 mapPrimitives = new HashMap<String,String>();
103                         arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
104                 mapNonPrimitivesJava = new HashMap<String,String>();
105                         arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
106                 mapNonPrimitivesCplus = new HashMap<String,String>();
107                         arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
108                 mapPortCount = new HashMap<String,Integer>();
109                 pw = null;
110                 dir = OUTPUT_DIRECTORY;
111                 subdir = null;
112                 mainClass = null;
113                 controllerClass = null;
114         }
115
116
117         /**
118          * setDriverClass() sets the name of the driver class.
119          */
120         public void setDriverClass(String intface, String driverClass) {
121                 
122                 List<String> drvList = mapInt2Drv.get(intface);
123                 if(drvList == null)
124                         drvList = new ArrayList<String>();
125                 drvList.add(driverClass);
126                 mapInt2Drv.put(intface, drvList);
127         }
128         
129         
130         /**
131          * setControllerClass() sets the name of the controller class.
132          */
133         public void setControllerClass(String _controllerClass) {
134                 
135                 controllerClass = _controllerClass;
136         }
137
138
139         /**
140          * setDataStructures() sets parse tree and other data structures based on policy files.
141          * <p>
142          * It also generates parse tree (ParseTreeHandler) and
143          * copies useful information from parse tree into
144          * InterfaceDecl, CapabilityDecl, and RequiresDecl 
145          * data structures.
146          * Additionally, the data structure handles are
147          * returned from tree-parsing for further process.
148          */
149         public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
150
151                 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
152                 DeclarationHandler decHandler = new DeclarationHandler();
153                 // Process ParseNode and generate Declaration objects
154                 // Interface
155                 ptHandler.processInterfaceDecl();
156                 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
157                 decHandler.addInterfaceDecl(origInt, intDecl);
158                 // Capabilities
159                 ptHandler.processCapabilityDecl();
160                 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
161                 decHandler.addCapabilityDecl(origInt, capDecl);
162                 // Requires
163                 ptHandler.processRequiresDecl();
164                 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
165                 decHandler.addRequiresDecl(origInt, reqDecl);
166                 // Enumeration
167                 ptHandler.processEnumDecl();
168                 EnumDecl enumDecl = ptHandler.getEnumDecl();
169                 decHandler.addEnumDecl(origInt, enumDecl);
170                 // Struct
171                 ptHandler.processStructDecl();
172                 StructDecl structDecl = ptHandler.getStructDecl();
173                 decHandler.addStructDecl(origInt, structDecl);
174
175                 mapIntfacePTH.put(origInt, ptHandler);
176                 mapIntDeclHand.put(origInt, decHandler);
177                 // Set object Id counter to 0 for each interface
178                 mapIntfaceObjId.put(origInt, countObjId++);
179         }
180         
181         
182         /**
183          * setObjectId() updates the object Id. This option is useful
184          * when the stub/skeleton are also used in other apps, so that
185          * we can set a single object Id for the stub/skeleton.
186          */
187         private void setObjectId(String intface, String objectId) {
188
189                 mapIntfaceObjId.put(intface, Integer.parseInt(objectId));
190         }
191
192
193         /**
194          * getMethodsForIntface() reads for methods in the data structure
195          * <p>
196          * It is going to give list of methods for a certain interface
197          *              based on the declaration of capabilities.
198          */
199         public void getMethodsForIntface(String origInt) {
200
201                 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
202                 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
203                 // Get set of new interfaces, e.g. CameraWithCaptureAndData
204                 // Generate this new interface with all the methods it needs
205                 //              from different capabilities it declares
206                 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
207                 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
208                 Set<String> setIntfaces = reqDecl.getInterfaces();
209                 for (String strInt : setIntfaces) {
210
211                         // Initialize a set of methods
212                         Set<String> setMethods = new HashSet<String>();
213                         // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
214                         List<String> listCapab = reqDecl.getCapabList(strInt);
215                         for (String strCap : listCapab) {
216
217                                 // Get list of methods for each capability
218                                 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
219                                 List<String> listCapabMeth = capDecl.getMethods(strCap);
220                                 for (String strMeth : listCapabMeth) {
221
222                                         // Add methods into setMethods
223                                         // This is to also handle redundancies (say two capabilities
224                                         //              share the same methods)
225                                         setMethods.add(strMeth);
226                                 }
227                         }
228                         // Add interface and methods information into map
229                         mapNewIntMethods.put(strInt, setMethods);
230                         // Map new interface method name to the original interface
231                         // TODO: perhaps need to check in the future if we have more than 1 stub interface for one original interface
232                         mapInt2NewIntName.put(origInt, strInt);
233                         if (mainClass == null)  // Take the first class as the main class (whichever is placed first in the order of compilation files)
234                                 mainClass = origInt;
235                 }
236                 // Map the map of interface-methods to the original interface
237                 mapInt2NewInts.put(origInt, mapNewIntMethods);
238         }
239
240         
241 /*================
242  * Java generation
243  *================/
244
245         /**
246          * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface
247          */
248         private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
249
250                 for (String method : methods) {
251
252                         List<String> methParams = intDecl.getMethodParams(method);
253                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
254                         print("public " + intDecl.getMethodType(method) + " " +
255                                 intDecl.getMethodId(method) + "(");
256                         for (int i = 0; i < methParams.size(); i++) {
257                                 // Check for params with driver class types and exchange it 
258                                 //              with its remote interface
259                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
260                                 print(paramType + " " + methParams.get(i));
261                                 // Check if this is the last element (don't print a comma)
262                                 if (i != methParams.size() - 1) {
263                                         print(", ");
264                                 }
265                         }
266                         println(");");
267                 }
268         }
269
270
271         /**
272          * HELPER: writeMethodJavaInterface() writes the method of the interface
273          */
274         private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
275
276                 for (String method : methods) {
277
278                         List<String> methParams = intDecl.getMethodParams(method);
279                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
280                         print("public " + intDecl.getMethodType(method) + " " +
281                                 intDecl.getMethodId(method) + "(");
282                         for (int i = 0; i < methParams.size(); i++) {
283                                 // Check for params with driver class types and exchange it 
284                                 //              with its remote interface
285                                 String paramType = methPrmTypes.get(i);
286                                 print(paramType + " " + methParams.get(i));
287                                 // Check if this is the last element (don't print a comma)
288                                 if (i != methParams.size() - 1) {
289                                         print(", ");
290                                 }
291                         }
292                         println(");");
293                 }
294         }
295
296
297         /**
298          * HELPER: generateEnumJava() writes the enumeration declaration
299          */
300         private void generateEnumJava() throws IOException {
301
302                 // Create a new directory
303                 createDirectory(dir);
304                 String path = createDirectories(dir, INTERFACES_DIRECTORY);
305                 for (String intface : mapIntfacePTH.keySet()) {
306                         // Get the right EnumDecl
307                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
308                         EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
309                         Set<String> enumTypes = enumDecl.getEnumDeclarations();
310                         // Iterate over enum declarations
311                         for (String enType : enumTypes) {
312                                 // Open a new file to write into
313                                 FileWriter fw = new FileWriter(path + "/" + enType + ".java");
314                                 pw = new PrintWriter(new BufferedWriter(fw));
315                                 println("package " + INTERFACE_PACKAGE + ";\n");
316                                 println("public enum " + enType + " {");
317                                 List<String> enumMembers = enumDecl.getMembers(enType);
318                                 for (int i = 0; i < enumMembers.size(); i++) {
319
320                                         String member = enumMembers.get(i);
321                                         print(member);
322                                         // Check if this is the last element (don't print a comma)
323                                         if (i != enumMembers.size() - 1)
324                                                 println(",");
325                                         else
326                                                 println("");
327                                 }
328                                 println("}\n");
329                                 pw.close();
330                                 System.out.println("IoTCompiler: Generated enum class " + enType + ".java...");
331                         }
332                 }
333         }
334
335
336         /**
337          * HELPER: generateStructJava() writes the struct declaration
338          */
339         private void generateStructJava() throws IOException {
340
341                 // Create a new directory
342                 createDirectory(dir);
343                 String path = createDirectories(dir, INTERFACES_DIRECTORY);
344                 for (String intface : mapIntfacePTH.keySet()) {
345                         // Get the right StructDecl
346                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
347                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
348                         List<String> structTypes = structDecl.getStructTypes();
349                         // Iterate over enum declarations
350                         for (String stType : structTypes) {
351                                 // Open a new file to write into
352                                 FileWriter fw = new FileWriter(path + "/" + stType + ".java");
353                                 pw = new PrintWriter(new BufferedWriter(fw));
354                                 println("package " + INTERFACE_PACKAGE + ";\n");
355                                 println("public class " + stType + " {");
356                                 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
357                                 List<String> structMembers = structDecl.getMembers(stType);
358                                 for (int i = 0; i < structMembers.size(); i++) {
359
360                                         String memberType = structMemberTypes.get(i);
361                                         String member = structMembers.get(i);
362                                         println("public static " + memberType + " " + member + ";");
363                                 }
364                                 println("}\n");
365                                 pw.close();
366                                 System.out.println("IoTCompiler: Generated struct class " + stType + ".java...");
367                         }
368                 }
369         }
370
371
372         /**
373          * generateJavaLocalInterface() writes the local interface and provides type-checking.
374          * <p>
375          * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
376          * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
377          * The local interface has to be the input parameter for the stub and the stub 
378          * interface has to be the input parameter for the local class.
379          */
380         public void generateJavaLocalInterfaces() throws IOException {
381
382                 // Create a new directory
383                 createDirectory(dir);
384                 String path = createDirectories(dir, INTERFACES_DIRECTORY);
385                 for (String intface : mapIntfacePTH.keySet()) {
386                         // Open a new file to write into
387                         FileWriter fw = new FileWriter(path + "/" + intface + ".java");
388                         pw = new PrintWriter(new BufferedWriter(fw));
389                         // Pass in set of methods and get import classes
390                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
391                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
392                         List<String> methods = intDecl.getMethods();
393                         Set<String> importClasses = getImportClasses(methods, intDecl);
394                         List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
395                         List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
396                         println("package " + INTERFACE_PACKAGE + ";\n");
397                         printImportStatements(allImportClasses);
398                         // Write interface header
399                         println("");
400                         println("public interface " + intface + " {");
401                         // Write methods
402                         writeMethodJavaLocalInterface(methods, intDecl);
403                         println("}");
404                         pw.close();
405                         System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
406                 }
407         }
408
409
410         /**
411          * HELPER: updateIntfaceObjIdMap() updates the mapping between new interface and object Id
412          */
413         private void updateIntfaceObjIdMap(String intface, String newIntface) {
414
415                 // We are assuming that we only generate one stub per one skeleton at this point @Feb 2017
416                 Integer objId = mapIntfaceObjId.get(intface);
417                 mapNewIntfaceObjId.put(newIntface, objId);
418         }
419
420
421         /**
422          * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
423          */
424         public void generateJavaInterfaces() throws IOException {
425
426                 // Create a new directory
427                 String path = createDirectories(dir, subdir);
428                 path = createDirectories(dir + "/" + subdir, INTERFACES_DIRECTORY);
429                 for (String intface : mapIntfacePTH.keySet()) {
430
431                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
432                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
433
434                                 // Open a new file to write into
435                                 String newIntface = intMeth.getKey();
436                                 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
437                                 pw = new PrintWriter(new BufferedWriter(fw));
438                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
439                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
440                                 // Pass in set of methods and get import classes
441                                 Set<String> methods = intMeth.getValue();
442                                 Set<String> importClasses = getImportClasses(methods, intDecl);
443                                 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
444                                 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
445                         println("package " + INTERFACE_PACKAGE + ";\n");
446                                 printImportStatements(allImportClasses);
447                                 // Write interface header
448                                 println("");
449                                 println("public interface " + newIntface + " {\n");
450                                 updateIntfaceObjIdMap(intface, newIntface);
451                                 // Write methods
452                                 writeMethodJavaInterface(methods, intDecl);
453                                 println("}");
454                                 pw.close();
455                                 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
456                         }
457                 }
458         }
459
460
461         /**
462          * HELPER: writePropertiesJavaPermission() writes the permission in properties
463          */
464         private void writePropertiesJavaPermission(String intface, InterfaceDecl intDecl) {
465
466                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
467                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
468                         String newIntface = intMeth.getKey();
469                         int newObjectId = getNewIntfaceObjectId(newIntface);
470                         Set<String> methodIds = intMeth.getValue();
471                         print("private static Integer[] object" + newObjectId + "Permission = { ");
472                         int i = 0;
473                         for (String methodId : methodIds) {
474                                 int methodNumId = intDecl.getMethodNumId(methodId);
475                                 print(Integer.toString(methodNumId));
476                                 // Check if this is the last element (don't print a comma)
477                                 if (i != methodIds.size() - 1) {
478                                         print(", ");
479                                 }
480                                 i++;
481                         }
482                         println(" };");
483                         println("private static List<Integer> set" + newObjectId + "Allowed;");
484                 }
485         }
486
487
488         /**
489          * HELPER: writePropertiesJavaStub() writes the properties of the stub class
490          */
491         private void writePropertiesJavaStub(String intface, Set<String> methods, InterfaceDecl intDecl) {
492
493                 // Get the object Id
494                 Integer objId = mapIntfaceObjId.get(intface);
495                 println("private int objectId = " + objId + ";");
496                 println("private IoTRMIComm rmiComm;");
497                 // Write the list of AtomicBoolean variables
498                 println("// Synchronization variables");
499                 for (String method : methods) {
500                         // Generate AtomicBooleans for methods that have return values
501                         String returnType = intDecl.getMethodType(method);
502                         int methodNumId = intDecl.getMethodNumId(method);
503                         if (!returnType.equals("void")) {
504                                 println("private AtomicBoolean retValueReceived" + methodNumId + " = new AtomicBoolean(false);");
505                         }
506                 }
507                 println("\n");
508         }
509
510
511         /**
512          * HELPER: writeConstructorJavaPermission() writes the permission in constructor
513          */
514         private void writeConstructorJavaPermission(String intface) {
515
516                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
517                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
518                         String newIntface = intMeth.getKey();
519                         int newObjectId = getNewIntfaceObjectId(newIntface);
520                         println("set" + newObjectId + "Allowed = new ArrayList<Integer>(Arrays.asList(object" + newObjectId +"Permission));");
521                 }
522         }
523
524
525         /**
526          * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
527          */
528         private void writeConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
529
530                 println("public " + newStubClass + "(int _localPortSend, int _localPortRecv, int _portSend, int _portRecv, String _skeletonAddress, int _rev) throws Exception {");
531                 println("if (_localPortSend != 0 && _localPortRecv != 0) {");
532                 println("rmiComm = new IoTRMICommClient(_localPortSend, _localPortRecv, _portSend, _portRecv, _skeletonAddress, _rev);");
533                 println("} else");
534                 println("{");
535                 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev);");
536                 println("}");
537                 // Register the AtomicBoolean variables
538                 for (String method : methods) {
539                         // Generate AtomicBooleans for methods that have return values
540                         String returnType = intDecl.getMethodType(method);
541                         int methodNumId = intDecl.getMethodNumId(method);
542                         if (!returnType.equals("void")) {
543                                 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
544                         }
545                 }
546                 println("IoTRMIUtil.mapStub.put(objectId, this);");
547                 println("}\n");
548         }
549
550
551         /**
552          * HELPER: writeCallbackConstructorJavaStub() writes the callback constructor of the stub class
553          */
554         private void writeCallbackConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
555
556                 println("public " + newStubClass + "(IoTRMIComm _rmiComm, int _objectId) throws Exception {");
557                 println("rmiComm = _rmiComm;");
558                 println("objectId = _objectId;");
559                 // Register the AtomicBoolean variables
560                 for (String method : methods) {
561                         // Generate AtomicBooleans for methods that have return values
562                         String returnType = intDecl.getMethodType(method);
563                         int methodNumId = intDecl.getMethodNumId(method);
564                         if (!returnType.equals("void")) {
565                                 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
566                         }
567                 }
568                 println("}\n");
569         }
570
571
572         /**
573          * HELPER: getPortCount() gets port count for different stubs and skeletons
574          */
575         private int getPortCount(String intface) {
576
577                 if (!mapPortCount.containsKey(intface))
578                         mapPortCount.put(intface, portCount++);
579                 return mapPortCount.get(intface);
580         }
581
582
583         /**
584          * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int)
585          */
586         private void checkAndWriteEnumTypeJavaStub(List<String> methParams, List<String> methPrmTypes) {
587
588                 // Iterate and find enum declarations
589                 for (int i = 0; i < methParams.size(); i++) {
590                         String paramType = methPrmTypes.get(i);
591                         String param = methParams.get(i);
592                         String simpleType = getGenericType(paramType);
593                         if (isEnumClass(simpleType)) {
594                         // Check if this is enum type
595                                 if (isArray(param)) {   // An array
596                                         println("int len" + i + " = " + getSimpleIdentifier(param) + ".length;");
597                                         println("int paramEnum" + i + "[] = new int[len" + i + "];");
598                                         println("for (int i = 0; i < len" + i + "; i++) {");
599                                         println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + "[i].ordinal();");
600                                         println("}");
601                                 } else if (isList(paramType)) { // A list
602                                         println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
603                                         println("int paramEnum" + i + "[] = new int[len" + i + "];");
604                                         println("for (int i = 0; i < len" + i + "; i++) {");
605                                         println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + ".get(i).ordinal();");
606                                         println("}");
607                                 } else {        // Just one element
608                                         println("int paramEnum" + i + "[] = new int[1];");
609                                         println("paramEnum" + i + "[0] = " + param + ".ordinal();");
610                                 }
611                         }
612                 }
613         }
614
615
616         /**
617          * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int)
618          */
619         private void checkAndWriteEnumRetTypeJavaStub(String retType, String method, InterfaceDecl intDecl) {
620
621                 // Write the wait-for-return-value part
622                 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
623                 // Strips off array "[]" for return type
624                 String pureType = getSimpleArrayType(getGenericType(retType));
625                 // Take the inner type of generic
626                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
627                         pureType = getGenericType(retType);
628                 if (isEnumClass(pureType)) {
629                 // Check if this is enum type
630                         // Enum decoder
631                         println("int[] retEnum = (int[]) retObj;");
632                         println(pureType + "[] enumVals = " + pureType + ".values();");
633                         if (isArray(retType)) {                 // An array
634                                 println("int retLen = retEnum.length;");
635                                 println(pureType + "[] enumRetVal = new " + pureType + "[retLen];");
636                                 println("for (int i = 0; i < retLen; i++) {");
637                                 println("enumRetVal[i] = enumVals[retEnum[i]];");
638                                 println("}");
639                         } else if (isList(retType)) {   // A list
640                                 println("int retLen = retEnum.length;");
641                                 println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();");
642                                 println("for (int i = 0; i < retLen; i++) {");
643                                 println("enumRetVal.add(enumVals[retEnum[i]]);");
644                                 println("}");
645                         } else {        // Just one element
646                                 println(pureType + " enumRetVal = enumVals[retEnum[0]];");
647                         }
648                         println("return enumRetVal;");
649                 }
650         }
651
652
653         /**
654          * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup
655          */
656         private void checkAndWriteStructSetupJavaStub(List<String> methParams, List<String> methPrmTypes, 
657                         InterfaceDecl intDecl, String method) {
658                 
659                 // Iterate and find struct declarations
660                 for (int i = 0; i < methParams.size(); i++) {
661                         String paramType = methPrmTypes.get(i);
662                         String param = methParams.get(i);
663                         String simpleType = getGenericType(paramType);
664                         if (isStructClass(simpleType)) {
665                         // Check if this is enum type
666                                 int methodNumId = intDecl.getMethodNumId(method);
667                                 String helperMethod = methodNumId + "struct" + i;
668                                 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
669                                 println("Class<?>[] paramClsStruct" + i + " = new Class<?>[] { int.class };");
670                                 if (isArray(param)) {   // An array
671                                         println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };");
672                                 } else if (isList(paramType)) { // A list
673                                         println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };");
674                                 } else {        // Just one element
675                                         println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };");
676                                 }
677                                 println("rmiComm.remoteCall(objectId, methodIdStruct" + i + 
678                                                 ", paramClsStruct" + i + ", paramObjStruct" + i + ");\n");
679                         }
680                 }
681         }
682
683
684         /**
685          * HELPER: isStructPresent() checks presence of struct
686          */
687         private boolean isStructPresent(List<String> methParams, List<String> methPrmTypes) {
688
689                 // Iterate and find enum declarations
690                 for (int i = 0; i < methParams.size(); i++) {
691                         String paramType = methPrmTypes.get(i);
692                         String param = methParams.get(i);
693                         String simpleType = getGenericType(paramType);
694                         if (isStructClass(simpleType))
695                                 return true;
696                 }
697                 return false;
698         }
699
700
701         /**
702          * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters
703          */
704         private void writeLengthStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
705
706                 // Iterate and find struct declarations - count number of params
707                 for (int i = 0; i < methParams.size(); i++) {
708                         String paramType = methPrmTypes.get(i);
709                         String param = methParams.get(i);
710                         String simpleType = getGenericType(paramType);
711                         if (isStructClass(simpleType)) {
712                                 int members = getNumOfMembers(simpleType);
713                                 if (isArray(param)) {                   // An array
714                                         String structLen = getSimpleArrayType(param) + ".length";
715                                         print(members + "*" + structLen);
716                                 } else if (isList(paramType)) { // A list
717                                         String structLen = getSimpleArrayType(param) + ".size()";
718                                         print(members + "*" + structLen);
719                                 } else
720                                         print(Integer.toString(members));
721                         } else
722                                 print("1");
723                         if (i != methParams.size() - 1) {
724                                 print("+");
725                         }
726                 }
727         }
728
729
730         /**
731          * HELPER: writeStructMembersJavaStub() writes parameters of struct
732          */
733         private void writeStructMembersJavaStub(String simpleType, String paramType, String param) {
734
735                 // Get the struct declaration for this struct and generate initialization code
736                 StructDecl structDecl = getStructDecl(simpleType);
737                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
738                 List<String> members = structDecl.getMembers(simpleType);
739                 if (isArray(param)) {                   // An array
740                         println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".length; i++) {");
741                         for (int i = 0; i < members.size(); i++) {
742                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
743                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
744                                 print("paramObj[pos++] = " + getSimpleIdentifier(param) + "[i].");
745                                 print(getSimpleIdentifier(members.get(i)));
746                                 println(";");
747                         }
748                         println("}");
749                 } else if (isList(paramType)) { // A list
750                         println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
751                         for (int i = 0; i < members.size(); i++) {
752                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
753                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
754                                 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".get(i).");
755                                 print(getSimpleIdentifier(members.get(i)));
756                                 println(";");
757                         }
758                         println("}");
759                 } else {        // Just one struct element
760                         for (int i = 0; i < members.size(); i++) {
761                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
762                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
763                                 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".");
764                                 print(getSimpleIdentifier(members.get(i)));
765                                 println(";");
766                         }
767                 }
768         }
769
770
771         /**
772          * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
773          */
774         private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
775
776                 print("int paramLen = ");
777                 writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
778                 println(";");
779                 println("Object[] paramObj = new Object[paramLen];");
780                 println("Class<?>[] paramCls = new Class<?>[paramLen];");
781                 println("int pos = 0;");
782                 // Iterate again over the parameters
783                 for (int i = 0; i < methParams.size(); i++) {
784                         String paramType = methPrmTypes.get(i);
785                         String param = methParams.get(i);
786                         String simpleType = getGenericType(paramType);
787                         if (isStructClass(simpleType)) {
788                                 writeStructMembersJavaStub(simpleType, paramType, param);
789                         } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
790                                 println("paramCls[pos] = int[].class;");
791                                 println("paramObj[pos++] = objIdSent" + i + ";");
792                         } else {
793                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
794                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
795                                 print("paramObj[pos++] = ");
796                                 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
797                                 println(";");
798                         }
799                 }
800                 
801         }
802
803
804         /**
805          * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
806          */
807         private void writeStructRetMembersJavaStub(String simpleType, String retType) {
808
809                 // Get the struct declaration for this struct and generate initialization code
810                 StructDecl structDecl = getStructDecl(simpleType);
811                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
812                 List<String> members = structDecl.getMembers(simpleType);
813                 if (isArrayOrList(retType, retType)) {  // An array or list
814                         println("for(int i = 0; i < retLen; i++) {");
815                 }
816                 if (isArray(retType)) { // An array
817                         for (int i = 0; i < members.size(); i++) {
818                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
819                                 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
820                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
821                         }
822                         println("}");
823                 } else if (isList(retType)) {   // A list
824                         println(simpleType + " structRetMem = new " + simpleType + "();");
825                         for (int i = 0; i < members.size(); i++) {
826                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
827                                 print("structRetMem." + getSimpleIdentifier(members.get(i)));
828                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
829                         }
830                         println("structRet.add(structRetMem);");
831                         println("}");
832                 } else {        // Just one struct element
833                         for (int i = 0; i < members.size(); i++) {
834                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
835                                 print("structRet." + getSimpleIdentifier(members.get(i)));
836                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
837                         }
838                 }
839                 println("return structRet;");
840         }
841
842
843         /**
844          * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
845          */
846         private void writeStructReturnJavaStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
847
848                 // Handle the returned struct size
849                 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
850                 // Minimum retLen is 1 if this is a single struct object
851                 println("int retLen = (int) retObj;");
852                 int numMem = getNumOfMembers(simpleType);
853                 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
854                 println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
855                 println("int retPos = 0;");
856                 // Get the struct declaration for this struct and generate initialization code
857                 StructDecl structDecl = getStructDecl(simpleType);
858                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
859                 List<String> members = structDecl.getMembers(simpleType);
860                 if (isArrayOrList(retType, retType)) {  // An array or list
861                         println("for(int i = 0; i < retLen; i++) {");
862                         for (int i = 0; i < members.size(); i++) {
863                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
864                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
865                                 println("retClsVal[retPos++] = null;");
866                         }
867                         println("}");
868                 } else {        // Just one struct element
869                         for (int i = 0; i < members.size(); i++) {
870                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
871                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
872                                 println("retClsVal[retPos++] = null;");
873                         }
874                 }
875                 // Handle the actual returned struct
876                 writeWaitForReturnValueJava(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
877                 if (isArray(retType)) {                 // An array
878                         println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
879                         println("for(int i = 0; i < retLen; i++) {");
880                         println("structRet[i] = new " + simpleType + "();");
881                         println("}");
882                 } else if (isList(retType)) {   // A list
883                         println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
884                 } else
885                         println(simpleType + " structRet = new " + simpleType + "();");
886                 println("int retObjPos = 0;");
887                 writeStructRetMembersJavaStub(simpleType, retType);
888         }
889
890
891         /**
892          * HELPER: writeWaitForReturnValueJava() writes the synchronization part for return values
893          */
894         private void writeWaitForReturnValueJava(String method, InterfaceDecl intDecl, String getReturnValue) {
895
896                 println("// Waiting for return value");         
897                 int methodNumId = intDecl.getMethodNumId(method);
898                 println("while (!retValueReceived" + methodNumId + ".get());");
899                 println(getReturnValue);
900                 println("retValueReceived" + methodNumId + ".set(false);");
901                 println("rmiComm.setGetReturnBytes();\n");
902         }
903
904
905         /**
906          * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
907          */
908         private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
909                         List<String> methPrmTypes, String method, Set<String> callbackType) {
910
911                 checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
912                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
913                 String retType = intDecl.getMethodType(method);
914                 println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
915                 checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
916                 // Generate array of parameter types
917                 if (isStructPresent(methParams, methPrmTypes)) {
918                         writeStructParamClassJavaStub(methParams, methPrmTypes, callbackType);
919                 } else {
920                         print("Class<?>[] paramCls = new Class<?>[] { ");
921                         for (int i = 0; i < methParams.size(); i++) {
922                                 String prmType = methPrmTypes.get(i);
923                                 if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object
924                                         print("int[].class");
925                                 } else { // Generate normal classes if it's not a callback object
926                                         String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
927                                         print(getSimpleType(getEnumType(paramType)) + ".class");
928                                 }
929                                 // Check if this is the last element (don't print a comma)
930                                 if (i != methParams.size() - 1) {
931                                         print(", ");
932                                 }
933                         }
934                         println(" };");
935                         // Generate array of parameter objects
936                         print("Object[] paramObj = new Object[] { ");
937                         for (int i = 0; i < methParams.size(); i++) {
938                                 String paramType = methPrmTypes.get(i);
939                                 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
940                                         print("objIdSent" + i);
941                                 } else
942                                         print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
943                                 // Check if this is the last element (don't print a comma)
944                                 if (i != methParams.size() - 1) {
945                                         print(", ");
946                                 }
947                         }
948                         println(" };");
949                 }
950                 // Send method call first and wait for return value separately
951                 println("rmiComm.remoteCall(objectId, methodId, paramCls, paramObj);");
952                 // Check if this is "void"
953                 if (!retType.equals("void")) { // We do have a return value
954                         // Generate array of parameter types
955                         if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
956                                 writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
957                         } else {
958                                 // This is an enum type
959                                 if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) {
960                                         //println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
961                                         checkAndWriteEnumRetTypeJavaStub(retType, method, intDecl);
962                                 } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
963                                 // Check if the return value NONPRIMITIVES
964                                         String retGenValType = getGenericType(retType);
965                                         println("Class<?> retGenValType = " + retGenValType + ".class;");
966                                         writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);");
967                                         println("return (" + retType + ")retObj;");
968                                 } else {
969                                         writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
970                                         println("return (" + retType + ")retObj;");
971                                 }
972                         }
973                 }
974         }
975
976
977         /**
978          * HELPER: returnGenericCallbackType() returns the callback type
979          */
980         private String returnGenericCallbackType(String paramType) {
981
982                 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
983                         return getGenericType(paramType);
984                 else
985                         return paramType;
986         }
987
988
989         /**
990          * HELPER: checkCallbackType() checks the callback type
991          */
992         private boolean checkCallbackType(String paramType, Set<String> callbackType) {
993
994                 String prmType = returnGenericCallbackType(paramType);
995                 if (callbackType == null)       // If there is no callbackType it means not a callback method
996                         return false;
997                 else {
998                         for (String type : callbackType) {
999                                 if (type.equals(prmType))
1000                                         return true;    // Check callbackType one by one
1001                         }
1002                         return false;
1003                 }
1004         }
1005
1006
1007         /**
1008          * HELPER: checkCallbackType() checks the callback type
1009          */
1010         private boolean checkCallbackType(String paramType, String callbackType) {
1011
1012                 String prmType = returnGenericCallbackType(paramType);
1013                 if (callbackType == null)       // If there is no callbackType it means not a callback method
1014                         return false;
1015                 else
1016                         return callbackType.equals(prmType);
1017         }
1018
1019
1020         /**
1021          * HELPER: writeCallbackInstantiationMethodBodyJavaStub() writes the callback object instantiation in the method of the stub class
1022          */
1023         private void writeCallbackInstantiationMethodBodyJavaStub(String paramIdent, String callbackType, int counter, boolean isMultipleCallbacks) {
1024
1025                 println("if (!IoTRMIUtil.mapSkel.containsKey(" + paramIdent + ")) {");
1026                 println("int newObjIdSent = rmiComm.getObjectIdCounter();");
1027                 if (isMultipleCallbacks)
1028                         println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1029                 else
1030                         println("objIdSent" + counter + "[0] = newObjIdSent;");
1031                 println("rmiComm.decrementObjectIdCounter();");
1032                 println(callbackType + "_Skeleton skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
1033                 println("IoTRMIUtil.mapSkel.put(" + paramIdent + ", skel" + counter + ");");
1034                 println("IoTRMIUtil.mapSkelId.put(" + paramIdent + ", newObjIdSent);");
1035                 println("Thread thread = new Thread() {");
1036                 println("public void run() {");
1037                 println("try {");
1038                 println("skel" + counter + ".___waitRequestInvokeMethod();");
1039                 println("} catch (Exception ex) {");
1040                 println("ex.printStackTrace();");
1041                 println("throw new Error(\"Exception when trying to run ___waitRequestInvokeMethod() for " + 
1042                         callbackType + "_Skeleton!\");");
1043                 println("}");
1044                 println("}");
1045                 println("};");
1046                 println("thread.start();");
1047                 println("while(!skel" + counter + ".didAlreadyInitWaitInvoke());");
1048                 println("}");
1049                 println("else");
1050                 println("{");
1051                 println("int newObjIdSent = IoTRMIUtil.mapSkelId.get(" + paramIdent + ");");
1052                 if (isMultipleCallbacks)
1053                         println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1054                 else
1055                         println("objIdSent" + counter + "[0] = newObjIdSent;");
1056                 println("}");
1057         }
1058
1059
1060         /**
1061          * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
1062          */
1063         private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
1064                         List<String> methPrmTypes, String method, Set<String> callbackType) {
1065
1066                 // Determine callback object counter type (List vs. single variable)
1067                 for (int i = 0; i < methParams.size(); i++) {
1068                         String paramType = methPrmTypes.get(i);
1069                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1070                                 print("int[] objIdSent" + i + " = ");
1071                                 String param = methParams.get(i);
1072                                 if (isArray(methParams.get(i)))
1073                                         println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".length];");
1074                                 else if (isList(methPrmTypes.get(i)))
1075                                         println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".size()];");
1076                                 else
1077                                         println("new int[1];");
1078                         }
1079                 }
1080                 println("try {");
1081                 // Check if this is single object, array, or list of objects
1082                 for (int i = 0; i < methParams.size(); i++) {
1083                         String paramType = methPrmTypes.get(i);
1084                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1085                                 String param = methParams.get(i);
1086                                 if (isArrayOrList(paramType, param)) {  // Generate loop
1087                                         println("int cnt" + i + " = 0;");
1088                                         println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
1089                                         writeCallbackInstantiationMethodBodyJavaStub("cb", returnGenericCallbackType(paramType), i, true);
1090                                 } else
1091                                         writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i, false);
1092                                 if (isArrayOrList(paramType, param))
1093                                         println("}");
1094                         }
1095                 }
1096                 print("}");
1097                 println(" catch (Exception ex) {");
1098                 println("ex.printStackTrace();");
1099                 println("throw new Error(\"Exception when generating skeleton objects!\");");
1100                 println("}\n");
1101         }
1102
1103
1104         /**
1105          * HELPER: writeMethodJavaStub() writes the methods of the stub class
1106          */
1107         private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
1108
1109                 for (String method : methods) {
1110
1111                         List<String> methParams = intDecl.getMethodParams(method);
1112                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1113                         print("public " + intDecl.getMethodType(method) + " " +
1114                                 intDecl.getMethodId(method) + "(");
1115                         boolean isCallbackMethod = false;
1116                         //String callbackType = null;
1117                         Set<String> callbackType = new HashSet<String>();
1118                         for (int i = 0; i < methParams.size(); i++) {
1119
1120                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1121                                 // Check if this has callback object
1122                                 if (callbackClasses.contains(paramType)) {
1123                                         isCallbackMethod = true;
1124                                         //callbackType = paramType;
1125                                         callbackType.add(paramType);
1126                                         // Even if there're 2 callback arguments, we expect them to be of the same interface
1127                                 }
1128                                 print(methPrmTypes.get(i) + " " + methParams.get(i));
1129                                 // Check if this is the last element (don't print a comma)
1130                                 if (i != methParams.size() - 1) {
1131                                         print(", ");
1132                                 }
1133                         }
1134                         println(") {");
1135                         // Now, write the body of stub!
1136                         if (isCallbackMethod)
1137                                 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1138                         writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1139                         println("}\n");
1140                 }
1141         }
1142
1143
1144         /**
1145          * HELPER: getStubInterface() gets stub interface name based on original interface
1146          */
1147         public String getStubInterface(String intface) {
1148
1149                 return mapInt2NewIntName.get(intface);
1150         }
1151
1152
1153         /**
1154          * generateJavaStubClasses() generate stubs based on the methods list in Java
1155          */
1156         public void generateJavaStubClasses() throws IOException {
1157
1158                 // Create a new directory
1159                 String path = createDirectories(dir, subdir);
1160                 for (String intface : mapIntfacePTH.keySet()) {
1161
1162                         // Check if there is more than 1 class that uses the same interface
1163                         List<String> drvList = mapInt2Drv.get(intface);
1164                         for(int i = 0; i < drvList.size(); i++) {
1165
1166                                 String driverClass = drvList.get(i);
1167                                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1168                                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1169
1170                                         // Open a new file to write into
1171                                         String newIntface = intMeth.getKey();
1172                                         String newStubClass = newIntface + "_Stub";
1173                                         String packageClass = null;
1174                                         // Check if this interface is a callback class
1175                                         if(isCallbackClass(intface)) {
1176                                                 packageClass = CODE_PREFIX + "." + driverClass;
1177                                                 path = createDirectories(dir + "/" + subdir, driverClass);
1178                                         } else {
1179                                                 packageClass = controllerClass;
1180                                                 path = createDirectories(dir + "/" + subdir, controllerClass);
1181                                         }
1182                                         FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1183                                         pw = new PrintWriter(new BufferedWriter(fw));
1184                                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1185                                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1186                                         // Pass in set of methods and get import classes
1187                                         Set<String> methods = intMeth.getValue();
1188                                         Set<String> importClasses = getImportClasses(methods, intDecl);
1189                                         List<String> stdImportClasses = getStandardJavaImportClasses();
1190                                         List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1191                                         // Find out if there are callback objects
1192                                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);                     
1193                                         boolean callbackExist = !callbackClasses.isEmpty();
1194                                         println("package " + packageClass + ";\n");
1195                                         printImportStatements(allImportClasses); 
1196                                         println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
1197                                         // Write class header
1198                                         println("public class " + newStubClass + " implements " + newIntface + " {\n");
1199                                         // Write properties
1200                                         writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
1201                                         // Write constructor
1202                                         writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1203                                         // Write callback constructor (used if this stub is treated as a callback stub)
1204                                         writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1205                                         // Write methods
1206                                         writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
1207                                         println("}");
1208                                         pw.close();
1209                                         System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
1210                                 }
1211                         }
1212                 }
1213         }
1214
1215
1216         /**
1217          * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
1218          */
1219         private void writePropertiesJavaSkeleton(String intface, InterfaceDecl intDecl) {
1220
1221                 println("private " + intface + " mainObj;");
1222                 Integer objId = mapIntfaceObjId.get(intface);
1223                 println("private int objectId = " + objId + ";");
1224                 println("// Communications and synchronizations");
1225                 println("private IoTRMIComm rmiComm;");
1226                 println("private AtomicBoolean didAlreadyInitWaitInvoke;");
1227                 println("private AtomicBoolean methodReceived;");
1228                 println("private byte[] methodBytes = null;");
1229                 println("// Permissions");
1230                 writePropertiesJavaPermission(intface, intDecl);
1231                 println("\n");
1232         }
1233
1234
1235         /**
1236          * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper
1237          */
1238         private void writeStructPermissionJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
1239
1240                 // Use this set to handle two same methodIds
1241                 for (String method : methods) {
1242                         List<String> methParams = intDecl.getMethodParams(method);
1243                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1244                         // Check for params with structs
1245                         for (int i = 0; i < methParams.size(); i++) {
1246                                 String paramType = methPrmTypes.get(i);
1247                                 String param = methParams.get(i);
1248                                 String simpleType = getGenericType(paramType);
1249                                 if (isStructClass(simpleType)) {
1250                                         int methodNumId = intDecl.getMethodNumId(method);
1251                                         String helperMethod = methodNumId + "struct" + i;
1252                                         int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod);
1253                                         // Iterate over interfaces to give permissions to
1254                                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1255                                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1256                                                 String newIntface = intMeth.getKey();
1257                                                 int newObjectId = getNewIntfaceObjectId(newIntface);
1258                                                 println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");");
1259                                         }
1260                                 }
1261                         }
1262                 }
1263         }
1264
1265
1266         /**
1267          * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
1268          */
1269         private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, 
1270                         Collection<String> methods, boolean callbackExist) {
1271
1272                 println("public " + newSkelClass + "(" + intface + " _mainObj, int _portSend, int _portRecv) throws Exception {");
1273                 println("mainObj = _mainObj;");
1274                 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv);");
1275                 // Generate permission control initialization
1276                 writeConstructorJavaPermission(intface);
1277                 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1278                 println("IoTRMIUtil.mapSkel.put(_mainObj, this);");
1279                 println("IoTRMIUtil.mapSkelId.put(_mainObj, objectId);");
1280                 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1281                 println("methodReceived = new AtomicBoolean(false);");
1282                 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1283                 println("Thread thread1 = new Thread() {");
1284                 println("public void run() {");
1285                 println("try {");
1286                 println("___waitRequestInvokeMethod();");
1287                 println("}");
1288                 println("catch (Exception ex)");
1289                 println("{");
1290                 println("ex.printStackTrace();");
1291                 println("}");
1292                 println("}");
1293                 println("};");
1294                 println("thread1.start();");
1295                 println("}\n");
1296         }
1297
1298
1299         /**
1300          * HELPER: writeCallbackConstructorJavaSkeleton() writes the constructor of the skeleton class
1301          */
1302         private void writeCallbackConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, 
1303                         Collection<String> methods, boolean callbackExist) {
1304
1305                 println("public " + newSkelClass + "(" + intface + " _mainObj, IoTRMIComm _rmiComm, int _objectId) throws Exception {");
1306                 println("mainObj = _mainObj;");
1307                 println("rmiComm = _rmiComm;");
1308                 println("objectId = _objectId;");
1309                 // Generate permission control initialization
1310                 writeConstructorJavaPermission(intface);
1311                 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1312                 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1313                 println("methodReceived = new AtomicBoolean(false);");
1314                 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1315                 println("}\n");
1316         }
1317
1318
1319         /**
1320          * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
1321          */
1322         private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
1323
1324                 if (methodType.equals("void"))
1325                         print("mainObj." + methodId + "(");
1326                 else
1327                         print("return mainObj." + methodId + "(");
1328                 for (int i = 0; i < methParams.size(); i++) {
1329
1330                         print(getSimpleIdentifier(methParams.get(i)));
1331                         // Check if this is the last element (don't print a comma)
1332                         if (i != methParams.size() - 1) {
1333                                 print(", ");
1334                         }
1335                 }
1336                 println(");");
1337         }
1338
1339
1340         /**
1341          * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
1342          */
1343         private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1344
1345                 for (String method : methods) {
1346
1347                         List<String> methParams = intDecl.getMethodParams(method);
1348                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1349                         String methodId = intDecl.getMethodId(method);
1350                         print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
1351                         for (int i = 0; i < methParams.size(); i++) {
1352
1353                                 String origParamType = methPrmTypes.get(i);
1354                                 String paramType = checkAndGetParamClass(origParamType);
1355                                 print(paramType + " " + methParams.get(i));
1356                                 // Check if this is the last element (don't print a comma)
1357                                 if (i != methParams.size() - 1) {
1358                                         print(", ");
1359                                 }
1360                         }
1361                         println(") {");
1362                         // Now, write the body of skeleton!
1363                         writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
1364                         println("}\n");
1365                 }
1366         }
1367
1368
1369         /**
1370          * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs
1371          */
1372         private void writeCallbackInstantiationJavaStubGeneration(String exchParamType, int counter) {
1373
1374                 println(exchParamType + " newStub" + counter + " = null;");
1375                 println("if(!IoTRMIUtil.mapStub.containsKey(objIdRecv" + counter + ")) {");
1376                 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
1377                 println("IoTRMIUtil.mapStub.put(objIdRecv" + counter + ", newStub" + counter + ");");
1378                 println("rmiComm.setObjectIdCounter(objIdRecv" + counter + ");");
1379                 println("rmiComm.decrementObjectIdCounter();");
1380                 println("}");
1381                 println("else {");
1382                 println("newStub" + counter + " = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv" + counter + ");");
1383                 println("}");
1384         }
1385
1386
1387         /**
1388          * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
1389          */
1390         private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes, 
1391                         Set<String> callbackType, boolean isStructMethod) {
1392
1393                 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
1394                 String offsetPfx = "";
1395                 if (isStructMethod)
1396                         offsetPfx = "offset";
1397                 // Iterate over callback objects
1398                 for (int i = 0; i < methParams.size(); i++) {
1399                         String paramType = methPrmTypes.get(i);
1400                         String param = methParams.get(i);
1401                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1402                                 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1403                                 // Print array if this is array or list if this is a list of callback objects
1404                                 println("int[] stubIdArray" + i + " = (int[]) paramObj[" + offsetPfx + i + "];");
1405                                 if (isArray(param)) {                           
1406                                         println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1407                                         println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1408                                 } else if (isList(paramType)) {
1409                                         println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1410                                         println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1411                                 } else {
1412                                         println("int objIdRecv" + i + " = stubIdArray" + i + "[0];");
1413                                         writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1414                                 }
1415                         }
1416                         // Generate a loop if needed
1417                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1418                                 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1419                                 if (isArray(param)) {
1420                                         println("for (int i = 0; i < numStubs" + i + "; i++) {");
1421                                         println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1422                                         writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1423                                         println("stub" + i + "[i] = newStub" + i + ";");
1424                                         println("}");
1425                                 } else if (isList(paramType)) {
1426                                         println("for (int i = 0; i < numStubs" + i + "; i++) {");
1427                                         println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1428                                         writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1429                                         println("stub" + i + ".add(newStub" + i + ");");
1430                                         println("}");
1431                                 } else
1432                                         println(exchParamType + " stub" + i + " = newStub" + i + ";");
1433                                 mapStubParam.put(i, "stub" + i);        // List of all stub parameters
1434                         }
1435                 }
1436                 return mapStubParam;
1437         }
1438
1439
1440         /**
1441          * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
1442          */
1443         private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes, boolean isStructMethod) {
1444
1445                 String offsetPfx = "";
1446                 if (isStructMethod)
1447                         offsetPfx = "offset";
1448                 // Iterate and find enum declarations
1449                 boolean printed = false;
1450                 for (int i = 0; i < methParams.size(); i++) {
1451                         String paramType = methPrmTypes.get(i);
1452                         String param = methParams.get(i);
1453                         String simpleType = getGenericType(paramType);
1454                         if (isEnumClass(simpleType)) {
1455                         // Check if this is enum type
1456                                 println("int paramInt" + i + "[] = (int[]) paramObj[" + offsetPfx + i + "];");
1457                                 if (!printed) {
1458                                         println(simpleType + "[] enumVals = " + simpleType + ".values();");
1459                                         printed = true;
1460                                 }
1461                                 if (isArray(param)) {   // An array
1462                                         println("int len" + i + " = paramInt" + i + ".length;");
1463                                         println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];");
1464                                         println("for (int i = 0; i < len" + i + "; i++) {");
1465                                         println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];");
1466                                         println("}");
1467                                 } else if (isList(paramType)) { // A list
1468                                         println("int len" + i + " = paramInt" + i + ".length;");
1469                                         println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();");
1470                                         println("for (int i = 0; i < len" + i + "; i++) {");
1471                                         println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);");
1472                                         println("}");
1473                                 } else {        // Just one element
1474                                         println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
1475                                 }
1476                         }
1477                 }
1478         }
1479
1480
1481         /**
1482          * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
1483          */
1484         private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
1485
1486                 // Strips off array "[]" for return type
1487                 String pureType = getSimpleArrayType(getGenericType(retType));
1488                 // Take the inner type of generic
1489                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1490                         pureType = getGenericType(retType);
1491                 if (isEnumClass(pureType)) {
1492                 // Check if this is enum type
1493                         // Enum decoder
1494                         if (isArray(retType)) {                 // An array
1495                                 print(pureType + "[] retEnum = " + methodId + "(");
1496                         } else if (isList(retType)) {   // A list
1497                                 print("List<" + pureType + "> retEnum = " + methodId + "(");
1498                         } else {        // Just one element
1499                                 print(pureType + " retEnum = " + methodId + "(");
1500                         }
1501                 }
1502         }
1503
1504
1505         /**
1506          * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
1507          */
1508         private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
1509
1510                 // Strips off array "[]" for return type
1511                 String pureType = getSimpleArrayType(getGenericType(retType));
1512                 // Take the inner type of generic
1513                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1514                         pureType = getGenericType(retType);
1515                 if (isEnumClass(pureType)) {
1516                 // Check if this is enum type
1517                         if (isArray(retType)) { // An array
1518                                 println("int retLen = retEnum.length;");
1519                                 println("int[] retEnumVal = new int[retLen];");
1520                                 println("for (int i = 0; i < retLen; i++) {");
1521                                 println("retEnumVal[i] = retEnum[i].ordinal();");
1522                                 println("}");
1523                         } else if (isList(retType)) {   // A list
1524                                 println("int retLen = retEnum.size();");
1525                                 println("int[] retEnumVal = new int[retLen];");
1526                                 println("for (int i = 0; i < retLen; i++) {");
1527                                 println("retEnumVal[i] = retEnum.get(i).ordinal();");
1528                                 println("}");
1529                         } else {        // Just one element
1530                                 println("int[] retEnumVal = new int[1];");
1531                                 println("retEnumVal[0] = retEnum.ordinal();");
1532                         }
1533                         println("Object retObj = retEnumVal;");
1534                 }
1535         }
1536         
1537         
1538         /**
1539          * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
1540          */
1541         private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes, 
1542                         String method, InterfaceDecl intDecl) {
1543
1544                 // Iterate and find struct declarations - count number of params
1545                 for (int i = 0; i < methParams.size(); i++) {
1546                         String paramType = methPrmTypes.get(i);
1547                         String param = methParams.get(i);
1548                         String simpleType = getGenericType(paramType);
1549                         if (isStructClass(simpleType)) {
1550                                 int members = getNumOfMembers(simpleType);
1551                                 print(Integer.toString(members) + "*");
1552                                 int methodNumId = intDecl.getMethodNumId(method);
1553                                 print("struct" + methodNumId + "Size" + i);
1554                         } else
1555                                 print("1");
1556                         if (i != methParams.size() - 1) {
1557                                 print("+");
1558                         }
1559                 }
1560         }
1561
1562         
1563         /**
1564          * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
1565          */
1566         private void writeStructMembersJavaSkeleton(String simpleType, String paramType, 
1567                         String param, String method, InterfaceDecl intDecl, int iVar) {
1568
1569                 // Get the struct declaration for this struct and generate initialization code
1570                 StructDecl structDecl = getStructDecl(simpleType);
1571                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1572                 List<String> members = structDecl.getMembers(simpleType);
1573                 if (isArrayOrList(paramType, param)) {  // An array or list
1574                         int methodNumId = intDecl.getMethodNumId(method);
1575                         String counter = "struct" + methodNumId + "Size" + iVar;
1576                         println("for(int i = 0; i < " + counter + "; i++) {");
1577                 }
1578                 if (isArrayOrList(paramType, param)) {  // An array or list
1579                         for (int i = 0; i < members.size(); i++) {
1580                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1581                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1582                                 println("paramClsGen[pos++] = null;");
1583                         }
1584                         println("}");
1585                 } else {        // Just one struct element
1586                         for (int i = 0; i < members.size(); i++) {
1587                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1588                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1589                                 println("paramClsGen[pos++] = null;");
1590                         }
1591                 }
1592         }
1593
1594
1595         /**
1596          * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
1597          */
1598         private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1599                         List<String> methPrmTypes, String method) {
1600
1601                 println("int objPos = 0;");
1602                 for (int i = 0; i < methParams.size(); i++) {
1603                         String paramType = methPrmTypes.get(i);
1604                         String param = methParams.get(i);
1605                         String simpleType = getGenericType(paramType);
1606                         if (isStructClass(simpleType)) {
1607                                 int methodNumId = intDecl.getMethodNumId(method);
1608                                 String counter = "struct" + methodNumId + "Size" + i;
1609                                 // Declaration
1610                                 if (isArray(param)) {                   // An array
1611                                         println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
1612                                         println("for(int i = 0; i < " + counter + "; i++) {");
1613                                         println("paramStruct" + i + "[i] = new " + simpleType + "();");
1614                                         println("}");
1615                                 } else if (isList(paramType)) { // A list
1616                                         println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
1617                                 } else
1618                                         println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
1619                                 // Initialize members
1620                                 StructDecl structDecl = getStructDecl(simpleType);
1621                                 List<String> members = structDecl.getMembers(simpleType);
1622                                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1623                                 if (isArrayOrList(paramType, param)) {  // An array or list
1624                                         println("for(int i = 0; i < " + counter + "; i++) {");
1625                                 }
1626                                 if (isArray(param)) {   // An array
1627                                         for (int j = 0; j < members.size(); j++) {
1628                                                 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1629                                                 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
1630                                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1631                                         }
1632                                         println("}");
1633                                 } else if (isList(paramType)) { // A list
1634                                         println(simpleType + " paramStructMem = new " + simpleType + "();");
1635                                         for (int j = 0; j < members.size(); j++) {
1636                                                 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1637                                                 print("paramStructMem." + getSimpleIdentifier(members.get(j)));
1638                                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1639                                         }
1640                                         println("paramStruct" + i + ".add(paramStructMem);");
1641                                         println("}");
1642                                 } else {        // Just one struct element
1643                                         for (int j = 0; j < members.size(); j++) {
1644                                                 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1645                                                 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
1646                                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1647                                         }
1648                                 }
1649                         } else {
1650                                 // Take offsets of parameters
1651                                 println("int offset" + i +" = objPos++;");
1652                         }
1653                 }
1654         }
1655
1656
1657         /**
1658          * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
1659          */
1660         private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
1661
1662                 // Minimum retLen is 1 if this is a single struct object
1663                 if (isArray(retType))
1664                         println("int retLen = retStruct.length;");
1665                 else if (isList(retType))
1666                         println("int retLen = retStruct.size();");
1667                 else    // Just single struct object
1668                         println("int retLen = 1;");
1669                 println("Object retLenObj = retLen;");
1670                 println("rmiComm.sendReturnObj(retLenObj, localMethodBytes);");
1671                 int numMem = getNumOfMembers(simpleType);
1672                 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
1673                 println("Object[] retObj = new Object[" + numMem + "*retLen];");
1674                 println("int retPos = 0;");
1675                 // Get the struct declaration for this struct and generate initialization code
1676                 StructDecl structDecl = getStructDecl(simpleType);
1677                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1678                 List<String> members = structDecl.getMembers(simpleType);
1679                 if (isArray(retType)) { // An array or list
1680                         println("for(int i = 0; i < retLen; i++) {");
1681                         for (int i = 0; i < members.size(); i++) {
1682                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1683                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1684                                 print("retObj[retPos++] = retStruct[i].");
1685                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1686                                 println(";");
1687                         }
1688                         println("}");
1689                 } else if (isList(retType)) {   // An array or list
1690                         println("for(int i = 0; i < retLen; i++) {");
1691                         for (int i = 0; i < members.size(); i++) {
1692                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1693                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1694                                 print("retObj[retPos++] = retStruct.get(i).");
1695                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1696                                 println(";");
1697                         }
1698                         println("}");
1699                 } else {        // Just one struct element
1700                         for (int i = 0; i < members.size(); i++) {
1701                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1702                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1703                                 print("retObj[retPos++] = retStruct.");
1704                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1705                                 println(";");
1706                         }
1707                 }
1708
1709         }
1710
1711
1712         /**
1713          * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
1714          */
1715         private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1716                         List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
1717                         boolean isStructMethod) {
1718
1719                 checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod);
1720                 Map<Integer,String> mapStubParam = null;
1721                 if (isCallbackMethod) {
1722                         println("try {");
1723                         mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType, isStructMethod);
1724                 }
1725                 // Check if this is "void"
1726                 String retType = intDecl.getMethodType(method);
1727                 if (retType.equals("void")) {
1728                         print(intDecl.getMethodId(method) + "(");
1729                 } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {  // Enum type
1730                         checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
1731                 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) {        // Struct type
1732                         print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
1733                 } else { // We do have a return value
1734                         print("Object retObj = " + intDecl.getMethodId(method) + "(");
1735                 }
1736                 for (int i = 0; i < methParams.size(); i++) {
1737
1738                         String paramType = methPrmTypes.get(i);
1739                         if (isCallbackMethod && checkCallbackType(paramType, callbackType)) {
1740                                 print(mapStubParam.get(i));     // Get the callback parameter
1741                         } else if (isEnumClass(getGenericType(paramType))) { // Enum class
1742                                 print(getEnumParam(paramType, methParams.get(i), i));
1743                         } else if (isStructClass(getGenericType(paramType))) {
1744                                 print("paramStruct" + i);
1745                         } else {
1746                                 String prmType = checkAndGetArray(paramType, methParams.get(i));
1747                                 if (isStructMethod)
1748                                         print("(" + prmType + ") paramObj[offset" + i + "]");
1749                                 else
1750                                         print("(" + prmType + ") paramObj[" + i + "]");
1751                         }
1752                         if (i != methParams.size() - 1)
1753                                 print(", ");
1754                 }
1755                 println(");");
1756                 if (!retType.equals("void")) {
1757                         if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1758                                 checkAndWriteEnumRetConvJavaSkeleton(retType);
1759                                 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1760                         } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1761                                 writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
1762                                 println("rmiComm.sendReturnObj(retCls, retObj, localMethodBytes);");
1763                         } else
1764                                 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1765                 }
1766                 if (isCallbackMethod) { // Catch exception if this is callback
1767                         print("}");
1768                         println(" catch(Exception ex) {");
1769                         println("ex.printStackTrace();");
1770                         println("throw new Error(\"Exception from callback object instantiation!\");");
1771                         println("}");
1772                 }
1773         }
1774
1775
1776         /**
1777          * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
1778          */
1779         private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1780                         List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1781
1782                 // Generate array of parameter objects
1783                 boolean isCallbackMethod = false;
1784                 Set<String> callbackType = new HashSet<String>();
1785                 println("byte[] localMethodBytes = methodBytes;");
1786                 println("rmiComm.setGetMethodBytes();");
1787                 print("int paramLen = ");
1788                 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
1789                 println(";");
1790                 println("Class<?>[] paramCls = new Class<?>[paramLen];");
1791                 println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
1792                 println("int pos = 0;");
1793                 // Iterate again over the parameters
1794                 for (int i = 0; i < methParams.size(); i++) {
1795                         String paramType = methPrmTypes.get(i);
1796                         String param = methParams.get(i);
1797                         String simpleType = getGenericType(paramType);
1798                         if (isStructClass(simpleType)) {
1799                                 writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
1800                         } else {
1801                                 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
1802                                 if (callbackClasses.contains(prmType)) {
1803                                         isCallbackMethod = true;
1804                                         //callbackType = prmType;
1805                                         callbackType.add(prmType);
1806                                         println("paramCls[pos] = int[].class;");
1807                                         println("paramClsGen[pos++] = null;");
1808                                 } else {        // Generate normal classes if it's not a callback object
1809                                         String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1810                                         println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
1811                                         print("paramClsGen[pos++] = ");
1812                                         String prmTypeOth = methPrmTypes.get(i);
1813                                         if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
1814                                                 println(getTypeOfGeneric(prmType)[0] + ".class;");
1815                                         else
1816                                                 println("null;");
1817                                 }
1818                         }
1819                 }
1820                 println("Object[] paramObj = rmiComm.getMethodParams(paramCls, paramClsGen, localMethodBytes);");
1821                 writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
1822                 // Write the return value part
1823                 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true);
1824         }
1825
1826
1827         /**
1828          * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1829          */
1830         private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1831                         List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1832
1833                 // Generate array of parameter objects
1834                 boolean isCallbackMethod = false;
1835                 Set<String> callbackType = new HashSet<String>();
1836                 println("byte[] localMethodBytes = methodBytes;");
1837                 println("rmiComm.setGetMethodBytes();");
1838                 print("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { ");
1839                 for (int i = 0; i < methParams.size(); i++) {
1840
1841                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1842                         if (callbackClasses.contains(paramType)) {
1843                                 isCallbackMethod = true;
1844                                 callbackType.add(paramType);
1845                                 print("int[].class");
1846                         } else {        // Generate normal classes if it's not a callback object
1847                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1848                                 print(getSimpleType(getEnumType(prmType)) + ".class");
1849                         }
1850                         if (i != methParams.size() - 1)
1851                                 print(", ");
1852                 }
1853                 // Generate generic class if it's a generic type.. null otherwise
1854                 print(" }, new Class<?>[] { ");
1855                 for (int i = 0; i < methParams.size(); i++) {
1856                         String prmType = methPrmTypes.get(i);
1857                         if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) &&
1858                                 !isEnumClass(getGenericType(prmType)) &&
1859                                 !callbackClasses.contains(getGenericType(prmType)))
1860                                         print(getGenericType(prmType) + ".class");
1861                         else
1862                                 print("null");
1863                         if (i != methParams.size() - 1)
1864                                 print(", ");
1865                 }
1866                 println(" }, localMethodBytes);");
1867                 // Write the return value part
1868                 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false);
1869         }
1870
1871
1872         /**
1873          * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1874          */
1875         private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1876
1877                 // Use this set to handle two same methodIds
1878                 Set<String> uniqueMethodIds = new HashSet<String>();
1879                 for (String method : methods) {
1880
1881                         List<String> methParams = intDecl.getMethodParams(method);
1882                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1883                         if (isStructPresent(methParams, methPrmTypes)) {        // Treat struct differently
1884                                 String methodId = intDecl.getMethodId(method);
1885                                 print("public void ___");
1886                                 String helperMethod = methodId;
1887                                 if (uniqueMethodIds.contains(methodId))
1888                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
1889                                 else
1890                                         uniqueMethodIds.add(methodId);
1891                                 String retType = intDecl.getMethodType(method);
1892                                 print(helperMethod + "(");
1893                                 boolean begin = true;
1894                                 for (int i = 0; i < methParams.size(); i++) { // Print size variables
1895                                         String paramType = methPrmTypes.get(i);
1896                                         String param = methParams.get(i);
1897                                         String simpleType = getGenericType(paramType);
1898                                         if (isStructClass(simpleType)) {
1899                                                 if (!begin)     // Generate comma for not the beginning variable
1900                                                         print(", ");
1901                                                 else
1902                                                         begin = false;
1903                                                 int methodNumId = intDecl.getMethodNumId(method);
1904                                                 print("int struct" + methodNumId + "Size" + i);
1905                                         }
1906                                 }
1907                                 // Check if this is "void"
1908                                 if (retType.equals("void"))
1909                                         println(") {");
1910                                 else
1911                                         println(") throws IOException {");
1912                                 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1913                                 println("}\n");
1914                         } else {
1915                                 String methodId = intDecl.getMethodId(method);
1916                                 print("public void ___");
1917                                 String helperMethod = methodId;
1918                                 if (uniqueMethodIds.contains(methodId))
1919                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
1920                                 else
1921                                         uniqueMethodIds.add(methodId);
1922                                 // Check if this is "void"
1923                                 String retType = intDecl.getMethodType(method);
1924                                 if (retType.equals("void"))
1925                                         println(helperMethod + "() {");
1926                                 else
1927                                         println(helperMethod + "() throws IOException {");
1928                                 // Now, write the helper body of skeleton!
1929                                 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1930                                 println("}\n");
1931                         }
1932                 }
1933                 // Write method helper for structs
1934                 writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
1935         }
1936
1937
1938         /**
1939          * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
1940          */
1941         private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods, 
1942                         InterfaceDecl intDecl) {
1943
1944                 // Use this set to handle two same methodIds
1945                 for (String method : methods) {
1946
1947                         List<String> methParams = intDecl.getMethodParams(method);
1948                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1949                         // Check for params with structs
1950                         for (int i = 0; i < methParams.size(); i++) {
1951                                 String paramType = methPrmTypes.get(i);
1952                                 String param = methParams.get(i);
1953                                 String simpleType = getGenericType(paramType);
1954                                 if (isStructClass(simpleType)) {
1955                                         int methodNumId = intDecl.getMethodNumId(method);
1956                                         print("public int ___");
1957                                         String helperMethod = methodNumId + "struct" + i;
1958                                         println(helperMethod + "() {");
1959                                         // Now, write the helper body of skeleton!
1960                                         println("byte[] localMethodBytes = methodBytes;");
1961                                         println("rmiComm.setGetMethodBytes();");
1962                                         println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null }, localMethodBytes);");
1963                                         println("return (int) paramObj[0];");
1964                                         println("}\n");
1965                                 }
1966                         }
1967                 }
1968         }
1969
1970
1971         /**
1972          * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
1973          */
1974         private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods, 
1975                         InterfaceDecl intDecl) {
1976
1977                 // Use this set to handle two same methodIds
1978                 for (String method : methods) {
1979
1980                         List<String> methParams = intDecl.getMethodParams(method);
1981                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1982                         // Check for params with structs
1983                         for (int i = 0; i < methParams.size(); i++) {
1984                                 String paramType = methPrmTypes.get(i);
1985                                 String param = methParams.get(i);
1986                                 String simpleType = getGenericType(paramType);
1987                                 if (isStructClass(simpleType)) {
1988                                         int methodNumId = intDecl.getMethodNumId(method);
1989                                         print("public int ___");
1990                                         String helperMethod = methodNumId + "struct" + i;
1991                                         println(helperMethod + "(IoTRMIObject rmiObj) {");
1992                                         // Now, write the helper body of skeleton!
1993                                         println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1994                                         println("return (int) paramObj[0];");
1995                                         println("}\n");
1996                                 }
1997                         }
1998                 }
1999         }
2000
2001
2002         /**
2003          * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
2004          */
2005         private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2006
2007                 // Use this set to handle two same methodIds
2008                 for (String method : methods) {
2009
2010                         List<String> methParams = intDecl.getMethodParams(method);
2011                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2012                         // Check for params with structs
2013                         for (int i = 0; i < methParams.size(); i++) {
2014                                 String paramType = methPrmTypes.get(i);
2015                                 String param = methParams.get(i);
2016                                 String simpleType = getGenericType(paramType);
2017                                 if (isStructClass(simpleType)) {
2018                                         int methodNumId = intDecl.getMethodNumId(method);
2019                                         println("int struct" + methodNumId + "Size" + i + " = 0;");
2020                                 }
2021                         }
2022                 }
2023         }
2024         
2025
2026         /**
2027          * HELPER: writeInputCountVarStructJavaSkeleton() writes input counter variable of struct for skeleton
2028          */
2029         private boolean writeInputCountVarStructJavaSkeleton(String method, InterfaceDecl intDecl) {
2030
2031                 List<String> methParams = intDecl.getMethodParams(method);
2032                 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2033                 boolean structExist = false;
2034                 boolean begin = true;
2035                 // Check for params with structs
2036                 for (int i = 0; i < methParams.size(); i++) {
2037                         String paramType = methPrmTypes.get(i);
2038                         String param = methParams.get(i);
2039                         String simpleType = getGenericType(paramType);
2040                         if (isStructClass(simpleType)) {
2041                                 structExist = true;
2042                                 if (!begin)
2043                                         print(", ");
2044                                 else
2045                                         begin = false;
2046                                 int methodNumId = intDecl.getMethodNumId(method);
2047                                 print("struct" + methodNumId + "Size" + i + "Final");
2048                         }
2049                 }
2050                 return structExist;
2051         }
2052
2053         
2054         /**
2055          * HELPER: writeInputCountVarStructCplusSkeleton() writes input counter variable of struct for skeleton
2056          */
2057         private boolean writeInputCountVarStructCplusSkeleton(String method, InterfaceDecl intDecl) {
2058
2059                 List<String> methParams = intDecl.getMethodParams(method);
2060                 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2061                 boolean structExist = false;
2062                 boolean begin = true;
2063                 // Check for params with structs
2064                 for (int i = 0; i < methParams.size(); i++) {
2065                         String paramType = methPrmTypes.get(i);
2066                         String param = methParams.get(i);
2067                         String simpleType = getGenericType(paramType);
2068                         if (isStructClass(simpleType)) {
2069                                 structExist = true;
2070                                 if (!begin)
2071                                         print(", ");
2072                                 else
2073                                         begin = false;
2074                                 int methodNumId = intDecl.getMethodNumId(method);
2075                                 print("struct" + methodNumId + "Size" + i);
2076                         }
2077                 }
2078                 return structExist;
2079         }
2080
2081
2082         /**
2083          * HELPER: writeMethodCallStructJavaSkeleton() writes method call for wait invoke in skeleton
2084          */
2085         private void writeMethodCallStructJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2086
2087                 // Use this set to handle two same methodIds
2088                 for (String method : methods) {
2089
2090                         List<String> methParams = intDecl.getMethodParams(method);
2091                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2092                         // Check for params with structs
2093                         for (int i = 0; i < methParams.size(); i++) {
2094                                 String paramType = methPrmTypes.get(i);
2095                                 String param = methParams.get(i);
2096                                 String simpleType = getGenericType(paramType);
2097                                 if (isStructClass(simpleType)) {
2098                                         int methodNumId = intDecl.getMethodNumId(method);
2099                                         print("case ");
2100                                         String helperMethod = methodNumId + "struct" + i;
2101                                         String tempVar = "struct" + methodNumId + "Size" + i;
2102                                         print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2103                                         print(tempVar + " = ___");
2104                                         println(helperMethod + "(); break;");
2105                                 }
2106                         }
2107                 }
2108         }
2109
2110
2111         /**
2112          * HELPER: writeMethodCallStructCplusSkeleton() writes method call for wait invoke in skeleton
2113          */
2114         private void writeMethodCallStructCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2115
2116                 // Use this set to handle two same methodIds
2117                 for (String method : methods) {
2118
2119                         List<String> methParams = intDecl.getMethodParams(method);
2120                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2121                         // Check for params with structs
2122                         for (int i = 0; i < methParams.size(); i++) {
2123                                 String paramType = methPrmTypes.get(i);
2124                                 String param = methParams.get(i);
2125                                 String simpleType = getGenericType(paramType);
2126                                 if (isStructClass(simpleType)) {
2127                                         int methodNumId = intDecl.getMethodNumId(method);
2128                                         print("case ");
2129                                         String helperMethod = methodNumId + "struct" + i;
2130                                         String tempVar = "struct" + methodNumId + "Size" + i;
2131                                         print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2132                                         print(tempVar + " = ___");
2133                                         println(helperMethod + "(skel); break;");
2134                                 }
2135                         }
2136                 }
2137         }
2138
2139
2140         /**
2141          * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
2142          */
2143         private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2144
2145                 // Use this set to handle two same methodIds
2146                 for (String method : methods) {
2147
2148                         List<String> methParams = intDecl.getMethodParams(method);
2149                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2150                         // Check for params with structs
2151                         for (int i = 0; i < methParams.size(); i++) {
2152                                 String paramType = methPrmTypes.get(i);
2153                                 String param = methParams.get(i);
2154                                 String simpleType = getGenericType(paramType);
2155                                 if (isStructClass(simpleType)) {
2156                                         int methodNumId = intDecl.getMethodNumId(method);
2157                                         print("case ");
2158                                         String helperMethod = methodNumId + "struct" + i;
2159                                         String tempVar = "struct" + methodNumId + "Size" + i;
2160                                         print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2161                                         print(tempVar + " = ___");
2162                                         println(helperMethod + "(rmiObj); break;");
2163                                 }
2164                         }
2165                 }
2166         }
2167
2168
2169         /**
2170          * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
2171          */
2172         private void writeJavaMethodPermission(String intface) {
2173
2174                 // Get all the different stubs
2175                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2176                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2177                         String newIntface = intMeth.getKey();
2178                         int newObjectId = getNewIntfaceObjectId(newIntface);
2179                         println("if (_objectId == objectId) {");
2180                         println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
2181                         println("throw new Error(\"Object with object Id: \" + _objectId + \"  is not allowed to access method: \" + methodId);");
2182                         println("}");
2183                         println("}");
2184                         println("else {");
2185                         println("continue;");
2186                         println("}");
2187                 }
2188         }
2189
2190
2191         /**
2192          * HELPER: writeFinalInputCountVarStructSkeleton() writes the final version of input counter variable of struct for skeleton
2193          */
2194         private boolean writeFinalInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
2195
2196                 List<String> methParams = intDecl.getMethodParams(method);
2197                 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2198                 boolean structExist = false;
2199                 boolean begin = true;
2200                 // Check for params with structs
2201                 for (int i = 0; i < methParams.size(); i++) {
2202                         String paramType = methPrmTypes.get(i);
2203                         String param = methParams.get(i);
2204                         String simpleType = getGenericType(paramType);
2205                         if (isStructClass(simpleType)) {
2206                                 structExist = true;
2207                                 int methodNumId = intDecl.getMethodNumId(method);
2208                                 println("final int struct" + methodNumId + "Size" + i + 
2209                                         "Final = struct" + methodNumId + "Size" + i + ";");
2210                         }
2211                 }
2212                 return structExist;
2213         }
2214
2215
2216         /**
2217          * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
2218          */
2219         private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, String intface) {
2220
2221                 // Use this set to handle two same methodIds
2222                 Set<String> uniqueMethodIds = new HashSet<String>();
2223                 println("public void ___waitRequestInvokeMethod() throws IOException {");
2224                 // Write variables here if we have callbacks or enums or structs
2225                 writeCountVarStructSkeleton(methods, intDecl);
2226                 println("didAlreadyInitWaitInvoke.compareAndSet(false, true);");
2227                 println("while (true) {");
2228                 println("if (!methodReceived.get()) {");
2229                 println("continue;");
2230                 println("}");
2231                 println("methodBytes = rmiComm.getMethodBytes();");
2232                 println("methodReceived.set(false);");
2233                 println("int _objectId = IoTRMIComm.getObjectId(methodBytes);");
2234                 println("int methodId = IoTRMIComm.getMethodId(methodBytes);");
2235                 // Generate permission check
2236                 writeJavaMethodPermission(intface);
2237                 println("switch (methodId) {");
2238                 // Print methods and method Ids
2239                 for (String method : methods) {
2240                         String methodId = intDecl.getMethodId(method);
2241                         int methodNumId = intDecl.getMethodNumId(method);
2242                         println("case " + methodNumId + ":");
2243                         // Check for stuct counters
2244                         writeFinalInputCountVarStructSkeleton(method, intDecl);
2245                         println("new Thread() {");
2246                         println("public void run() {");
2247                         println("try {");
2248                         print("___");
2249                         String helperMethod = methodId;
2250                         if (uniqueMethodIds.contains(methodId))
2251                                 helperMethod = helperMethod + methodNumId;
2252                         else
2253                                 uniqueMethodIds.add(methodId);
2254                         print(helperMethod + "(");
2255                         writeInputCountVarStructJavaSkeleton(method, intDecl);
2256                         println(");");
2257                         println("}");
2258                         println("catch (Exception ex) {");
2259                         println("ex.printStackTrace();");
2260                         println("}");
2261                         println("}");
2262                         println("}.start();");
2263                         println("break;");
2264                 }
2265                 String method = "___initCallBack()";
2266                 writeMethodCallStructJavaSkeleton(methods, intDecl);
2267                 println("default: ");
2268                 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2269                 println("}");
2270                 println("}");
2271                 println("}\n");
2272         }
2273
2274
2275         /**
2276          * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
2277          */
2278         private void writeReturnDidAlreadyInitWaitInvoke() {
2279
2280                 println("public boolean didAlreadyInitWaitInvoke() {");
2281                 println("return didAlreadyInitWaitInvoke.get();");
2282                 println("}\n");
2283         }
2284
2285
2286         /**
2287          * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
2288          */
2289         public void generateJavaSkeletonClass() throws IOException {
2290
2291                 // Create a new directory
2292                 String path = createDirectories(dir, subdir);
2293                 for (String intface : mapIntfacePTH.keySet()) {
2294                 
2295                         // Check if there is more than 1 class that uses the same interface
2296                         List<String> drvList = mapInt2Drv.get(intface);
2297                         for(int i = 0; i < drvList.size(); i++) {
2298
2299                                 // Get driver class
2300                                 String driverClass = drvList.get(i);
2301                                 // Open a new file to write into
2302                                 String newSkelClass = intface + "_Skeleton";
2303                                 String packageClass = null;
2304                                 // Check if this interface is a callback class
2305                                 if(isCallbackClass(intface)) {
2306                                         packageClass = controllerClass;
2307                                         path = createDirectories(dir + "/" + subdir, controllerClass);
2308                                 } else {
2309                                         packageClass = CODE_PREFIX + "." + driverClass;
2310                                         path = createDirectories(dir + "/" + subdir, driverClass);
2311                                 }
2312                                 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2313                                 pw = new PrintWriter(new BufferedWriter(fw));
2314                                 // Pass in set of methods and get import classes
2315                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2316                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2317                                 List<String> methods = intDecl.getMethods();
2318                                 Set<String> importClasses = getImportClasses(methods, intDecl);
2319                                 List<String> stdImportClasses = getStandardJavaImportClasses();
2320                                 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2321                                 // Find out if there are callback objects
2322                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2323                                 boolean callbackExist = !callbackClasses.isEmpty();
2324                                 println("package " + packageClass + ";\n");
2325                                 printImportStatements(allImportClasses);
2326                                 println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
2327                                 // Write class header
2328                                 println("public class " + newSkelClass  + " implements " + intface + " {\n");
2329                                 // Write properties
2330                                 writePropertiesJavaSkeleton(intface, intDecl);
2331                                 // Write constructor
2332                                 writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2333                                 // Write constructor that is called when this object is a callback object
2334                                 writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2335                                 // Write function to return didAlreadyInitWaitInvoke
2336                                 writeReturnDidAlreadyInitWaitInvoke();
2337                                 // Write methods
2338                                 writeMethodJavaSkeleton(methods, intDecl);
2339                                 // Write method helper
2340                                 writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
2341                                 // Write waitRequestInvokeMethod() - main loop
2342                                 writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
2343                                 println("}");
2344                                 pw.close();
2345                                 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
2346                         }
2347                 }
2348         }
2349
2350         
2351 /*================================================================================
2352  *
2353  *              C++ generation
2354  *
2355  *================================================================================/
2356
2357         /**
2358          * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
2359          */
2360         private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
2361
2362                 for (String method : methods) {
2363
2364                         List<String> methParams = intDecl.getMethodParams(method);
2365                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2366                         print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2367                                 intDecl.getMethodId(method) + "(");
2368                         for (int i = 0; i < methParams.size(); i++) {
2369                                 // Check for params with driver class types and exchange it 
2370                                 //              with its remote interface
2371                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2372                                 paramType = checkAndGetCplusType(paramType);
2373                                 // Check for arrays - translate into vector in C++
2374                                 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2375                                 print(paramComplete);
2376                                 // Check if this is the last element (don't print a comma)
2377                                 if (i != methParams.size() - 1) {
2378                                         print(", ");
2379                                 }
2380                         }
2381                         println(") = 0;");
2382                 }
2383         }
2384
2385
2386         /**
2387          * HELPER: writeMethodCplusInterface() writes the method of the interface
2388          */
2389         private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
2390
2391                 for (String method : methods) {
2392
2393                         List<String> methParams = intDecl.getMethodParams(method);
2394                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2395                         print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2396                                 intDecl.getMethodId(method) + "(");
2397                         for (int i = 0; i < methParams.size(); i++) {
2398                                 // Check for params with driver class types and exchange it 
2399                                 //              with its remote interface
2400                                 String paramType = methPrmTypes.get(i);
2401                                 paramType = checkAndGetCplusType(paramType);
2402                                 // Check for arrays - translate into vector in C++
2403                                 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2404                                 print(paramComplete);
2405                                 // Check if this is the last element (don't print a comma)
2406                                 if (i != methParams.size() - 1) {
2407                                         print(", ");
2408                                 }
2409                         }
2410                         println(") = 0;");
2411                 }
2412         }
2413
2414
2415         /**
2416          * HELPER: generateEnumCplus() writes the enumeration declaration
2417          */
2418         public void generateEnumCplus() throws IOException {
2419
2420                 // Create a new directory
2421                 createDirectory(dir);
2422                 String path = createDirectories(dir, VIRTUALS_DIRECTORY);
2423                 for (String intface : mapIntfacePTH.keySet()) {
2424                         // Get the right StructDecl
2425                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2426                         EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
2427                         Set<String> enumTypes = enumDecl.getEnumDeclarations();
2428                         // Iterate over enum declarations
2429                         for (String enType : enumTypes) {
2430                                 // Open a new file to write into
2431                                 FileWriter fw = new FileWriter(path + "/" + enType + ".hpp");
2432                                 pw = new PrintWriter(new BufferedWriter(fw));
2433                                 // Write file headers
2434                                 println("#ifndef _" + enType.toUpperCase() + "_HPP__");
2435                                 println("#define _" + enType.toUpperCase() + "_HPP__");
2436                                 println("enum " + enType + " {");
2437                                 List<String> enumMembers = enumDecl.getMembers(enType);
2438                                 for (int i = 0; i < enumMembers.size(); i++) {
2439
2440                                         String member = enumMembers.get(i);
2441                                         print(member);
2442                                         // Check if this is the last element (don't print a comma)
2443                                         if (i != enumMembers.size() - 1)
2444                                                 println(",");
2445                                         else
2446                                                 println("");
2447                                 }
2448                                 println("};\n");
2449                                 println("#endif");
2450                                 pw.close();
2451                                 System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
2452                         }
2453                 }
2454         }
2455
2456
2457         /**
2458          * HELPER: generateStructCplus() writes the struct declaration
2459          */
2460         public void generateStructCplus() throws IOException {
2461
2462                 // Create a new directory
2463                 createDirectory(dir);
2464                 String path = createDirectories(dir, VIRTUALS_DIRECTORY);
2465                 for (String intface : mapIntfacePTH.keySet()) {
2466                         // Get the right StructDecl
2467                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2468                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
2469                         List<String> structTypes = structDecl.getStructTypes();
2470                         // Iterate over enum declarations
2471                         for (String stType : structTypes) {
2472                                 // Open a new file to write into
2473                                 FileWriter fw = new FileWriter(path + "/" + stType + ".hpp");
2474                                 pw = new PrintWriter(new BufferedWriter(fw));
2475                                 // Write file headers
2476                                 println("#ifndef _" + stType.toUpperCase() + "_HPP__");
2477                                 println("#define _" + stType.toUpperCase() + "_HPP__");
2478                                 println("using namespace std;");
2479                                 println("struct " + stType + " {");
2480                                 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
2481                                 List<String> structMembers = structDecl.getMembers(stType);
2482                                 for (int i = 0; i < structMembers.size(); i++) {
2483
2484                                         String memberType = structMemberTypes.get(i);
2485                                         String member = structMembers.get(i);
2486                                         String structTypeC = checkAndGetCplusType(memberType);
2487                                         String structComplete = checkAndGetCplusArray(structTypeC, member);
2488                                         println(structComplete + ";");
2489                                 }
2490                                 println("};\n");
2491                                 println("#endif");
2492                                 pw.close();
2493                                 System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
2494                         }
2495                 }
2496         }
2497
2498
2499         /**
2500          * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
2501          * <p>
2502          * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
2503          * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
2504          * The local interface has to be the input parameter for the stub and the stub 
2505          * interface has to be the input parameter for the local class.
2506          */
2507         public void generateCplusLocalInterfaces() throws IOException {
2508
2509                 // Create a new directory
2510                 createDirectory(dir);
2511                 String path = createDirectories(dir, VIRTUALS_DIRECTORY);
2512                 for (String intface : mapIntfacePTH.keySet()) {
2513                         // Open a new file to write into
2514                         FileWriter fw = new FileWriter(path + "/" + intface + ".hpp");
2515                         pw = new PrintWriter(new BufferedWriter(fw));
2516                         // Write file headers
2517                         println("#ifndef _" + intface.toUpperCase() + "_HPP__");
2518                         println("#define _" + intface.toUpperCase() + "_HPP__");
2519                         println("#include <iostream>");
2520                         // Pass in set of methods and get include classes
2521                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2522                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2523                         List<String> methods = intDecl.getMethods();
2524                         Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
2525                         printIncludeStatements(includeClasses); println("");
2526                         println("using namespace std;\n");
2527                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2528                         if (!intface.equals(mainClass)) // Forward declare if not main class
2529                                 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, true);
2530                         println("class " + intface); println("{");
2531                         println("public:");
2532                         // Write methods
2533                         writeMethodCplusLocalInterface(methods, intDecl);
2534                         println("};");
2535                         println("#endif");
2536                         pw.close();
2537                         System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
2538                 }
2539         }
2540
2541
2542         /**
2543          * HELPER: writeMethodCplusInterfaceForwardDecl() writes the forward declaration of the interface
2544          */
2545         private void writeMethodCplusInterfaceForwardDecl(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, boolean needNewIntface) {
2546
2547                 Set<String> isDefined = new HashSet<String>();
2548                 for (String method : methods) {
2549
2550                         List<String> methParams = intDecl.getMethodParams(method);
2551                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2552                         for (int i = 0; i < methParams.size(); i++) {
2553                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2554                                 // Check if this has callback object
2555                                 if (callbackClasses.contains(paramType)) {
2556                                         if (!isDefined.contains(paramType)) {
2557                                                 if (needNewIntface)
2558                                                         println("class " + getStubInterface(paramType) + ";\n");
2559                                                 else
2560                                                         println("class " + paramType + ";\n");
2561                                                 isDefined.add(paramType);
2562                                         }                                               
2563                                 }
2564                         }
2565                 }
2566         }
2567
2568
2569         /**
2570          * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
2571          * <p>
2572          * For C++ we use virtual classe as interface
2573          */
2574         public void generateCPlusInterfaces() throws IOException {
2575
2576                 // Create a new directory
2577                 String path = createDirectories(dir, subdir);
2578                 path = createDirectories(dir + "/" + subdir, VIRTUALS_DIRECTORY);
2579                 for (String intface : mapIntfacePTH.keySet()) {
2580
2581                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2582                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2583
2584                                 // Open a new file to write into
2585                                 String newIntface = intMeth.getKey();
2586                                 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
2587                                 pw = new PrintWriter(new BufferedWriter(fw));
2588                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2589                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2590                                 // Write file headers
2591                                 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
2592                                 println("#define _" + newIntface.toUpperCase() + "_HPP__");
2593                                 println("#include <iostream>");
2594                                 updateIntfaceObjIdMap(intface, newIntface);
2595                                 // Pass in set of methods and get import classes
2596                                 Set<String> methods = intMeth.getValue();
2597                                 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, false);
2598                                 printIncludeStatements(includeClasses); println("");
2599                                 println("using namespace std;\n");
2600                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2601                                 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, false);
2602                                 println("class " + newIntface);
2603                                 println("{");
2604                                 println("public:");
2605                                 // Write methods
2606                                 writeMethodCplusInterface(methods, intDecl);
2607                                 println("};");
2608                                 println("#endif");
2609                                 pw.close();
2610                                 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
2611                         }
2612                 }
2613         }
2614
2615
2616         /**
2617          * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub
2618          */
2619         private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
2620
2621                 for (String method : methods) {
2622
2623                         List<String> methParams = intDecl.getMethodParams(method);
2624                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2625                         print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2626                                 intDecl.getMethodId(method) + "(");
2627                         for (int i = 0; i < methParams.size(); i++) {
2628
2629                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2630                                 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2631                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2632                                 print(methParamComplete);
2633                                 // Check if this is the last element (don't print a comma)
2634                                 if (i != methParams.size() - 1) {
2635                                         print(", ");
2636                                 }
2637                         }
2638                         println(");");
2639                 }
2640         }
2641
2642
2643         /**
2644          * HELPER: writeMethodCplusStub() writes the methods of the stub
2645          */
2646         private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
2647
2648                 for (String method : methods) {
2649
2650                         List<String> methParams = intDecl.getMethodParams(method);
2651                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2652                         // Print the mutex lock first
2653                         int methodNumId = intDecl.getMethodNumId(method);
2654                         String mutexVar = "mtx" + newStubClass + "MethodExec" + methodNumId;
2655                         println("mutex " + mutexVar + ";");
2656                         print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + newStubClass + "::" +
2657                                 intDecl.getMethodId(method) + "(");
2658                         boolean isCallbackMethod = false;
2659                         Set<String> callbackType = new HashSet<String>();
2660                         for (int i = 0; i < methParams.size(); i++) {
2661
2662                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2663                                 // Check if this has callback object
2664                                 if (callbackClasses.contains(paramType)) {
2665                                         isCallbackMethod = true;
2666                                         //callbackType = paramType;
2667                                         callbackType.add(paramType);
2668                                         // Even if there're 2 callback arguments, we expect them to be of the same interface
2669                                 }
2670                                 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2671                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2672                                 print(methParamComplete);
2673                                 // Check if this is the last element (don't print a comma)
2674                                 if (i != methParams.size() - 1) {
2675                                         print(", ");
2676                                 }
2677                         }
2678                         println(") { ");
2679                         println("lock_guard<mutex> guard(" + mutexVar + ");");
2680                         if (isCallbackMethod)
2681                                 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
2682                         writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType, isCallbackMethod);
2683                         println("}\n");
2684
2685                 }
2686         }
2687
2688
2689         /**
2690          * HELPER: writeCallbackInstantiationMethodBodyCplusStub() writes the callback object instantiation in the method of the stub class
2691          */
2692         private void writeCallbackInstantiationMethodBodyCplusStub(String paramIdent, String callbackType, int counter) {
2693
2694                 println("auto it" + counter + " = IoTRMIUtil::mapSkel->find(" + paramIdent + ");");
2695                 println("if (it" + counter + " == IoTRMIUtil::mapSkel->end()) {");
2696                 println("int newObjIdSent = rmiComm->getObjectIdCounter();");
2697                 println("objIdSent" + counter + ".push_back(newObjIdSent);");
2698                 println("rmiComm->decrementObjectIdCounter();");
2699                 println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
2700                 println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel" + counter + "));");
2701                 println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));");
2702                 println("thread th" + counter + " (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, skel" + counter + 
2703                         ", skel" + counter +");");
2704                 println("th" + counter + ".detach();");
2705                 println("while(!skel" + counter + "->didInitWaitInvoke());");
2706                 println("}");
2707                 println("else");
2708                 println("{");
2709                 println("auto itId = IoTRMIUtil::mapSkelId->find(" + paramIdent + ");");
2710                 println("objIdSent" + counter + ".push_back(itId->second);");
2711                 println("}");
2712         }
2713
2714
2715         /**
2716          * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
2717          */
2718         private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2719                         List<String> methPrmTypes, String method, Set<String> callbackType) {
2720
2721                 // Check if this is single object, array, or list of objects
2722                 boolean isArrayOrList = false;
2723                 String callbackParam = null;
2724                 for (int i = 0; i < methParams.size(); i++) {
2725                         String paramType = methPrmTypes.get(i);
2726                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2727                                 println("vector<int> objIdSent" + i + ";");
2728                                 String param = methParams.get(i);
2729                                 if (isArrayOrList(paramType, param)) {  // Generate loop                                
2730                                         println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
2731                                         writeCallbackInstantiationMethodBodyCplusStub("cb", returnGenericCallbackType(paramType), i);
2732                                         isArrayOrList = true;
2733                                         callbackParam = getSimpleIdentifier(param);
2734                                 } else {
2735                                         writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i);
2736                                 }
2737                                 if (isArrayOrList)
2738                                         println("}");
2739                                 println("vector<int> ___paramCB" + i + " = objIdSent" + i + ";");
2740                         }
2741                 }
2742         }
2743
2744
2745         /**
2746          * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
2747          */
2748         private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
2749
2750                 // Iterate and find enum declarations
2751                 for (int i = 0; i < methParams.size(); i++) {
2752                         String paramType = methPrmTypes.get(i);
2753                         String param = methParams.get(i);
2754                         if (isEnumClass(getGenericType(paramType))) {
2755                         // Check if this is enum type
2756                                 if (isArrayOrList(paramType, param)) {  // An array or vector
2757                                         println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
2758                                         println("vector<int> paramEnum" + i + "(len" + i + ");");
2759                                         println("for (int i = 0; i < len" + i + "; i++) {");
2760                                         println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
2761                                         println("}");
2762                                 } else {        // Just one element
2763                                         println("vector<int> paramEnum" + i + "(1);");
2764                                         println("paramEnum" + i + "[0] = (int) " + param + ";");
2765                                 }
2766                         }
2767                 }
2768         }
2769
2770
2771         /**
2772          * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
2773          */
2774         private void checkAndWriteEnumRetTypeCplusStub(String retType, String method, InterfaceDecl intDecl) {
2775
2776                 // Strips off array "[]" for return type
2777                 String pureType = getSimpleArrayType(getGenericType(retType));
2778                 // Take the inner type of generic
2779                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2780                         pureType = getGenericType(retType);
2781                 if (isEnumClass(pureType)) {
2782                 // Check if this is enum type
2783                         println("vector<int> retEnumInt;");
2784                         println("void* retObj = &retEnumInt;");
2785                         println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2786                         writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
2787                         if (isArrayOrList(retType, retType)) {  // An array or vector
2788                                 println("int retLen = retEnumInt.size();");
2789                                 println("vector<" + pureType + "> retVal(retLen);");
2790                                 println("for (int i = 0; i < retLen; i++) {");
2791                                 println("retVal[i] = (" + pureType + ") retEnumInt[i];");
2792                                 println("}");
2793                         } else {        // Just one element
2794                                 println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
2795                         }
2796                         println("return retVal;");
2797                 }
2798         }
2799
2800
2801         /**
2802          * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
2803          */
2804         private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes, 
2805                         InterfaceDecl intDecl, String method) {
2806                 
2807                 // Iterate and find struct declarations
2808                 for (int i = 0; i < methParams.size(); i++) {
2809                         String paramType = methPrmTypes.get(i);
2810                         String param = methParams.get(i);
2811                         String simpleType = getGenericType(paramType);
2812                         if (isStructClass(simpleType)) {
2813                         // Check if this is enum type
2814                                 println("int numParam" + i + " = 1;");
2815                                 int methodNumId = intDecl.getMethodNumId(method);
2816                                 String helperMethod = methodNumId + "struct" + i;
2817                                 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
2818                                 //println("string retTypeStruct" + i + " = \"void\";");
2819                                 println("string paramClsStruct" + i + "[] = { \"int\" };");
2820                                 print("int structLen" + i + " = ");
2821                                 if (isArrayOrList(paramType, param)) {  // An array
2822                                         println(getSimpleArrayType(param) + ".size();");
2823                                 } else {        // Just one element
2824                                         println("1;");
2825                                 }
2826                                 println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
2827                                 println("rmiComm->remoteCall(objectId, methodIdStruct" + i + 
2828                                                 ", paramClsStruct" + i + ", paramObjStruct" + i + 
2829                                                 ", numParam" + i + ");\n");
2830                         }
2831                 }
2832         }
2833
2834
2835         /**
2836          * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
2837          */
2838         private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2839
2840                 // Iterate and find struct declarations - count number of params
2841                 for (int i = 0; i < methParams.size(); i++) {
2842                         String paramType = methPrmTypes.get(i);
2843                         String param = methParams.get(i);
2844                         String simpleType = getGenericType(paramType);
2845                         if (isStructClass(simpleType)) {
2846                                 int members = getNumOfMembers(simpleType);
2847                                 if (isArrayOrList(paramType, param)) {  // An array or list
2848                                         String structLen = getSimpleIdentifier(param) + ".size()";
2849                                         print(members + "*" + structLen);
2850                                 } else
2851                                         print(Integer.toString(members));
2852                         } else
2853                                 print("1");
2854                         if (i != methParams.size() - 1) {
2855                                 print("+");
2856                         }
2857                 }
2858         }
2859
2860
2861         /**
2862          * HELPER: writeStructMembersCplusStub() writes member parameters of struct
2863          */
2864         private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
2865
2866                 // Get the struct declaration for this struct and generate initialization code
2867                 StructDecl structDecl = getStructDecl(simpleType);
2868                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2869                 List<String> members = structDecl.getMembers(simpleType);
2870                 if (isArrayOrList(paramType, param)) {  // An array or list
2871                         println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
2872                 }
2873                 if (isArrayOrList(paramType, param)) {  // An array or list
2874                         for (int i = 0; i < members.size(); i++) {
2875                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2876                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
2877                                 print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
2878                                 print(getSimpleIdentifier(members.get(i)));
2879                                 println(";");
2880                         }
2881                         println("}");
2882                 } else {        // Just one struct element
2883                         for (int i = 0; i < members.size(); i++) {
2884                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2885                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
2886                                 print("paramObj[pos++] = &" + param + ".");
2887                                 print(getSimpleIdentifier(members.get(i)));
2888                                 println(";");
2889                         }
2890                 }
2891         }
2892
2893
2894         /**
2895          * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
2896          */
2897         private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
2898
2899                 print("int numParam = ");
2900                 writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
2901                 println(";");
2902                 println("void* paramObj[numParam];");
2903                 println("string paramCls[numParam];");
2904                 println("int pos = 0;");
2905                 // Iterate again over the parameters
2906                 for (int i = 0; i < methParams.size(); i++) {
2907                         String paramType = methPrmTypes.get(i);
2908                         String param = methParams.get(i);
2909                         String simpleType = getGenericType(paramType);
2910                         if (isStructClass(simpleType)) {
2911                                 writeStructMembersCplusStub(simpleType, paramType, param);
2912                         } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2913                                 println("paramCls[pos] = \"int\";");
2914                                 println("paramObj[pos++] = &___paramCB" + i + ";");
2915                         } else {
2916                                 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2917                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
2918                                 print("paramObj[pos++] = &");
2919                                 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2920                                 println(";");
2921                         }
2922                 }
2923                 
2924         }
2925
2926
2927         /**
2928          * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
2929          */
2930         private void writeStructRetMembersCplusStub(String simpleType, String retType) {
2931
2932                 // Get the struct declaration for this struct and generate initialization code
2933                 StructDecl structDecl = getStructDecl(simpleType);