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