Extending the compiler to include the case where we can have multiple driver classes...
[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          * getMethodsForIntface() reads for methods in the data structure
184          * <p>
185          * It is going to give list of methods for a certain interface
186          *              based on the declaration of capabilities.
187          */
188         public void getMethodsForIntface(String origInt) {
189
190                 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
191                 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
192                 // Get set of new interfaces, e.g. CameraWithCaptureAndData
193                 // Generate this new interface with all the methods it needs
194                 //              from different capabilities it declares
195                 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
196                 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
197                 Set<String> setIntfaces = reqDecl.getInterfaces();
198                 for (String strInt : setIntfaces) {
199
200                         // Initialize a set of methods
201                         Set<String> setMethods = new HashSet<String>();
202                         // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
203                         List<String> listCapab = reqDecl.getCapabList(strInt);
204                         for (String strCap : listCapab) {
205
206                                 // Get list of methods for each capability
207                                 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
208                                 List<String> listCapabMeth = capDecl.getMethods(strCap);
209                                 for (String strMeth : listCapabMeth) {
210
211                                         // Add methods into setMethods
212                                         // This is to also handle redundancies (say two capabilities
213                                         //              share the same methods)
214                                         setMethods.add(strMeth);
215                                 }
216                         }
217                         // Add interface and methods information into map
218                         mapNewIntMethods.put(strInt, setMethods);
219                         // Map new interface method name to the original interface
220                         // TODO: perhaps need to check in the future if we have more than 1 stub interface for one original interface
221                         mapInt2NewIntName.put(origInt, strInt);
222                         if (mainClass == null)  // Take the first class as the main class (whichever is placed first in the order of compilation files)
223                                 mainClass = origInt;
224                 }
225                 // Map the map of interface-methods to the original interface
226                 mapInt2NewInts.put(origInt, mapNewIntMethods);
227         }
228
229         
230 /*================
231  * Java generation
232  *================/
233
234         /**
235          * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface
236          */
237         private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
238
239                 for (String method : methods) {
240
241                         List<String> methParams = intDecl.getMethodParams(method);
242                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
243                         print("public " + intDecl.getMethodType(method) + " " +
244                                 intDecl.getMethodId(method) + "(");
245                         for (int i = 0; i < methParams.size(); i++) {
246                                 // Check for params with driver class types and exchange it 
247                                 //              with its remote interface
248                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
249                                 print(paramType + " " + methParams.get(i));
250                                 // Check if this is the last element (don't print a comma)
251                                 if (i != methParams.size() - 1) {
252                                         print(", ");
253                                 }
254                         }
255                         println(");");
256                 }
257         }
258
259
260         /**
261          * HELPER: writeMethodJavaInterface() writes the method of the interface
262          */
263         private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
264
265                 for (String method : methods) {
266
267                         List<String> methParams = intDecl.getMethodParams(method);
268                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
269                         print("public " + intDecl.getMethodType(method) + " " +
270                                 intDecl.getMethodId(method) + "(");
271                         for (int i = 0; i < methParams.size(); i++) {
272                                 // Check for params with driver class types and exchange it 
273                                 //              with its remote interface
274                                 String paramType = methPrmTypes.get(i);
275                                 print(paramType + " " + methParams.get(i));
276                                 // Check if this is the last element (don't print a comma)
277                                 if (i != methParams.size() - 1) {
278                                         print(", ");
279                                 }
280                         }
281                         println(");");
282                 }
283         }
284
285
286         /**
287          * HELPER: generateEnumJava() writes the enumeration declaration
288          */
289         private void generateEnumJava() throws IOException {
290
291                 // Create a new directory
292                 createDirectory(dir);
293                 String path = createDirectories(dir, INTERFACES_DIRECTORY);
294                 for (String intface : mapIntfacePTH.keySet()) {
295                         // Get the right EnumDecl
296                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
297                         EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
298                         Set<String> enumTypes = enumDecl.getEnumDeclarations();
299                         // Iterate over enum declarations
300                         for (String enType : enumTypes) {
301                                 // Open a new file to write into
302                                 FileWriter fw = new FileWriter(path + "/" + enType + ".java");
303                                 pw = new PrintWriter(new BufferedWriter(fw));
304                                 println("package " + INTERFACE_PACKAGE + ";\n");
305                                 println("public enum " + enType + " {");
306                                 List<String> enumMembers = enumDecl.getMembers(enType);
307                                 for (int i = 0; i < enumMembers.size(); i++) {
308
309                                         String member = enumMembers.get(i);
310                                         print(member);
311                                         // Check if this is the last element (don't print a comma)
312                                         if (i != enumMembers.size() - 1)
313                                                 println(",");
314                                         else
315                                                 println("");
316                                 }
317                                 println("}\n");
318                                 pw.close();
319                                 System.out.println("IoTCompiler: Generated enum class " + enType + ".java...");
320                         }
321                 }
322         }
323
324
325         /**
326          * HELPER: generateStructJava() writes the struct declaration
327          */
328         private void generateStructJava() throws IOException {
329
330                 // Create a new directory
331                 createDirectory(dir);
332                 String path = createDirectories(dir, INTERFACES_DIRECTORY);
333                 for (String intface : mapIntfacePTH.keySet()) {
334                         // Get the right StructDecl
335                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
336                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
337                         List<String> structTypes = structDecl.getStructTypes();
338                         // Iterate over enum declarations
339                         for (String stType : structTypes) {
340                                 // Open a new file to write into
341                                 FileWriter fw = new FileWriter(path + "/" + stType + ".java");
342                                 pw = new PrintWriter(new BufferedWriter(fw));
343                                 println("package " + INTERFACE_PACKAGE + ";\n");
344                                 println("public class " + stType + " {");
345                                 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
346                                 List<String> structMembers = structDecl.getMembers(stType);
347                                 for (int i = 0; i < structMembers.size(); i++) {
348
349                                         String memberType = structMemberTypes.get(i);
350                                         String member = structMembers.get(i);
351                                         println("public static " + memberType + " " + member + ";");
352                                 }
353                                 println("}\n");
354                                 pw.close();
355                                 System.out.println("IoTCompiler: Generated struct class " + stType + ".java...");
356                         }
357                 }
358         }
359
360
361         /**
362          * generateJavaLocalInterface() writes the local interface and provides type-checking.
363          * <p>
364          * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
365          * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
366          * The local interface has to be the input parameter for the stub and the stub 
367          * interface has to be the input parameter for the local class.
368          */
369         public void generateJavaLocalInterfaces() throws IOException {
370
371                 // Create a new directory
372                 createDirectory(dir);
373                 String path = createDirectories(dir, INTERFACES_DIRECTORY);
374                 for (String intface : mapIntfacePTH.keySet()) {
375                         // Open a new file to write into
376                         FileWriter fw = new FileWriter(path + "/" + intface + ".java");
377                         pw = new PrintWriter(new BufferedWriter(fw));
378                         // Pass in set of methods and get import classes
379                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
380                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
381                         List<String> methods = intDecl.getMethods();
382                         Set<String> importClasses = getImportClasses(methods, intDecl);
383                         List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
384                         List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
385                         println("package " + INTERFACE_PACKAGE + ";\n");
386                         printImportStatements(allImportClasses);
387                         // Write interface header
388                         println("");
389                         println("public interface " + intface + " {");
390                         // Write methods
391                         writeMethodJavaLocalInterface(methods, intDecl);
392                         println("}");
393                         pw.close();
394                         System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
395                 }
396         }
397
398
399         /**
400          * HELPER: updateIntfaceObjIdMap() updates the mapping between new interface and object Id
401          */
402         private void updateIntfaceObjIdMap(String intface, String newIntface) {
403
404                 // We are assuming that we only generate one stub per one skeleton at this point @Feb 2017
405                 Integer objId = mapIntfaceObjId.get(intface);
406                 mapNewIntfaceObjId.put(newIntface, objId);
407         }
408
409
410         /**
411          * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
412          */
413         public void generateJavaInterfaces() throws IOException {
414
415                 // Create a new directory
416                 String path = createDirectories(dir, subdir);
417                 path = createDirectories(dir + "/" + subdir, INTERFACES_DIRECTORY);
418                 for (String intface : mapIntfacePTH.keySet()) {
419
420                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
421                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
422
423                                 // Open a new file to write into
424                                 String newIntface = intMeth.getKey();
425                                 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
426                                 pw = new PrintWriter(new BufferedWriter(fw));
427                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
428                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
429                                 // Pass in set of methods and get import classes
430                                 Set<String> methods = intMeth.getValue();
431                                 Set<String> importClasses = getImportClasses(methods, intDecl);
432                                 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
433                                 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
434                         println("package " + INTERFACE_PACKAGE + ";\n");
435                                 printImportStatements(allImportClasses);
436                                 // Write interface header
437                                 println("");
438                                 println("public interface " + newIntface + " {\n");
439                                 updateIntfaceObjIdMap(intface, newIntface);
440                                 // Write methods
441                                 writeMethodJavaInterface(methods, intDecl);
442                                 println("}");
443                                 pw.close();
444                                 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
445                         }
446                 }
447         }
448
449
450         /**
451          * HELPER: writePropertiesJavaPermission() writes the permission in properties
452          */
453         private void writePropertiesJavaPermission(String intface, InterfaceDecl intDecl) {
454
455                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
456                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
457                         String newIntface = intMeth.getKey();
458                         int newObjectId = getNewIntfaceObjectId(newIntface);
459                         Set<String> methodIds = intMeth.getValue();
460                         print("private static Integer[] object" + newObjectId + "Permission = { ");
461                         int i = 0;
462                         for (String methodId : methodIds) {
463                                 int methodNumId = intDecl.getMethodNumId(methodId);
464                                 print(Integer.toString(methodNumId));
465                                 // Check if this is the last element (don't print a comma)
466                                 if (i != methodIds.size() - 1) {
467                                         print(", ");
468                                 }
469                                 i++;
470                         }
471                         println(" };");
472                         println("private static List<Integer> set" + newObjectId + "Allowed;");
473                 }
474         }
475
476
477         /**
478          * HELPER: writePropertiesJavaStub() writes the properties of the stub class
479          */
480         private void writePropertiesJavaStub(String intface, Set<String> methods, InterfaceDecl intDecl) {
481
482                 // Get the object Id
483                 Integer objId = mapIntfaceObjId.get(intface);
484                 println("private int objectId = " + objId + ";");
485                 println("private IoTRMIComm rmiComm;");
486                 // Write the list of AtomicBoolean variables
487                 println("// Synchronization variables");
488                 for (String method : methods) {
489                         // Generate AtomicBooleans for methods that have return values
490                         String returnType = intDecl.getMethodType(method);
491                         int methodNumId = intDecl.getMethodNumId(method);
492                         if (!returnType.equals("void")) {
493                                 println("private AtomicBoolean retValueReceived" + methodNumId + " = new AtomicBoolean(false);");
494                         }
495                 }
496                 println("\n");
497         }
498
499
500         /**
501          * HELPER: writeConstructorJavaPermission() writes the permission in constructor
502          */
503         private void writeConstructorJavaPermission(String intface) {
504
505                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
506                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
507                         String newIntface = intMeth.getKey();
508                         int newObjectId = getNewIntfaceObjectId(newIntface);
509                         println("set" + newObjectId + "Allowed = new ArrayList<Integer>(Arrays.asList(object" + newObjectId +"Permission));");
510                 }
511         }
512
513
514         /**
515          * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
516          */
517         private void writeConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
518
519                 println("public " + newStubClass + "(int _localPortSend, int _localPortRecv, int _portSend, int _portRecv, String _skeletonAddress, int _rev) throws Exception {");
520                 println("if (_localPortSend != 0 && _localPortRecv != 0) {");
521                 println("rmiComm = new IoTRMICommClient(_localPortSend, _localPortRecv, _portSend, _portRecv, _skeletonAddress, _rev);");
522                 println("} else");
523                 println("{");
524                 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev);");
525                 println("}");
526                 // Register the AtomicBoolean variables
527                 for (String method : methods) {
528                         // Generate AtomicBooleans for methods that have return values
529                         String returnType = intDecl.getMethodType(method);
530                         int methodNumId = intDecl.getMethodNumId(method);
531                         if (!returnType.equals("void")) {
532                                 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
533                         }
534                 }
535                 println("IoTRMIUtil.mapStub.put(objectId, this);");
536                 println("}\n");
537         }
538
539
540         /**
541          * HELPER: writeCallbackConstructorJavaStub() writes the callback constructor of the stub class
542          */
543         private void writeCallbackConstructorJavaStub(String intface, String newStubClass, Set<String> methods, InterfaceDecl intDecl) {
544
545                 println("public " + newStubClass + "(IoTRMIComm _rmiComm, int _objectId) throws Exception {");
546                 println("rmiComm = _rmiComm;");
547                 println("objectId = _objectId;");
548                 // Register the AtomicBoolean variables
549                 for (String method : methods) {
550                         // Generate AtomicBooleans for methods that have return values
551                         String returnType = intDecl.getMethodType(method);
552                         int methodNumId = intDecl.getMethodNumId(method);
553                         if (!returnType.equals("void")) {
554                                 println("rmiComm.registerStub(objectId, " + methodNumId + ", retValueReceived" + methodNumId + ");");
555                         }
556                 }
557                 println("}\n");
558         }
559
560
561         /**
562          * HELPER: getPortCount() gets port count for different stubs and skeletons
563          */
564         private int getPortCount(String intface) {
565
566                 if (!mapPortCount.containsKey(intface))
567                         mapPortCount.put(intface, portCount++);
568                 return mapPortCount.get(intface);
569         }
570
571
572         /**
573          * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int)
574          */
575         private void checkAndWriteEnumTypeJavaStub(List<String> methParams, List<String> methPrmTypes) {
576
577                 // Iterate and find enum declarations
578                 for (int i = 0; i < methParams.size(); i++) {
579                         String paramType = methPrmTypes.get(i);
580                         String param = methParams.get(i);
581                         String simpleType = getGenericType(paramType);
582                         if (isEnumClass(simpleType)) {
583                         // Check if this is enum type
584                                 if (isArray(param)) {   // An array
585                                         println("int len" + i + " = " + getSimpleIdentifier(param) + ".length;");
586                                         println("int paramEnum" + i + "[] = new int[len" + i + "];");
587                                         println("for (int i = 0; i < len" + i + "; i++) {");
588                                         println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + "[i].ordinal();");
589                                         println("}");
590                                 } else if (isList(paramType)) { // A list
591                                         println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
592                                         println("int paramEnum" + i + "[] = new int[len" + i + "];");
593                                         println("for (int i = 0; i < len" + i + "; i++) {");
594                                         println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + ".get(i).ordinal();");
595                                         println("}");
596                                 } else {        // Just one element
597                                         println("int paramEnum" + i + "[] = new int[1];");
598                                         println("paramEnum" + i + "[0] = " + param + ".ordinal();");
599                                 }
600                         }
601                 }
602         }
603
604
605         /**
606          * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int)
607          */
608         private void checkAndWriteEnumRetTypeJavaStub(String retType, String method, InterfaceDecl intDecl) {
609
610                 // Write the wait-for-return-value part
611                 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
612                 // Strips off array "[]" for return type
613                 String pureType = getSimpleArrayType(getGenericType(retType));
614                 // Take the inner type of generic
615                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
616                         pureType = getGenericType(retType);
617                 if (isEnumClass(pureType)) {
618                 // Check if this is enum type
619                         // Enum decoder
620                         println("int[] retEnum = (int[]) retObj;");
621                         println(pureType + "[] enumVals = " + pureType + ".values();");
622                         if (isArray(retType)) {                 // An array
623                                 println("int retLen = retEnum.length;");
624                                 println(pureType + "[] enumRetVal = new " + pureType + "[retLen];");
625                                 println("for (int i = 0; i < retLen; i++) {");
626                                 println("enumRetVal[i] = enumVals[retEnum[i]];");
627                                 println("}");
628                         } else if (isList(retType)) {   // A list
629                                 println("int retLen = retEnum.length;");
630                                 println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();");
631                                 println("for (int i = 0; i < retLen; i++) {");
632                                 println("enumRetVal.add(enumVals[retEnum[i]]);");
633                                 println("}");
634                         } else {        // Just one element
635                                 println(pureType + " enumRetVal = enumVals[retEnum[0]];");
636                         }
637                         println("return enumRetVal;");
638                 }
639         }
640
641
642         /**
643          * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup
644          */
645         private void checkAndWriteStructSetupJavaStub(List<String> methParams, List<String> methPrmTypes, 
646                         InterfaceDecl intDecl, String method) {
647                 
648                 // Iterate and find struct declarations
649                 for (int i = 0; i < methParams.size(); i++) {
650                         String paramType = methPrmTypes.get(i);
651                         String param = methParams.get(i);
652                         String simpleType = getGenericType(paramType);
653                         if (isStructClass(simpleType)) {
654                         // Check if this is enum type
655                                 int methodNumId = intDecl.getMethodNumId(method);
656                                 String helperMethod = methodNumId + "struct" + i;
657                                 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
658                                 println("Class<?>[] paramClsStruct" + i + " = new Class<?>[] { int.class };");
659                                 if (isArray(param)) {   // An array
660                                         println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };");
661                                 } else if (isList(paramType)) { // A list
662                                         println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };");
663                                 } else {        // Just one element
664                                         println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };");
665                                 }
666                                 println("rmiComm.remoteCall(objectId, methodIdStruct" + i + 
667                                                 ", paramClsStruct" + i + ", paramObjStruct" + i + ");\n");
668                         }
669                 }
670         }
671
672
673         /**
674          * HELPER: isStructPresent() checks presence of struct
675          */
676         private boolean isStructPresent(List<String> methParams, List<String> methPrmTypes) {
677
678                 // Iterate and find enum declarations
679                 for (int i = 0; i < methParams.size(); i++) {
680                         String paramType = methPrmTypes.get(i);
681                         String param = methParams.get(i);
682                         String simpleType = getGenericType(paramType);
683                         if (isStructClass(simpleType))
684                                 return true;
685                 }
686                 return false;
687         }
688
689
690         /**
691          * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters
692          */
693         private void writeLengthStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
694
695                 // Iterate and find struct declarations - count number of params
696                 for (int i = 0; i < methParams.size(); i++) {
697                         String paramType = methPrmTypes.get(i);
698                         String param = methParams.get(i);
699                         String simpleType = getGenericType(paramType);
700                         if (isStructClass(simpleType)) {
701                                 int members = getNumOfMembers(simpleType);
702                                 if (isArray(param)) {                   // An array
703                                         String structLen = getSimpleArrayType(param) + ".length";
704                                         print(members + "*" + structLen);
705                                 } else if (isList(paramType)) { // A list
706                                         String structLen = getSimpleArrayType(param) + ".size()";
707                                         print(members + "*" + structLen);
708                                 } else
709                                         print(Integer.toString(members));
710                         } else
711                                 print("1");
712                         if (i != methParams.size() - 1) {
713                                 print("+");
714                         }
715                 }
716         }
717
718
719         /**
720          * HELPER: writeStructMembersJavaStub() writes parameters of struct
721          */
722         private void writeStructMembersJavaStub(String simpleType, String paramType, String param) {
723
724                 // Get the struct declaration for this struct and generate initialization code
725                 StructDecl structDecl = getStructDecl(simpleType);
726                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
727                 List<String> members = structDecl.getMembers(simpleType);
728                 if (isArray(param)) {                   // An array
729                         println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".length; i++) {");
730                         for (int i = 0; i < members.size(); i++) {
731                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
732                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
733                                 print("paramObj[pos++] = " + getSimpleIdentifier(param) + "[i].");
734                                 print(getSimpleIdentifier(members.get(i)));
735                                 println(";");
736                         }
737                         println("}");
738                 } else if (isList(paramType)) { // A list
739                         println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
740                         for (int i = 0; i < members.size(); i++) {
741                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
742                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
743                                 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".get(i).");
744                                 print(getSimpleIdentifier(members.get(i)));
745                                 println(";");
746                         }
747                         println("}");
748                 } else {        // Just one struct element
749                         for (int i = 0; i < members.size(); i++) {
750                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
751                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
752                                 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".");
753                                 print(getSimpleIdentifier(members.get(i)));
754                                 println(";");
755                         }
756                 }
757         }
758
759
760         /**
761          * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
762          */
763         private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
764
765                 print("int paramLen = ");
766                 writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
767                 println(";");
768                 println("Object[] paramObj = new Object[paramLen];");
769                 println("Class<?>[] paramCls = new Class<?>[paramLen];");
770                 println("int pos = 0;");
771                 // Iterate again over the parameters
772                 for (int i = 0; i < methParams.size(); i++) {
773                         String paramType = methPrmTypes.get(i);
774                         String param = methParams.get(i);
775                         String simpleType = getGenericType(paramType);
776                         if (isStructClass(simpleType)) {
777                                 writeStructMembersJavaStub(simpleType, paramType, param);
778                         } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
779                                 println("paramCls[pos] = int[].class;");
780                                 println("paramObj[pos++] = objIdSent" + i + ";");
781                         } else {
782                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
783                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
784                                 print("paramObj[pos++] = ");
785                                 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
786                                 println(";");
787                         }
788                 }
789                 
790         }
791
792
793         /**
794          * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
795          */
796         private void writeStructRetMembersJavaStub(String simpleType, String retType) {
797
798                 // Get the struct declaration for this struct and generate initialization code
799                 StructDecl structDecl = getStructDecl(simpleType);
800                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
801                 List<String> members = structDecl.getMembers(simpleType);
802                 if (isArrayOrList(retType, retType)) {  // An array or list
803                         println("for(int i = 0; i < retLen; i++) {");
804                 }
805                 if (isArray(retType)) { // An array
806                         for (int i = 0; i < members.size(); i++) {
807                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
808                                 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
809                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
810                         }
811                         println("}");
812                 } else if (isList(retType)) {   // A list
813                         println(simpleType + " structRetMem = new " + simpleType + "();");
814                         for (int i = 0; i < members.size(); i++) {
815                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
816                                 print("structRetMem." + getSimpleIdentifier(members.get(i)));
817                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
818                         }
819                         println("structRet.add(structRetMem);");
820                         println("}");
821                 } else {        // Just one struct element
822                         for (int i = 0; i < members.size(); i++) {
823                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
824                                 print("structRet." + getSimpleIdentifier(members.get(i)));
825                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retActualObj[retObjPos++];");
826                         }
827                 }
828                 println("return structRet;");
829         }
830
831
832         /**
833          * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
834          */
835         private void writeStructReturnJavaStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
836
837                 // Handle the returned struct size
838                 writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
839                 // Minimum retLen is 1 if this is a single struct object
840                 println("int retLen = (int) retObj;");
841                 int numMem = getNumOfMembers(simpleType);
842                 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
843                 println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
844                 println("int retPos = 0;");
845                 // Get the struct declaration for this struct and generate initialization code
846                 StructDecl structDecl = getStructDecl(simpleType);
847                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
848                 List<String> members = structDecl.getMembers(simpleType);
849                 if (isArrayOrList(retType, retType)) {  // An array or list
850                         println("for(int i = 0; i < retLen; i++) {");
851                         for (int i = 0; i < members.size(); i++) {
852                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
853                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
854                                 println("retClsVal[retPos++] = null;");
855                         }
856                         println("}");
857                 } else {        // Just one struct element
858                         for (int i = 0; i < members.size(); i++) {
859                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
860                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
861                                 println("retClsVal[retPos++] = null;");
862                         }
863                 }
864                 // Handle the actual returned struct
865                 writeWaitForReturnValueJava(method, intDecl, "Object[] retActualObj = rmiComm.getStructObjects(retCls, retClsVal);");
866                 if (isArray(retType)) {                 // An array
867                         println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
868                         println("for(int i = 0; i < retLen; i++) {");
869                         println("structRet[i] = new " + simpleType + "();");
870                         println("}");
871                 } else if (isList(retType)) {   // A list
872                         println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
873                 } else
874                         println(simpleType + " structRet = new " + simpleType + "();");
875                 println("int retObjPos = 0;");
876                 writeStructRetMembersJavaStub(simpleType, retType);
877         }
878
879
880         /**
881          * HELPER: writeWaitForReturnValueJava() writes the synchronization part for return values
882          */
883         private void writeWaitForReturnValueJava(String method, InterfaceDecl intDecl, String getReturnValue) {
884
885                 println("// Waiting for return value");         
886                 int methodNumId = intDecl.getMethodNumId(method);
887                 println("while (!retValueReceived" + methodNumId + ".get());");
888                 println(getReturnValue);
889                 println("retValueReceived" + methodNumId + ".set(false);");
890                 println("rmiComm.setGetReturnBytes();\n");
891         }
892
893
894         /**
895          * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
896          */
897         private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
898                         List<String> methPrmTypes, String method, Set<String> callbackType) {
899
900                 checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
901                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
902                 String retType = intDecl.getMethodType(method);
903                 println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
904                 checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
905                 // Generate array of parameter types
906                 if (isStructPresent(methParams, methPrmTypes)) {
907                         writeStructParamClassJavaStub(methParams, methPrmTypes, callbackType);
908                 } else {
909                         print("Class<?>[] paramCls = new Class<?>[] { ");
910                         for (int i = 0; i < methParams.size(); i++) {
911                                 String prmType = methPrmTypes.get(i);
912                                 if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object
913                                         print("int[].class");
914                                 } else { // Generate normal classes if it's not a callback object
915                                         String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
916                                         print(getSimpleType(getEnumType(paramType)) + ".class");
917                                 }
918                                 // Check if this is the last element (don't print a comma)
919                                 if (i != methParams.size() - 1) {
920                                         print(", ");
921                                 }
922                         }
923                         println(" };");
924                         // Generate array of parameter objects
925                         print("Object[] paramObj = new Object[] { ");
926                         for (int i = 0; i < methParams.size(); i++) {
927                                 String paramType = methPrmTypes.get(i);
928                                 if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
929                                         print("objIdSent" + i);
930                                 } else
931                                         print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
932                                 // Check if this is the last element (don't print a comma)
933                                 if (i != methParams.size() - 1) {
934                                         print(", ");
935                                 }
936                         }
937                         println(" };");
938                 }
939                 // Send method call first and wait for return value separately
940                 println("rmiComm.remoteCall(objectId, methodId, paramCls, paramObj);");
941                 // Check if this is "void"
942                 if (!retType.equals("void")) { // We do have a return value
943                         // Generate array of parameter types
944                         if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
945                                 writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
946                         } else {
947                                 // This is an enum type
948                                 if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) {
949                                         //println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
950                                         checkAndWriteEnumRetTypeJavaStub(retType, method, intDecl);
951                                 } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
952                                 // Check if the return value NONPRIMITIVES
953                                         String retGenValType = getGenericType(retType);
954                                         println("Class<?> retGenValType = " + retGenValType + ".class;");
955                                         writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, retGenValType);");
956                                         println("return (" + retType + ")retObj;");
957                                 } else {
958                                         writeWaitForReturnValueJava(method, intDecl, "Object retObj = rmiComm.getReturnValue(retType, null);");
959                                         println("return (" + retType + ")retObj;");
960                                 }
961                         }
962                 }
963         }
964
965
966         /**
967          * HELPER: returnGenericCallbackType() returns the callback type
968          */
969         private String returnGenericCallbackType(String paramType) {
970
971                 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
972                         return getGenericType(paramType);
973                 else
974                         return paramType;
975         }
976
977
978         /**
979          * HELPER: checkCallbackType() checks the callback type
980          */
981         private boolean checkCallbackType(String paramType, Set<String> callbackType) {
982
983                 String prmType = returnGenericCallbackType(paramType);
984                 if (callbackType == null)       // If there is no callbackType it means not a callback method
985                         return false;
986                 else {
987                         for (String type : callbackType) {
988                                 if (type.equals(prmType))
989                                         return true;    // Check callbackType one by one
990                         }
991                         return false;
992                 }
993         }
994
995
996         /**
997          * HELPER: checkCallbackType() checks the callback type
998          */
999         private boolean checkCallbackType(String paramType, String callbackType) {
1000
1001                 String prmType = returnGenericCallbackType(paramType);
1002                 if (callbackType == null)       // If there is no callbackType it means not a callback method
1003                         return false;
1004                 else
1005                         return callbackType.equals(prmType);
1006         }
1007
1008
1009         /**
1010          * HELPER: writeCallbackInstantiationMethodBodyJavaStub() writes the callback object instantiation in the method of the stub class
1011          */
1012         private void writeCallbackInstantiationMethodBodyJavaStub(String paramIdent, String callbackType, int counter, boolean isMultipleCallbacks) {
1013
1014                 println("if (!IoTRMIUtil.mapSkel.containsKey(" + paramIdent + ")) {");
1015                 println("int newObjIdSent = rmiComm.getObjectIdCounter();");
1016                 if (isMultipleCallbacks)
1017                         println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1018                 else
1019                         println("objIdSent" + counter + "[0] = newObjIdSent;");
1020                 println("rmiComm.decrementObjectIdCounter();");
1021                 println(callbackType + "_Skeleton skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
1022                 println("IoTRMIUtil.mapSkel.put(" + paramIdent + ", skel" + counter + ");");
1023                 println("IoTRMIUtil.mapSkelId.put(" + paramIdent + ", newObjIdSent);");
1024                 println("Thread thread = new Thread() {");
1025                 println("public void run() {");
1026                 println("try {");
1027                 println("skel" + counter + ".___waitRequestInvokeMethod();");
1028                 println("} catch (Exception ex) {");
1029                 println("ex.printStackTrace();");
1030                 println("throw new Error(\"Exception when trying to run ___waitRequestInvokeMethod() for " + 
1031                         callbackType + "_Skeleton!\");");
1032                 println("}");
1033                 println("}");
1034                 println("};");
1035                 println("thread.start();");
1036                 println("while(!skel" + counter + ".didAlreadyInitWaitInvoke());");
1037                 println("}");
1038                 println("else");
1039                 println("{");
1040                 println("int newObjIdSent = IoTRMIUtil.mapSkelId.get(" + paramIdent + ");");
1041                 if (isMultipleCallbacks)
1042                         println("objIdSent" + counter + "[cnt" + counter + "++] = newObjIdSent;");
1043                 else
1044                         println("objIdSent" + counter + "[0] = newObjIdSent;");
1045                 println("}");
1046         }
1047
1048
1049         /**
1050          * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
1051          */
1052         private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
1053                         List<String> methPrmTypes, String method, Set<String> callbackType) {
1054
1055                 // Determine callback object counter type (List vs. single variable)
1056                 for (int i = 0; i < methParams.size(); i++) {
1057                         String paramType = methPrmTypes.get(i);
1058                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1059                                 print("int[] objIdSent" + i + " = ");
1060                                 String param = methParams.get(i);
1061                                 if (isArray(methParams.get(i)))
1062                                         println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".length];");
1063                                 else if (isList(methPrmTypes.get(i)))
1064                                         println("new int[" + getSimpleIdentifier(methParams.get(i)) + ".size()];");
1065                                 else
1066                                         println("new int[1];");
1067                         }
1068                 }
1069                 println("try {");
1070                 // Check if this is single object, array, or list of objects
1071                 for (int i = 0; i < methParams.size(); i++) {
1072                         String paramType = methPrmTypes.get(i);
1073                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1074                                 String param = methParams.get(i);
1075                                 if (isArrayOrList(paramType, param)) {  // Generate loop
1076                                         println("int cnt" + i + " = 0;");
1077                                         println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
1078                                         writeCallbackInstantiationMethodBodyJavaStub("cb", returnGenericCallbackType(paramType), i, true);
1079                                 } else
1080                                         writeCallbackInstantiationMethodBodyJavaStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i, false);
1081                                 if (isArrayOrList(paramType, param))
1082                                         println("}");
1083                         }
1084                 }
1085                 print("}");
1086                 println(" catch (Exception ex) {");
1087                 println("ex.printStackTrace();");
1088                 println("throw new Error(\"Exception when generating skeleton objects!\");");
1089                 println("}\n");
1090         }
1091
1092
1093         /**
1094          * HELPER: writeMethodJavaStub() writes the methods of the stub class
1095          */
1096         private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
1097
1098                 for (String method : methods) {
1099
1100                         List<String> methParams = intDecl.getMethodParams(method);
1101                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1102                         print("public " + intDecl.getMethodType(method) + " " +
1103                                 intDecl.getMethodId(method) + "(");
1104                         boolean isCallbackMethod = false;
1105                         //String callbackType = null;
1106                         Set<String> callbackType = new HashSet<String>();
1107                         for (int i = 0; i < methParams.size(); i++) {
1108
1109                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1110                                 // Check if this has callback object
1111                                 if (callbackClasses.contains(paramType)) {
1112                                         isCallbackMethod = true;
1113                                         //callbackType = paramType;
1114                                         callbackType.add(paramType);
1115                                         // Even if there're 2 callback arguments, we expect them to be of the same interface
1116                                 }
1117                                 print(methPrmTypes.get(i) + " " + methParams.get(i));
1118                                 // Check if this is the last element (don't print a comma)
1119                                 if (i != methParams.size() - 1) {
1120                                         print(", ");
1121                                 }
1122                         }
1123                         println(") {");
1124                         // Now, write the body of stub!
1125                         if (isCallbackMethod)
1126                                 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1127                         writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1128                         println("}\n");
1129                 }
1130         }
1131
1132
1133         /**
1134          * HELPER: getStubInterface() gets stub interface name based on original interface
1135          */
1136         public String getStubInterface(String intface) {
1137
1138                 return mapInt2NewIntName.get(intface);
1139         }
1140
1141
1142         /**
1143          * generateJavaStubClasses() generate stubs based on the methods list in Java
1144          */
1145         public void generateJavaStubClasses() throws IOException {
1146
1147                 // Create a new directory
1148                 String path = createDirectories(dir, subdir);
1149                 for (String intface : mapIntfacePTH.keySet()) {
1150
1151                         // Check if there is more than 1 class that uses the same interface
1152                         List<String> drvList = mapInt2Drv.get(intface);
1153                         for(int i = 0; i < drvList.size(); i++) {
1154
1155                                 String driverClass = drvList.get(i);
1156                                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1157                                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1158
1159                                         // Open a new file to write into
1160                                         String newIntface = intMeth.getKey();
1161                                         String newStubClass = newIntface + "_Stub";
1162                                         String packageClass = null;
1163                                         // Check if this interface is a callback class
1164                                         if(isCallbackClass(intface)) {
1165                                                 packageClass = CODE_PREFIX + "." + driverClass;
1166                                                 path = createDirectories(dir + "/" + subdir, driverClass);
1167                                         } else {
1168                                                 packageClass = controllerClass;
1169                                                 path = createDirectories(dir + "/" + subdir, controllerClass);
1170                                         }
1171                                         FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1172                                         pw = new PrintWriter(new BufferedWriter(fw));
1173                                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1174                                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1175                                         // Pass in set of methods and get import classes
1176                                         Set<String> methods = intMeth.getValue();
1177                                         Set<String> importClasses = getImportClasses(methods, intDecl);
1178                                         List<String> stdImportClasses = getStandardJavaImportClasses();
1179                                         List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1180                                         // Find out if there are callback objects
1181                                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);                     
1182                                         boolean callbackExist = !callbackClasses.isEmpty();
1183                                         println("package " + packageClass + ";\n");
1184                                         printImportStatements(allImportClasses); 
1185                                         println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
1186                                         // Write class header
1187                                         println("public class " + newStubClass + " implements " + newIntface + " {\n");
1188                                         // Write properties
1189                                         writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
1190                                         // Write constructor
1191                                         writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1192                                         // Write callback constructor (used if this stub is treated as a callback stub)
1193                                         writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
1194                                         // Write methods
1195                                         writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
1196                                         println("}");
1197                                         pw.close();
1198                                         System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
1199                                 }
1200                         }
1201                 }
1202         }
1203
1204
1205         /**
1206          * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
1207          */
1208         private void writePropertiesJavaSkeleton(String intface, InterfaceDecl intDecl) {
1209
1210                 println("private " + intface + " mainObj;");
1211                 Integer objId = mapIntfaceObjId.get(intface);
1212                 println("private int objectId = " + objId + ";");
1213                 println("// Communications and synchronizations");
1214                 println("private IoTRMIComm rmiComm;");
1215                 println("private AtomicBoolean didAlreadyInitWaitInvoke;");
1216                 println("private AtomicBoolean methodReceived;");
1217                 println("private byte[] methodBytes = null;");
1218                 println("// Permissions");
1219                 writePropertiesJavaPermission(intface, intDecl);
1220                 println("\n");
1221         }
1222
1223
1224         /**
1225          * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper
1226          */
1227         private void writeStructPermissionJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
1228
1229                 // Use this set to handle two same methodIds
1230                 for (String method : methods) {
1231                         List<String> methParams = intDecl.getMethodParams(method);
1232                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1233                         // Check for params with structs
1234                         for (int i = 0; i < methParams.size(); i++) {
1235                                 String paramType = methPrmTypes.get(i);
1236                                 String param = methParams.get(i);
1237                                 String simpleType = getGenericType(paramType);
1238                                 if (isStructClass(simpleType)) {
1239                                         int methodNumId = intDecl.getMethodNumId(method);
1240                                         String helperMethod = methodNumId + "struct" + i;
1241                                         int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod);
1242                                         // Iterate over interfaces to give permissions to
1243                                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1244                                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1245                                                 String newIntface = intMeth.getKey();
1246                                                 int newObjectId = getNewIntfaceObjectId(newIntface);
1247                                                 println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");");
1248                                         }
1249                                 }
1250                         }
1251                 }
1252         }
1253
1254
1255         /**
1256          * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
1257          */
1258         private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, 
1259                         Collection<String> methods, boolean callbackExist) {
1260
1261                 println("public " + newSkelClass + "(" + intface + " _mainObj, int _portSend, int _portRecv) throws Exception {");
1262                 println("mainObj = _mainObj;");
1263                 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv);");
1264                 // Generate permission control initialization
1265                 writeConstructorJavaPermission(intface);
1266                 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1267                 println("IoTRMIUtil.mapSkel.put(_mainObj, this);");
1268                 println("IoTRMIUtil.mapSkelId.put(_mainObj, objectId);");
1269                 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1270                 println("methodReceived = new AtomicBoolean(false);");
1271                 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1272                 println("Thread thread1 = new Thread() {");
1273                 println("public void run() {");
1274                 println("try {");
1275                 println("___waitRequestInvokeMethod();");
1276                 println("}");
1277                 println("catch (Exception ex)");
1278                 println("{");
1279                 println("ex.printStackTrace();");
1280                 println("}");
1281                 println("}");
1282                 println("};");
1283                 println("thread1.start();");
1284                 println("}\n");
1285         }
1286
1287
1288         /**
1289          * HELPER: writeCallbackConstructorJavaSkeleton() writes the constructor of the skeleton class
1290          */
1291         private void writeCallbackConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, 
1292                         Collection<String> methods, boolean callbackExist) {
1293
1294                 println("public " + newSkelClass + "(" + intface + " _mainObj, IoTRMIComm _rmiComm, int _objectId) throws Exception {");
1295                 println("mainObj = _mainObj;");
1296                 println("rmiComm = _rmiComm;");
1297                 println("objectId = _objectId;");
1298                 // Generate permission control initialization
1299                 writeConstructorJavaPermission(intface);
1300                 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1301                 println("didAlreadyInitWaitInvoke = new AtomicBoolean(false);");
1302                 println("methodReceived = new AtomicBoolean(false);");
1303                 println("rmiComm.registerSkeleton(objectId, methodReceived);");
1304                 println("}\n");
1305         }
1306
1307
1308         /**
1309          * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
1310          */
1311         private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
1312
1313                 if (methodType.equals("void"))
1314                         print("mainObj." + methodId + "(");
1315                 else
1316                         print("return mainObj." + methodId + "(");
1317                 for (int i = 0; i < methParams.size(); i++) {
1318
1319                         print(getSimpleIdentifier(methParams.get(i)));
1320                         // Check if this is the last element (don't print a comma)
1321                         if (i != methParams.size() - 1) {
1322                                 print(", ");
1323                         }
1324                 }
1325                 println(");");
1326         }
1327
1328
1329         /**
1330          * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
1331          */
1332         private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1333
1334                 for (String method : methods) {
1335
1336                         List<String> methParams = intDecl.getMethodParams(method);
1337                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1338                         String methodId = intDecl.getMethodId(method);
1339                         print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
1340                         for (int i = 0; i < methParams.size(); i++) {
1341
1342                                 String origParamType = methPrmTypes.get(i);
1343                                 String paramType = checkAndGetParamClass(origParamType);
1344                                 print(paramType + " " + methParams.get(i));
1345                                 // Check if this is the last element (don't print a comma)
1346                                 if (i != methParams.size() - 1) {
1347                                         print(", ");
1348                                 }
1349                         }
1350                         println(") {");
1351                         // Now, write the body of skeleton!
1352                         writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
1353                         println("}\n");
1354                 }
1355         }
1356
1357
1358         /**
1359          * HELPER: writeCallbackInstantiationJavaStubGeneration() writes the instantiation of callback stubs
1360          */
1361         private void writeCallbackInstantiationJavaStubGeneration(String exchParamType, int counter) {
1362
1363                 println(exchParamType + " newStub" + counter + " = null;");
1364                 println("if(!IoTRMIUtil.mapStub.containsKey(objIdRecv" + counter + ")) {");
1365                 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
1366                 println("IoTRMIUtil.mapStub.put(objIdRecv" + counter + ", newStub" + counter + ");");
1367                 println("rmiComm.setObjectIdCounter(objIdRecv" + counter + ");");
1368                 println("rmiComm.decrementObjectIdCounter();");
1369                 println("}");
1370                 println("else {");
1371                 println("newStub" + counter + " = (" + exchParamType + "_Stub) IoTRMIUtil.mapStub.get(objIdRecv" + counter + ");");
1372                 println("}");
1373         }
1374
1375
1376         /**
1377          * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
1378          */
1379         private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes, 
1380                         Set<String> callbackType, boolean isStructMethod) {
1381
1382                 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
1383                 String offsetPfx = "";
1384                 if (isStructMethod)
1385                         offsetPfx = "offset";
1386                 // Iterate over callback objects
1387                 for (int i = 0; i < methParams.size(); i++) {
1388                         String paramType = methPrmTypes.get(i);
1389                         String param = methParams.get(i);
1390                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1391                                 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1392                                 // Print array if this is array or list if this is a list of callback objects
1393                                 println("int[] stubIdArray" + i + " = (int[]) paramObj[" + offsetPfx + i + "];");
1394                                 if (isArray(param)) {                           
1395                                         println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1396                                         println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1397                                 } else if (isList(paramType)) {
1398                                         println("int numStubs" + i + " = stubIdArray" + i + ".length;");
1399                                         println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1400                                 } else {
1401                                         println("int objIdRecv" + i + " = stubIdArray" + i + "[0];");
1402                                         writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1403                                 }
1404                         }
1405                         // Generate a loop if needed
1406                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1407                                 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1408                                 if (isArray(param)) {
1409                                         println("for (int i = 0; i < numStubs" + i + "; i++) {");
1410                                         println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1411                                         writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1412                                         println("stub" + i + "[i] = newStub" + i + ";");
1413                                         println("}");
1414                                 } else if (isList(paramType)) {
1415                                         println("for (int i = 0; i < numStubs" + i + "; i++) {");
1416                                         println("int objIdRecv" + i + " = stubIdArray" + i + "[i];");
1417                                         writeCallbackInstantiationJavaStubGeneration(exchParamType, i);
1418                                         println("stub" + i + ".add(newStub" + i + ");");
1419                                         println("}");
1420                                 } else
1421                                         println(exchParamType + " stub" + i + " = newStub" + i + ";");
1422                                 mapStubParam.put(i, "stub" + i);        // List of all stub parameters
1423                         }
1424                 }
1425                 return mapStubParam;
1426         }
1427
1428
1429         /**
1430          * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
1431          */
1432         private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes, boolean isStructMethod) {
1433
1434                 String offsetPfx = "";
1435                 if (isStructMethod)
1436                         offsetPfx = "offset";
1437                 // Iterate and find enum declarations
1438                 boolean printed = false;
1439                 for (int i = 0; i < methParams.size(); i++) {
1440                         String paramType = methPrmTypes.get(i);
1441                         String param = methParams.get(i);
1442                         String simpleType = getGenericType(paramType);
1443                         if (isEnumClass(simpleType)) {
1444                         // Check if this is enum type
1445                                 println("int paramInt" + i + "[] = (int[]) paramObj[" + offsetPfx + i + "];");
1446                                 if (!printed) {
1447                                         println(simpleType + "[] enumVals = " + simpleType + ".values();");
1448                                         printed = true;
1449                                 }
1450                                 if (isArray(param)) {   // An array
1451                                         println("int len" + i + " = paramInt" + i + ".length;");
1452                                         println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];");
1453                                         println("for (int i = 0; i < len" + i + "; i++) {");
1454                                         println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];");
1455                                         println("}");
1456                                 } else if (isList(paramType)) { // A list
1457                                         println("int len" + i + " = paramInt" + i + ".length;");
1458                                         println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();");
1459                                         println("for (int i = 0; i < len" + i + "; i++) {");
1460                                         println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);");
1461                                         println("}");
1462                                 } else {        // Just one element
1463                                         println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
1464                                 }
1465                         }
1466                 }
1467         }
1468
1469
1470         /**
1471          * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
1472          */
1473         private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
1474
1475                 // Strips off array "[]" for return type
1476                 String pureType = getSimpleArrayType(getGenericType(retType));
1477                 // Take the inner type of generic
1478                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1479                         pureType = getGenericType(retType);
1480                 if (isEnumClass(pureType)) {
1481                 // Check if this is enum type
1482                         // Enum decoder
1483                         if (isArray(retType)) {                 // An array
1484                                 print(pureType + "[] retEnum = " + methodId + "(");
1485                         } else if (isList(retType)) {   // A list
1486                                 print("List<" + pureType + "> retEnum = " + methodId + "(");
1487                         } else {        // Just one element
1488                                 print(pureType + " retEnum = " + methodId + "(");
1489                         }
1490                 }
1491         }
1492
1493
1494         /**
1495          * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
1496          */
1497         private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
1498
1499                 // Strips off array "[]" for return type
1500                 String pureType = getSimpleArrayType(getGenericType(retType));
1501                 // Take the inner type of generic
1502                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1503                         pureType = getGenericType(retType);
1504                 if (isEnumClass(pureType)) {
1505                 // Check if this is enum type
1506                         if (isArray(retType)) { // An array
1507                                 println("int retLen = retEnum.length;");
1508                                 println("int[] retEnumVal = new int[retLen];");
1509                                 println("for (int i = 0; i < retLen; i++) {");
1510                                 println("retEnumVal[i] = retEnum[i].ordinal();");
1511                                 println("}");
1512                         } else if (isList(retType)) {   // A list
1513                                 println("int retLen = retEnum.size();");
1514                                 println("int[] retEnumVal = new int[retLen];");
1515                                 println("for (int i = 0; i < retLen; i++) {");
1516                                 println("retEnumVal[i] = retEnum.get(i).ordinal();");
1517                                 println("}");
1518                         } else {        // Just one element
1519                                 println("int[] retEnumVal = new int[1];");
1520                                 println("retEnumVal[0] = retEnum.ordinal();");
1521                         }
1522                         println("Object retObj = retEnumVal;");
1523                 }
1524         }
1525         
1526         
1527         /**
1528          * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
1529          */
1530         private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes, 
1531                         String method, InterfaceDecl intDecl) {
1532
1533                 // Iterate and find struct declarations - count number of params
1534                 for (int i = 0; i < methParams.size(); i++) {
1535                         String paramType = methPrmTypes.get(i);
1536                         String param = methParams.get(i);
1537                         String simpleType = getGenericType(paramType);
1538                         if (isStructClass(simpleType)) {
1539                                 int members = getNumOfMembers(simpleType);
1540                                 print(Integer.toString(members) + "*");
1541                                 int methodNumId = intDecl.getMethodNumId(method);
1542                                 print("struct" + methodNumId + "Size" + i);
1543                         } else
1544                                 print("1");
1545                         if (i != methParams.size() - 1) {
1546                                 print("+");
1547                         }
1548                 }
1549         }
1550
1551         
1552         /**
1553          * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
1554          */
1555         private void writeStructMembersJavaSkeleton(String simpleType, String paramType, 
1556                         String param, String method, InterfaceDecl intDecl, int iVar) {
1557
1558                 // Get the struct declaration for this struct and generate initialization code
1559                 StructDecl structDecl = getStructDecl(simpleType);
1560                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1561                 List<String> members = structDecl.getMembers(simpleType);
1562                 if (isArrayOrList(paramType, param)) {  // An array or list
1563                         int methodNumId = intDecl.getMethodNumId(method);
1564                         String counter = "struct" + methodNumId + "Size" + iVar;
1565                         println("for(int i = 0; i < " + counter + "; i++) {");
1566                 }
1567                 if (isArrayOrList(paramType, param)) {  // An array or list
1568                         for (int i = 0; i < members.size(); i++) {
1569                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1570                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1571                                 println("paramClsGen[pos++] = null;");
1572                         }
1573                         println("}");
1574                 } else {        // Just one struct element
1575                         for (int i = 0; i < members.size(); i++) {
1576                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1577                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1578                                 println("paramClsGen[pos++] = null;");
1579                         }
1580                 }
1581         }
1582
1583
1584         /**
1585          * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
1586          */
1587         private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1588                         List<String> methPrmTypes, String method) {
1589
1590                 println("int objPos = 0;");
1591                 for (int i = 0; i < methParams.size(); i++) {
1592                         String paramType = methPrmTypes.get(i);
1593                         String param = methParams.get(i);
1594                         String simpleType = getGenericType(paramType);
1595                         if (isStructClass(simpleType)) {
1596                                 int methodNumId = intDecl.getMethodNumId(method);
1597                                 String counter = "struct" + methodNumId + "Size" + i;
1598                                 // Declaration
1599                                 if (isArray(param)) {                   // An array
1600                                         println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
1601                                         println("for(int i = 0; i < " + counter + "; i++) {");
1602                                         println("paramStruct" + i + "[i] = new " + simpleType + "();");
1603                                         println("}");
1604                                 } else if (isList(paramType)) { // A list
1605                                         println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
1606                                 } else
1607                                         println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
1608                                 // Initialize members
1609                                 StructDecl structDecl = getStructDecl(simpleType);
1610                                 List<String> members = structDecl.getMembers(simpleType);
1611                                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1612                                 if (isArrayOrList(paramType, param)) {  // An array or list
1613                                         println("for(int i = 0; i < " + counter + "; i++) {");
1614                                 }
1615                                 if (isArray(param)) {   // An array
1616                                         for (int j = 0; j < members.size(); j++) {
1617                                                 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1618                                                 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
1619                                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1620                                         }
1621                                         println("}");
1622                                 } else if (isList(paramType)) { // A list
1623                                         println(simpleType + " paramStructMem = new " + simpleType + "();");
1624                                         for (int j = 0; j < members.size(); j++) {
1625                                                 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1626                                                 print("paramStructMem." + getSimpleIdentifier(members.get(j)));
1627                                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1628                                         }
1629                                         println("paramStruct" + i + ".add(paramStructMem);");
1630                                         println("}");
1631                                 } else {        // Just one struct element
1632                                         for (int j = 0; j < members.size(); j++) {
1633                                                 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1634                                                 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
1635                                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1636                                         }
1637                                 }
1638                         } else {
1639                                 // Take offsets of parameters
1640                                 println("int offset" + i +" = objPos++;");
1641                         }
1642                 }
1643         }
1644
1645
1646         /**
1647          * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
1648          */
1649         private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
1650
1651                 // Minimum retLen is 1 if this is a single struct object
1652                 if (isArray(retType))
1653                         println("int retLen = retStruct.length;");
1654                 else if (isList(retType))
1655                         println("int retLen = retStruct.size();");
1656                 else    // Just single struct object
1657                         println("int retLen = 1;");
1658                 println("Object retLenObj = retLen;");
1659                 println("rmiComm.sendReturnObj(retLenObj, localMethodBytes);");
1660                 int numMem = getNumOfMembers(simpleType);
1661                 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
1662                 println("Object[] retObj = new Object[" + numMem + "*retLen];");
1663                 println("int retPos = 0;");
1664                 // Get the struct declaration for this struct and generate initialization code
1665                 StructDecl structDecl = getStructDecl(simpleType);
1666                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1667                 List<String> members = structDecl.getMembers(simpleType);
1668                 if (isArray(retType)) { // An array or list
1669                         println("for(int i = 0; i < retLen; i++) {");
1670                         for (int i = 0; i < members.size(); i++) {
1671                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1672                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1673                                 print("retObj[retPos++] = retStruct[i].");
1674                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1675                                 println(";");
1676                         }
1677                         println("}");
1678                 } else if (isList(retType)) {   // An array or list
1679                         println("for(int i = 0; i < retLen; i++) {");
1680                         for (int i = 0; i < members.size(); i++) {
1681                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1682                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1683                                 print("retObj[retPos++] = retStruct.get(i).");
1684                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1685                                 println(";");
1686                         }
1687                         println("}");
1688                 } else {        // Just one struct element
1689                         for (int i = 0; i < members.size(); i++) {
1690                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1691                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1692                                 print("retObj[retPos++] = retStruct.");
1693                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1694                                 println(";");
1695                         }
1696                 }
1697
1698         }
1699
1700
1701         /**
1702          * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
1703          */
1704         private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1705                         List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
1706                         boolean isStructMethod) {
1707
1708                 checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod);
1709                 Map<Integer,String> mapStubParam = null;
1710                 if (isCallbackMethod) {
1711                         println("try {");
1712                         mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType, isStructMethod);
1713                 }
1714                 // Check if this is "void"
1715                 String retType = intDecl.getMethodType(method);
1716                 if (retType.equals("void")) {
1717                         print(intDecl.getMethodId(method) + "(");
1718                 } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {  // Enum type
1719                         checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
1720                 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) {        // Struct type
1721                         print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
1722                 } else { // We do have a return value
1723                         print("Object retObj = " + intDecl.getMethodId(method) + "(");
1724                 }
1725                 for (int i = 0; i < methParams.size(); i++) {
1726
1727                         String paramType = methPrmTypes.get(i);
1728                         if (isCallbackMethod && checkCallbackType(paramType, callbackType)) {
1729                                 print(mapStubParam.get(i));     // Get the callback parameter
1730                         } else if (isEnumClass(getGenericType(paramType))) { // Enum class
1731                                 print(getEnumParam(paramType, methParams.get(i), i));
1732                         } else if (isStructClass(getGenericType(paramType))) {
1733                                 print("paramStruct" + i);
1734                         } else {
1735                                 String prmType = checkAndGetArray(paramType, methParams.get(i));
1736                                 if (isStructMethod)
1737                                         print("(" + prmType + ") paramObj[offset" + i + "]");
1738                                 else
1739                                         print("(" + prmType + ") paramObj[" + i + "]");
1740                         }
1741                         if (i != methParams.size() - 1)
1742                                 print(", ");
1743                 }
1744                 println(");");
1745                 if (!retType.equals("void")) {
1746                         if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1747                                 checkAndWriteEnumRetConvJavaSkeleton(retType);
1748                                 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1749                         } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1750                                 writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
1751                                 println("rmiComm.sendReturnObj(retCls, retObj, localMethodBytes);");
1752                         } else
1753                                 println("rmiComm.sendReturnObj(retObj, localMethodBytes);");
1754                 }
1755                 if (isCallbackMethod) { // Catch exception if this is callback
1756                         print("}");
1757                         println(" catch(Exception ex) {");
1758                         println("ex.printStackTrace();");
1759                         println("throw new Error(\"Exception from callback object instantiation!\");");
1760                         println("}");
1761                 }
1762         }
1763
1764
1765         /**
1766          * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
1767          */
1768         private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1769                         List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1770
1771                 // Generate array of parameter objects
1772                 boolean isCallbackMethod = false;
1773                 Set<String> callbackType = new HashSet<String>();
1774                 println("byte[] localMethodBytes = methodBytes;");
1775                 println("rmiComm.setGetMethodBytes();");
1776                 print("int paramLen = ");
1777                 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
1778                 println(";");
1779                 println("Class<?>[] paramCls = new Class<?>[paramLen];");
1780                 println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
1781                 println("int pos = 0;");
1782                 // Iterate again over the parameters
1783                 for (int i = 0; i < methParams.size(); i++) {
1784                         String paramType = methPrmTypes.get(i);
1785                         String param = methParams.get(i);
1786                         String simpleType = getGenericType(paramType);
1787                         if (isStructClass(simpleType)) {
1788                                 writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
1789                         } else {
1790                                 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
1791                                 if (callbackClasses.contains(prmType)) {
1792                                         isCallbackMethod = true;
1793                                         //callbackType = prmType;
1794                                         callbackType.add(prmType);
1795                                         println("paramCls[pos] = int[].class;");
1796                                         println("paramClsGen[pos++] = null;");
1797                                 } else {        // Generate normal classes if it's not a callback object
1798                                         String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1799                                         println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
1800                                         print("paramClsGen[pos++] = ");
1801                                         String prmTypeOth = methPrmTypes.get(i);
1802                                         if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
1803                                                 println(getTypeOfGeneric(prmType)[0] + ".class;");
1804                                         else
1805                                                 println("null;");
1806                                 }
1807                         }
1808                 }
1809                 println("Object[] paramObj = rmiComm.getMethodParams(paramCls, paramClsGen, localMethodBytes);");
1810                 writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
1811                 // Write the return value part
1812                 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true);
1813         }
1814
1815
1816         /**
1817          * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1818          */
1819         private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1820                         List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1821
1822                 // Generate array of parameter objects
1823                 boolean isCallbackMethod = false;
1824                 Set<String> callbackType = new HashSet<String>();
1825                 println("byte[] localMethodBytes = methodBytes;");
1826                 println("rmiComm.setGetMethodBytes();");
1827                 print("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { ");
1828                 for (int i = 0; i < methParams.size(); i++) {
1829
1830                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1831                         if (callbackClasses.contains(paramType)) {
1832                                 isCallbackMethod = true;
1833                                 callbackType.add(paramType);
1834                                 print("int[].class");
1835                         } else {        // Generate normal classes if it's not a callback object
1836                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1837                                 print(getSimpleType(getEnumType(prmType)) + ".class");
1838                         }
1839                         if (i != methParams.size() - 1)
1840                                 print(", ");
1841                 }
1842                 // Generate generic class if it's a generic type.. null otherwise
1843                 print(" }, new Class<?>[] { ");
1844                 for (int i = 0; i < methParams.size(); i++) {
1845                         String prmType = methPrmTypes.get(i);
1846                         if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) &&
1847                                 !isEnumClass(getGenericType(prmType)) &&
1848                                 !callbackClasses.contains(getGenericType(prmType)))
1849                                         print(getGenericType(prmType) + ".class");
1850                         else
1851                                 print("null");
1852                         if (i != methParams.size() - 1)
1853                                 print(", ");
1854                 }
1855                 println(" }, localMethodBytes);");
1856                 // Write the return value part
1857                 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false);
1858         }
1859
1860
1861         /**
1862          * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1863          */
1864         private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1865
1866                 // Use this set to handle two same methodIds
1867                 Set<String> uniqueMethodIds = new HashSet<String>();
1868                 for (String method : methods) {
1869
1870                         List<String> methParams = intDecl.getMethodParams(method);
1871                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1872                         if (isStructPresent(methParams, methPrmTypes)) {        // Treat struct differently
1873                                 String methodId = intDecl.getMethodId(method);
1874                                 print("public void ___");
1875                                 String helperMethod = methodId;
1876                                 if (uniqueMethodIds.contains(methodId))
1877                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
1878                                 else
1879                                         uniqueMethodIds.add(methodId);
1880                                 String retType = intDecl.getMethodType(method);
1881                                 print(helperMethod + "(");
1882                                 boolean begin = true;
1883                                 for (int i = 0; i < methParams.size(); i++) { // Print size variables
1884                                         String paramType = methPrmTypes.get(i);
1885                                         String param = methParams.get(i);
1886                                         String simpleType = getGenericType(paramType);
1887                                         if (isStructClass(simpleType)) {
1888                                                 if (!begin)     // Generate comma for not the beginning variable
1889                                                         print(", ");
1890                                                 else
1891                                                         begin = false;
1892                                                 int methodNumId = intDecl.getMethodNumId(method);
1893                                                 print("int struct" + methodNumId + "Size" + i);
1894                                         }
1895                                 }
1896                                 // Check if this is "void"
1897                                 if (retType.equals("void"))
1898                                         println(") {");
1899                                 else
1900                                         println(") throws IOException {");
1901                                 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1902                                 println("}\n");
1903                         } else {
1904                                 String methodId = intDecl.getMethodId(method);
1905                                 print("public void ___");
1906                                 String helperMethod = methodId;
1907                                 if (uniqueMethodIds.contains(methodId))
1908                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
1909                                 else
1910                                         uniqueMethodIds.add(methodId);
1911                                 // Check if this is "void"
1912                                 String retType = intDecl.getMethodType(method);
1913                                 if (retType.equals("void"))
1914                                         println(helperMethod + "() {");
1915                                 else
1916                                         println(helperMethod + "() throws IOException {");
1917                                 // Now, write the helper body of skeleton!
1918                                 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1919                                 println("}\n");
1920                         }
1921                 }
1922                 // Write method helper for structs
1923                 writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
1924         }
1925
1926
1927         /**
1928          * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
1929          */
1930         private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods, 
1931                         InterfaceDecl intDecl) {
1932
1933                 // Use this set to handle two same methodIds
1934                 for (String method : methods) {
1935
1936                         List<String> methParams = intDecl.getMethodParams(method);
1937                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1938                         // Check for params with structs
1939                         for (int i = 0; i < methParams.size(); i++) {
1940                                 String paramType = methPrmTypes.get(i);
1941                                 String param = methParams.get(i);
1942                                 String simpleType = getGenericType(paramType);
1943                                 if (isStructClass(simpleType)) {
1944                                         int methodNumId = intDecl.getMethodNumId(method);
1945                                         print("public int ___");
1946                                         String helperMethod = methodNumId + "struct" + i;
1947                                         println(helperMethod + "() {");
1948                                         // Now, write the helper body of skeleton!
1949                                         println("byte[] localMethodBytes = methodBytes;");
1950                                         println("rmiComm.setGetMethodBytes();");
1951                                         println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null }, localMethodBytes);");
1952                                         println("return (int) paramObj[0];");
1953                                         println("}\n");
1954                                 }
1955                         }
1956                 }
1957         }
1958
1959
1960         /**
1961          * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
1962          */
1963         private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods, 
1964                         InterfaceDecl intDecl) {
1965
1966                 // Use this set to handle two same methodIds
1967                 for (String method : methods) {
1968
1969                         List<String> methParams = intDecl.getMethodParams(method);
1970                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1971                         // Check for params with structs
1972                         for (int i = 0; i < methParams.size(); i++) {
1973                                 String paramType = methPrmTypes.get(i);
1974                                 String param = methParams.get(i);
1975                                 String simpleType = getGenericType(paramType);
1976                                 if (isStructClass(simpleType)) {
1977                                         int methodNumId = intDecl.getMethodNumId(method);
1978                                         print("public int ___");
1979                                         String helperMethod = methodNumId + "struct" + i;
1980                                         println(helperMethod + "(IoTRMIObject rmiObj) {");
1981                                         // Now, write the helper body of skeleton!
1982                                         println("Object[] paramObj = rmiComm.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1983                                         println("return (int) paramObj[0];");
1984                                         println("}\n");
1985                                 }
1986                         }
1987                 }
1988         }
1989
1990
1991         /**
1992          * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
1993          */
1994         private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1995
1996                 // Use this set to handle two same methodIds
1997                 for (String method : methods) {
1998
1999                         List<String> methParams = intDecl.getMethodParams(method);
2000                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2001                         // Check for params with structs
2002                         for (int i = 0; i < methParams.size(); i++) {
2003                                 String paramType = methPrmTypes.get(i);
2004                                 String param = methParams.get(i);
2005                                 String simpleType = getGenericType(paramType);
2006                                 if (isStructClass(simpleType)) {
2007                                         int methodNumId = intDecl.getMethodNumId(method);
2008                                         println("int struct" + methodNumId + "Size" + i + " = 0;");
2009                                 }
2010                         }
2011                 }
2012         }
2013         
2014
2015         /**
2016          * HELPER: writeInputCountVarStructJavaSkeleton() writes input counter variable of struct for skeleton
2017          */
2018         private boolean writeInputCountVarStructJavaSkeleton(String method, InterfaceDecl intDecl) {
2019
2020                 List<String> methParams = intDecl.getMethodParams(method);
2021                 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2022                 boolean structExist = false;
2023                 boolean begin = true;
2024                 // Check for params with structs
2025                 for (int i = 0; i < methParams.size(); i++) {
2026                         String paramType = methPrmTypes.get(i);
2027                         String param = methParams.get(i);
2028                         String simpleType = getGenericType(paramType);
2029                         if (isStructClass(simpleType)) {
2030                                 structExist = true;
2031                                 if (!begin)
2032                                         print(", ");
2033                                 else
2034                                         begin = false;
2035                                 int methodNumId = intDecl.getMethodNumId(method);
2036                                 print("struct" + methodNumId + "Size" + i + "Final");
2037                         }
2038                 }
2039                 return structExist;
2040         }
2041
2042         
2043         /**
2044          * HELPER: writeInputCountVarStructCplusSkeleton() writes input counter variable of struct for skeleton
2045          */
2046         private boolean writeInputCountVarStructCplusSkeleton(String method, InterfaceDecl intDecl) {
2047
2048                 List<String> methParams = intDecl.getMethodParams(method);
2049                 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2050                 boolean structExist = false;
2051                 boolean begin = true;
2052                 // Check for params with structs
2053                 for (int i = 0; i < methParams.size(); i++) {
2054                         String paramType = methPrmTypes.get(i);
2055                         String param = methParams.get(i);
2056                         String simpleType = getGenericType(paramType);
2057                         if (isStructClass(simpleType)) {
2058                                 structExist = true;
2059                                 if (!begin)
2060                                         print(", ");
2061                                 else
2062                                         begin = false;
2063                                 int methodNumId = intDecl.getMethodNumId(method);
2064                                 print("struct" + methodNumId + "Size" + i);
2065                         }
2066                 }
2067                 return structExist;
2068         }
2069
2070
2071         /**
2072          * HELPER: writeMethodCallStructJavaSkeleton() writes method call for wait invoke in skeleton
2073          */
2074         private void writeMethodCallStructJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2075
2076                 // Use this set to handle two same methodIds
2077                 for (String method : methods) {
2078
2079                         List<String> methParams = intDecl.getMethodParams(method);
2080                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2081                         // Check for params with structs
2082                         for (int i = 0; i < methParams.size(); i++) {
2083                                 String paramType = methPrmTypes.get(i);
2084                                 String param = methParams.get(i);
2085                                 String simpleType = getGenericType(paramType);
2086                                 if (isStructClass(simpleType)) {
2087                                         int methodNumId = intDecl.getMethodNumId(method);
2088                                         print("case ");
2089                                         String helperMethod = methodNumId + "struct" + i;
2090                                         String tempVar = "struct" + methodNumId + "Size" + i;
2091                                         print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2092                                         print(tempVar + " = ___");
2093                                         println(helperMethod + "(); break;");
2094                                 }
2095                         }
2096                 }
2097         }
2098
2099
2100         /**
2101          * HELPER: writeMethodCallStructCplusSkeleton() writes method call for wait invoke in skeleton
2102          */
2103         private void writeMethodCallStructCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2104
2105                 // Use this set to handle two same methodIds
2106                 for (String method : methods) {
2107
2108                         List<String> methParams = intDecl.getMethodParams(method);
2109                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2110                         // Check for params with structs
2111                         for (int i = 0; i < methParams.size(); i++) {
2112                                 String paramType = methPrmTypes.get(i);
2113                                 String param = methParams.get(i);
2114                                 String simpleType = getGenericType(paramType);
2115                                 if (isStructClass(simpleType)) {
2116                                         int methodNumId = intDecl.getMethodNumId(method);
2117                                         print("case ");
2118                                         String helperMethod = methodNumId + "struct" + i;
2119                                         String tempVar = "struct" + methodNumId + "Size" + i;
2120                                         print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2121                                         print(tempVar + " = ___");
2122                                         println(helperMethod + "(skel); break;");
2123                                 }
2124                         }
2125                 }
2126         }
2127
2128
2129         /**
2130          * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
2131          */
2132         private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2133
2134                 // Use this set to handle two same methodIds
2135                 for (String method : methods) {
2136
2137                         List<String> methParams = intDecl.getMethodParams(method);
2138                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2139                         // Check for params with structs
2140                         for (int i = 0; i < methParams.size(); i++) {
2141                                 String paramType = methPrmTypes.get(i);
2142                                 String param = methParams.get(i);
2143                                 String simpleType = getGenericType(paramType);
2144                                 if (isStructClass(simpleType)) {
2145                                         int methodNumId = intDecl.getMethodNumId(method);
2146                                         print("case ");
2147                                         String helperMethod = methodNumId + "struct" + i;
2148                                         String tempVar = "struct" + methodNumId + "Size" + i;
2149                                         print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2150                                         print(tempVar + " = ___");
2151                                         println(helperMethod + "(rmiObj); break;");
2152                                 }
2153                         }
2154                 }
2155         }
2156
2157
2158         /**
2159          * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
2160          */
2161         private void writeJavaMethodPermission(String intface) {
2162
2163                 // Get all the different stubs
2164                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2165                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2166                         String newIntface = intMeth.getKey();
2167                         int newObjectId = getNewIntfaceObjectId(newIntface);
2168                         println("if (_objectId == objectId) {");
2169                         println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
2170                         println("throw new Error(\"Object with object Id: \" + _objectId + \"  is not allowed to access method: \" + methodId);");
2171                         println("}");
2172                         println("}");
2173                         println("else {");
2174                         println("continue;");
2175                         println("}");
2176                 }
2177         }
2178
2179
2180         /**
2181          * HELPER: writeFinalInputCountVarStructSkeleton() writes the final version of input counter variable of struct for skeleton
2182          */
2183         private boolean writeFinalInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
2184
2185                 List<String> methParams = intDecl.getMethodParams(method);
2186                 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2187                 boolean structExist = false;
2188                 boolean begin = true;
2189                 // Check for params with structs
2190                 for (int i = 0; i < methParams.size(); i++) {
2191                         String paramType = methPrmTypes.get(i);
2192                         String param = methParams.get(i);
2193                         String simpleType = getGenericType(paramType);
2194                         if (isStructClass(simpleType)) {
2195                                 structExist = true;
2196                                 int methodNumId = intDecl.getMethodNumId(method);
2197                                 println("final int struct" + methodNumId + "Size" + i + 
2198                                         "Final = struct" + methodNumId + "Size" + i + ";");
2199                         }
2200                 }
2201                 return structExist;
2202         }
2203
2204
2205         /**
2206          * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
2207          */
2208         private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, String intface) {
2209
2210                 // Use this set to handle two same methodIds
2211                 Set<String> uniqueMethodIds = new HashSet<String>();
2212                 println("public void ___waitRequestInvokeMethod() throws IOException {");
2213                 // Write variables here if we have callbacks or enums or structs
2214                 writeCountVarStructSkeleton(methods, intDecl);
2215                 println("didAlreadyInitWaitInvoke.compareAndSet(false, true);");
2216                 println("while (true) {");
2217                 println("if (!methodReceived.get()) {");
2218                 println("continue;");
2219                 println("}");
2220                 println("methodBytes = rmiComm.getMethodBytes();");
2221                 println("methodReceived.set(false);");
2222                 println("int _objectId = IoTRMIComm.getObjectId(methodBytes);");
2223                 println("int methodId = IoTRMIComm.getMethodId(methodBytes);");
2224                 // Generate permission check
2225                 writeJavaMethodPermission(intface);
2226                 println("switch (methodId) {");
2227                 // Print methods and method Ids
2228                 for (String method : methods) {
2229                         String methodId = intDecl.getMethodId(method);
2230                         int methodNumId = intDecl.getMethodNumId(method);
2231                         println("case " + methodNumId + ":");
2232                         // Check for stuct counters
2233                         writeFinalInputCountVarStructSkeleton(method, intDecl);
2234                         println("new Thread() {");
2235                         println("public void run() {");
2236                         println("try {");
2237                         print("___");
2238                         String helperMethod = methodId;
2239                         if (uniqueMethodIds.contains(methodId))
2240                                 helperMethod = helperMethod + methodNumId;
2241                         else
2242                                 uniqueMethodIds.add(methodId);
2243                         print(helperMethod + "(");
2244                         writeInputCountVarStructJavaSkeleton(method, intDecl);
2245                         println(");");
2246                         println("}");
2247                         println("catch (Exception ex) {");
2248                         println("ex.printStackTrace();");
2249                         println("}");
2250                         println("}");
2251                         println("}.start();");
2252                         println("break;");
2253                 }
2254                 String method = "___initCallBack()";
2255                 writeMethodCallStructJavaSkeleton(methods, intDecl);
2256                 println("default: ");
2257                 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2258                 println("}");
2259                 println("}");
2260                 println("}\n");
2261         }
2262
2263
2264         /**
2265          * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
2266          */
2267         private void writeReturnDidAlreadyInitWaitInvoke() {
2268
2269                 println("public boolean didAlreadyInitWaitInvoke() {");
2270                 println("return didAlreadyInitWaitInvoke.get();");
2271                 println("}\n");
2272         }
2273
2274
2275         /**
2276          * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
2277          */
2278         public void generateJavaSkeletonClass() throws IOException {
2279
2280                 // Create a new directory
2281                 String path = createDirectories(dir, subdir);
2282                 for (String intface : mapIntfacePTH.keySet()) {
2283                 
2284                         // Check if there is more than 1 class that uses the same interface
2285                         List<String> drvList = mapInt2Drv.get(intface);
2286                         for(int i = 0; i < drvList.size(); i++) {
2287
2288                                 // Get driver class
2289                                 String driverClass = drvList.get(i);
2290                                 // Open a new file to write into
2291                                 String newSkelClass = intface + "_Skeleton";
2292                                 String packageClass = null;
2293                                 // Check if this interface is a callback class
2294                                 if(isCallbackClass(intface)) {
2295                                         packageClass = controllerClass;
2296                                         path = createDirectories(dir + "/" + subdir, controllerClass);
2297                                 } else {
2298                                         packageClass = CODE_PREFIX + "." + driverClass;
2299                                         path = createDirectories(dir + "/" + subdir, driverClass);
2300                                 }
2301                                 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2302                                 pw = new PrintWriter(new BufferedWriter(fw));
2303                                 // Pass in set of methods and get import classes
2304                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2305                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2306                                 List<String> methods = intDecl.getMethods();
2307                                 Set<String> importClasses = getImportClasses(methods, intDecl);
2308                                 List<String> stdImportClasses = getStandardJavaImportClasses();
2309                                 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2310                                 // Find out if there are callback objects
2311                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2312                                 boolean callbackExist = !callbackClasses.isEmpty();
2313                                 println("package " + packageClass + ";\n");
2314                                 printImportStatements(allImportClasses);
2315                                 println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
2316                                 // Write class header
2317                                 println("public class " + newSkelClass  + " implements " + intface + " {\n");
2318                                 // Write properties
2319                                 writePropertiesJavaSkeleton(intface, intDecl);
2320                                 // Write constructor
2321                                 writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2322                                 // Write constructor that is called when this object is a callback object
2323                                 writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2324                                 // Write function to return didAlreadyInitWaitInvoke
2325                                 writeReturnDidAlreadyInitWaitInvoke();
2326                                 // Write methods
2327                                 writeMethodJavaSkeleton(methods, intDecl);
2328                                 // Write method helper
2329                                 writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
2330                                 // Write waitRequestInvokeMethod() - main loop
2331                                 writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
2332                                 println("}");
2333                                 pw.close();
2334                                 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
2335                         }
2336                 }
2337         }
2338
2339         
2340 /*================================================================================
2341  *
2342  *              C++ generation
2343  *
2344  *================================================================================/
2345
2346         /**
2347          * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
2348          */
2349         private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
2350
2351                 for (String method : methods) {
2352
2353                         List<String> methParams = intDecl.getMethodParams(method);
2354                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2355                         print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2356                                 intDecl.getMethodId(method) + "(");
2357                         for (int i = 0; i < methParams.size(); i++) {
2358                                 // Check for params with driver class types and exchange it 
2359                                 //              with its remote interface
2360                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2361                                 paramType = checkAndGetCplusType(paramType);
2362                                 // Check for arrays - translate into vector in C++
2363                                 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2364                                 print(paramComplete);
2365                                 // Check if this is the last element (don't print a comma)
2366                                 if (i != methParams.size() - 1) {
2367                                         print(", ");
2368                                 }
2369                         }
2370                         println(") = 0;");
2371                 }
2372         }
2373
2374
2375         /**
2376          * HELPER: writeMethodCplusInterface() writes the method of the interface
2377          */
2378         private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
2379
2380                 for (String method : methods) {
2381
2382                         List<String> methParams = intDecl.getMethodParams(method);
2383                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2384                         print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2385                                 intDecl.getMethodId(method) + "(");
2386                         for (int i = 0; i < methParams.size(); i++) {
2387                                 // Check for params with driver class types and exchange it 
2388                                 //              with its remote interface
2389                                 String paramType = methPrmTypes.get(i);
2390                                 paramType = checkAndGetCplusType(paramType);
2391                                 // Check for arrays - translate into vector in C++
2392                                 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2393                                 print(paramComplete);
2394                                 // Check if this is the last element (don't print a comma)
2395                                 if (i != methParams.size() - 1) {
2396                                         print(", ");
2397                                 }
2398                         }
2399                         println(") = 0;");
2400                 }
2401         }
2402
2403
2404         /**
2405          * HELPER: generateEnumCplus() writes the enumeration declaration
2406          */
2407         public void generateEnumCplus() throws IOException {
2408
2409                 // Create a new directory
2410                 createDirectory(dir);
2411                 String path = createDirectories(dir, VIRTUALS_DIRECTORY);
2412                 for (String intface : mapIntfacePTH.keySet()) {
2413                         // Get the right StructDecl
2414                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2415                         EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
2416                         Set<String> enumTypes = enumDecl.getEnumDeclarations();
2417                         // Iterate over enum declarations
2418                         for (String enType : enumTypes) {
2419                                 // Open a new file to write into
2420                                 FileWriter fw = new FileWriter(path + "/" + enType + ".hpp");
2421                                 pw = new PrintWriter(new BufferedWriter(fw));
2422                                 // Write file headers
2423                                 println("#ifndef _" + enType.toUpperCase() + "_HPP__");
2424                                 println("#define _" + enType.toUpperCase() + "_HPP__");
2425                                 println("enum " + enType + " {");
2426                                 List<String> enumMembers = enumDecl.getMembers(enType);
2427                                 for (int i = 0; i < enumMembers.size(); i++) {
2428
2429                                         String member = enumMembers.get(i);
2430                                         print(member);
2431                                         // Check if this is the last element (don't print a comma)
2432                                         if (i != enumMembers.size() - 1)
2433                                                 println(",");
2434                                         else
2435                                                 println("");
2436                                 }
2437                                 println("};\n");
2438                                 println("#endif");
2439                                 pw.close();
2440                                 System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
2441                         }
2442                 }
2443         }
2444
2445
2446         /**
2447          * HELPER: generateStructCplus() writes the struct declaration
2448          */
2449         public void generateStructCplus() throws IOException {
2450
2451                 // Create a new directory
2452                 createDirectory(dir);
2453                 String path = createDirectories(dir, VIRTUALS_DIRECTORY);
2454                 for (String intface : mapIntfacePTH.keySet()) {
2455                         // Get the right StructDecl
2456                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2457                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
2458                         List<String> structTypes = structDecl.getStructTypes();
2459                         // Iterate over enum declarations
2460                         for (String stType : structTypes) {
2461                                 // Open a new file to write into
2462                                 FileWriter fw = new FileWriter(path + "/" + stType + ".hpp");
2463                                 pw = new PrintWriter(new BufferedWriter(fw));
2464                                 // Write file headers
2465                                 println("#ifndef _" + stType.toUpperCase() + "_HPP__");
2466                                 println("#define _" + stType.toUpperCase() + "_HPP__");
2467                                 println("using namespace std;");
2468                                 println("struct " + stType + " {");
2469                                 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
2470                                 List<String> structMembers = structDecl.getMembers(stType);
2471                                 for (int i = 0; i < structMembers.size(); i++) {
2472
2473                                         String memberType = structMemberTypes.get(i);
2474                                         String member = structMembers.get(i);
2475                                         String structTypeC = checkAndGetCplusType(memberType);
2476                                         String structComplete = checkAndGetCplusArray(structTypeC, member);
2477                                         println(structComplete + ";");
2478                                 }
2479                                 println("};\n");
2480                                 println("#endif");
2481                                 pw.close();
2482                                 System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
2483                         }
2484                 }
2485         }
2486
2487
2488         /**
2489          * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
2490          * <p>
2491          * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
2492          * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
2493          * The local interface has to be the input parameter for the stub and the stub 
2494          * interface has to be the input parameter for the local class.
2495          */
2496         public void generateCplusLocalInterfaces() throws IOException {
2497
2498                 // Create a new directory
2499                 createDirectory(dir);
2500                 String path = createDirectories(dir, VIRTUALS_DIRECTORY);
2501                 for (String intface : mapIntfacePTH.keySet()) {
2502                         // Open a new file to write into
2503                         FileWriter fw = new FileWriter(path + "/" + intface + ".hpp");
2504                         pw = new PrintWriter(new BufferedWriter(fw));
2505                         // Write file headers
2506                         println("#ifndef _" + intface.toUpperCase() + "_HPP__");
2507                         println("#define _" + intface.toUpperCase() + "_HPP__");
2508                         println("#include <iostream>");
2509                         // Pass in set of methods and get include classes
2510                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2511                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2512                         List<String> methods = intDecl.getMethods();
2513                         Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
2514                         printIncludeStatements(includeClasses); println("");
2515                         println("using namespace std;\n");
2516                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2517                         if (!intface.equals(mainClass)) // Forward declare if not main class
2518                                 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, true);
2519                         println("class " + intface); println("{");
2520                         println("public:");
2521                         // Write methods
2522                         writeMethodCplusLocalInterface(methods, intDecl);
2523                         println("};");
2524                         println("#endif");
2525                         pw.close();
2526                         System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
2527                 }
2528         }
2529
2530
2531         /**
2532          * HELPER: writeMethodCplusInterfaceForwardDecl() writes the forward declaration of the interface
2533          */
2534         private void writeMethodCplusInterfaceForwardDecl(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, boolean needNewIntface) {
2535
2536                 Set<String> isDefined = new HashSet<String>();
2537                 for (String method : methods) {
2538
2539                         List<String> methParams = intDecl.getMethodParams(method);
2540                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2541                         for (int i = 0; i < methParams.size(); i++) {
2542                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2543                                 // Check if this has callback object
2544                                 if (callbackClasses.contains(paramType)) {
2545                                         if (!isDefined.contains(paramType)) {
2546                                                 if (needNewIntface)
2547                                                         println("class " + getStubInterface(paramType) + ";\n");
2548                                                 else
2549                                                         println("class " + paramType + ";\n");
2550                                                 isDefined.add(paramType);
2551                                         }                                               
2552                                 }
2553                         }
2554                 }
2555         }
2556
2557
2558         /**
2559          * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
2560          * <p>
2561          * For C++ we use virtual classe as interface
2562          */
2563         public void generateCPlusInterfaces() throws IOException {
2564
2565                 // Create a new directory
2566                 String path = createDirectories(dir, subdir);
2567                 path = createDirectories(dir + "/" + subdir, VIRTUALS_DIRECTORY);
2568                 for (String intface : mapIntfacePTH.keySet()) {
2569
2570                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2571                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2572
2573                                 // Open a new file to write into
2574                                 String newIntface = intMeth.getKey();
2575                                 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
2576                                 pw = new PrintWriter(new BufferedWriter(fw));
2577                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2578                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2579                                 // Write file headers
2580                                 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
2581                                 println("#define _" + newIntface.toUpperCase() + "_HPP__");
2582                                 println("#include <iostream>");
2583                                 updateIntfaceObjIdMap(intface, newIntface);
2584                                 // Pass in set of methods and get import classes
2585                                 Set<String> methods = intMeth.getValue();
2586                                 Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, false);
2587                                 printIncludeStatements(includeClasses); println("");
2588                                 println("using namespace std;\n");
2589                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2590                                 writeMethodCplusInterfaceForwardDecl(methods, intDecl, callbackClasses, false);
2591                                 println("class " + newIntface);
2592                                 println("{");
2593                                 println("public:");
2594                                 // Write methods
2595                                 writeMethodCplusInterface(methods, intDecl);
2596                                 println("};");
2597                                 println("#endif");
2598                                 pw.close();
2599                                 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
2600                         }
2601                 }
2602         }
2603
2604
2605         /**
2606          * HELPER: writeMethodDeclCplusStub() writes the method declarations of the stub
2607          */
2608         private void writeMethodDeclCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
2609
2610                 for (String method : methods) {
2611
2612                         List<String> methParams = intDecl.getMethodParams(method);
2613                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2614                         print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2615                                 intDecl.getMethodId(method) + "(");
2616                         for (int i = 0; i < methParams.size(); i++) {
2617
2618                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2619                                 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2620                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2621                                 print(methParamComplete);
2622                                 // Check if this is the last element (don't print a comma)
2623                                 if (i != methParams.size() - 1) {
2624                                         print(", ");
2625                                 }
2626                         }
2627                         println(");");
2628                 }
2629         }
2630
2631
2632         /**
2633          * HELPER: writeMethodCplusStub() writes the methods of the stub
2634          */
2635         private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, String newStubClass) {
2636
2637                 for (String method : methods) {
2638
2639                         List<String> methParams = intDecl.getMethodParams(method);
2640                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2641                         // Print the mutex lock first
2642                         int methodNumId = intDecl.getMethodNumId(method);
2643                         String mutexVar = "mtx" + newStubClass + "MethodExec" + methodNumId;
2644                         println("mutex " + mutexVar + ";");
2645                         print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + newStubClass + "::" +
2646                                 intDecl.getMethodId(method) + "(");
2647                         boolean isCallbackMethod = false;
2648                         Set<String> callbackType = new HashSet<String>();
2649                         for (int i = 0; i < methParams.size(); i++) {
2650
2651                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2652                                 // Check if this has callback object
2653                                 if (callbackClasses.contains(paramType)) {
2654                                         isCallbackMethod = true;
2655                                         //callbackType = paramType;
2656                                         callbackType.add(paramType);
2657                                         // Even if there're 2 callback arguments, we expect them to be of the same interface
2658                                 }
2659                                 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2660                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2661                                 print(methParamComplete);
2662                                 // Check if this is the last element (don't print a comma)
2663                                 if (i != methParams.size() - 1) {
2664                                         print(", ");
2665                                 }
2666                         }
2667                         println(") { ");
2668                         println("lock_guard<mutex> guard(" + mutexVar + ");");
2669                         if (isCallbackMethod)
2670                                 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
2671                         writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType, isCallbackMethod);
2672                         println("}\n");
2673
2674                 }
2675         }
2676
2677
2678         /**
2679          * HELPER: writeCallbackInstantiationMethodBodyCplusStub() writes the callback object instantiation in the method of the stub class
2680          */
2681         private void writeCallbackInstantiationMethodBodyCplusStub(String paramIdent, String callbackType, int counter) {
2682
2683                 println("auto it" + counter + " = IoTRMIUtil::mapSkel->find(" + paramIdent + ");");
2684                 println("if (it" + counter + " == IoTRMIUtil::mapSkel->end()) {");
2685                 println("int newObjIdSent = rmiComm->getObjectIdCounter();");
2686                 println("objIdSent" + counter + ".push_back(newObjIdSent);");
2687                 println("rmiComm->decrementObjectIdCounter();");
2688                 println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
2689                 println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel" + counter + "));");
2690                 println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));");
2691                 println("thread th" + counter + " (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, skel" + counter + 
2692                         ", skel" + counter +");");
2693                 println("th" + counter + ".detach();");
2694                 println("while(!skel" + counter + "->didInitWaitInvoke());");
2695                 println("}");
2696                 println("else");
2697                 println("{");
2698                 println("auto itId = IoTRMIUtil::mapSkelId->find(" + paramIdent + ");");
2699                 println("objIdSent" + counter + ".push_back(itId->second);");
2700                 println("}");
2701         }
2702
2703
2704         /**
2705          * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
2706          */
2707         private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2708                         List<String> methPrmTypes, String method, Set<String> callbackType) {
2709
2710                 // Check if this is single object, array, or list of objects
2711                 boolean isArrayOrList = false;
2712                 String callbackParam = null;
2713                 for (int i = 0; i < methParams.size(); i++) {
2714                         String paramType = methPrmTypes.get(i);
2715                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2716                                 println("vector<int> objIdSent" + i + ";");
2717                                 String param = methParams.get(i);
2718                                 if (isArrayOrList(paramType, param)) {  // Generate loop                                
2719                                         println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
2720                                         writeCallbackInstantiationMethodBodyCplusStub("cb", returnGenericCallbackType(paramType), i);
2721                                         isArrayOrList = true;
2722                                         callbackParam = getSimpleIdentifier(param);
2723                                 } else {
2724                                         writeCallbackInstantiationMethodBodyCplusStub(getSimpleIdentifier(param), returnGenericCallbackType(paramType), i);
2725                                 }
2726                                 if (isArrayOrList)
2727                                         println("}");
2728                                 println("vector<int> ___paramCB" + i + " = objIdSent" + i + ";");
2729                         }
2730                 }
2731         }
2732
2733
2734         /**
2735          * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
2736          */
2737         private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
2738
2739                 // Iterate and find enum declarations
2740                 for (int i = 0; i < methParams.size(); i++) {
2741                         String paramType = methPrmTypes.get(i);
2742                         String param = methParams.get(i);
2743                         if (isEnumClass(getGenericType(paramType))) {
2744                         // Check if this is enum type
2745                                 if (isArrayOrList(paramType, param)) {  // An array or vector
2746                                         println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
2747                                         println("vector<int> paramEnum" + i + "(len" + i + ");");
2748                                         println("for (int i = 0; i < len" + i + "; i++) {");
2749                                         println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
2750                                         println("}");
2751                                 } else {        // Just one element
2752                                         println("vector<int> paramEnum" + i + "(1);");
2753                                         println("paramEnum" + i + "[0] = (int) " + param + ";");
2754                                 }
2755                         }
2756                 }
2757         }
2758
2759
2760         /**
2761          * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
2762          */
2763         private void checkAndWriteEnumRetTypeCplusStub(String retType, String method, InterfaceDecl intDecl) {
2764
2765                 // Strips off array "[]" for return type
2766                 String pureType = getSimpleArrayType(getGenericType(retType));
2767                 // Take the inner type of generic
2768                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2769                         pureType = getGenericType(retType);
2770                 if (isEnumClass(pureType)) {
2771                 // Check if this is enum type
2772                         println("vector<int> retEnumInt;");
2773                         println("void* retObj = &retEnumInt;");
2774                         println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2775                         writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
2776                         if (isArrayOrList(retType, retType)) {  // An array or vector
2777                                 println("int retLen = retEnumInt.size();");
2778                                 println("vector<" + pureType + "> retVal(retLen);");
2779                                 println("for (int i = 0; i < retLen; i++) {");
2780                                 println("retVal[i] = (" + pureType + ") retEnumInt[i];");
2781                                 println("}");
2782                         } else {        // Just one element
2783                                 println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
2784                         }
2785                         println("return retVal;");
2786                 }
2787         }
2788
2789
2790         /**
2791          * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
2792          */
2793         private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes, 
2794                         InterfaceDecl intDecl, String method) {
2795                 
2796                 // Iterate and find struct declarations
2797                 for (int i = 0; i < methParams.size(); i++) {
2798                         String paramType = methPrmTypes.get(i);
2799                         String param = methParams.get(i);
2800                         String simpleType = getGenericType(paramType);
2801                         if (isStructClass(simpleType)) {
2802                         // Check if this is enum type
2803                                 println("int numParam" + i + " = 1;");
2804                                 int methodNumId = intDecl.getMethodNumId(method);
2805                                 String helperMethod = methodNumId + "struct" + i;
2806                                 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
2807                                 //println("string retTypeStruct" + i + " = \"void\";");
2808                                 println("string paramClsStruct" + i + "[] = { \"int\" };");
2809                                 print("int structLen" + i + " = ");
2810                                 if (isArrayOrList(paramType, param)) {  // An array
2811                                         println(getSimpleArrayType(param) + ".size();");
2812                                 } else {        // Just one element
2813                                         println("1;");
2814                                 }
2815                                 println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
2816                                 println("rmiComm->remoteCall(objectId, methodIdStruct" + i + 
2817                                                 ", paramClsStruct" + i + ", paramObjStruct" + i + 
2818                                                 ", numParam" + i + ");\n");
2819                         }
2820                 }
2821         }
2822
2823
2824         /**
2825          * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
2826          */
2827         private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2828
2829                 // Iterate and find struct declarations - count number of params
2830                 for (int i = 0; i < methParams.size(); i++) {
2831                         String paramType = methPrmTypes.get(i);
2832                         String param = methParams.get(i);
2833                         String simpleType = getGenericType(paramType);
2834                         if (isStructClass(simpleType)) {
2835                                 int members = getNumOfMembers(simpleType);
2836                                 if (isArrayOrList(paramType, param)) {  // An array or list
2837                                         String structLen = getSimpleIdentifier(param) + ".size()";
2838                                         print(members + "*" + structLen);
2839                                 } else
2840                                         print(Integer.toString(members));
2841                         } else
2842                                 print("1");
2843                         if (i != methParams.size() - 1) {
2844                                 print("+");
2845                         }
2846                 }
2847         }
2848
2849
2850         /**
2851          * HELPER: writeStructMembersCplusStub() writes member parameters of struct
2852          */
2853         private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
2854
2855                 // Get the struct declaration for this struct and generate initialization code
2856                 StructDecl structDecl = getStructDecl(simpleType);
2857                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2858                 List<String> members = structDecl.getMembers(simpleType);
2859                 if (isArrayOrList(paramType, param)) {  // An array or list
2860                         println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
2861                 }
2862                 if (isArrayOrList(paramType, param)) {  // An array or list
2863                         for (int i = 0; i < members.size(); i++) {
2864                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2865                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
2866                                 print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
2867                                 print(getSimpleIdentifier(members.get(i)));
2868                                 println(";");
2869                         }
2870                         println("}");
2871                 } else {        // Just one struct element
2872                         for (int i = 0; i < members.size(); i++) {
2873                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2874                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
2875                                 print("paramObj[pos++] = &" + param + ".");
2876                                 print(getSimpleIdentifier(members.get(i)));
2877                                 println(";");
2878                         }
2879                 }
2880         }
2881
2882
2883         /**
2884          * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
2885          */
2886         private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
2887
2888                 print("int numParam = ");
2889                 writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
2890                 println(";");
2891                 println("void* paramObj[numParam];");
2892                 println("string paramCls[numParam];");
2893                 println("int pos = 0;");
2894                 // Iterate again over the parameters
2895                 for (int i = 0; i < methParams.size(); i++) {
2896                         String paramType = methPrmTypes.get(i);
2897                         String param = methParams.get(i);
2898                         String simpleType = getGenericType(paramType);
2899                         if (isStructClass(simpleType)) {
2900                                 writeStructMembersCplusStub(simpleType, paramType, param);
2901                         } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2902                                 println("paramCls[pos] = \"int\";");
2903                                 println("paramObj[pos++] = &___paramCB" + i + ";");
2904                         } else {
2905                                 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2906                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
2907                                 print("paramObj[pos++] = &");
2908                                 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2909                                 println(";");
2910                         }
2911                 }
2912                 
2913         }
2914
2915
2916         /**
2917          * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
2918          */
2919         private void writeStructRetMembersCplusStub(String simpleType, String retType) {
2920
2921                 // Get the struct declaration for this struct and generate initialization code
2922                 StructDecl structDecl = getStructDecl(simpleType);
2923                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2924                 List<String> members = structDecl.getMembers(simpleType);
2925                 if (isArrayOrList(retType, retType)) {  // An array or list
2926                         println("for(int i = 0; i < retLen; i++) {");
2927                 }
2928                 if (isArrayOrList(retType, retType)) {  // An array or list
2929                         for (int i = 0; i < members.size(); i++) {
2930                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2931                                 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
2932                                 println(" = retParam" + i + "[i];");
2933                         }
2934                         println("}");
2935                 } else {        // Just one struct element
2936                         for (int i = 0; i < members.size(); i++) {
2937                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2938                                 print("structRet." + getSimpleIdentifier(members.get(i)));
2939                                 println(" = retParam" + i + ";");
2940                         }
2941                 }
2942                 println("return structRet;");
2943         }
2944
2945
2946         /**
2947          * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
2948          */
2949         private void writeStructReturnCplusStub(String simpleType, String retType, String method, InterfaceDecl intDecl) {
2950
2951                 // Minimum retLen is 1 if this is a single struct object
2952                 println("int retLen = 0;");
2953                 println("void* retLenObj = { &retLen };");
2954                 // Handle the returned struct!!!
2955                 println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
2956                 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retLenObj);");
2957                 int numMem = getNumOfMembers(simpleType);
2958                 println("int numRet = " + numMem + "*retLen;");
2959                 println("string retCls[numRet];");
2960                 println("void* retObj[numRet];");
2961                 StructDecl structDecl = getStructDecl(simpleType);
2962                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2963                 List<String> members = structDecl.getMembers(simpleType);
2964                 // Set up variables
2965                 if (isArrayOrList(retType, retType)) {  // An array or list
2966                         for (int i = 0; i < members.size(); i++) {
2967                                 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2968                                 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2969                                 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + "[retLen];");
2970                         }
2971                 } else {        // Just one struct element
2972                         for (int i = 0; i < members.size(); i++) {
2973                                 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
2974                                 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
2975                                 println(getSimpleType(getEnumType(prmType)) + " retParam" + i + ";");
2976                         }
2977                 }
2978                 println("int retPos = 0;");
2979                 // Get the struct declaration for this struct and generate initialization code
2980                 if (isArrayOrList(retType, retType)) {  // An array or list
2981                         println("for(int i = 0; i < retLen; i++) {");
2982                         for (int i = 0; i < members.size(); i++) {
2983                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2984                                 println("retCls[retPos] = \"" + prmTypeC + "\";");
2985                                 println("retObj[retPos++] = &retParam" + i + "[i];");
2986                         }
2987                         println("}");
2988                 } else {        // Just one struct element
2989                         for (int i = 0; i < members.size(); i++) {
2990                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2991                                 println("retCls[retPos] = \"" + prmTypeC + "\";");
2992                                 println("retObj[retPos++] = &retParam" + i + ";");
2993                         }
2994                 }
2995                 writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getStructObjects(retCls, numRet, retObj);");
2996                 if (isArrayOrList(retType, retType)) {  // An array or list
2997                         println("vector<" + simpleType + "> structRet(retLen);");
2998                 } else
2999                         println(simpleType + " structRet;");
3000                 writeStructRetMembersCplusStub(simpleType, retType);
3001         }
3002
3003
3004         /**
3005          * HELPER: writeWaitForReturnValueCplus() writes the synchronization part for return values
3006          */
3007         private void writeWaitForReturnValueCplus(String method, InterfaceDecl intDecl, String getReturnValue) {
3008
3009                 println("// Waiting for return value");         
3010                 int methodNumId = intDecl.getMethodNumId(method);
3011                 println("while (!retValueReceived" + methodNumId + ");");
3012                 println(getReturnValue);
3013                 println("retValueReceived" + methodNumId + " = false;");
3014                 println("didGetReturnBytes.exchange(true);\n");
3015         }
3016
3017
3018         /**
3019          * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
3020          */
3021         private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
3022                         List<String> methPrmTypes, String method, Set<String> callbackType, boolean isCallbackMethod) {
3023
3024                 checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
3025                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
3026                 String retType = intDecl.getMethodType(method);
3027                 println("string retType = \"" + checkAndGetCplusRetClsType(getStructType(getEnumType(retType))) + "\";");
3028                 checkAndWriteEnumTypeCplusStub(methParams, methPrmTypes);
3029                 // Generate array of parameter types
3030                 if (isStructPresent(methParams, methPrmTypes)) {
3031                         writeStructParamClassCplusStub(methParams, methPrmTypes, callbackType);
3032                 } else {
3033                         println("int numParam = " + methParams.size() + ";");
3034                         print("string paramCls[] = { ");
3035                         for (int i = 0; i < methParams.size(); i++) {
3036                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3037                                 if (checkCallbackType(paramType, callbackType)) {
3038                                         print("\"int*\"");
3039                                 } else {
3040                                         String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3041                                         print("\"" + paramTypeC + "\"");
3042                                 }
3043                                 // Check if this is the last element (don't print a comma)
3044                                 if (i != methParams.size() - 1) {
3045                                         print(", ");
3046                                 }
3047                         }
3048                         println(" };");
3049                         // Generate array of parameter objects
3050                         print("void* paramObj[] = { ");
3051                         for (int i = 0; i < methParams.size(); i++) {
3052                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3053                                 if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3054                                         print("&___paramCB" + i);
3055                                 else
3056                                         print("&" + getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
3057                                 // Check if this is the last element (don't print a comma)
3058                                 if (i != methParams.size() - 1) {
3059                                         print(", ");
3060                                 }
3061                         }
3062                         println(" };");
3063                 }
3064                 // Check if this is "void"
3065                 if (retType.equals("void")) {
3066                         println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3067                 } else { // We do have a return value
3068                         // Generate array of parameter types
3069                         if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
3070                                 writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType, method, intDecl);
3071                         } else {
3072                         // Check if the return value NONPRIMITIVES
3073                                 if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {
3074                                         checkAndWriteEnumRetTypeCplusStub(retType, method, intDecl);
3075                                 } else {
3076                                         //if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3077                                         if (isArrayOrList(retType,retType))
3078                                                 println(checkAndGetCplusType(retType) + " retVal;");
3079                                         else {
3080                                                 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
3081                                         }
3082                                         println("void* retObj = &retVal;");
3083                                         println("rmiComm->remoteCall(objectId, methodId, paramCls, paramObj, numParam);");
3084                                         writeWaitForReturnValueCplus(method, intDecl, "rmiComm->getReturnValue(retType, retObj);");
3085                                         println("return retVal;");
3086                                 }
3087                         }
3088                 }
3089         }
3090
3091
3092         /**
3093          * HELPER: writePropertiesCplusPermission() writes the properties of the stub class
3094          */
3095         private void writePropertiesCplusPermission(String intface) {
3096
3097                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3098                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3099                         String newIntface = intMeth.getKey();
3100                         int newObjectId = getNewIntfaceObjectId(newIntface);
3101                         println("static set<int> set" + newObjectId + "Allowed;");
3102                 }
3103         }       
3104
3105         /**
3106          * HELPER: writePropertiesCplusStub() writes the properties of the stub class
3107          */
3108         private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist, 
3109                         Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3110
3111                 println("IoTRMIComm *rmiComm;");
3112                 // Get the object Id
3113                 Integer objId = mapIntfaceObjId.get(intface);
3114                 println("int objectId = " + objId + ";");
3115                 println("// Synchronization variables");
3116                 for (String method : methods) {
3117                         // Generate AtomicBooleans for methods that have return values
3118                         String returnType = intDecl.getMethodType(method);
3119                         int methodNumId = intDecl.getMethodNumId(method);
3120                         if (!returnType.equals("void")) {
3121                                 println("bool retValueReceived" + methodNumId + " = false;");
3122                         }
3123                 }
3124                 println("\n");
3125         }
3126
3127
3128         /**
3129          * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
3130          */
3131         private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, 
3132                         Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3133
3134                 println(newStubClass + "::" + newStubClass +
3135                         "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult) {");
3136                 println("rmiComm = new IoTRMICommClient(_portSend, _portRecv, _skeletonAddress, _rev, _bResult);");
3137                 // Register the AtomicBoolean variables
3138                 for (String method : methods) {
3139                         // Generate AtomicBooleans for methods that have return values
3140                         String returnType = intDecl.getMethodType(method);
3141                         int methodNumId = intDecl.getMethodNumId(method);
3142                         if (!returnType.equals("void")) {
3143                                 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3144                         }
3145                 }
3146                 println("IoTRMIUtil::mapStub->insert(make_pair(objectId, this));");
3147                 println("}\n");
3148         }
3149
3150
3151         /**
3152          * HELPER: writeCallbackConstructorCplusStub() writes the callback constructor of the stub class
3153          */
3154         private void writeCallbackConstructorCplusStub(String newStubClass, boolean callbackExist, 
3155                         Set<String> callbackClasses, Set<String> methods, InterfaceDecl intDecl) {
3156
3157                 println(newStubClass + "::" + newStubClass + "(IoTRMIComm* _rmiComm, int _objectId) {");
3158                 println("rmiComm = _rmiComm;");
3159                 println("objectId = _objectId;");
3160                 // Register the AtomicBoolean variables
3161                 for (String method : methods) {
3162                         // Generate AtomicBooleans for methods that have return values
3163                         String returnType = intDecl.getMethodType(method);
3164                         int methodNumId = intDecl.getMethodNumId(method);
3165                         if (!returnType.equals("void")) {
3166                                 println("rmiComm->registerStub(objectId, " + methodNumId + ", &retValueReceived" + methodNumId + ");");
3167                         }
3168                 }
3169                 println("}\n");
3170         }
3171
3172
3173         /**
3174          * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
3175          */
3176         private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
3177
3178                 println(newStubClass + "::~" + newStubClass + "() {");
3179                 println("if (rmiComm != NULL) {");
3180                 println("delete rmiComm;");
3181                 println("rmiComm = NULL;");
3182                 println("}");
3183                 println("}");
3184                 println("");
3185         }
3186
3187
3188         /**
3189          * generateCPlusStubClassesHpp() generate stubs based on the methods list in C++ (.hpp file)
3190          */
3191         public void generateCPlusStubClassesHpp() throws IOException {
3192
3193                 // Create a new directory
3194                 String path = createDirectories(dir, subdir);
3195                 for (String intface : mapIntfacePTH.keySet()) {
3196
3197                         // Check if there is more than 1 class that uses the same interface
3198                         List<String> drvList = mapInt2Drv.get(intface);
3199                         for(int i = 0; i < drvList.size(); i++) {
3200
3201                                 String driverClass = drvList.get(i);
3202                                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3203                                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3204                                         // Open a new file to write into
3205                                         String newIntface = intMeth.getKey();
3206                                         String newStubClass = newIntface + "_Stub";
3207                                         // Check if this interface is a callback class
3208                                         if(isCallbackClass(intface))
3209                                                 path = createDirectories(dir + "/" + subdir, driverClass);
3210                                         else
3211                                                 path = createDirectories(dir + "/" + subdir, controllerClass);
3212                                         FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
3213                                         pw = new PrintWriter(new BufferedWriter(fw));
3214                                         // Write file headers
3215                                         println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
3216                                         println("#define _" + newStubClass.toUpperCase() + "_HPP__");
3217                                         println("#include <iostream>");
3218                                         // Find out if there are callback objects
3219                                         Set<String> methods = intMeth.getValue();
3220                                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3221                                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3222                                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3223                                         boolean callbackExist = !callbackClasses.isEmpty();
3224                                         println("#include <thread>");
3225                                         println("#include <mutex>");
3226                                         List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
3227                                         printIncludeStatements(stdIncludeClasses); println("");
3228                                         println("#include \"" + newIntface + ".hpp\""); println("");            
3229                                         println("using namespace std;"); println("");
3230                                         println("class " + newStubClass + " : public " + newIntface); println("{");
3231                                         println("private:\n");
3232                                         writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
3233                                         println("public:\n");
3234                                         // Add default constructor and destructor
3235                                         println(newStubClass + "();");
3236                                         // Declarations
3237                                         println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
3238                                         println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
3239                                         println("~" + newStubClass + "();");
3240                                         // Write methods
3241                                         writeMethodDeclCplusStub(methods, intDecl);
3242                                         print("}"); println(";");
3243                                         println("#endif");
3244                                         pw.close();
3245                                         System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
3246                                 }
3247                         }
3248                 }
3249         }
3250
3251
3252         /**
3253          * writeStubExternalCFunctions() generate external functions for .so file
3254          */
3255         public void writeStubExternalCFunctions(String newStubClass) throws IOException {
3256
3257                 println("extern \"C\" void* create" + newStubClass + "(void** params) {");
3258                 println("// Args: int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult");
3259                 println("return new " + newStubClass + "(*((int*) params[0]), *((int*) params[1]), ((string*) params[2])->c_str(), " + 
3260                         "*((int*) params[3]), (bool*) params[4]);");
3261                 println("}\n");
3262                 println("extern \"C\" void destroy" + newStubClass + "(void* t) {");
3263                 println(newStubClass + "* obj = (" + newStubClass + "*) t;");
3264                 println("delete obj;");
3265                 println("}\n");
3266                 println("extern \"C\" void init" + newStubClass + "(void* t) {");
3267                 println("}\n");
3268         }
3269
3270
3271         /**
3272          * generateCPlusStubClassesCpp() generate stubs based on the methods list in C++ (.cpp file)
3273          */
3274         public void generateCPlusStubClassesCpp() throws IOException {
3275
3276                 // Create a new directory
3277                 String path = createDirectories(dir, subdir);
3278                 for (String intface : mapIntfacePTH.keySet()) {
3279
3280                         // Check if there is more than 1 class that uses the same interface
3281                         List<String> drvList = mapInt2Drv.get(intface);
3282                         for(int i = 0; i < drvList.size(); i++) {
3283
3284                                 String driverClass = drvList.get(i);
3285                                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3286                                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3287                                         // Open a new file to write into
3288                                         String newIntface = intMeth.getKey();
3289                                         String newStubClass = newIntface + "_Stub";
3290                                         // Check if this interface is a callback class
3291                                         if(isCallbackClass(intface))
3292                                                 path = createDirectories(dir + "/" + subdir, driverClass);
3293                                         else
3294                                                 path = createDirectories(dir + "/" + subdir, controllerClass);
3295                                         FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
3296                                         pw = new PrintWriter(new BufferedWriter(fw));
3297                                         // Write file headers
3298                                         println("#include <iostream>");
3299                                         // Find out if there are callback objects
3300                                         Set<String> methods = intMeth.getValue();
3301                                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
3302                                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
3303                                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
3304                                         boolean callbackExist = !callbackClasses.isEmpty();
3305                                         println("#include \"" + newStubClass + ".hpp\""); println("");
3306                                         for(String str: callbackClasses) {
3307                                                 if (intface.equals(mainClass))
3308                                                         println("#include \"" + str + "_Skeleton.cpp\"\n");
3309                                                 else
3310                                                         println("#include \"" + str + "_Skeleton.hpp\"\n");
3311                                         }
3312                                         println("using namespace std;"); println("");
3313                                         // Add default constructor and destructor
3314                                         writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3315                                         writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
3316                                         writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
3317                                         // Write methods
3318                                         writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
3319                                         // Write external functions for .so file
3320                                         writeStubExternalCFunctions(newStubClass);
3321                                         // TODO: Remove this later
3322                                         if (intface.equals(mainClass)) {
3323                                                 println("int main() {");
3324                                                 println("return 0;");
3325                                                 println("}");
3326                                         }
3327                                         pw.close();
3328                                         System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
3329                                 }
3330                         }
3331                 }
3332         }
3333
3334
3335         /**
3336          * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
3337          */
3338         private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
3339
3340                 println(intface + " *mainObj;");
3341                 println("IoTRMIComm *rmiComm;");
3342                 println("char* methodBytes;");
3343                 println("int methodLen;");
3344                 Integer objId = mapIntfaceObjId.get(intface);
3345                 println("int objectId = " + objId + ";");
3346                 // Keep track of object Ids of all stubs registered to this interface
3347                 writePropertiesCplusPermission(intface);
3348                 println("// Synchronization variables");
3349                 println("bool methodReceived = false;");
3350                 println("bool didAlreadyInitWaitInvoke = false;");
3351                 println("\n");
3352         }
3353
3354
3355         /**
3356          * HELPER: writeObjectIdCountInitializationCplus() writes the initialization of objIdCnt variable
3357          */
3358         private void writeObjectIdCountInitializationCplus(String newSkelClass, boolean callbackExist) {
3359
3360                 if (callbackExist)
3361                         println("int " + newSkelClass + "::objIdCnt = 0;");
3362         }
3363
3364
3365         /**
3366          * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
3367          */
3368         private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
3369
3370                 // Keep track of object Ids of all stubs registered to this interface
3371                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3372                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3373                         String newIntface = intMeth.getKey();
3374                         int newObjectId = getNewIntfaceObjectId(newIntface);
3375                         print("set<int> " + newSkelClass + "::set" + newObjectId + "Allowed { ");
3376                         Set<String> methodIds = intMeth.getValue();
3377                         int i = 0;
3378                         for (String methodId : methodIds) {
3379                                 int methodNumId = intDecl.getMethodNumId(methodId);
3380                                 print(Integer.toString(methodNumId));
3381                                 // Check if this is the last element (don't print a comma)
3382                                 if (i != methodIds.size() - 1) {
3383                                         print(", ");
3384                                 }
3385                                 i++;
3386                         }
3387                         println(" };");
3388                 }       
3389         }
3390
3391
3392         /**
3393          * HELPER: writeStructPermissionCplusSkeleton() writes permission for struct helper
3394          */
3395         private void writeStructPermissionCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
3396
3397                 // Use this set to handle two same methodIds
3398                 for (String method : methods) {
3399                         List<String> methParams = intDecl.getMethodParams(method);
3400                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3401                         // Check for params with structs
3402                         for (int i = 0; i < methParams.size(); i++) {
3403                                 String paramType = methPrmTypes.get(i);
3404                                 String param = methParams.get(i);
3405                                 String simpleType = getGenericType(paramType);
3406                                 if (isStructClass(simpleType)) {
3407                                         int methodNumId = intDecl.getMethodNumId(method);
3408                                         String helperMethod = methodNumId + "struct" + i;
3409                                         int helperMethodNumId = intDecl.getHelperMethodNumId(helperMethod);
3410                                         // Iterate over interfaces to give permissions to
3411                                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
3412                                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
3413                                                 String newIntface = intMeth.getKey();
3414                                                 int newObjectId = getNewIntfaceObjectId(newIntface);
3415                                                 println("set" + newObjectId + "Allowed.insert(" + helperMethodNumId + ");");
3416                                         }
3417                                 }
3418                         }
3419                 }
3420         }
3421
3422
3423         /**
3424          * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
3425          */
3426         private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3427
3428                 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, int _portSend, int _portRecv) {");
3429                 println("bool _bResult = false;");
3430                 println("mainObj = _mainObj;");
3431                 println("rmiComm = new IoTRMICommServer(_portSend, _portRecv, &_bResult);");
3432                 println("IoTRMIUtil::mapSkel->insert(make_pair(_mainObj, this));");
3433                 println("IoTRMIUtil::mapSkelId->insert(make_pair(_mainObj, objectId));");
3434                 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3435                 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3436                 println("thread th1 (&" + newSkelClass + "::___waitRequestInvokeMethod, this, this);");
3437                 println("th1.join();");
3438                 println("}\n");
3439         }
3440
3441
3442         /**
3443          * HELPER: writeCallbackConstructorCplusSkeleton() writes the callback constructor of the skeleton class
3444          */
3445         private void writeCallbackConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
3446
3447                 println(newSkelClass + "::" + newSkelClass + "(" + intface + " *_mainObj, IoTRMIComm *_rmiComm, int _objectId) {");
3448                 println("bool _bResult = false;");
3449                 println("mainObj = _mainObj;");
3450                 println("rmiComm = _rmiComm;");
3451                 println("objectId = _objectId;");
3452                 println("rmiComm->registerSkeleton(objectId, &methodReceived);");
3453                 writeStructPermissionCplusSkeleton(methods, intDecl, intface);
3454                 println("}\n");
3455         }
3456
3457
3458         /**
3459          * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
3460          */
3461         private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
3462
3463                 println(newSkelClass + "::~" + newSkelClass + "() {");
3464                 println("if (rmiComm != NULL) {");
3465                 println("delete rmiComm;");
3466                 println("rmiComm = NULL;");
3467                 println("}");
3468                 println("}");
3469                 println("");
3470         }
3471
3472
3473         /**
3474          * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
3475          */
3476         private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
3477
3478                 if (methodType.equals("void"))
3479                         print("mainObj->" + methodId + "(");
3480                 else
3481                         print("return mainObj->" + methodId + "(");
3482                 for (int i = 0; i < methParams.size(); i++) {
3483
3484                         print(getSimpleIdentifier(methParams.get(i)));
3485                         // Check if this is the last element (don't print a comma)
3486                         if (i != methParams.size() - 1) {
3487                                 print(", ");
3488                         }
3489                 }
3490                 println(");");
3491         }
3492
3493
3494         /**
3495          * HELPER: writeMethodDeclCplusSkeleton() writes the method declaration of the skeleton class
3496          */
3497         private void writeMethodDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, 
3498                         Set<String> callbackClasses) {
3499
3500                 for (String method : methods) {
3501
3502                         List<String> methParams = intDecl.getMethodParams(method);
3503                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3504                         String methodId = intDecl.getMethodId(method);
3505                         String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3506                         print(methodType + " " + methodId + "(");
3507                         boolean isCallbackMethod = false;
3508                         String callbackType = null;
3509                         for (int i = 0; i < methParams.size(); i++) {
3510
3511                                 String origParamType = methPrmTypes.get(i);
3512                                 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
3513                                         isCallbackMethod = true;
3514                                         callbackType = origParamType;   
3515                                 }
3516                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3517                                 String methPrmType = checkAndGetCplusType(paramType);
3518                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3519                                 print(methParamComplete);
3520                                 // Check if this is the last element (don't print a comma)
3521                                 if (i != methParams.size() - 1) {
3522                                         print(", ");
3523                                 }
3524                         }
3525                         println(");");
3526                 }
3527         }
3528
3529
3530         /**
3531          * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
3532          */
3533         private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3534
3535                 for (String method : methods) {
3536
3537                         List<String> methParams = intDecl.getMethodParams(method);
3538                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
3539                         String methodId = intDecl.getMethodId(method);
3540                         String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
3541                         print(methodType + " " + newSkelClass + "::" + methodId + "(");
3542                         for (int i = 0; i < methParams.size(); i++) {
3543
3544                                 String origParamType = methPrmTypes.get(i);
3545                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
3546                                 String methPrmType = checkAndGetCplusType(paramType);
3547                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3548                                 print(methParamComplete);
3549                                 // Check if this is the last element (don't print a comma)
3550                                 if (i != methParams.size() - 1) {
3551                                         print(", ");
3552                                 }
3553                         }
3554                         println(") {");
3555                         // Now, write the body of skeleton!
3556                         writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
3557                         println("}\n");
3558                 }
3559         }
3560
3561
3562         /**
3563          * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
3564          */
3565         private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3566
3567                 for (int i = 0; i < methParams.size(); i++) {
3568                         String paramType = methPrmTypes.get(i);
3569                         String param = methParams.get(i);
3570                         if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
3571                                 println("vector<int> numStubIdArray" + i + ";");
3572                 }
3573         }
3574
3575
3576         /**
3577          * HELPER: writeCallbackInstantiationCplusStubGeneration() writes the instantiation of callback stubs
3578          */
3579         private void writeCallbackInstantiationCplusStubGeneration(String exchParamType, int counter) {
3580
3581                 println(exchParamType + "* newStub" + counter + " = NULL;");
3582                 println("auto it" + counter + " = IoTRMIUtil::mapStub->find(objIdRecv" + counter + ");");
3583                 println("if (it" + counter + " == IoTRMIUtil::mapStub->end()) {");
3584                 println("newStub" + counter + " = new " + exchParamType + "_Stub(rmiComm, objIdRecv" + counter + ");");
3585                 println("IoTRMIUtil::mapStub->insert(make_pair(objIdRecv" + counter + ", newStub" + counter + "));");
3586                 println("rmiComm->setObjectIdCounter(objIdRecv" + counter + ");");
3587                 println("rmiComm->decrementObjectIdCounter();");
3588                 println("}");
3589                 println("else {");
3590                 println("newStub" + counter + " = (" + exchParamType + "_Stub*) it" + counter + "->second;");
3591                 println("}");
3592         }
3593
3594
3595         /**
3596          * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
3597          */
3598         private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, Set<String> callbackType) {
3599
3600                 // Iterate over callback objects
3601                 for (int i = 0; i < methParams.size(); i++) {
3602                         String paramType = methPrmTypes.get(i);
3603                         String param = methParams.get(i);
3604                         // Generate a loop if needed
3605                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
3606                                 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
3607                                 if (isArrayOrList(paramType, param)) {
3608                                         println("vector<" + exchParamType + "*> stub" + i + ";");
3609                                         println("for (int i = 0; i < numStubIdArray" + i + ".size(); i++) {");
3610                                         println("int objIdRecv" + i + " = numStubIdArray" + i + "[i];");
3611                                         writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3612                                         println("stub" + i + ".push_back(newStub" + i + ");");
3613                                         println("}");
3614                                 } else {
3615                                         println("int objIdRecv" + i + " = numStubIdArray" + i + "[0];");
3616                                         writeCallbackInstantiationCplusStubGeneration(exchParamType, i);
3617                                         println(exchParamType + "* stub" + i + " = newStub" + i + ";");
3618                                 }
3619                         }
3620                 }
3621         }
3622
3623
3624         /**
3625          * HELPER: checkAndWriteEnumTypeCplusSkeleton() writes the enum type (convert from enum to int)
3626          */
3627         private void checkAndWriteEnumTypeCplusSkeleton(List<String> methParams, List<String> methPrmTypes) {
3628
3629                 // Iterate and find enum declarations
3630                 for (int i = 0; i < methParams.size(); i++) {
3631                         String paramType = methPrmTypes.get(i);
3632                         String param = methParams.get(i);
3633                         String simpleType = getGenericType(paramType);
3634                         if (isEnumClass(simpleType)) {
3635                         // Check if this is enum type
3636                                 if (isArrayOrList(paramType, param)) {  // An array
3637                                         println("int len" + i + " = paramEnumInt" + i + ".size();");
3638                                         println("vector<" + simpleType + "> paramEnum" + i + "(len" + i + ");");
3639                                         println("for (int i=0; i < len" + i + "; i++) {");
3640                                         println("paramEnum" + i + "[i] = (" + simpleType + ") paramEnumInt" + i + "[i];");
3641                                         println("}");
3642                                 } else {        // Just one element
3643                                         println(simpleType + " paramEnum" + i + ";");
3644                                         println("paramEnum" + i + " = (" + simpleType + ") paramEnumInt" + i + "[0];");
3645                                 }
3646                         }
3647                 }
3648         }
3649
3650
3651         /**
3652          * HELPER: checkAndWriteEnumRetTypeCplusSkeleton() writes the enum return type (convert from enum to int)
3653          */
3654         private void checkAndWriteEnumRetTypeCplusSkeleton(String retType) {
3655
3656                 // Strips off array "[]" for return type
3657                 String pureType = getSimpleArrayType(getGenericType(retType));
3658                 // Take the inner type of generic
3659                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
3660                         pureType = getGenericType(retType);
3661                 if (isEnumClass(pureType)) {
3662                 // Check if this is enum type
3663                         // Enum decoder
3664                         if (isArrayOrList(retType, retType)) {  // An array
3665                                 println("int retLen = retEnum.size();");
3666                                 println("vector<int> retEnumInt(retLen);");
3667                                 println("for (int i=0; i < retLen; i++) {");
3668                                 println("retEnumInt[i] = (int) retEnum[i];");
3669                                 println("}");
3670                         } else {        // Just one element
3671                                 println("vector<int> retEnumInt(1);");
3672                                 println("retEnumInt[0] = (int) retEnum;");
3673                         }
3674                 }
3675         }
3676
3677
3678         /**
3679          * HELPER: writeMethodInputParameters() writes the parameter variables for C++ skeleton
3680          */
3681         private void writeMethodInputParameters(List<String> methParams, List<String> methPrmTypes, 
3682                         Set<String> callbackClasses, String methodId) {
3683
3684                 print(methodId + "(");
3685                 for (int i = 0; i < methParams.size(); i++) {
3686                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3687                         if (callbackClasses.contains(paramType))
3688                                 print("stub" + i);
3689                         else if (isEnumClass(getGenericType(paramType)))        // Check if this is enum type
3690                                 print("paramEnum" + i);
3691                         else if (isStructClass(getGenericType(paramType)))      // Struct type
3692                                 print("paramStruct" + i);
3693                         else
3694                                 print(getSimpleIdentifier(methParams.get(i)));
3695                         if (i != methParams.size() - 1) {
3696                                 print(", ");
3697                         }
3698                 }
3699                 println(");");
3700         }
3701
3702
3703         /**
3704          * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
3705          */
3706         private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3707                         List<String> methPrmTypes, String method, boolean isCallbackMethod, Set<String> callbackType,
3708                         String methodId, Set<String> callbackClasses) {
3709
3710                 println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
3711                 if (isCallbackMethod)
3712                         writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType);
3713                 checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes);
3714                 writeStructMembersInitCplusSkeleton(intDecl, methParams, methPrmTypes, method);
3715                 // Check if this is "void"
3716                 String retType = intDecl.getMethodType(method);
3717                 // Check if this is "void"
3718                 if (retType.equals("void")) {
3719                         writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3720                 } else { // We do have a return value
3721                         if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3722                                 print(checkAndGetCplusType(retType) + " retEnum = ");
3723                         else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3724                                 print(checkAndGetCplusType(retType) + " retStruct = ");
3725                         else
3726                                 print(checkAndGetCplusType(retType) + " retVal = ");
3727                         writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
3728                         checkAndWriteEnumRetTypeCplusSkeleton(retType);
3729                         if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3730                                 writeStructReturnCplusSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
3731                         if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
3732                                 println("void* retObj = &retEnumInt;");
3733                         else
3734                                 if (!isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3735                                         println("void* retObj = &retVal;");
3736                         String retTypeC = checkAndGetCplusType(retType);
3737                         if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
3738                                 println("rmiComm->sendReturnObj(retObj, retCls, numRetObj, localMethodBytes);");
3739                         else
3740                                 println("rmiComm->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\", localMethodBytes);");
3741                 }
3742         }
3743
3744
3745         /**
3746          * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
3747          */
3748         private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3749                         List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3750
3751                 // Generate array of parameter types
3752                 boolean isCallbackMethod = false;
3753                 Set<String> callbackType = new HashSet<String>();
3754                 print("string paramCls[] = { ");
3755                 for (int i = 0; i < methParams.size(); i++) {
3756                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3757                         if (callbackClasses.contains(paramType)) {
3758                                 isCallbackMethod = true;
3759                                 callbackType.add(paramType);
3760                                 print("\"int*\"");
3761                         } else {        // Generate normal classes if it's not a callback object
3762                                 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3763                                 print("\"" + paramTypeC + "\"");
3764                         }
3765                         if (i != methParams.size() - 1) {
3766                                 print(", ");
3767                         }
3768                 }
3769                 println(" };");
3770                 println("int numParam = " + methParams.size() + ";");
3771                 if (isCallbackMethod)
3772                         writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
3773                 // Generate parameters
3774                 for (int i = 0; i < methParams.size(); i++) {
3775                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3776                         if (!callbackClasses.contains(paramType)) {
3777                                 String methParamType = methPrmTypes.get(i);
3778                                 if (isEnumClass(getSimpleArrayType(getGenericType(methParamType)))) {   
3779                                 // Check if this is enum type
3780                                         println("vector<int> paramEnumInt" + i + ";");
3781                                 } else {
3782                                         String methPrmType = checkAndGetCplusType(methParamType);
3783                                         String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
3784                     println(methParamComplete + ";");
3785                                 }
3786                         }
3787                 }
3788                 // Generate array of parameter objects
3789                 print("void* paramObj[] = { ");
3790                 for (int i = 0; i < methParams.size(); i++) {
3791                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
3792                         if (callbackClasses.contains(paramType))
3793                                 print("&numStubIdArray" + i);
3794                         else if (isEnumClass(getGenericType(paramType)))        // Check if this is enum type
3795                                 print("&paramEnumInt" + i);
3796                         else
3797                                 print("&" + getSimpleIdentifier(methParams.get(i)));
3798                         if (i != methParams.size() - 1) {
3799                                 print(", ");
3800                         }
3801                 }
3802                 println(" };");
3803                 // Write the return value part
3804                 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, 
3805                         callbackType, methodId, callbackClasses);
3806         }
3807
3808
3809         /**
3810          * HELPER: writeStructMembersCplusSkeleton() writes member parameters of struct
3811          */
3812         private void writeStructMembersCplusSkeleton(String simpleType, String paramType, 
3813                         String param, String method, InterfaceDecl intDecl, int iVar) {
3814
3815                 // Get the struct declaration for this struct and generate initialization code
3816                 StructDecl structDecl = getStructDecl(simpleType);
3817                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3818                 List<String> members = structDecl.getMembers(simpleType);
3819                 int methodNumId = intDecl.getMethodNumId(method);
3820                 String counter = "struct" + methodNumId + "Size" + iVar;
3821                 // Set up variables
3822                 if (isArrayOrList(paramType, param)) {  // An array or list
3823                         for (int i = 0; i < members.size(); i++) {
3824                                 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3825                                 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3826                                 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + "[" + counter + "];");
3827                         }
3828                 } else {        // Just one struct element
3829                         for (int i = 0; i < members.size(); i++) {
3830                                 String prmTypeC = checkAndGetCplusType(memTypes.get(i));
3831                                 String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
3832                                 println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + ";");
3833                         }
3834                 }
3835                 if (isArrayOrList(paramType, param)) {  // An array or list
3836                         println("for(int i = 0; i < " + counter + "; i++) {");
3837                 }
3838                 if (isArrayOrList(paramType, param)) {  // An array or list
3839                         for (int i = 0; i < members.size(); i++) {
3840                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3841                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
3842                                 println("paramObj[pos++] = &param" + iVar + i + "[i];");
3843                         }
3844                         println("}");
3845                 } else {        // Just one struct element
3846                         for (int i = 0; i < members.size(); i++) {
3847                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3848                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
3849                                 println("paramObj[pos++] = &param" + iVar + i + ";");
3850                         }
3851                 }
3852         }
3853
3854
3855         /**
3856          * HELPER: writeStructMembersInitCplusSkeleton() writes member parameters initialization of struct
3857          */
3858         private void writeStructMembersInitCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3859                         List<String> methPrmTypes, String method) {
3860
3861                 for (int i = 0; i < methParams.size(); i++) {
3862                         String paramType = methPrmTypes.get(i);
3863                         String param = methParams.get(i);
3864                         String simpleType = getGenericType(paramType);
3865                         if (isStructClass(simpleType)) {
3866                                 int methodNumId = intDecl.getMethodNumId(method);
3867                                 String counter = "struct" + methodNumId + "Size" + i;
3868                                 // Declaration
3869                                 if (isArrayOrList(paramType, param)) {  // An array or list
3870                                         println("vector<" + simpleType + "> paramStruct" + i + "(" + counter + ");");
3871                                 } else
3872                                         println(simpleType + " paramStruct" + i + ";");
3873                                 // Initialize members
3874                                 StructDecl structDecl = getStructDecl(simpleType);
3875                                 List<String> members = structDecl.getMembers(simpleType);
3876                                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3877                                 if (isArrayOrList(paramType, param)) {  // An array or list
3878                                         println("for(int i = 0; i < " + counter + "; i++) {");
3879                                         for (int j = 0; j < members.size(); j++) {
3880                                                 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
3881                                                 println(" = param" + i + j + "[i];");
3882                                         }
3883                                         println("}");
3884                                 } else {        // Just one struct element
3885                                         for (int j = 0; j < members.size(); j++) {
3886                                                 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
3887                                                 println(" = param" + i + j + ";");
3888                                         }
3889                                 }
3890                         }
3891                 }
3892         }
3893
3894
3895         /**
3896          * HELPER: writeStructReturnCplusSkeleton() writes parameters of struct for return statement
3897          */
3898         private void writeStructReturnCplusSkeleton(String simpleType, String retType) {
3899
3900                 // Minimum retLen is 1 if this is a single struct object
3901                 if (isArrayOrList(retType, retType))
3902                         println("int retLen = retStruct.size();");
3903                 else    // Just single struct object
3904                         println("int retLen = 1;");
3905                 println("void* retLenObj = &retLen;");
3906                 println("rmiComm->sendReturnObj(retLenObj, \"int\", localMethodBytes);");
3907                 int numMem = getNumOfMembers(simpleType);
3908                 println("int numRetObj = " + numMem + "*retLen;");
3909                 println("string retCls[numRetObj];");
3910                 println("void* retObj[numRetObj];");
3911                 println("int retPos = 0;");
3912                 // Get the struct declaration for this struct and generate initialization code
3913                 StructDecl structDecl = getStructDecl(simpleType);
3914                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
3915                 List<String> members = structDecl.getMembers(simpleType);
3916                 if (isArrayOrList(retType, retType)) {  // An array or list
3917                         println("for(int i = 0; i < retLen; i++) {");
3918                         for (int i = 0; i < members.size(); i++) {
3919                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3920                                 println("retCls[retPos] = \"" + prmTypeC + "\";");
3921                                 print("retObj[retPos++] = &retStruct[i].");
3922                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3923                                 println(";");
3924                         }
3925                         println("}");
3926                 } else {        // Just one struct element
3927                         for (int i = 0; i < members.size(); i++) {
3928                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
3929                                 println("retCls[retPos] = \"" + prmTypeC + "\";");
3930                                 print("retObj[retPos++] = &retStruct.");
3931                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
3932                                 println(";");
3933                         }
3934                 }
3935
3936         }
3937
3938
3939         /**
3940          * HELPER: writeMethodHelperStructCplusSkeleton() writes the struct in skeleton
3941          */
3942         private void writeMethodHelperStructCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
3943                         List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
3944
3945                 // Generate array of parameter objects
3946                 boolean isCallbackMethod = false;
3947                 Set<String> callbackType = new HashSet<String>();
3948                 print("int numParam = ");
3949                 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
3950                 println(";");
3951                 println("string paramCls[numParam];");
3952                 println("void* paramObj[numParam];");
3953                 println("int pos = 0;");
3954                 // Iterate again over the parameters
3955                 for (int i = 0; i < methParams.size(); i++) {
3956                         String paramType = methPrmTypes.get(i);
3957                         String param = methParams.get(i);
3958                         String simpleType = getGenericType(paramType);
3959                         if (isStructClass(simpleType)) {
3960                                 writeStructMembersCplusSkeleton(simpleType, paramType, param, method, intDecl, i);
3961                         } else {
3962                                 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
3963                                 if (callbackClasses.contains(prmType)) {
3964                                         isCallbackMethod = true;
3965                                         callbackType.add(prmType);
3966                                         println("vector<int> numStubIdArray" + i + ";");
3967                                         println("paramCls[pos] = \"int*\";");
3968                                         println("paramObj[pos++] = &numStubIdArray" + i + ";");
3969                                 } else {        // Generate normal classes if it's not a callback object
3970                                         String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
3971                                         if (isEnumClass(getGenericType(paramTypeC))) {  // Check if this is enum type
3972                                                 println("vector<int> paramEnumInt" + i + ";");
3973                                         } else {
3974                                                 String methParamComplete = checkAndGetCplusArray(paramTypeC, methParams.get(i));
3975                                                 println(methParamComplete + ";");
3976                                         }
3977                                         String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
3978                                         println("paramCls[pos] = \"" + prmTypeC + "\";");
3979                                         if (isEnumClass(getGenericType(paramType)))     // Check if this is enum type
3980                                                 println("paramObj[pos++] = &paramEnumInt" + i + ";");
3981                                         else
3982                                                 println("paramObj[pos++] = &" + getSimpleIdentifier(methParams.get(i)) + ";");
3983                                 }
3984                         }
3985                 }
3986                 // Write the return value part
3987                 writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, 
3988                         callbackType, methodId, callbackClasses);
3989         }
3990
3991
3992         /**
3993          * HELPER: writeMethodHelperDeclCplusSkeleton() writes the method helper declarations of the skeleton class
3994          */
3995         private void writeMethodHelperDeclCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String newSkelClass) {
3996
3997                 // Use this set to handle two same methodIds
3998                 Set<String> uniqueMethodIds = new HashSet<String>();
3999                 for (String method : methods) {
4000
4001                         List<String> methParams = intDecl.getMethodParams(method);
4002                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4003                         if (isStructPresent(methParams, methPrmTypes)) {        // Treat struct differently
4004                                 String methodId = intDecl.getMethodId(method);
4005                                 print("void ___");
4006                                 String helperMethod = methodId;
4007                                 if (uniqueMethodIds.contains(methodId))
4008                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
4009                                 else
4010                                         uniqueMethodIds.add(methodId);
4011                                 String retType = intDecl.getMethodType(method);
4012                                 print(helperMethod + "(");
4013                                 boolean begin = true;
4014                                 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4015                                         String paramType = methPrmTypes.get(i);
4016                                         String param = methParams.get(i);
4017                                         String simpleType = getGenericType(paramType);
4018                                         if (isStructClass(simpleType)) {
4019                                                 if (!begin)     // Generate comma for not the beginning variable
4020                                                         print(", ");
4021                                                 else
4022                                                         begin = false;
4023                                                 int methodNumId = intDecl.getMethodNumId(method);
4024                                                 print("int struct" + methodNumId + "Size" + i);
4025                                         }
4026                                 }
4027                                 println(", " + newSkelClass + "* skel);");
4028                         } else {
4029                                 String methodId = intDecl.getMethodId(method);
4030                                 print("void ___");
4031                                 String helperMethod = methodId;
4032                                 if (uniqueMethodIds.contains(methodId))
4033                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
4034                                 else
4035                                         uniqueMethodIds.add(methodId);
4036                                 // Check if this is "void"
4037                                 String retType = intDecl.getMethodType(method);
4038                                 println(helperMethod + "(" + newSkelClass + "* skel);");
4039                         }
4040                 }
4041                 // Write method helper for structs
4042                 writeMethodHelperStructDeclSetupCplusSkeleton(methods, intDecl, newSkelClass);
4043         }
4044
4045
4046         /**
4047          * HELPER: writeMethodHelperStructDeclSetupCplusSkeleton() writes the struct method helper declaration in skeleton class
4048          */
4049         private void writeMethodHelperStructDeclSetupCplusSkeleton(Collection<String> methods, 
4050                         InterfaceDecl intDecl, String newSkelClass) {
4051
4052                 // Use this set to handle two same methodIds
4053                 for (String method : methods) {
4054
4055                         List<String> methParams = intDecl.getMethodParams(method);
4056                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4057                         // Check for params with structs
4058                         for (int i = 0; i < methParams.size(); i++) {
4059                                 String paramType = methPrmTypes.get(i);
4060                                 String param = methParams.get(i);
4061                                 String simpleType = getGenericType(paramType);
4062                                 if (isStructClass(simpleType)) {
4063                                         int methodNumId = intDecl.getMethodNumId(method);
4064                                         print("int ___");
4065                                         String helperMethod = methodNumId + "struct" + i;
4066                                         println(helperMethod + "(" + newSkelClass + "* skel);");
4067                                 }
4068                         }
4069                 }
4070         }
4071
4072
4073         /**
4074          * HELPER: writeMethodBytesCopy() writes the methodBytes copy part in C++ skeleton
4075          */
4076         private void writeMethodBytesCopy() {
4077
4078                 println("char* localMethodBytes = new char[methodLen];");
4079                 println("memcpy(localMethodBytes, skel->methodBytes, methodLen);");
4080                 println("didGetMethodBytes.exchange(true);");
4081         }
4082
4083
4084         /**
4085          * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
4086          */
4087         private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, 
4088                         Set<String> callbackClasses, String newSkelClass) {
4089
4090                 // Use this set to handle two same methodIds
4091                 Set<String> uniqueMethodIds = new HashSet<String>();
4092                 for (String method : methods) {
4093
4094                         List<String> methParams = intDecl.getMethodParams(method);
4095                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4096                         if (isStructPresent(methParams, methPrmTypes)) {        // Treat struct differently
4097                                 String methodId = intDecl.getMethodId(method);
4098                                 print("void " + newSkelClass + "::___");
4099                                 String helperMethod = methodId;
4100                                 if (uniqueMethodIds.contains(methodId))
4101                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
4102                                 else
4103                                         uniqueMethodIds.add(methodId);
4104                                 String retType = intDecl.getMethodType(method);
4105                                 print(helperMethod + "(");
4106                                 boolean begin = true;
4107                                 for (int i = 0; i < methParams.size(); i++) { // Print size variables
4108                                         String paramType = methPrmTypes.get(i);
4109                                         String param = methParams.get(i);
4110                                         String simpleType = getGenericType(paramType);
4111                                         if (isStructClass(simpleType)) {
4112                                                 if (!begin)     // Generate comma for not the beginning variable
4113                                                         print(", ");
4114                                                 else
4115                                                         begin = false;
4116                                                 int methodNumId = intDecl.getMethodNumId(method);
4117                                                 print("int struct" + methodNumId + "Size" + i);
4118                                         }
4119                                 }
4120                                 println(", " + newSkelClass + "* skel) {");
4121                                 writeMethodBytesCopy();
4122                                 writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4123                                 println("delete[] localMethodBytes;");
4124                                 println("}\n");
4125                         } else {
4126                                 String methodId = intDecl.getMethodId(method);
4127                                 print("void " + newSkelClass + "::___");
4128                                 String helperMethod = methodId;
4129                                 if (uniqueMethodIds.contains(methodId))
4130                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
4131                                 else
4132                                         uniqueMethodIds.add(methodId);
4133                                 // Check if this is "void"
4134                                 String retType = intDecl.getMethodType(method);
4135                                 println(helperMethod + "(" + newSkelClass + "* skel) {");
4136                                 writeMethodBytesCopy();
4137                                 // Now, write the helper body of skeleton!
4138                                 writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
4139                                 println("delete[] localMethodBytes;");
4140                                 println("}\n");
4141                         }
4142                 }
4143                 // Write method helper for structs
4144                 writeMethodHelperStructSetupCplusSkeleton(methods, intDecl, newSkelClass);
4145         }
4146
4147
4148         /**
4149          * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class
4150          */
4151         private void writeMethodHelperStructSetupCplusSkeleton(Collection<String> methods, 
4152                         InterfaceDecl intDecl, String newSkelClass) {
4153
4154                 // Use this set to handle two same methodIds
4155                 for (String method : methods) {
4156
4157                         List<String> methParams = intDecl.getMethodParams(method);
4158                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4159                         // Check for params with structs
4160                         for (int i = 0; i < methParams.size(); i++) {
4161                                 String paramType = methPrmTypes.get(i);
4162                                 String param = methParams.get(i);
4163                                 String simpleType = getGenericType(paramType);
4164                                 if (isStructClass(simpleType)) {
4165                                         int methodNumId = intDecl.getMethodNumId(method);
4166                                         print("int " + newSkelClass + "::___");
4167                                         String helperMethod = methodNumId + "struct" + i;
4168                                         println(helperMethod + "(" + newSkelClass + "* skel) {");
4169                                         // Now, write the helper body of skeleton!
4170                                         writeMethodBytesCopy();
4171                                         println("string paramCls[] = { \"int\" };");
4172                                         println("int numParam = 1;");
4173                                         println("int param0 = 0;");
4174                                         println("void* paramObj[] = { &param0 };");
4175                                         println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4176                                         println("return param0;");
4177                                         println("delete[] localMethodBytes;");
4178                                         println("}\n");
4179                                 }
4180                         }
4181                 }
4182         }
4183
4184
4185         /**
4186          * HELPER: writeMethodHelperStructSetupCplusCallbackSkeleton() writes the method helper of struct in skeleton class
4187          */
4188         private void writeMethodHelperStructSetupCplusCallbackSkeleton(Collection<String> methods, 
4189                         InterfaceDecl intDecl) {
4190
4191                 // Use this set to handle two same methodIds
4192                 for (String method : methods) {
4193
4194                         List<String> methParams = intDecl.getMethodParams(method);
4195                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4196                         // Check for params with structs
4197                         for (int i = 0; i < methParams.size(); i++) {
4198                                 String paramType = methPrmTypes.get(i);
4199                                 String param = methParams.get(i);
4200                                 String simpleType = getGenericType(paramType);
4201                                 if (isStructClass(simpleType)) {
4202                                         int methodNumId = intDecl.getMethodNumId(method);
4203                                         print("int ___");
4204                                         String helperMethod = methodNumId + "struct" + i;
4205                                         println(helperMethod + "(IoTRMIObject* rmiObj) {");
4206                                         // Now, write the helper body of skeleton!
4207                                         println("string paramCls[] = { \"int\" };");
4208                                         println("int numParam = 1;");
4209                                         println("int param0 = 0;");
4210                                         println("void* paramObj[] = { &param0 };");
4211                                         println("rmiComm->getMethodParams(paramCls, numParam, paramObj, localMethodBytes);");
4212                                         println("return param0;");
4213                                         println("}\n");
4214                                 }
4215                         }
4216                 }
4217         }
4218
4219
4220         /**
4221          * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
4222          */
4223         private void writeCplusMethodPermission(String intface) {
4224
4225                 // Get all the different stubs
4226                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
4227                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
4228                         String newIntface = intMeth.getKey();
4229                         int newObjectId = getNewIntfaceObjectId(newIntface);
4230                         println("if (_objectId == objectId) {");
4231                         println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
4232                         println("cerr << \"Object with object Id: \" << _objectId << \"  is not allowed to access method: \" << methodId << endl;");
4233                         println("return;");
4234                         println("}");
4235                         println("}");
4236                         println("else {");
4237                         println("continue;");
4238                         println("}");
4239                 }
4240         }
4241
4242
4243         /**
4244          * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
4245          */
4246         private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, 
4247                         boolean callbackExist, String intface, String newSkelClass) {
4248
4249                 // Use this set to handle two same methodIds
4250                 Set<String> uniqueMethodIds = new HashSet<String>();
4251                 println("void " + newSkelClass + "::___waitRequestInvokeMethod(" + newSkelClass + "* skel) {");
4252                 // Write variables here if we have callbacks or enums or structs
4253                 writeCountVarStructSkeleton(methods, intDecl);
4254                 println("skel->didAlreadyInitWaitInvoke = true;");
4255                 println("while (true) {");
4256                 println("if (!methodReceived) {");
4257                 println("continue;");
4258                 println("}");
4259                 println("skel->methodBytes = skel->rmiComm->getMethodBytes();");
4260                 println("skel->methodLen = skel->rmiComm->getMethodLength();");
4261                 println("methodReceived = false;");
4262                 println("int _objectId = skel->rmiComm->getObjectId(skel->methodBytes);");
4263                 println("int methodId = skel->rmiComm->getMethodId(skel->methodBytes);");
4264                 // Generate permission check
4265                 writeCplusMethodPermission(intface);
4266                 println("switch (methodId) {");
4267                 // Print methods and method Ids
4268                 for (String method : methods) {
4269                         String methodId = intDecl.getMethodId(method);
4270                         int methodNumId = intDecl.getMethodNumId(method);
4271                         println("case " + methodNumId + ": {");
4272                         print("thread th" + methodNumId + " (&" + newSkelClass + "::___");
4273                         String helperMethod = methodId;
4274                         if (uniqueMethodIds.contains(methodId))
4275                                 helperMethod = helperMethod + methodNumId;
4276                         else
4277                                 uniqueMethodIds.add(methodId);
4278                         print(helperMethod + ", skel, ");
4279                         boolean structExists = writeInputCountVarStructCplusSkeleton(method, intDecl);
4280                         if (structExists)
4281                                 print(", ");
4282                         println("skel);");
4283                         println("th" + methodNumId + ".detach(); break;");
4284                         println("}");
4285                 }
4286                 writeMethodCallStructCplusSkeleton(methods, intDecl);
4287                 println("default: ");
4288                 println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
4289                 println("return;");
4290                 println("}");
4291                 println("}");
4292                 println("}\n");
4293         }
4294
4295
4296         /**
4297          * generateCplusSkeletonClassHpp() generate skeletons based on the methods list in C++ (.hpp file)
4298          */
4299         public void generateCplusSkeletonClassHpp() throws IOException {
4300
4301                 // Create a new directory
4302                 String path = createDirectories(dir, subdir);
4303                 for (String intface : mapIntfacePTH.keySet()) {
4304                 
4305                         // Check if there is more than 1 class that uses the same interface
4306                         List<String> drvList = mapInt2Drv.get(intface);
4307                         for(int i = 0; i < drvList.size(); i++) {
4308
4309                                 // Open a new file to write into
4310                                 String newSkelClass = intface + "_Skeleton";
4311                                 // Get driver class
4312                                 String driverClass = drvList.get(i);
4313                                 // Check if this interface is a callback class
4314                                 if(isCallbackClass(intface))
4315                                         path = createDirectories(dir + "/" + subdir, controllerClass);
4316                                 else
4317                                         path = createDirectories(dir + "/" + subdir, driverClass);
4318                                 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
4319                                 pw = new PrintWriter(new BufferedWriter(fw));
4320                                 // Write file headers
4321                                 println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
4322                                 println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
4323                                 println("#include <iostream>");
4324                                 println("#include \"" + intface + ".hpp\"\n");
4325                                 // Pass in set of methods and get import classes
4326                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4327                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4328                                 List<String> methods = intDecl.getMethods();
4329                                 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
4330                                 printIncludeStatements(stdIncludeClasses); println("");
4331                                 println("using namespace std;\n");
4332                                 // Find out if there are callback objects
4333                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4334                                 boolean callbackExist = !callbackClasses.isEmpty();
4335                                 // Write class header
4336                                 println("class " + newSkelClass + " : public " + intface); println("{");
4337                                 println("private:\n");
4338                                 // Write properties
4339                                 writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
4340                                 println("public:\n");
4341                                 // Write constructors
4342                                 println(newSkelClass + "();");
4343                                 println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
4344                                 println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
4345                                 // Write deconstructor
4346                                 println("~" + newSkelClass + "();");
4347                                 // Write method declarations
4348                                 println("bool didInitWaitInvoke();");
4349                                 writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
4350                                 // Write method helper declarations
4351                                 writeMethodHelperDeclCplusSkeleton(methods, intDecl, newSkelClass);
4352                                 // Write waitRequestInvokeMethod() declaration - main loop
4353                                 println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
4354                                 println("};");
4355                                 writePermissionInitializationCplus(intface, newSkelClass, intDecl);
4356                                 println("#endif");
4357                                 pw.close();
4358                                 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
4359                         }
4360                 }
4361         }
4362
4363         /**
4364          * HELPER: writeReturnDidAlreadyInitWaitInvoke() writes the function to return didAlreadyInitWaitInvoke
4365          */
4366         private void writeReturnDidAlreadyInitWaitInvoke(String newSkelClass) {
4367
4368                 println("bool " + newSkelClass + "::didInitWaitInvoke() {");
4369                 println("return didAlreadyInitWaitInvoke;");
4370                 println("}\n");
4371         }
4372
4373
4374         /**
4375          * writeSkelExternalCFunctions() generate external functions for .so file
4376          */
4377         public void writeSkelExternalCFunctions(String newSkelClass, String intface) throws IOException {
4378
4379                 println("extern \"C\" void* create" + newSkelClass + "(void** params) {");
4380                 println("// Args: *_mainObj, int _portSend, int _portRecv");
4381                 println("return new " + newSkelClass + "((" + intface + "*) params[0], *((int*) params[1]), *((int*) params[2]));");
4382                 println("}\n");
4383                 println("extern \"C\" void destroy" + newSkelClass + "(void* t) {");
4384                 println(newSkelClass + "* obj = (" + newSkelClass + "*) t;");
4385                 println("delete obj;");
4386                 println("}\n");
4387                 println("extern \"C\" void init" + newSkelClass + "(void* t) {");
4388                 println("}\n");
4389         }
4390
4391
4392         /**
4393          * generateCplusSkeletonClassCpp() generate skeletons based on the methods list in C++ (.cpp file)
4394          */
4395         public void generateCplusSkeletonClassCpp() throws IOException {
4396
4397                 // Create a new directory
4398                 String path = createDirectories(dir, subdir);
4399                 for (String intface : mapIntfacePTH.keySet()) {
4400
4401                         // Check if there is more than 1 class that uses the same interface
4402                         List<String> drvList = mapInt2Drv.get(intface);
4403                         for(int i = 0; i < drvList.size(); i++) {
4404
4405                                 // Open a new file to write into
4406                                 String newSkelClass = intface + "_Skeleton";
4407                                 // Get driver class
4408                                 String driverClass = drvList.get(i);
4409                                 // Check if this interface is a callback class
4410                                 if(isCallbackClass(intface))
4411                                         path = createDirectories(dir + "/" + subdir, controllerClass);
4412                                 else
4413                                         path = createDirectories(dir + "/" + subdir, driverClass);
4414                                 FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
4415                                 pw = new PrintWriter(new BufferedWriter(fw));
4416                                 // Write file headers
4417                                 println("#include <iostream>");
4418                                 println("#include \"" + newSkelClass + ".hpp\"\n");
4419                                 // Pass in set of methods and get import classes
4420                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4421                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
4422                                 List<String> methods = intDecl.getMethods();
4423                                 // Find out if there are callback objects
4424                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
4425                                 boolean callbackExist = !callbackClasses.isEmpty();
4426                                 for(String str: callbackClasses) {
4427                                         if (intface.equals(mainClass))
4428                                                 println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
4429                                         else
4430                                                 println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
4431                                 }
4432                                 println("using namespace std;\n");
4433                                 // Write constructor
4434                                 writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4435                                 // Write callback constructor
4436                                 writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
4437                                 // Write deconstructor
4438                                 writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
4439                                 // Write didInitWaitInvoke() to return bool
4440                                 writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
4441                                 // Write methods
4442                                 writeMethodCplusSkeleton(methods, intDecl, newSkelClass);
4443                                 // Write method helper
4444                                 writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
4445                                 // Write waitRequestInvokeMethod() - main loop
4446                                 writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
4447                                 // Write external functions for .so file
4448                                 writeSkelExternalCFunctions(newSkelClass, intface);
4449                                 // TODO: Remove this later
4450                                 if (intface.equals(mainClass)) {
4451                                         println("int main() {");
4452                                         println("return 0;");
4453                                         println("}");
4454                                 }
4455                                 pw.close();
4456                                 System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
4457                         }
4458                 }
4459         }
4460
4461
4462         /**
4463          * generateInitializer() generate initializer based on type
4464          */
4465         public String generateCplusInitializer(String type) {
4466
4467                 // Generate dummy returns for now
4468                 if (type.equals("short")||
4469                         type.equals("int")      ||
4470                         type.equals("long") ||
4471                         type.equals("float")||
4472                         type.equals("double")) {
4473
4474                         return "0";
4475                 } else if ( type.equals("String") ||
4476                                         type.equals("string")) {
4477   
4478                         return "\"\"";
4479                 } else if ( type.equals("char") ||
4480                                         type.equals("byte")) {
4481
4482                         return "\' \'";
4483                 } else if ( type.equals("boolean")) {
4484
4485                         return "false";
4486                 } else {
4487                         return "NULL";
4488                 }
4489         }
4490
4491
4492         /**
4493          * setDirectory() sets a new directory for stub files
4494          */
4495         public void setDirectory(String _subdir) {
4496
4497                 subdir = _subdir;
4498         }
4499
4500
4501         /**
4502          * printUsage() prints the usage of this compiler
4503          */
4504         public static void printUsage() {
4505
4506                 System.out.println();
4507                 System.out.println("Vigilia interface and stub compiler version 1.0");
4508                 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
4509                 System.out.println("All rights reserved.");
4510                 System.out.println("Usage:");
4511                 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
4512                 System.out.println("\t\tDisplay this help texts\n\n");
4513                 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
4514                 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
4515                 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
4516                 System.out.println("Options:");
4517                 System.out.println("\t-cont\t<controller-class>\tSpecify controller class name");
4518                 System.out.println("\t-drv\t<driver-class>\t\tSpecify driver class name");
4519                 System.out.println("\t-cplus\t<directory>\t\tGenerate C++ stub files");
4520                 System.out.println("\t-java\t<directory>\t\tGenerate Java stub files\n");
4521                 System.out.println("\t\tNote: The options -cont and -drv have to be defined before -cplus and -java");
4522                 System.out.println();
4523         }
4524
4525
4526         /**
4527          * parseFile() prepares Lexer and Parser objects, then parses the file
4528          */
4529         public static ParseNode parseFile(String file) {
4530
4531                 ParseNode pn = null;
4532                 try {
4533                         ComplexSymbolFactory csf = new ComplexSymbolFactory();
4534                         ScannerBuffer lexer = 
4535                                 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
4536                         Parser parse = new Parser(lexer,csf);
4537                         pn = (ParseNode) parse.parse().value;
4538                 } catch (Exception e) {
4539                         e.printStackTrace();
4540                         throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file + "\n");
4541                 }
4542
4543                 return pn;
4544         }
4545
4546
4547         /**================
4548          * Basic helper functions
4549          **================
4550          */
4551         boolean newline=true;
4552         int tablevel=0;
4553
4554         private void print(String str) {
4555                 if (newline) {
4556                         int tab=tablevel;
4557                         if (str.equals("}"))
4558                                 tab--;
4559                         for(int i=0; i<tab; i++)
4560                                 pw.print("\t");
4561                 }
4562                 pw.print(str);
4563                 updatetabbing(str);
4564                 newline=false;
4565         }
4566
4567
4568         /**
4569          * This function converts Java to C++ type for compilation
4570          */
4571         private String convertType(String type) {
4572
4573                 if (mapPrimitives.containsKey(type))
4574                         return mapPrimitives.get(type);
4575                 else
4576                         return type;
4577         }
4578
4579
4580         /**
4581          * A collection of methods with print-to-file functionality
4582          */
4583         private void println(String str) {
4584                 if (newline) {
4585                         int tab = tablevel;
4586                         if (str.contains("}") && !str.contains("{"))
4587                                 tab--;
4588                         for(int i=0; i<tab; i++)
4589                                 pw.print("\t");
4590                 }
4591                 pw.println(str);
4592                 updatetabbing(str);
4593                 newline = true;
4594         }
4595
4596
4597         private void updatetabbing(String str) {
4598
4599                 tablevel+=count(str,'{')-count(str,'}');
4600         }
4601
4602
4603         private int count(String str, char key) {
4604                 char[] array = str.toCharArray();
4605                 int count = 0;
4606                 for(int i=0; i<array.length; i++) {
4607                         if (array[i] == key)
4608                                 count++;
4609                 }
4610                 return count;
4611         }
4612
4613
4614         private void createDirectory(String dirName) {
4615
4616                 File file = new File(dirName);
4617                 if (!file.exists()) {
4618                         if (file.mkdir()) {
4619                                 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
4620                         } else {
4621                                 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
4622                         }
4623                 } else {
4624                         System.out.println("IoTCompiler: Directory " + dirName + " exists...");
4625                 }
4626         }
4627
4628
4629         // Create a directory and possibly a sub directory
4630         private String createDirectories(String dir, String subdir) {
4631
4632                 String path = dir;
4633                 createDirectory(path);
4634                 if (subdir != null) {
4635                         path = path + "/" + subdir;
4636                         createDirectory(path);
4637                 }
4638                 return path;
4639         }
4640
4641
4642         // Inserting array members into a Map object
4643         // that maps arrKey to arrVal objects
4644         private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
4645
4646                 for(int i = 0; i < arrKey.length; i++) {
4647
4648                         map.put(arrKey[i], arrVal[i]);
4649                 }
4650         }
4651
4652
4653         // Check and find object Id for new interface in mapNewIntfaceObjId (callbacks)
4654         // Throw an error if the new interface is not found!
4655         // Basically the compiler needs to parse the policy (and requires) files for callback class first
4656         private int getNewIntfaceObjectId(String newIntface) {
4657
4658                 int retObjId = mapNewIntfaceObjId.get(newIntface);
4659                 return retObjId;
4660         }
4661
4662
4663         // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, USERDEFINED, ENUM, or STRUCT
4664         private ParamCategory getParamCategory(String paramType) {
4665
4666                 if (mapPrimitives.containsKey(paramType)) {
4667                         return ParamCategory.PRIMITIVES;
4668                 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
4669                 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
4670                         return ParamCategory.NONPRIMITIVES;
4671                 } else if (isEnumClass(paramType)) {
4672                         return ParamCategory.ENUM;
4673                 } else if (isStructClass(paramType)) {
4674                         return ParamCategory.STRUCT;
4675                 } else
4676                         return ParamCategory.USERDEFINED;
4677         }
4678
4679
4680         // Return full class name for non-primitives to generate Java import statements
4681         // e.g. java.util.Set for Set
4682         private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
4683
4684                 return mapNonPrimitivesJava.get(paramNonPrimitives);
4685         }
4686
4687
4688         // Return full class name for non-primitives to generate Cplus include statements
4689         // e.g. #include <set> for Set
4690         private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
4691
4692                 return mapNonPrimitivesCplus.get(paramNonPrimitives);
4693         }
4694
4695
4696         // Get simple types, e.g. HashSet for HashSet<...>
4697         // Basically strip off the "<...>"
4698         private String getSimpleType(String paramType) {
4699
4700                 // Check if this is generics
4701                 if(paramType.contains("<")) {
4702                         String[] type = paramType.split("<");
4703                         return type[0];
4704                 } else
4705                         return paramType;
4706         }
4707
4708
4709         // Generate a set of standard classes for import statements
4710         private List<String> getStandardJavaIntfaceImportClasses() {
4711
4712                 List<String> importClasses = new ArrayList<String>();
4713                 // Add the standard list first
4714                 importClasses.add("java.util.List");
4715                 importClasses.add("java.util.ArrayList");
4716
4717                 return importClasses;
4718         }
4719
4720
4721         // Generate a set of standard classes for import statements
4722         private List<String> getStandardJavaImportClasses() {
4723
4724                 List<String> importClasses = new ArrayList<String>();
4725                 // Add the standard list first
4726                 importClasses.add("java.io.IOException");
4727                 importClasses.add("java.util.List");
4728                 importClasses.add("java.util.ArrayList");
4729                 importClasses.add("java.util.Arrays");
4730                 importClasses.add("java.util.Map");
4731                 importClasses.add("java.util.HashMap");
4732                 importClasses.add("java.util.concurrent.atomic.AtomicBoolean");
4733                 importClasses.add("iotrmi.Java.IoTRMIComm");
4734                 importClasses.add("iotrmi.Java.IoTRMICommClient");
4735                 importClasses.add("iotrmi.Java.IoTRMICommServer");
4736                 importClasses.add("iotrmi.Java.IoTRMIUtil");
4737
4738                 return importClasses;
4739         }
4740
4741
4742         // Generate a set of standard classes for import statements
4743         private List<String> getStandardCplusIncludeClasses() {
4744
4745                 List<String> importClasses = new ArrayList<String>();
4746                 // Add the standard list first
4747                 importClasses.add("<vector>");
4748                 importClasses.add("<set>");
4749                 importClasses.add("\"IoTRMIComm.hpp\"");
4750                 importClasses.add("\"IoTRMICommClient.hpp\"");
4751                 importClasses.add("\"IoTRMICommServer.hpp\"");
4752
4753                 return importClasses;
4754         }
4755
4756
4757         // Combine all classes for import statements
4758         private List<String> getAllLibClasses(Collection<String> stdLibClasses, Collection<String> libClasses) {
4759
4760                 List<String> allLibClasses = new ArrayList<String>(stdLibClasses);
4761                 // Iterate over the list of import classes
4762                 for (String str : libClasses) {
4763                         if (!allLibClasses.contains(str)) {
4764                                 allLibClasses.add(str);
4765                         }
4766                 }
4767                 return allLibClasses;
4768         }
4769
4770
4771
4772         // Generate a set of classes for import statements
4773         private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
4774
4775                 Set<String> importClasses = new HashSet<String>();
4776                 for (String method : methods) {
4777                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4778                         for (String paramType : methPrmTypes) {
4779
4780                                 String simpleType = getSimpleType(paramType);
4781                                 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4782                                         importClasses.add(getNonPrimitiveJavaClass(simpleType));
4783                                 }
4784                         }
4785                 }
4786                 return importClasses;
4787         }
4788
4789
4790         // Handle and return the correct enum declaration
4791         // In Java, if we declare enum in Camera interface, then it becomes "Camera.<enum>"
4792         private String getEnumParamDecl(String type, InterfaceDecl intDecl) {
4793
4794                 // Strips off array "[]" for return type
4795                 String pureType = getSimpleArrayType(type);
4796                 // Take the inner type of generic
4797                 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4798                         pureType = getTypeOfGeneric(type)[0];
4799                 if (isEnumClass(pureType)) {
4800                         String enumType = intDecl.getInterface() + "." + type;
4801                         return enumType;
4802                 } else
4803                         return type;
4804         }
4805
4806
4807         // Handle and return the correct type
4808         private String getEnumParam(String type, String param, int i) {
4809
4810                 // Strips off array "[]" for return type
4811                 String pureType = getSimpleArrayType(type);
4812                 // Take the inner type of generic
4813                 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4814                         pureType = getTypeOfGeneric(type)[0];
4815                 if (isEnumClass(pureType)) {
4816                         String enumParam = "paramEnum" + i;
4817                         return enumParam;
4818                 } else
4819                         return param;
4820         }
4821
4822
4823         // Handle and return the correct enum declaration translate into int[]
4824         private String getEnumType(String type) {
4825
4826                 // Strips off array "[]" for return type
4827                 String pureType = getSimpleArrayType(type);
4828                 // Take the inner type of generic
4829                 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4830                         pureType = getGenericType(type);
4831                 if (isEnumClass(pureType)) {
4832                         String enumType = "int[]";
4833                         return enumType;
4834                 } else
4835                         return type;
4836         }
4837
4838         // Handle and return the correct enum declaration translate into int* for C
4839         private String getEnumCplusClsType(String type) {
4840
4841                 // Strips off array "[]" for return type
4842                 String pureType = getSimpleArrayType(type);
4843                 // Take the inner type of generic
4844                 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4845                         pureType = getGenericType(type);
4846                 if (isEnumClass(pureType)) {
4847                         String enumType = "int*";
4848                         return enumType;
4849                 } else
4850                         return type;
4851         }
4852
4853
4854         // Handle and return the correct struct declaration
4855         private String getStructType(String type) {
4856
4857                 // Strips off array "[]" for return type
4858                 String pureType = getSimpleArrayType(type);
4859                 // Take the inner type of generic
4860                 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES)
4861                         pureType = getGenericType(type);
4862                 if (isStructClass(pureType)) {
4863                         String structType = "int";
4864                         return structType;
4865                 } else
4866                         return type;
4867         }
4868
4869
4870         // Check if this an enum declaration
4871         private boolean isEnumClass(String type) {
4872
4873                 // Just iterate over the set of interfaces
4874                 for (String intface : mapIntfacePTH.keySet()) {
4875                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4876                         EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
4877                         Set<String> setEnumDecl = enumDecl.getEnumDeclarations();
4878                         if (setEnumDecl.contains(type))
4879                                 return true;
4880                 }
4881                 return false;
4882         }
4883
4884
4885         // Check if this an struct declaration
4886         private boolean isStructClass(String type) {
4887
4888                 // Just iterate over the set of interfaces
4889                 for (String intface : mapIntfacePTH.keySet()) {
4890                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4891                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4892                         List<String> listStructDecl = structDecl.getStructTypes();
4893                         if (listStructDecl.contains(type))
4894                                 return true;
4895                 }
4896                 return false;
4897         }
4898
4899
4900         // Return a struct declaration
4901         private StructDecl getStructDecl(String type) {
4902
4903                 // Just iterate over the set of interfaces
4904                 for (String intface : mapIntfacePTH.keySet()) {
4905                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4906                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4907                         List<String> listStructDecl = structDecl.getStructTypes();
4908                         if (listStructDecl.contains(type))
4909                                 return structDecl;
4910                 }
4911                 return null;
4912         }
4913
4914
4915         // Return number of members (-1 if not found)
4916         private int getNumOfMembers(String type) {
4917
4918                 // Just iterate over the set of interfaces
4919                 for (String intface : mapIntfacePTH.keySet()) {
4920                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
4921                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
4922                         List<String> listStructDecl = structDecl.getStructTypes();
4923                         if (listStructDecl.contains(type))
4924                                 return structDecl.getNumOfMembers(type);
4925                 }
4926                 return -1;
4927         }
4928
4929
4930         // Generate a set of classes for include statements
4931         private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl, String intface, boolean needExchange) {
4932
4933                 Set<String> includeClasses = new HashSet<String>();
4934                 for (String method : methods) {
4935
4936                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4937                         List<String> methParams = intDecl.getMethodParams(method);
4938                         for (int i = 0; i < methPrmTypes.size(); i++) {
4939
4940                                 String genericType = getGenericType(methPrmTypes.get(i));
4941                                 String simpleType = getSimpleType(methPrmTypes.get(i));
4942                                 String param = methParams.get(i);
4943                                 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
4944                                         includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
4945                                 //} else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
4946                                 }
4947                                 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.USERDEFINED) {
4948                                         // For original interface, we need it exchanged... not for stub interfaces
4949                                         if (needExchange) {
4950                                                 //includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
4951                                                 includeClasses.add("\"" + exchangeParamType(getSimpleArrayType(genericType)) + ".hpp\"");
4952                                         } else {
4953                                                 //includeClasses.add("\"" + simpleType + ".hpp\"");
4954                                                 includeClasses.add("\"" + getSimpleArrayType(genericType) + ".hpp\"");
4955                                         }
4956                                 }
4957                                 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.ENUM) {
4958                                         includeClasses.add("\"" + genericType + ".hpp\"");
4959                                 }
4960                                 if (getParamCategory(getSimpleArrayType(genericType)) == ParamCategory.STRUCT) {
4961                                         includeClasses.add("\"" + genericType + ".hpp\"");
4962                                 }
4963                                 if (param.contains("[]")) {
4964                                 // Check if this is array for C++; translate into vector
4965                                         includeClasses.add("<vector>");
4966                                 }
4967                         }
4968                 }
4969                 return includeClasses;
4970         }
4971
4972
4973         // Generate a set of callback classes
4974         private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
4975
4976                 Set<String> callbackClasses = new HashSet<String>();
4977                 for (String method : methods) {
4978
4979                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
4980                         List<String> methParams = intDecl.getMethodParams(method);
4981                         for (int i = 0; i < methPrmTypes.size(); i++) {
4982
4983                                 String type = methPrmTypes.get(i);
4984                                 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4985                                         callbackClasses.add(type);
4986                                 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
4987                                 // Can be a List<...> of callback objects ...
4988                                         String genericType = getTypeOfGeneric(type)[0];
4989                                         if (getParamCategory(type) == ParamCategory.USERDEFINED) {
4990                                                 callbackClasses.add(type);
4991                                         }
4992                                 }
4993                         }
4994                 }
4995                 return callbackClasses;
4996         }
4997         
4998
4999         // Check if this is a callback class
5000         private boolean isCallbackClass(String className) {
5001
5002                 Set<String> intfaceSet = mapIntDeclHand.keySet();
5003                 for(String intface : intfaceSet) {
5004
5005                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
5006                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
5007                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
5008                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
5009                                 Set<String> methods = intMeth.getValue();
5010                                 for (String method : methods) {
5011
5012                                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
5013                                         List<String> methParams = intDecl.getMethodParams(method);
5014                                         for (int i = 0; i < methPrmTypes.size(); i++) {
5015
5016                                                 String type = methPrmTypes.get(i);
5017                                                 if (getParamCategory(type) == ParamCategory.USERDEFINED) {
5018                                                         // Final check to see if this is the searched class
5019                                                         if (type.equals(className))
5020                                                                 return true;
5021                                                 } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
5022                                                 // Can be a List<...> of callback objects ...
5023                                                         String genericType = getTypeOfGeneric(type)[0];
5024                                                         if (getParamCategory(type) == ParamCategory.USERDEFINED) {
5025                                                                 if (type.equals(className))
5026                                                                         return true;
5027                                                         }
5028                                                 }
5029                                         }
5030                                 }
5031                         }
5032                 }
5033
5034                 return false;
5035         }
5036
5037
5038         // Print import statements into file
5039         private void printImportStatements(Collection<String> importClasses) {
5040
5041                 for(String cls : importClasses) {
5042                         println("import " + cls + ";");
5043                 }
5044         }
5045
5046
5047         // Print include statements into file
5048         private void printIncludeStatements(Collection<String> includeClasses) {
5049
5050                 for(String cls : includeClasses) {
5051                         println("#include " + cls);
5052                 }
5053         }
5054
5055
5056         // Get the C++ version of a non-primitive type
5057         // e.g. set for Set and map for Map
5058         // Input nonPrimitiveType has to be generics in format
5059         private String[] getTypeOfGeneric(String nonPrimitiveType) {
5060
5061                 // Handle <, >, and , for 2-type generic/template
5062                 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
5063                 return substr;
5064         }
5065
5066
5067         // Gets generic type inside "<" and ">"
5068         private String getGenericType(String type) {
5069
5070                 // Handle <, >, and , for 2-type generic/template
5071                 if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
5072                         String[] substr = type.split("<")[1].split(">")[0].split(",");
5073                         return substr[0];
5074                 } else
5075                         return type;
5076         }
5077
5078
5079         // This helper function strips off array declaration, e.g. int[] becomes int
5080         private String getSimpleArrayType(String type) {
5081
5082                 // Handle [ for array declaration
5083                 String substr = type;
5084                 if (type.contains("[]")) {
5085                         substr = type.split("\\[\\]")[0];
5086                 }
5087                 return substr;
5088         }
5089
5090
5091         // This helper function strips off array declaration, e.g. D[] becomes D
5092         private String getSimpleIdentifier(String ident) {
5093
5094                 // Handle [ for array declaration
5095                 String substr = ident;
5096                 if (ident.contains("[]")) {
5097                         substr = ident.split("\\[\\]")[0];
5098                 }
5099                 return substr;
5100         }
5101
5102
5103         // Checks and gets type in C++
5104         private String checkAndGetCplusType(String paramType) {
5105
5106                 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
5107                         return convertType(paramType);
5108                 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
5109
5110                         // Check for generic/template format
5111                         if (paramType.contains("<") && paramType.contains(">")) {
5112
5113                                 String genericClass = getSimpleType(paramType);
5114                                 String genericType = getGenericType(paramType);
5115                                 String cplusTemplate = null;
5116                                 cplusTemplate = getNonPrimitiveCplusClass(genericClass);
5117                                 if(getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED) {
5118                                         cplusTemplate = cplusTemplate + "<" + genericType + "*>";
5119                                 } else {
5120                                         cplusTemplate = cplusTemplate + "<" + convertType(genericType) + ">";
5121                                 }
5122                                 return cplusTemplate;
5123                         } else
5124                                 return getNonPrimitiveCplusClass(paramType);
5125                 } else if(paramType.contains("[]")) {   // Array type (used for return type only)
5126                         String cArray = "vector<" + convertType(getSimpleArrayType(paramType)) + ">";
5127                         return cArray;
5128                 } else if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5129                         return paramType + "*";
5130                 } else
5131                         // Just return it as is if it's not non-primitives
5132                         return paramType;
5133         }
5134
5135
5136         // Detect array declaration, e.g. int A[],
5137         //              then generate "int A[]" in C++ as "vector<int> A"
5138         private String checkAndGetCplusArray(String paramType, String param) {
5139
5140                 String paramComplete = null;
5141                 // Check for array declaration
5142                 if (param.contains("[]")) {
5143                         paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
5144                 } else
5145                         // Just return it as is if it's not an array
5146                         paramComplete = paramType + " " + param;
5147
5148                 return paramComplete;
5149         }
5150         
5151
5152         // Detect array declaration, e.g. int A[],
5153         //              then generate "int A[]" in C++ as "vector<int> A"
5154         // This method just returns the type
5155         private String checkAndGetCplusArrayType(String paramType) {
5156
5157                 String paramTypeRet = null;
5158                 // Check for array declaration
5159                 if (paramType.contains("[]")) {
5160                         String type = paramType.split("\\[\\]")[0];
5161                         paramTypeRet = checkAndGetCplusType(type) + "[]";
5162                 } else if (paramType.contains("vector")) {
5163                         // Just return it as is if it's not an array
5164                         String type = paramType.split("<")[1].split(">")[0];
5165                         paramTypeRet = checkAndGetCplusType(type) + "[]";
5166                 } else
5167                         paramTypeRet = paramType;
5168
5169                 return paramTypeRet;
5170         }
5171         
5172         
5173         // Detect array declaration, e.g. int A[],
5174         //              then generate "int A[]" in C++ as "vector<int> A"
5175         // This method just returns the type
5176         private String checkAndGetCplusArrayType(String paramType, String param) {
5177
5178                 String paramTypeRet = null;
5179                 // Check for array declaration
5180                 if (param.contains("[]")) {
5181                         paramTypeRet = checkAndGetCplusType(paramType) + "[]";
5182                 } else if (paramType.contains("vector")) {
5183                         // Just return it as is if it's not an array
5184                         String type = paramType.split("<")[1].split(">")[0];
5185                         paramTypeRet = checkAndGetCplusType(type) + "[]";
5186                 } else
5187                         paramTypeRet = paramType;
5188
5189                 return paramTypeRet;
5190         }
5191
5192
5193         // Return the class type for class resolution (for return value)
5194         // - Check and return C++ array class, e.g. int A[] into int*
5195         // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5196         private String checkAndGetCplusRetClsType(String paramType) {
5197
5198                 String paramTypeRet = null;
5199                 // Check for array declaration
5200                 if (paramType.contains("[]")) {
5201                         String type = paramType.split("\\[\\]")[0];
5202                         paramTypeRet = getSimpleArrayType(type) + "*";
5203                 } else if (paramType.contains("<") && paramType.contains(">")) {
5204                         // Just return it as is if it's not an array
5205                         String type = paramType.split("<")[1].split(">")[0];
5206                         paramTypeRet = "vector<" + getGenericType(type) + ">";
5207                 } else
5208                         paramTypeRet = paramType;
5209
5210                 return paramTypeRet;
5211         }
5212
5213
5214         // Return the class type for class resolution (for method arguments)
5215         // - Check and return C++ array class, e.g. int A[] into int*
5216         // - Check and return C++ vector class, e.g. List<Integer> A into vector<int>
5217         private String checkAndGetCplusArgClsType(String paramType, String param) {
5218
5219                 String paramTypeRet = getEnumCplusClsType(paramType);
5220                 if (!paramTypeRet.equals(paramType)) 
5221                 // Just return if it is an enum type
5222                 // Type will still be the same if it's not an enum type
5223                         return paramTypeRet;
5224
5225                 // Check for array declaration
5226                 if (param.contains("[]")) {
5227                         paramTypeRet = getSimpleArrayType(paramType) + "*";
5228                 } else if (paramType.contains("<") && paramType.contains(">")) {
5229                         // Just return it as is if it's not an array
5230                         String type = paramType.split("<")[1].split(">")[0];
5231                         paramTypeRet = "vector<" + getGenericType(type) + ">";
5232                 } else
5233                         paramTypeRet = paramType;
5234
5235                 return paramTypeRet;
5236         }
5237
5238
5239         // Detect array declaration, e.g. int A[],
5240         //              then generate type "int[]"
5241         private String checkAndGetArray(String paramType, String param) {
5242
5243                 String paramTypeRet = null;
5244                 // Check for array declaration
5245                 if (param.contains("[]")) {
5246                         paramTypeRet = paramType + "[]";
5247                 } else
5248                         // Just return it as is if it's not an array
5249                         paramTypeRet = paramType;
5250
5251                 return paramTypeRet;
5252         }
5253
5254
5255         // Is array or list?
5256         private boolean isArrayOrList(String paramType, String param) {
5257
5258                 // Check for array declaration
5259                 if (isArray(param))
5260                         return true;
5261                 else if (isList(paramType))
5262                         return true;
5263                 else
5264                         return false;
5265         }
5266
5267
5268         // Is array? 
5269         // For return type we use retType as input parameter
5270         private boolean isArray(String param) {
5271
5272                 // Check for array declaration
5273                 if (param.contains("[]"))
5274                         return true;
5275                 else
5276                         return false;
5277         }
5278
5279
5280         // Is list?
5281         private boolean isList(String paramType) {
5282
5283                 // Check for array declaration
5284                 if (paramType.contains("List"))
5285                         return true;
5286                 else
5287                         return false;
5288         }
5289
5290
5291         // Get the right type for a callback object
5292         private String checkAndGetParamClass(String paramType) {
5293
5294                 // Check if this is generics
5295                 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
5296                         return exchangeParamType(paramType);
5297                 } else if (isList(paramType) &&
5298                                 (getParamCategory(getGenericType(paramType)) == ParamCategory.USERDEFINED)) {
5299                         return "List<" + exchangeParamType(getGenericType(paramType)) + ">";
5300                 } else
5301                         return paramType;
5302         }
5303
5304
5305         // Returns the other interface for type-checking purposes for USERDEFINED
5306         //              classes based on the information provided in multiple policy files
5307         // e.g. return CameraWithXXX instead of Camera
5308         private String exchangeParamType(String intface) {
5309
5310                 // Param type that's passed is the interface name we need to look for
5311                 //              in the map of interfaces, based on available policy files.
5312                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
5313                 if (decHandler != null) {
5314                 // We've found the required interface policy files
5315                         RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
5316                         Set<String> setExchInt = reqDecl.getInterfaces();
5317                         if (setExchInt.size() == 1) {
5318                                 Iterator iter = setExchInt.iterator();
5319                                 return (String) iter.next();
5320                         } else {
5321                                 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() + 
5322                                         ". Only one new interface can be declared if the object " + intface +
5323                                         " needs to be passed in as an input parameter!\n");
5324                         }
5325                 } else {
5326                 // NULL value - this means policy files missing
5327                         throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
5328                                 "... Please provide the necessary policy files for user-defined types." +
5329                                 " If this is an array please type the brackets after the variable name," +
5330                                 " e.g. \"String str[]\", not \"String[] str\"." +
5331                                 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
5332                                 " supports List/ArrayList (Java) or list (C++).\n");
5333                 }
5334         }
5335
5336
5337         public static void main(String[] args) throws Exception {
5338
5339                 // If there is no argument or just "--help" or "-h", then invoke printUsage()
5340                 if ((args.length == 0        ||
5341                          args[0].equals("-help") ||
5342                          args[0].equals("--help")||
5343                          args[0].equals("-h"))) {
5344
5345                         IoTCompiler.printUsage();
5346
5347                 } else if (args.length > 1) {
5348
5349                         IoTCompiler comp = new IoTCompiler();
5350                         int i = 0;
5351                         //boolean driverDefined = false;
5352                         boolean controllerDefined = false;
5353                         do {
5354                                 if (!controllerDefined && args[i].equals("-cont")) {
5355                                         comp.setControllerClass(args[i+1]);
5356                                         controllerDefined = true;
5357                                         i = i + 2;
5358                                 }
5359                             // Parse main policy file
5360                             ParseNode pnPol = IoTCompiler.parseFile(args[i]);
5361                             // Parse "requires" policy file
5362                             ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
5363                             // Get interface name
5364                             String intface = ParseTreeHandler.getOrigIntface(pnPol);
5365                             comp.setDataStructures(intface, pnPol, pnReq);
5366                             comp.getMethodsForIntface(intface);
5367                                 i = i + 2;
5368                                 if (args[i].equals("-drv")) {
5369                                         comp.setDriverClass(intface, args[i+1]);
5370                                         i = i + 2;
5371                                 } else
5372                                         throw new Error("IoTCompiler: ERROR - driver class name is needed for the interface: " + intface + "\n");
5373                         // 1) Check if this is the last option before "-java" or "-cplus"
5374                         // 2) Check if this is really the last option
5375                         } while(!args[i].equals("-java") &&
5376                                         !args[i].equals("-cplus") &&
5377                                         (i < args.length));
5378                         // Controller class name needs to be defined at least once
5379                         if (!controllerDefined)
5380                                 throw new Error("IoTCompiler: ERROR - controller class name has not been specified!\n");
5381
5382                         // Generate everything if we don't see "-java" or "-cplus"
5383                         if (i == args.length) {
5384                                 comp.generateEnumJava();
5385                                 comp.generateStructJava();
5386                                 comp.generateJavaLocalInterfaces();
5387                                 comp.generateJavaInterfaces();
5388                                 comp.generateJavaStubClasses();
5389                                 comp.generateJavaSkeletonClass();
5390                                 comp.generateEnumCplus();
5391                                 comp.generateStructCplus();
5392                                 comp.generateCplusLocalInterfaces();
5393                                 comp.generateCPlusInterfaces();
5394                                 comp.generateCPlusStubClassesHpp();
5395                                 comp.generateCPlusStubClassesCpp();
5396                                 comp.generateCplusSkeletonClassHpp();
5397                                 comp.generateCplusSkeletonClassCpp();
5398                         } else {
5399                         // Check other options
5400                                 while(i < args.length) {
5401                                         // Error checking
5402                                         if (!args[i].equals("-java") &&
5403                                                 !args[i].equals("-cplus")) {
5404                                                 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i] + "\n");
5405                                         } else {
5406                                                 if (i + 1 < args.length) {
5407                                                         comp.setDirectory(args[i+1]);
5408                                                 } else
5409                                                         throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i] + "\n");
5410
5411                                                 if (args[i].equals("-java")) {
5412                                                         comp.generateEnumJava();
5413                                                         comp.generateStructJava();
5414                                                         comp.generateJavaLocalInterfaces();
5415                                                         comp.generateJavaInterfaces();
5416                                                         comp.generateJavaStubClasses();
5417                                                         comp.generateJavaSkeletonClass();
5418                                                 } else {
5419                                                         comp.generateEnumCplus();
5420                                                         comp.generateStructCplus();
5421                                                         comp.generateCplusLocalInterfaces();
5422                                                         comp.generateCPlusInterfaces();
5423                                                         comp.generateCPlusStubClassesHpp();
5424                                                         comp.generateCPlusStubClassesCpp();
5425                                                         comp.generateCplusSkeletonClassHpp();
5426                                                         comp.generateCplusSkeletonClassCpp();
5427                                                 }
5428                                         }
5429                                         i = i + 2;
5430                                 }
5431                         }
5432                 } else {
5433                 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
5434                         IoTCompiler.printUsage();
5435                         throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!\n");
5436                 }
5437         }
5438 }
5439
5440
5441