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