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