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