e461706c1757ce42a11b8d3660be9792477bce6c
[iot2.git] / iotjava / iotpolicy / IoTCompiler.java
1 package iotpolicy;
2
3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
5 import java.io.*;
6 import java.util.Arrays;
7 import java.util.ArrayList;
8 import java.util.Collection;
9 import java.util.Collections;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.Iterator;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16
17 import iotpolicy.parser.Lexer;
18 import iotpolicy.parser.Parser;
19 import iotpolicy.tree.ParseNode;
20 import iotpolicy.tree.ParseNodeVector;
21 import iotpolicy.tree.ParseTreeHandler;
22 import iotpolicy.tree.Declaration;
23 import iotpolicy.tree.DeclarationHandler;
24 import iotpolicy.tree.CapabilityDecl;
25 import iotpolicy.tree.InterfaceDecl;
26 import iotpolicy.tree.RequiresDecl;
27 import iotpolicy.tree.EnumDecl;
28 import iotpolicy.tree.StructDecl;
29
30 import iotrmi.Java.IoTRMITypes;
31
32
33 /** Class IoTCompiler is the main interface/stub compiler for
34  *  files generation. This class calls helper classes
35  *  such as Parser, Lexer, InterfaceDecl, CapabilityDecl,
36  *  RequiresDecl, ParseTreeHandler, etc.
37  *
38  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
39  * @version     1.0
40  * @since       2016-09-22
41  */
42 public class IoTCompiler {
43
44         /**
45          * Class properties
46          */
47         // Maps multiple interfaces to multiple objects of ParseTreeHandler
48         private Map<String,ParseTreeHandler> mapIntfacePTH;
49         private Map<String,DeclarationHandler> mapIntDeclHand;
50         private Map<String,Map<String,Set<String>>> mapInt2NewInts;
51         // Data structure to store our types (primitives and non-primitives) for compilation
52         private Map<String,String> mapPrimitives;
53         private Map<String,String> mapNonPrimitivesJava;
54         private Map<String,String> mapNonPrimitivesCplus;
55         // Other data structures
56         private Map<String,Integer> mapIntfaceObjId;            // Maps interface name to object Id
57         private Map<String,Integer> mapNewIntfaceObjId;         // Maps new interface name to its object Id (keep track of stubs)
58         private PrintWriter pw;
59         private String dir;
60         private String subdir;
61
62
63         /**
64          * Class constants
65          */
66         private final static String OUTPUT_DIRECTORY = "output_files";
67
68         private enum ParamCategory {
69
70                 PRIMITIVES,             // All the primitive types, e.g. byte, short, int, long, etc.
71                 NONPRIMITIVES,  // Non-primitive types, e.g. Set, Map, List, etc.
72                 ENUM,                   // Enum type
73                 STRUCT,                 // Struct type
74                 USERDEFINED             // Assumed as driver classes
75         }
76
77
78         /**
79          * Class constructors
80          */
81         public IoTCompiler() {
82
83                 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
84                 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
85                 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
86                 mapIntfaceObjId = new HashMap<String,Integer>();
87                 mapNewIntfaceObjId = new HashMap<String,Integer>();
88                 mapPrimitives = new HashMap<String,String>();
89                         arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
90                 mapNonPrimitivesJava = new HashMap<String,String>();
91                         arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
92                 mapNonPrimitivesCplus = new HashMap<String,String>();
93                         arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
94                 pw = null;
95                 dir = OUTPUT_DIRECTORY;
96                 subdir = null;
97         }
98
99
100         /**
101          * setDataStructures() sets parse tree and other data structures based on policy files.
102          * <p>
103          * It also generates parse tree (ParseTreeHandler) and
104          * copies useful information from parse tree into
105          * InterfaceDecl, CapabilityDecl, and RequiresDecl 
106          * data structures.
107          * Additionally, the data structure handles are
108          * returned from tree-parsing for further process.
109          */
110         public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
111
112                 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
113                 DeclarationHandler decHandler = new DeclarationHandler();
114                 // Process ParseNode and generate Declaration objects
115                 // Interface
116                 ptHandler.processInterfaceDecl();
117                 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
118                 decHandler.addInterfaceDecl(origInt, intDecl);
119                 // Capabilities
120                 ptHandler.processCapabilityDecl();
121                 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
122                 decHandler.addCapabilityDecl(origInt, capDecl);
123                 // Requires
124                 ptHandler.processRequiresDecl();
125                 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
126                 decHandler.addRequiresDecl(origInt, reqDecl);
127                 // Enumeration
128                 ptHandler.processEnumDecl();
129                 EnumDecl enumDecl = ptHandler.getEnumDecl();
130                 decHandler.addEnumDecl(origInt, enumDecl);
131                 // Struct
132                 ptHandler.processStructDecl();
133                 StructDecl structDecl = ptHandler.getStructDecl();
134                 decHandler.addStructDecl(origInt, structDecl);
135
136                 mapIntfacePTH.put(origInt, ptHandler);
137                 mapIntDeclHand.put(origInt, decHandler);
138                 // Set object Id counter to 0 for each interface
139                 mapIntfaceObjId.put(origInt, new Integer(0));
140         }
141
142
143         /**
144          * getMethodsForIntface() reads for methods in the data structure
145          * <p>
146          * It is going to give list of methods for a certain interface
147          *              based on the declaration of capabilities.
148          */
149         public void getMethodsForIntface(String origInt) {
150
151                 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
152                 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
153                 // Get set of new interfaces, e.g. CameraWithCaptureAndData
154                 // Generate this new interface with all the methods it needs
155                 //              from different capabilities it declares
156                 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
157                 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
158                 Set<String> setIntfaces = reqDecl.getInterfaces();
159                 for (String strInt : setIntfaces) {
160
161                         // Initialize a set of methods
162                         Set<String> setMethods = new HashSet<String>();
163                         // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
164                         List<String> listCapab = reqDecl.getCapabList(strInt);
165                         for (String strCap : listCapab) {
166
167                                 // Get list of methods for each capability
168                                 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
169                                 List<String> listCapabMeth = capDecl.getMethods(strCap);
170                                 for (String strMeth : listCapabMeth) {
171
172                                         // Add methods into setMethods
173                                         // This is to also handle redundancies (say two capabilities
174                                         //              share the same methods)
175                                         setMethods.add(strMeth);
176                                 }
177                         }
178                         // Add interface and methods information into map
179                         mapNewIntMethods.put(strInt, setMethods);
180                 }
181                 // Map the map of interface-methods to the original interface
182                 mapInt2NewInts.put(origInt, mapNewIntMethods);
183         }
184
185
186         /**
187          * HELPER: writeMethodJavaLocalInterface() writes the method of the local interface
188          */
189         private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
190
191                 for (String method : methods) {
192
193                         List<String> methParams = intDecl.getMethodParams(method);
194                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
195                         print("public " + intDecl.getMethodType(method) + " " +
196                                 intDecl.getMethodId(method) + "(");
197                         for (int i = 0; i < methParams.size(); i++) {
198                                 // Check for params with driver class types and exchange it 
199                                 //              with its remote interface
200                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
201                                 print(paramType + " " + methParams.get(i));
202                                 // Check if this is the last element (don't print a comma)
203                                 if (i != methParams.size() - 1) {
204                                         print(", ");
205                                 }
206                         }
207                         println(");");
208                 }
209         }
210
211
212         /**
213          * HELPER: writeMethodJavaInterface() writes the method of the interface
214          */
215         private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
216
217                 for (String method : methods) {
218
219                         List<String> methParams = intDecl.getMethodParams(method);
220                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
221                         print("public " + intDecl.getMethodType(method) + " " +
222                                 intDecl.getMethodId(method) + "(");
223                         for (int i = 0; i < methParams.size(); i++) {
224                                 // Check for params with driver class types and exchange it 
225                                 //              with its remote interface
226                                 String paramType = methPrmTypes.get(i);
227                                 print(paramType + " " + methParams.get(i));
228                                 // Check if this is the last element (don't print a comma)
229                                 if (i != methParams.size() - 1) {
230                                         print(", ");
231                                 }
232                         }
233                         println(");");
234                 }
235         }
236
237
238         /**
239          * HELPER: generateEnumJava() writes the enumeration declaration
240          */
241         private void generateEnumJava() throws IOException {
242
243                 // Create a new directory
244                 createDirectory(dir);
245                 for (String intface : mapIntfacePTH.keySet()) {
246                         // Get the right EnumDecl
247                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
248                         EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
249                         Set<String> enumTypes = enumDecl.getEnumDeclarations();
250                         // Iterate over enum declarations
251                         for (String enType : enumTypes) {
252                                 // Open a new file to write into
253                                 FileWriter fw = new FileWriter(dir + "/" + enType + ".java");
254                                 pw = new PrintWriter(new BufferedWriter(fw));
255                                 println("public enum " + enType + " {");
256                                 List<String> enumMembers = enumDecl.getMembers(enType);
257                                 for (int i = 0; i < enumMembers.size(); i++) {
258
259                                         String member = enumMembers.get(i);
260                                         print(member);
261                                         // Check if this is the last element (don't print a comma)
262                                         if (i != enumMembers.size() - 1)
263                                                 println(",");
264                                         else
265                                                 println("");
266                                 }
267                                 println("}\n");
268                                 pw.close();
269                                 System.out.println("IoTCompiler: Generated enum class " + enType + ".java...");
270                         }
271                 }
272         }
273
274
275         /**
276          * HELPER: generateStructJava() writes the struct declaration
277          */
278         private void generateStructJava() throws IOException {
279
280                 // Create a new directory
281                 createDirectory(dir);
282                 for (String intface : mapIntfacePTH.keySet()) {
283                         // Get the right StructDecl
284                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
285                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
286                         List<String> structTypes = structDecl.getStructTypes();
287                         // Iterate over enum declarations
288                         for (String stType : structTypes) {
289                                 // Open a new file to write into
290                                 FileWriter fw = new FileWriter(dir + "/" + stType + ".java");
291                                 pw = new PrintWriter(new BufferedWriter(fw));
292                                 println("public class " + stType + " {");
293                                 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
294                                 List<String> structMembers = structDecl.getMembers(stType);
295                                 for (int i = 0; i < structMembers.size(); i++) {
296
297                                         String memberType = structMemberTypes.get(i);
298                                         String member = structMembers.get(i);
299                                         println("public static " + memberType + " " + member + ";");
300                                 }
301                                 println("}\n");
302                                 pw.close();
303                                 System.out.println("IoTCompiler: Generated struct class " + stType + ".java...");
304                         }
305                 }
306         }
307
308
309         /**
310          * generateJavaLocalInterface() writes the local interface and provides type-checking.
311          * <p>
312          * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
313          * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
314          * The local interface has to be the input parameter for the stub and the stub 
315          * interface has to be the input parameter for the local class.
316          */
317         public void generateJavaLocalInterfaces() throws IOException {
318
319                 // Create a new directory
320                 createDirectory(dir);
321                 for (String intface : mapIntfacePTH.keySet()) {
322                         // Open a new file to write into
323                         FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
324                         pw = new PrintWriter(new BufferedWriter(fw));
325                         // Pass in set of methods and get import classes
326                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
327                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
328                         List<String> methods = intDecl.getMethods();
329                         Set<String> importClasses = getImportClasses(methods, intDecl);
330                         List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
331                         List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
332                         printImportStatements(allImportClasses);
333                         // Write interface header
334                         println("");
335                         println("public interface " + intface + " {");
336                         // Write methods
337                         writeMethodJavaLocalInterface(methods, intDecl);
338                         println("}");
339                         pw.close();
340                         System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
341                 }
342         }
343
344
345         /**
346          * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
347          */
348         public void generateJavaInterfaces() throws IOException {
349
350                 // Create a new directory
351                 String path = createDirectories(dir, subdir);
352                 for (String intface : mapIntfacePTH.keySet()) {
353
354                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
355                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
356
357                                 // Open a new file to write into
358                                 String newIntface = intMeth.getKey();
359                                 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
360                                 pw = new PrintWriter(new BufferedWriter(fw));
361                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
362                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
363                                 // Pass in set of methods and get import classes
364                                 List<String> methods = intDecl.getMethods();
365                                 Set<String> importClasses = getImportClasses(methods, intDecl);
366                                 List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
367                                 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
368                                 printImportStatements(allImportClasses);
369                                 // Write interface header
370                                 println("");
371                                 println("public interface " + newIntface + " {\n");
372                                 // Write methods
373                                 writeMethodJavaInterface(methods, intDecl);
374                                 println("}");
375                                 pw.close();
376                                 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
377                         }
378                 }
379         }
380
381
382         /**
383          * HELPER: writePropertiesJavaPermission() writes the permission in properties
384          */
385         private void writePropertiesJavaPermission(String intface, InterfaceDecl intDecl) {
386
387                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
388                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
389                         String newIntface = intMeth.getKey();
390                         int newObjectId = getNewIntfaceObjectId(newIntface);
391                         println("private final static int object" + newObjectId + "Id = " + 
392                                 newObjectId + ";\t//" + newIntface);
393                         Set<String> methodIds = intMeth.getValue();
394                         print("private static Integer[] object" + newObjectId + "Permission = { ");
395                         int i = 0;
396                         for (String methodId : methodIds) {
397                                 int methodNumId = intDecl.getMethodNumId(methodId);
398                                 print(Integer.toString(methodNumId));
399                                 // Check if this is the last element (don't print a comma)
400                                 if (i != methodIds.size() - 1) {
401                                         print(", ");
402                                 }
403                                 i++;
404                         }
405                         println(" };");
406                         println("private static List<Integer> set" + newObjectId + "Allowed;");
407                 }
408         }
409
410
411         /**
412          * HELPER: writePropertiesJavaStub() writes the properties of the stub class
413          */
414         private void writePropertiesJavaStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
415
416                 println("private IoTRMICall rmiCall;");
417                 println("private String address;");
418                 println("private int[] ports;\n");
419                 // Get the object Id
420                 Integer objId = mapIntfaceObjId.get(intface);
421                 println("private final static int objectId = " + objId + ";");
422                 mapNewIntfaceObjId.put(newIntface, objId);
423                 mapIntfaceObjId.put(intface, objId++);
424                 if (callbackExist) {
425                 // We assume that each class only has one callback interface for now
426                         Iterator it = callbackClasses.iterator();
427                         String callbackType = (String) it.next();
428                         println("// Callback properties");
429                         println("private IoTRMIObject rmiObj;");
430                         println("List<" + callbackType + "> listCallbackObj;");
431                         println("private static int objIdCnt = 0;");
432                         // Generate permission stuff for callback stubs
433                         DeclarationHandler decHandler = mapIntDeclHand.get(callbackType);
434                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType);
435                         writePropertiesJavaPermission(callbackType, intDecl);
436                 }
437                 println("\n");
438         }
439
440
441         /**
442          * HELPER: writeConstructorJavaPermission() writes the permission in constructor
443          */
444         private void writeConstructorJavaPermission(String intface) {
445
446                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
447                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
448                         String newIntface = intMeth.getKey();
449                         int newObjectId = getNewIntfaceObjectId(newIntface);
450                         println("set" + newObjectId + "Allowed = new ArrayList<Integer>(Arrays.asList(object" + newObjectId +"Permission));");
451                 }
452         }
453
454
455         /**
456          * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
457          */
458         private void writeConstructorJavaStub(String intface, String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
459
460                 println("public " + newStubClass + "(int _port, String _address, int _rev, int[] _ports) throws Exception {");
461                 println("address = _address;");
462                 println("ports = _ports;");
463                 println("rmiCall = new IoTRMICall(_port, _address, _rev);");
464                 if (callbackExist) {
465                         Iterator it = callbackClasses.iterator();
466                         String callbackType = (String) it.next();
467                         writeConstructorJavaPermission(intface);
468                         println("listCallbackObj = new ArrayList<" + callbackType + ">();");
469                         println("___initCallBack();");
470                 }
471                 println("}\n");
472         }
473
474
475         /**
476          * HELPER: writeJavaMethodCallbackPermission() writes permission checks in stub for callbacks
477          */
478         private void writeJavaMethodCallbackPermission(String intface) {
479
480                 println("int methodId = IoTRMIObject.getMethodId(method);");
481                 // Get all the different stubs
482                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
483                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
484                         String newIntface = intMeth.getKey();
485                         int newObjectId = getNewIntfaceObjectId(newIntface);
486                         println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
487                         println("throw new Error(\"Callback object for " + intface + " is not allowed to access method: \" + methodId);");
488                         println("}");
489                 }
490         }
491
492
493         /**
494          * HELPER: writeJavaInitCallbackPermission() writes the permission for callback
495          */
496         private void writeJavaInitCallbackPermission(String intface, InterfaceDecl intDecl, boolean callbackExist) {
497
498                 if (callbackExist) {
499                         String method = "___initCallBack()";
500                         int methodNumId = intDecl.getHelperMethodNumId(method);
501                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
502                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
503                                 String newIntface = intMeth.getKey();
504                                 int newObjectId = getNewIntfaceObjectId(newIntface);
505                                 println("set" + newObjectId + "Allowed.add(" + methodNumId + ");");
506                         }
507                 }
508         }
509
510
511         /**
512          * HELPER: writeInitCallbackJavaStub() writes callback initialization in stub
513          */
514         private void writeInitCallbackJavaStub(String intface, InterfaceDecl intDecl) {
515
516                 println("public void ___initCallBack() {");
517                 // Generate main thread for callbacks
518                 println("Thread thread = new Thread() {");
519                 println("public void run() {");
520                 println("try {");
521                 println("rmiObj = new IoTRMIObject(ports[0]);");
522                 println("while (true) {");
523                 println("byte[] method = rmiObj.getMethodBytes();");
524                 writeJavaMethodCallbackPermission(intface);
525                 println("int objId = IoTRMIObject.getObjectId(method);");
526                 println(intface + "_CallbackSkeleton skel = (" + intface + "_CallbackSkeleton) listCallbackObj.get(objId);");
527                 println("if (skel != null) {");
528                 println("skel.invokeMethod(rmiObj);");
529                 print("}");
530                 println(" else {");
531                 println("throw new Error(\"" + intface + ": Object with Id \" + objId + \" not found!\");");
532                 println("}");
533                 println("}");
534                 print("}");
535                 println(" catch (Exception ex) {");
536                 println("ex.printStackTrace();");
537                 println("throw new Error(\"Error instantiating class " + intface + "_CallbackSkeleton!\");");
538                 println("}");
539                 println("}");
540                 println("};");
541                 println("thread.start();\n");
542                 // Generate info sending part
543                 String method = "___initCallBack()";
544                 int methodNumId = intDecl.getHelperMethodNumId(method);
545                 println("int methodId = " + methodNumId + ";");
546                 println("Class<?> retType = void.class;");
547                 println("Class<?>[] paramCls = new Class<?>[] { int.class, String.class, int.class };");
548                 println("Object[] paramObj = new Object[] { ports[0], address, 0 };");
549                 println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
550                 println("}\n");
551         }
552
553
554         /**
555          * HELPER: checkAndWriteEnumTypeJavaStub() writes the enum type (convert from enum to int)
556          */
557         private void checkAndWriteEnumTypeJavaStub(List<String> methParams, List<String> methPrmTypes) {
558
559                 // Iterate and find enum declarations
560                 for (int i = 0; i < methParams.size(); i++) {
561                         String paramType = methPrmTypes.get(i);
562                         String param = methParams.get(i);
563                         String simpleType = getGenericType(paramType);
564                         if (isEnumClass(simpleType)) {
565                         // Check if this is enum type
566                                 if (isArray(param)) {   // An array
567                                         println("int len" + i + " = " + getSimpleIdentifier(param) + ".length;");
568                                         println("int paramEnum" + i + "[] = new int[len" + i + "];");
569                                         println("for (int i = 0; i < len" + i + "; i++) {");
570                                         println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + "[i].ordinal();");
571                                         println("}");
572                                 } else if (isList(paramType)) { // A list
573                                         println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
574                                         println("int paramEnum" + i + "[] = new int[len" + i + "];");
575                                         println("for (int i = 0; i < len" + i + "; i++) {");
576                                         println("paramEnum" + i + "[i] = " + getSimpleIdentifier(param) + ".get(i).ordinal();");
577                                         println("}");
578                                 } else {        // Just one element
579                                         println("int paramEnum" + i + "[] = new int[1];");
580                                         println("paramEnum" + i + "[0] = " + param + ".ordinal();");
581                                 }
582                         }
583                 }
584         }
585
586
587         /**
588          * HELPER: checkAndWriteEnumRetTypeJavaStub() writes the enum return type (convert from enum to int)
589          */
590         private void checkAndWriteEnumRetTypeJavaStub(String retType) {
591
592                 // Strips off array "[]" for return type
593                 String pureType = getSimpleArrayType(getGenericType(retType));
594                 // Take the inner type of generic
595                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
596                         pureType = getGenericType(retType);
597                 if (isEnumClass(pureType)) {
598                 // Check if this is enum type
599                         // Enum decoder
600                         println("int[] retEnum = (int[]) retObj;");
601                         println(pureType + "[] enumVals = " + pureType + ".values();");
602                         if (isArray(retType)) {                 // An array
603                                 println("int retLen = retEnum.length;");
604                                 println(pureType + "[] enumRetVal = new " + pureType + "[retLen];");
605                                 println("for (int i = 0; i < retLen; i++) {");
606                                 println("enumRetVal[i] = enumVals[retEnum[i]];");
607                                 println("}");
608                         } else if (isList(retType)) {   // A list
609                                 println("int retLen = retEnum.length;");
610                                 println("List<" + pureType + "> enumRetVal = new ArrayList<" + pureType + ">();");
611                                 println("for (int i = 0; i < retLen; i++) {");
612                                 println("enumRetVal.add(enumVals[retEnum[i]]);");
613                                 println("}");
614                         } else {        // Just one element
615                                 println(pureType + " enumRetVal = enumVals[retEnum[0]];");
616                         }
617                         println("return enumRetVal;");
618                 }
619         }
620
621
622         /**
623          * HELPER: checkAndWriteStructSetupJavaStub() writes the struct type setup
624          */
625         private void checkAndWriteStructSetupJavaStub(List<String> methParams, List<String> methPrmTypes, 
626                         InterfaceDecl intDecl, String method) {
627                 
628                 // Iterate and find struct declarations
629                 for (int i = 0; i < methParams.size(); i++) {
630                         String paramType = methPrmTypes.get(i);
631                         String param = methParams.get(i);
632                         String simpleType = getGenericType(paramType);
633                         if (isStructClass(simpleType)) {
634                         // Check if this is enum type
635                                 int methodNumId = intDecl.getMethodNumId(method);
636                                 String helperMethod = methodNumId + "struct" + i;
637                                 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
638                                 println("Class<?> retTypeStruct" + i + " = void.class;");
639                                 println("Class<?>[] paramClsStruct" + i + " = new Class<?>[] { int.class };");
640                                 if (isArray(param)) {   // An array
641                                         println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".length };");
642                                 } else if (isList(paramType)) { // A list
643                                         println("Object[] paramObjStruct" + i + " = new Object[] { " + getSimpleArrayType(param) + ".size() };");
644                                 } else {        // Just one element
645                                         println("Object[] paramObjStruct" + i + " = new Object[] { new Integer(1) };");
646                                 }
647                                 println("rmiCall.remoteCall(objectId, methodIdStruct" + i + 
648                                                 ", retTypeStruct" + i + ", null, paramClsStruct" + i + 
649                                                 ", paramObjStruct" + i + ");\n");
650                         }
651                 }
652         }
653
654
655         /**
656          * HELPER: isStructPresent() checks presence of struct
657          */
658         private boolean isStructPresent(List<String> methParams, List<String> methPrmTypes) {
659
660                 // Iterate and find enum declarations
661                 for (int i = 0; i < methParams.size(); i++) {
662                         String paramType = methPrmTypes.get(i);
663                         String param = methParams.get(i);
664                         String simpleType = getGenericType(paramType);
665                         if (isStructClass(simpleType))
666                                 return true;
667                 }
668                 return false;
669         }
670
671
672         /**
673          * HELPER: writeLengthStructParamClassJavaStub() writes lengths of parameters
674          */
675         private void writeLengthStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
676
677                 // Iterate and find struct declarations - count number of params
678                 for (int i = 0; i < methParams.size(); i++) {
679                         String paramType = methPrmTypes.get(i);
680                         String param = methParams.get(i);
681                         String simpleType = getGenericType(paramType);
682                         if (isStructClass(simpleType)) {
683                                 int members = getNumOfMembers(simpleType);
684                                 if (isArray(param)) {                   // An array
685                                         String structLen = getSimpleArrayType(param) + ".length";
686                                         print(members + "*" + structLen);
687                                 } else if (isList(paramType)) { // A list
688                                         String structLen = getSimpleArrayType(param) + ".size()";
689                                         print(members + "*" + structLen);
690                                 } else
691                                         print(Integer.toString(members));
692                         } else
693                                 print("1");
694                         if (i != methParams.size() - 1) {
695                                 print("+");
696                         }
697                 }
698         }
699
700
701         /**
702          * HELPER: writeStructMembersJavaStub() writes parameters of struct
703          */
704         private void writeStructMembersJavaStub(String simpleType, String paramType, String param) {
705
706                 // Get the struct declaration for this struct and generate initialization code
707                 StructDecl structDecl = getStructDecl(simpleType);
708                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
709                 List<String> members = structDecl.getMembers(simpleType);
710                 if (isArray(param)) {                   // An array
711                         println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".length; i++) {");
712                         for (int i = 0; i < members.size(); i++) {
713                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
714                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
715                                 print("paramObj[pos++] = " + getSimpleIdentifier(param) + "[i].");
716                                 print(getSimpleIdentifier(members.get(i)));
717                                 println(";");
718                         }
719                         println("}");
720                 } else if (isList(paramType)) { // A list
721                         println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
722                         for (int i = 0; i < members.size(); i++) {
723                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
724                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
725                                 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".get(i).");
726                                 print(getSimpleIdentifier(members.get(i)));
727                                 println(";");
728                         }
729                         println("}");
730                 } else {        // Just one struct element
731                         for (int i = 0; i < members.size(); i++) {
732                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
733                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
734                                 print("paramObj[pos++] = " + getSimpleIdentifier(param) + ".");
735                                 print(getSimpleIdentifier(members.get(i)));
736                                 println(";");
737                         }
738                 }
739         }
740
741
742         /**
743          * HELPER: writeStructParamClassJavaStub() writes parameters if struct is present
744          */
745         private void writeStructParamClassJavaStub(List<String> methParams, List<String> methPrmTypes) {
746
747                 print("int paramLen = ");
748                 writeLengthStructParamClassJavaStub(methParams, methPrmTypes);
749                 println(";");
750                 println("Object[] paramObj = new Object[paramLen];");
751                 println("Class<?>[] paramCls = new Class<?>[paramLen];");
752                 println("int pos = 0;");
753                 // Iterate again over the parameters
754                 for (int i = 0; i < methParams.size(); i++) {
755                         String paramType = methPrmTypes.get(i);
756                         String param = methParams.get(i);
757                         String simpleType = getGenericType(paramType);
758                         if (isStructClass(simpleType)) {
759                                 writeStructMembersJavaStub(simpleType, paramType, param);
760                         } else {
761                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
762                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
763                                 print("paramObj[pos++] = ");
764                                 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
765                                 println(";");
766                         }
767                 }
768                 
769         }
770
771
772         /**
773          * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
774          */
775         private void writeStructRetMembersJavaStub(String simpleType, String retType) {
776
777                 // Get the struct declaration for this struct and generate initialization code
778                 StructDecl structDecl = getStructDecl(simpleType);
779                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
780                 List<String> members = structDecl.getMembers(simpleType);
781                 if (isArrayOrList(retType, retType)) {  // An array or list
782                         println("for(int i = 0; i < retLen; i++) {");
783                 }
784                 if (isArray(retType)) { // An array
785                         for (int i = 0; i < members.size(); i++) {
786                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
787                                 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
788                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];");
789                         }
790                         println("}");
791                 } else if (isList(retType)) {   // A list
792                         println(simpleType + " structRetMem = new " + simpleType + "();");
793                         for (int i = 0; i < members.size(); i++) {
794                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
795                                 print("structRetMem." + getSimpleIdentifier(members.get(i)));
796                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];");
797                         }
798                         println("structRet.add(structRetMem);");
799                         println("}");
800                 } else {        // Just one struct element
801                         for (int i = 0; i < members.size(); i++) {
802                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
803                                 print("structRet." + getSimpleIdentifier(members.get(i)));
804                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];");
805                         }
806                 }
807                 println("return structRet;");
808         }
809
810
811         /**
812          * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
813          */
814         private void writeStructReturnJavaStub(String simpleType, String retType) {
815
816                 // Handle the returned struct!!!
817                 println("Object retLenObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
818                 // Minimum retLen is 1 if this is a single struct object
819                 println("int retLen = (int) retLenObj;");
820                 int numMem = getNumOfMembers(simpleType);
821                 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
822                 println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
823                 println("int retPos = 0;");
824                 // Get the struct declaration for this struct and generate initialization code
825                 StructDecl structDecl = getStructDecl(simpleType);
826                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
827                 List<String> members = structDecl.getMembers(simpleType);
828                 if (isArrayOrList(retType, retType)) {  // An array or list
829                         println("for(int i = 0; i < retLen; i++) {");
830                         for (int i = 0; i < members.size(); i++) {
831                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
832                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
833                                 println("retClsVal[retPos++] = null;");
834                         }
835                         println("}");
836                 } else {        // Just one struct element
837                         for (int i = 0; i < members.size(); i++) {
838                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
839                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
840                                 println("retClsVal[retPos++] = null;");
841                         }
842                 }
843                 println("Object[] retObj = rmiCall.getStructObjects(retCls, retClsVal);");
844                 if (isArray(retType)) {                 // An array
845                         println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
846                         println("for(int i = 0; i < retLen; i++) {");
847                         println("structRet[i] = new " + simpleType + "();");
848                         println("}");
849                 } else if (isList(retType)) {   // A list
850                         println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
851                 } else
852                         println(simpleType + " structRet = new " + simpleType + "();");
853                 println("int retObjPos = 0;");
854                 writeStructRetMembersJavaStub(simpleType, retType);
855         }
856
857
858         /**
859          * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
860          */
861         private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
862                         List<String> methPrmTypes, String method) {
863
864                 checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
865                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
866                 String retType = intDecl.getMethodType(method);
867                 println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
868                 checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
869                 // Generate array of parameter types
870                 if (isStructPresent(methParams, methPrmTypes)) {
871                         writeStructParamClassJavaStub(methParams, methPrmTypes);
872                 } else {
873                         print("Class<?>[] paramCls = new Class<?>[] { ");
874                         for (int i = 0; i < methParams.size(); i++) {
875                                 String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
876                                 print(getSimpleType(getEnumType(paramType)) + ".class");
877                                 // Check if this is the last element (don't print a comma)
878                                 if (i != methParams.size() - 1) {
879                                         print(", ");
880                                 }
881                         }
882                         println(" };");
883                         // Generate array of parameter objects
884                         print("Object[] paramObj = new Object[] { ");
885                         for (int i = 0; i < methParams.size(); i++) {
886                                 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
887                                 // Check if this is the last element (don't print a comma)
888                                 if (i != methParams.size() - 1) {
889                                         print(", ");
890                                 }
891                         }
892                         println(" };");
893                 }
894                 // Check if this is "void"
895                 if (retType.equals("void")) {
896                         println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
897                 } else { // We do have a return value
898                         // Generate array of parameter types
899                         if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
900                                 writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType);
901                         } else {
902                                 // This is an enum type
903                                 if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) {
904                                         println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
905                                         checkAndWriteEnumRetTypeJavaStub(retType);
906                                 } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
907                                 // Check if the return value NONPRIMITIVES
908                                         String retGenValType = getGenericType(retType);
909                                         println("Class<?> retGenValType = " + retGenValType + ".class;");
910                                         println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);");
911                                         println("return (" + retType + ")retObj;");
912                                 } else {
913                                         println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
914                                         println("return (" + retType + ")retObj;");
915                                 }
916                         }
917                 }
918         }
919
920
921         /**
922          * HELPER: returnGenericCallbackType() returns the callback type
923          */
924         private String returnGenericCallbackType(String paramType) {
925
926                 if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
927                         return getGenericType(paramType);
928                 else
929                         return paramType;
930         }
931
932
933         /**
934          * HELPER: checkCallbackType() checks the callback type
935          */
936         private boolean checkCallbackType(String paramType, String callbackType) {
937
938                 String prmType = returnGenericCallbackType(paramType);
939                 return callbackType.equals(prmType);
940         }
941
942
943         /**
944          * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
945          */
946         private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
947                         List<String> methPrmTypes, String method, String callbackType) {
948
949                 println("try {");
950                 // Check if this is single object, array, or list of objects
951                 for (int i = 0; i < methParams.size(); i++) {
952                         String paramType = methPrmTypes.get(i);
953                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
954                                 String param = methParams.get(i);
955                                 if (isArrayOrList(paramType, param)) {  // Generate loop
956                                         println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
957                                         println(callbackType + "_CallbackSkeleton skel" + i + " = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);");
958                                 } else
959                                         println(callbackType + "_CallbackSkeleton skel" + i + " = new " + callbackType + "_CallbackSkeleton(" +
960                                                 getSimpleIdentifier(param) + ", objIdCnt++);");
961                                 println("listCallbackObj.add(skel" + i + ");");
962                                 if (isArrayOrList(paramType, param))
963                                         println("}");
964                         }
965                 }
966                 print("}");
967                 println(" catch (Exception ex) {");
968                 println("ex.printStackTrace();");
969                 println("throw new Error(\"Exception when generating skeleton objects!\");");
970                 println("}\n");
971                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
972                 String retType = intDecl.getMethodType(method);
973                 println("Class<?> retType = " + getSimpleType(getEnumType(retType)) + ".class;");
974                 // Generate array of parameter types
975                 print("Class<?>[] paramCls = new Class<?>[] { ");
976                 for (int i = 0; i < methParams.size(); i++) {
977                         String paramType = methPrmTypes.get(i);
978                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
979                                 print("int.class");
980                         } else { // Generate normal classes if it's not a callback object
981                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
982                                 print(getSimpleType(prmType) + ".class");
983                         }
984                         if (i != methParams.size() - 1) // Check if this is the last element
985                                 print(", ");
986                 }
987                 println(" };");
988                 // Generate array of parameter objects
989                 print("Object[] paramObj = new Object[] { ");
990                 for (int i = 0; i < methParams.size(); i++) {
991                         String paramType = methPrmTypes.get(i);
992                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
993                                 //if (isArray(methPrmTypes.get(i), methParams.get(i)))
994                                 if (isArray(methParams.get(i)))
995                                         print(getSimpleIdentifier(methParams.get(i)) + ".length");
996                                 else if (isList(methPrmTypes.get(i)))
997                                         print(getSimpleIdentifier(methParams.get(i)) + ".size()");
998                                 else
999                                         print("new Integer(1)");
1000                         } else
1001                                 print(getSimpleIdentifier(methParams.get(i)));
1002                         if (i != methParams.size() - 1)
1003                                 print(", ");
1004                 }
1005                 println(" };");
1006                 // Check if this is "void"
1007                 if (retType.equals("void")) {
1008                         println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
1009                 } else { // We do have a return value
1010                 // Check if the return value NONPRIMITIVES
1011                         if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
1012                                 String[] retGenValType = getTypeOfGeneric(retType);
1013                                 println("Class<?> retGenValType = " + retGenValType[0] + ".class;");
1014                                 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);");
1015                                 println("return (" + retType + ")retObj;");
1016                         } else {
1017                                 println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
1018                                 println("return (" + retType + ")retObj;");
1019                         }
1020                 }
1021         }
1022
1023
1024         /**
1025          * HELPER: writeMethodJavaStub() writes the methods of the stub class
1026          */
1027         private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1028
1029                 boolean isDefined = false;
1030                 for (String method : methods) {
1031
1032                         List<String> methParams = intDecl.getMethodParams(method);
1033                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1034                         print("public " + intDecl.getMethodType(method) + " " +
1035                                 intDecl.getMethodId(method) + "(");
1036                         boolean isCallbackMethod = false;
1037                         String callbackType = null;
1038                         for (int i = 0; i < methParams.size(); i++) {
1039
1040                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1041                                 // Check if this has callback object
1042                                 if (callbackClasses.contains(paramType)) {
1043                                         isCallbackMethod = true;
1044                                         callbackType = paramType;       
1045                                         // Even if there're 2 callback arguments, we expect them to be of the same interface
1046                                 }
1047                                 print(methPrmTypes.get(i) + " " + methParams.get(i));
1048                                 // Check if this is the last element (don't print a comma)
1049                                 if (i != methParams.size() - 1) {
1050                                         print(", ");
1051                                 }
1052                         }
1053                         println(") {");
1054                         // Now, write the body of stub!
1055                         if (isCallbackMethod)
1056                                 writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
1057                         else
1058                                 writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method);
1059                         println("}\n");
1060                         // Write the init callback helper method
1061                         if (isCallbackMethod && !isDefined) {
1062                                 writeInitCallbackJavaStub(callbackType, intDecl);
1063                                 isDefined = true;
1064                         }
1065                 }
1066         }
1067
1068
1069         /**
1070          * generateJavaStubClasses() generate stubs based on the methods list in Java
1071          */
1072         public void generateJavaStubClasses() throws IOException {
1073
1074                 // Create a new directory
1075                 String path = createDirectories(dir, subdir);
1076                 for (String intface : mapIntfacePTH.keySet()) {
1077
1078                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1079                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1080
1081                                 // Open a new file to write into
1082                                 String newIntface = intMeth.getKey();
1083                                 String newStubClass = newIntface + "_Stub";
1084                                 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1085                                 pw = new PrintWriter(new BufferedWriter(fw));
1086                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1087                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1088                                 // Pass in set of methods and get import classes
1089                                 Set<String> methods = intMeth.getValue();
1090                                 Set<String> importClasses = getImportClasses(methods, intDecl);
1091                                 List<String> stdImportClasses = getStandardJavaImportClasses();
1092                                 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1093                                 printImportStatements(allImportClasses); println("");
1094                                 // Find out if there are callback objects
1095                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1096                                 boolean callbackExist = !callbackClasses.isEmpty();
1097                                 // Write class header
1098                                 println("public class " + newStubClass + " implements " + newIntface + " {\n");
1099                                 // Write properties
1100                                 writePropertiesJavaStub(intface, newIntface, callbackExist, callbackClasses);
1101                                 // Write constructor
1102                                 writeConstructorJavaStub(intface, newStubClass, callbackExist, callbackClasses);
1103                                 // Write methods
1104                                 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
1105                                 println("}");
1106                                 pw.close();
1107                                 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
1108                         }
1109                 }
1110         }
1111
1112
1113         /**
1114          * HELPER: writePropertiesJavaCallbackStub() writes the properties of the callback stub class
1115          */
1116         private void writePropertiesJavaCallbackStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
1117
1118                 println("private IoTRMICall rmiCall;");
1119                 println("private String address;");
1120                 println("private int[] ports;\n");
1121                 // Get the object Id
1122                 println("private static int objectId = 0;");
1123                 if (callbackExist) {
1124                 // We assume that each class only has one callback interface for now
1125                         Iterator it = callbackClasses.iterator();
1126                         String callbackType = (String) it.next();
1127                         println("// Callback properties");
1128                         println("private IoTRMIObject rmiObj;");
1129                         println("List<" + callbackType + "> listCallbackObj;");
1130                         println("private static int objIdCnt = 0;");
1131                         // Generate permission stuff for callback stubs
1132                         DeclarationHandler decHandler = mapIntDeclHand.get(callbackType);
1133                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType);
1134                         writePropertiesJavaPermission(callbackType, intDecl);
1135                 }
1136                 println("\n");
1137         }
1138
1139
1140         /**
1141          * HELPER: writeConstructorJavaCallbackStub() writes the constructor of the callback stub class
1142          */
1143         private void writeConstructorJavaCallbackStub(String intface, String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
1144
1145                 // TODO: If we want callback in callback, then we need to add address and port initializations
1146                 println("public " + newStubClass + "(IoTRMICall _rmiCall, int _objectId) throws Exception {");
1147                 println("objectId = _objectId;");
1148                 println("rmiCall = _rmiCall;");
1149                 if (callbackExist) {
1150                         Iterator it = callbackClasses.iterator();
1151                         String callbackType = (String) it.next();
1152                         writeConstructorJavaPermission(intface);
1153                         println("listCallbackObj = new ArrayList<" + callbackType + ">();");
1154                         println("___initCallBack();");
1155                         println("// TODO: Add address and port initialization here if we want callback in callback!");
1156                 }
1157                 println("}\n");
1158         }
1159
1160
1161         /**
1162          * generateJavaCallbackStubClasses() generate callback stubs based on the methods list in Java
1163          * <p>
1164          * Callback stubs gets the IoTRMICall objects from outside of the class as contructor input
1165          * because all these stubs are populated by the class that takes in this object as a callback
1166          * object. In such a class, we only use one socket, hence one IoTRMICall, for all callback objects.
1167          */
1168         public void generateJavaCallbackStubClasses() throws IOException {
1169
1170                 // Create a new directory
1171                 String path = createDirectories(dir, subdir);
1172                 for (String intface : mapIntfacePTH.keySet()) {
1173
1174                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1175                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1176
1177                                 // Open a new file to write into
1178                                 String newIntface = intMeth.getKey();
1179                                 String newStubClass = newIntface + "_CallbackStub";
1180                                 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
1181                                 pw = new PrintWriter(new BufferedWriter(fw));
1182                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
1183                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
1184                                 // Pass in set of methods and get import classes
1185                                 Set<String> methods = intMeth.getValue();
1186                                 Set<String> importClasses = getImportClasses(methods, intDecl);
1187                                 List<String> stdImportClasses = getStandardJavaImportClasses();
1188                                 List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
1189                                 printImportStatements(allImportClasses); println("");
1190                                 // Find out if there are callback objects
1191                                 Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
1192                                 boolean callbackExist = !callbackClasses.isEmpty();
1193                                 // Write class header
1194                                 println("public class " + newStubClass + " implements " + newIntface + " {\n");
1195                                 // Write properties
1196                                 writePropertiesJavaCallbackStub(intface, newIntface, callbackExist, callbackClasses);
1197                                 // Write constructor
1198                                 writeConstructorJavaCallbackStub(intface, newStubClass, callbackExist, callbackClasses);
1199                                 // Write methods
1200                                 // TODO: perhaps need to generate callback for callback
1201                                 writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
1202                                 println("}");
1203                                 pw.close();
1204                                 System.out.println("IoTCompiler: Generated callback stub class " + newStubClass + ".java...");
1205                         }
1206                 }
1207         }
1208
1209
1210         /**
1211          * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
1212          */
1213         private void writePropertiesJavaSkeleton(String intface, boolean callbackExist, InterfaceDecl intDecl) {
1214
1215                 println("private " + intface + " mainObj;");
1216                 //println("private int ports;");
1217                 println("private IoTRMIObject rmiObj;\n");
1218                 // Callback
1219                 if (callbackExist) {
1220                         println("private static int objIdCnt = 0;");
1221                         println("private IoTRMICall rmiCall;");
1222                 }
1223                 writePropertiesJavaPermission(intface, intDecl);
1224                 println("\n");
1225         }
1226
1227
1228         /**
1229          * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper
1230          */
1231         private void writeStructPermissionJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
1232
1233                 // Use this set to handle two same methodIds
1234                 for (String method : methods) {
1235                         List<String> methParams = intDecl.getMethodParams(method);
1236                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1237                         // Check for params with structs
1238                         for (int i = 0; i < methParams.size(); i++) {
1239                                 String paramType = methPrmTypes.get(i);
1240                                 String param = methParams.get(i);
1241                                 String simpleType = getGenericType(paramType);
1242                                 if (isStructClass(simpleType)) {
1243                                         int methodNumId = intDecl.getMethodNumId(method);
1244                                         String helperMethod = methodNumId + "struct" + i;
1245                                         int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod);
1246                                         // Iterate over interfaces to give permissions to
1247                                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
1248                                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
1249                                                 String newIntface = intMeth.getKey();
1250                                                 int newObjectId = getNewIntfaceObjectId(newIntface);
1251                                                 println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");");
1252                                         }
1253                                 }
1254                         }
1255                 }
1256         }
1257
1258
1259         /**
1260          * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
1261          */
1262         private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, Collection<String> methods, boolean callbackExist) {
1263
1264                 println("public " + newSkelClass + "(" + intface + " _mainObj, int _port) throws Exception {");
1265                 println("mainObj = _mainObj;");
1266                 println("rmiObj = new IoTRMIObject(_port);");
1267                 // Generate permission control initialization
1268                 writeConstructorJavaPermission(intface);
1269                 writeJavaInitCallbackPermission(intface, intDecl, callbackExist);
1270                 writeStructPermissionJavaSkeleton(methods, intDecl, intface);
1271                 println("___waitRequestInvokeMethod();");
1272                 println("}\n");
1273         }
1274
1275
1276         /**
1277          * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
1278          */
1279         private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
1280
1281                 if (methodType.equals("void"))
1282                         print("mainObj." + methodId + "(");
1283                 else
1284                         print("return mainObj." + methodId + "(");
1285                 for (int i = 0; i < methParams.size(); i++) {
1286
1287                         print(getSimpleIdentifier(methParams.get(i)));
1288                         // Check if this is the last element (don't print a comma)
1289                         if (i != methParams.size() - 1) {
1290                                 print(", ");
1291                         }
1292                 }
1293                 println(");");
1294         }
1295
1296
1297         /**
1298          * HELPER: writeInitCallbackJavaSkeleton() writes the init callback method for skeleton class
1299          */
1300         private void writeInitCallbackJavaSkeleton(boolean callbackSkeleton) {
1301
1302                 // This is a callback skeleton generation
1303                 if (callbackSkeleton)
1304                         println("public void ___regCB(IoTRMIObject rmiObj) throws IOException {");
1305                 else
1306                         println("public void ___regCB() throws IOException {");
1307                 print("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, String.class, int.class },");
1308                 println("new Class<?>[] { null, null, null });");
1309                 println("rmiCall = new IoTRMICall((int) paramObj[0], (String) paramObj[1], (int) paramObj[2]);");
1310                 println("}\n");
1311         }
1312
1313
1314         /**
1315          * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
1316          */
1317         private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses, 
1318                         boolean callbackSkeleton) {
1319
1320                 boolean isDefined = false;
1321                 for (String method : methods) {
1322
1323                         List<String> methParams = intDecl.getMethodParams(method);
1324                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1325                         String methodId = intDecl.getMethodId(method);
1326                         print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
1327                         boolean isCallbackMethod = false;
1328                         String callbackType = null;
1329                         for (int i = 0; i < methParams.size(); i++) {
1330
1331                                 String origParamType = methPrmTypes.get(i);
1332                                 String paramType = checkAndGetParamClass(origParamType);
1333                                 if (callbackClasses.contains(origParamType)) { // Check if this has callback object
1334                                         isCallbackMethod = true;
1335                                         callbackType = origParamType;   
1336                                 }
1337                                 print(paramType + " " + methParams.get(i));
1338                                 // Check if this is the last element (don't print a comma)
1339                                 if (i != methParams.size() - 1) {
1340                                         print(", ");
1341                                 }
1342                         }
1343                         println(") {");
1344                         // Now, write the body of skeleton!
1345                         writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
1346                         println("}\n");
1347                         if (isCallbackMethod && !isDefined) {   // Make sure that this function is only defined once!
1348                                 writeInitCallbackJavaSkeleton(callbackSkeleton);
1349                                 isDefined = true;
1350                         }
1351                 }
1352         }
1353
1354
1355         /**
1356          * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
1357          */
1358         private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes, 
1359                         String callbackType) {
1360
1361                 Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
1362                 // Iterate over callback objects
1363                 for (int i = 0; i < methParams.size(); i++) {
1364                         String paramType = methPrmTypes.get(i);
1365                         String param = methParams.get(i);
1366                         //if (callbackType.equals(paramType)) {
1367                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1368                                 println("try {");
1369                                 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1370                                 // Print array if this is array or list if this is a list of callback objects
1371                                 if (isArray(param)) {
1372                                         println("int numStubs" + i + " = (int) paramObj[" + i + "];");
1373                                         println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
1374                                 } else if (isList(paramType)) {
1375                                         println("int numStubs" + i + " = (int) paramObj[" + i + "];");
1376                                         println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
1377                                 } else {
1378                                         println(exchParamType + " stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
1379                                         println("objIdCnt++;");
1380                                 }
1381                         }
1382                         // Generate a loop if needed
1383                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
1384                                 String exchParamType = checkAndGetParamClass(getGenericType(paramType));
1385                                 if (isArray(param)) {
1386                                         println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
1387                                         println("stub" + i + "[objId] = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
1388                                         println("objIdCnt++;");
1389                                         println("}");
1390                                 } else if (isList(paramType)) {
1391                                         println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
1392                                         println("stub" + i + ".add(new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt));");
1393                                         println("objIdCnt++;");
1394                                         println("}");
1395                                 }
1396                                 mapStubParam.put(i, "stub" + i);        // List of all stub parameters
1397                         }
1398                 }
1399                 return mapStubParam;
1400         }
1401
1402
1403         /**
1404          * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
1405          */
1406         private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes) {
1407
1408                 // Iterate and find enum declarations
1409                 for (int i = 0; i < methParams.size(); i++) {
1410                         String paramType = methPrmTypes.get(i);
1411                         String param = methParams.get(i);
1412                         String simpleType = getGenericType(paramType);
1413                         if (isEnumClass(simpleType)) {
1414                         // Check if this is enum type
1415                                 println("int paramInt" + i + "[] = (int[]) paramObj[" + i + "];");
1416                                 println(simpleType + "[] enumVals = " + simpleType + ".values();");
1417                                 if (isArray(param)) {   // An array
1418                                         println("int len" + i + " = paramInt" + i + ".length;");
1419                                         println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];");
1420                                         println("for (int i = 0; i < len" + i + "; i++) {");
1421                                         println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];");
1422                                         println("}");
1423                                 } else if (isList(paramType)) { // A list
1424                                         println("int len" + i + " = paramInt" + i + ".length;");
1425                                         println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();");
1426                                         println("for (int i = 0; i < len" + i + "; i++) {");
1427                                         println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);");
1428                                         println("}");
1429                                 } else {        // Just one element
1430                                         println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
1431                                 }
1432                         }
1433                 }
1434         }
1435
1436
1437         /**
1438          * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
1439          */
1440         private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
1441
1442                 // Strips off array "[]" for return type
1443                 String pureType = getSimpleArrayType(getGenericType(retType));
1444                 // Take the inner type of generic
1445                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1446                         pureType = getGenericType(retType);
1447                 if (isEnumClass(pureType)) {
1448                 // Check if this is enum type
1449                         // Enum decoder
1450                         if (isArray(retType)) {                 // An array
1451                                 print(pureType + "[] retEnum = " + methodId + "(");
1452                         } else if (isList(retType)) {   // A list
1453                                 print("List<" + pureType + "> retEnum = " + methodId + "(");
1454                         } else {        // Just one element
1455                                 print(pureType + " retEnum = " + methodId + "(");
1456                         }
1457                 }
1458         }
1459
1460
1461         /**
1462          * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
1463          */
1464         private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
1465
1466                 // Strips off array "[]" for return type
1467                 String pureType = getSimpleArrayType(getGenericType(retType));
1468                 // Take the inner type of generic
1469                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
1470                         pureType = getGenericType(retType);
1471                 if (isEnumClass(pureType)) {
1472                 // Check if this is enum type
1473                         if (isArray(retType)) { // An array
1474                                 println("int retLen = retEnum.length;");
1475                                 println("int[] retEnumVal = new int[retLen];");
1476                                 println("for (int i = 0; i < retLen; i++) {");
1477                                 println("retEnumVal[i] = retEnum[i].ordinal();");
1478                                 println("}");
1479                         } else if (isList(retType)) {   // A list
1480                                 println("int retLen = retEnum.size();");
1481                                 println("int[] retEnumVal = new int[retLen];");
1482                                 println("for (int i = 0; i < retLen; i++) {");
1483                                 println("retEnumVal[i] = retEnum.get(i).ordinal();");
1484                                 println("}");
1485                         } else {        // Just one element
1486                                 println("int[] retEnumVal = new int[1];");
1487                                 println("retEnumVal[0] = retEnum.ordinal();");
1488                         }
1489                         println("Object retObj = retEnumVal;");
1490                 }
1491         }
1492         
1493         
1494         /**
1495          * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
1496          */
1497         private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes, 
1498                         String method, InterfaceDecl intDecl) {
1499
1500                 // Iterate and find struct declarations - count number of params
1501                 for (int i = 0; i < methParams.size(); i++) {
1502                         String paramType = methPrmTypes.get(i);
1503                         String param = methParams.get(i);
1504                         String simpleType = getGenericType(paramType);
1505                         if (isStructClass(simpleType)) {
1506                                 int members = getNumOfMembers(simpleType);
1507                                 print(Integer.toString(members) + "*");
1508                                 int methodNumId = intDecl.getMethodNumId(method);
1509                                 print("struct" + methodNumId + "Size" + i);
1510                         } else
1511                                 print("1");
1512                         if (i != methParams.size() - 1) {
1513                                 print("+");
1514                         }
1515                 }
1516         }
1517
1518         
1519         /**
1520          * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
1521          */
1522         private void writeStructMembersJavaSkeleton(String simpleType, String paramType, 
1523                         String param, String method, InterfaceDecl intDecl, int iVar) {
1524
1525                 // Get the struct declaration for this struct and generate initialization code
1526                 StructDecl structDecl = getStructDecl(simpleType);
1527                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1528                 List<String> members = structDecl.getMembers(simpleType);
1529                 println("int pos = 0;");
1530                 if (isArrayOrList(paramType, param)) {  // An array or list
1531                         int methodNumId = intDecl.getMethodNumId(method);
1532                         String counter = "struct" + methodNumId + "Size" + iVar;
1533                         println("for(int i = 0; i < " + counter + "; i++) {");
1534                 }
1535                 if (isArrayOrList(paramType, param)) {  // An array or list
1536                         for (int i = 0; i < members.size(); i++) {
1537                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1538                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1539                                 println("paramClsGen[pos++] = null;");
1540                         }
1541                         println("}");
1542                 } else {        // Just one struct element
1543                         for (int i = 0; i < members.size(); i++) {
1544                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1545                                 println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1546                                 println("paramClsGen[pos++] = null;");
1547                         }
1548                 }
1549         }
1550
1551
1552         /**
1553          * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
1554          */
1555         private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1556                         List<String> methPrmTypes, String method) {
1557
1558                 for (int i = 0; i < methParams.size(); i++) {
1559                         String paramType = methPrmTypes.get(i);
1560                         String param = methParams.get(i);
1561                         String simpleType = getGenericType(paramType);
1562                         if (isStructClass(simpleType)) {
1563                                 int methodNumId = intDecl.getMethodNumId(method);
1564                                 String counter = "struct" + methodNumId + "Size" + i;
1565                                 // Declaration
1566                                 if (isArray(param)) {                   // An array
1567                                         println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
1568                                         println("for(int i = 0; i < " + counter + "; i++) {");
1569                                         println("paramStruct" + i + "[i] = new " + simpleType + "();");
1570                                         println("}");
1571                                 } else if (isList(paramType)) { // A list
1572                                         println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
1573                                 } else
1574                                         println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
1575                                 println("int objPos = 0;");
1576                                 // Initialize members
1577                                 StructDecl structDecl = getStructDecl(simpleType);
1578                                 List<String> members = structDecl.getMembers(simpleType);
1579                                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1580                                 if (isArrayOrList(paramType, param)) {  // An array or list
1581                                         println("for(int i = 0; i < " + counter + "; i++) {");
1582                                 }
1583                                 if (isArray(param)) {   // An array
1584                                         for (int j = 0; j < members.size(); j++) {
1585                                                 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1586                                                 print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
1587                                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1588                                         }
1589                                         println("}");
1590                                 } else if (isList(paramType)) { // A list
1591                                         println(simpleType + " paramStructMem = new " + simpleType + "();");
1592                                         for (int j = 0; j < members.size(); j++) {
1593                                                 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1594                                                 print("paramStructMem." + getSimpleIdentifier(members.get(j)));
1595                                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1596                                         }
1597                                         println("paramStruct" + i + ".add(paramStructMem);");
1598                                         println("}");
1599                                 } else {        // Just one struct element
1600                                         for (int j = 0; j < members.size(); j++) {
1601                                                 String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
1602                                                 print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
1603                                                 println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
1604                                         }
1605                                 }
1606                         } else {
1607                                 // Take offsets of parameters
1608                                 println("int offset" + i +" = objPos;");
1609                         }
1610                 }
1611         }
1612
1613
1614         /**
1615          * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
1616          */
1617         private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
1618
1619                 // Minimum retLen is 1 if this is a single struct object
1620                 if (isArray(retType))
1621                         println("int retLen = retStruct.length;");
1622                 else if (isList(retType))
1623                         println("int retLen = retStruct.size();");
1624                 else    // Just single struct object
1625                         println("int retLen = 1;");
1626                 println("Object retLenObj = retLen;");
1627                 println("rmiObj.sendReturnObj(retLenObj);");
1628                 int numMem = getNumOfMembers(simpleType);
1629                 println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
1630                 println("Object[] retObj = new Object[" + numMem + "*retLen];");
1631                 println("int retPos = 0;");
1632                 // Get the struct declaration for this struct and generate initialization code
1633                 StructDecl structDecl = getStructDecl(simpleType);
1634                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
1635                 List<String> members = structDecl.getMembers(simpleType);
1636                 if (isArray(retType)) { // An array or list
1637                         println("for(int i = 0; i < retLen; i++) {");
1638                         for (int i = 0; i < members.size(); i++) {
1639                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1640                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1641                                 print("retObj[retPos++] = retStruct[i].");
1642                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1643                                 println(";");
1644                         }
1645                         println("}");
1646                 } else if (isList(retType)) {   // An array or list
1647                         println("for(int i = 0; i < retLen; i++) {");
1648                         for (int i = 0; i < members.size(); i++) {
1649                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1650                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1651                                 print("retObj[retPos++] = retStruct.get(i).");
1652                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1653                                 println(";");
1654                         }
1655                         println("}");
1656                 } else {        // Just one struct element
1657                         for (int i = 0; i < members.size(); i++) {
1658                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
1659                                 println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
1660                                 print("retObj[retPos++] = retStruct.");
1661                                 print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
1662                                 println(";");
1663                         }
1664                 }
1665
1666         }
1667
1668
1669         /**
1670          * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
1671          */
1672         private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1673                         List<String> methPrmTypes, String method, boolean isCallbackMethod, String callbackType,
1674                         boolean isStructMethod) {
1675
1676                 checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes);
1677                 Map<Integer,String> mapStubParam = null;
1678                 if (isCallbackMethod)
1679                         mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType);
1680                 // Check if this is "void"
1681                 String retType = intDecl.getMethodType(method);
1682                 if (retType.equals("void")) {
1683                         print(intDecl.getMethodId(method) + "(");
1684                 } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {  // Enum type
1685                         checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
1686                 } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) {        // Struct type
1687                         print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
1688                 } else { // We do have a return value
1689                         print("Object retObj = " + intDecl.getMethodId(method) + "(");
1690                 }
1691                 for (int i = 0; i < methParams.size(); i++) {
1692
1693                         if (isCallbackMethod) {
1694                                 print(mapStubParam.get(i));     // Get the callback parameter
1695                         } else if (isEnumClass(getGenericType(methPrmTypes.get(i)))) { // Enum class
1696                                 print(getEnumParam(methPrmTypes.get(i), methParams.get(i), i));
1697                         } else if (isStructClass(getGenericType(methPrmTypes.get(i)))) {
1698                                 print("paramStruct" + i);
1699                         } else {
1700                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1701                                 if (isStructMethod)
1702                                         print("(" + prmType + ") paramObj[offset" + i + "]");
1703                                 else
1704                                         print("(" + prmType + ") paramObj[" + i + "]");
1705                         }
1706                         if (i != methParams.size() - 1)
1707                                 print(", ");
1708                 }
1709                 println(");");
1710                 if (!retType.equals("void")) {
1711                         if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
1712                                 checkAndWriteEnumRetConvJavaSkeleton(retType);
1713                                 println("rmiObj.sendReturnObj(retObj);");
1714                         } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
1715                                 writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
1716                                 println("rmiObj.sendReturnObj(retCls, retObj);");
1717                         } else
1718                                 println("rmiObj.sendReturnObj(retObj);");
1719                 }
1720                 if (isCallbackMethod) { // Catch exception if this is callback
1721                         print("}");
1722                         println(" catch(Exception ex) {");
1723                         println("ex.printStackTrace();");
1724                         println("throw new Error(\"Exception from callback object instantiation!\");");
1725                         println("}");
1726                 }
1727         }
1728
1729
1730         /**
1731          * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
1732          */
1733         private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1734                         List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1735
1736                 // Generate array of parameter objects
1737                 boolean isCallbackMethod = false;
1738                 String callbackType = null;
1739                 print("int paramLen = ");
1740                 writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
1741                 println(";");
1742                 println("Class<?>[] paramCls = new Class<?>[paramLen];");
1743                 println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
1744                 // Iterate again over the parameters
1745                 for (int i = 0; i < methParams.size(); i++) {
1746                         String paramType = methPrmTypes.get(i);
1747                         String param = methParams.get(i);
1748                         String simpleType = getGenericType(paramType);
1749                         if (isStructClass(simpleType)) {
1750                                 writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
1751                         } else {
1752                                 String prmType = returnGenericCallbackType(methPrmTypes.get(i));
1753                                 if (callbackClasses.contains(prmType)) {
1754                                         isCallbackMethod = true;
1755                                         callbackType = prmType;
1756                                         println("paramCls[pos] = int.class;");
1757                                         println("paramClsGen[pos++] = null;");
1758                                 } else {        // Generate normal classes if it's not a callback object
1759                                         String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1760                                         println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
1761                                         print("paramClsGen[pos++] = ");
1762                                         String prmTypeOth = methPrmTypes.get(i);
1763                                         if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
1764                                                 println(getTypeOfGeneric(prmType)[0] + ".class;");
1765                                         else
1766                                                 println("null;");
1767                                 }
1768                         }
1769                 }
1770                 println("Object[] paramObj = rmiObj.getMethodParams(paramCls, paramClsGen);");
1771                 writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
1772                 // Write the return value part
1773                 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true);
1774         }
1775
1776
1777         /**
1778          * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
1779          */
1780         private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
1781                         List<String> methPrmTypes, String method, Set<String> callbackClasses) {
1782
1783                 // Generate array of parameter objects
1784                 boolean isCallbackMethod = false;
1785                 String callbackType = null;
1786                 print("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { ");
1787                 for (int i = 0; i < methParams.size(); i++) {
1788
1789                         String paramType = returnGenericCallbackType(methPrmTypes.get(i));
1790                         if (callbackClasses.contains(paramType)) {
1791                                 isCallbackMethod = true;
1792                                 callbackType = paramType;
1793                                 print("int.class");
1794                         } else {        // Generate normal classes if it's not a callback object
1795                                 String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
1796                                 print(getSimpleType(getEnumType(prmType)) + ".class");
1797                         }
1798                         if (i != methParams.size() - 1)
1799                                 print(", ");
1800                 }
1801                 println(" }, ");
1802                 // Generate generic class if it's a generic type.. null otherwise
1803                 print("new Class<?>[] { ");
1804                 for (int i = 0; i < methParams.size(); i++) {
1805                         String prmType = methPrmTypes.get(i);
1806                         if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) &&
1807                                 !isEnumClass(getGenericType(prmType)) &&
1808                                 !callbackClasses.contains(getGenericType(prmType)))
1809                                         print(getGenericType(prmType) + ".class");
1810                         else
1811                                 print("null");
1812                         if (i != methParams.size() - 1)
1813                                 print(", ");
1814                 }
1815                 println(" });");
1816                 // Write the return value part
1817                 writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false);
1818         }
1819
1820
1821         /**
1822          * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
1823          */
1824         private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
1825
1826                 // Use this set to handle two same methodIds
1827                 Set<String> uniqueMethodIds = new HashSet<String>();
1828                 for (String method : methods) {
1829
1830                         List<String> methParams = intDecl.getMethodParams(method);
1831                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1832                         if (isStructPresent(methParams, methPrmTypes)) {        // Treat struct differently
1833                                 String methodId = intDecl.getMethodId(method);
1834                                 print("public void ___");
1835                                 String helperMethod = methodId;
1836                                 if (uniqueMethodIds.contains(methodId))
1837                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
1838                                 else
1839                                         uniqueMethodIds.add(methodId);
1840                                 String retType = intDecl.getMethodType(method);
1841                                 print(helperMethod + "(");
1842                                 boolean begin = true;
1843                                 for (int i = 0; i < methParams.size(); i++) { // Print size variables
1844                                         String paramType = methPrmTypes.get(i);
1845                                         String param = methParams.get(i);
1846                                         String simpleType = getGenericType(paramType);
1847                                         if (isStructClass(simpleType)) {
1848                                                 if (!begin) {   // Generate comma for not the beginning variable
1849                                                         print(", "); begin = false;
1850                                                 }
1851                                                 int methodNumId = intDecl.getMethodNumId(method);
1852                                                 print("int struct" + methodNumId + "Size" + i);
1853                                         }
1854                                 }
1855                                 // Check if this is "void"
1856                                 if (retType.equals("void"))
1857                                         println(") {");
1858                                 else
1859                                         println(") throws IOException {");
1860                                 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1861                                 println("}\n");
1862                         } else {
1863                                 String methodId = intDecl.getMethodId(method);
1864                                 print("public void ___");
1865                                 String helperMethod = methodId;
1866                                 if (uniqueMethodIds.contains(methodId))
1867                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
1868                                 else
1869                                         uniqueMethodIds.add(methodId);
1870                                 // Check if this is "void"
1871                                 String retType = intDecl.getMethodType(method);
1872                                 if (retType.equals("void"))
1873                                         println(helperMethod + "() {");
1874                                 else
1875                                         println(helperMethod + "() throws IOException {");
1876                                 // Now, write the helper body of skeleton!
1877                                 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
1878                                 println("}\n");
1879                         }
1880                 }
1881                 // Write method helper for structs
1882                 writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
1883         }
1884
1885
1886         /**
1887          * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
1888          */
1889         private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods, 
1890                         InterfaceDecl intDecl) {
1891
1892                 // Use this set to handle two same methodIds
1893                 for (String method : methods) {
1894
1895                         List<String> methParams = intDecl.getMethodParams(method);
1896                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1897                         // Check for params with structs
1898                         for (int i = 0; i < methParams.size(); i++) {
1899                                 String paramType = methPrmTypes.get(i);
1900                                 String param = methParams.get(i);
1901                                 String simpleType = getGenericType(paramType);
1902                                 if (isStructClass(simpleType)) {
1903                                         int methodNumId = intDecl.getMethodNumId(method);
1904                                         print("public int ___");
1905                                         String helperMethod = methodNumId + "struct" + i;
1906                                         println(helperMethod + "() {");
1907                                         // Now, write the helper body of skeleton!
1908                                         println("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1909                                         println("return (int) paramObj[0];");
1910                                         println("}\n");
1911                                 }
1912                         }
1913                 }
1914         }
1915
1916
1917         /**
1918          * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
1919          */
1920         private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods, 
1921                         InterfaceDecl intDecl) {
1922
1923                 // Use this set to handle two same methodIds
1924                 for (String method : methods) {
1925
1926                         List<String> methParams = intDecl.getMethodParams(method);
1927                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1928                         // Check for params with structs
1929                         for (int i = 0; i < methParams.size(); i++) {
1930                                 String paramType = methPrmTypes.get(i);
1931                                 String param = methParams.get(i);
1932                                 String simpleType = getGenericType(paramType);
1933                                 if (isStructClass(simpleType)) {
1934                                         int methodNumId = intDecl.getMethodNumId(method);
1935                                         print("public int ___");
1936                                         String helperMethod = methodNumId + "struct" + i;
1937                                         println(helperMethod + "(IoTRMIObject rmiObj) {");
1938                                         // Now, write the helper body of skeleton!
1939                                         println("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
1940                                         println("return (int) paramObj[0];");
1941                                         println("}\n");
1942                                 }
1943                         }
1944                 }
1945         }
1946
1947
1948         /**
1949          * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
1950          */
1951         private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
1952
1953                 // Use this set to handle two same methodIds
1954                 for (String method : methods) {
1955
1956                         List<String> methParams = intDecl.getMethodParams(method);
1957                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1958                         // Check for params with structs
1959                         for (int i = 0; i < methParams.size(); i++) {
1960                                 String paramType = methPrmTypes.get(i);
1961                                 String param = methParams.get(i);
1962                                 String simpleType = getGenericType(paramType);
1963                                 if (isStructClass(simpleType)) {
1964                                         int methodNumId = intDecl.getMethodNumId(method);
1965                                         println("int struct" + methodNumId + "Size" + i + " = 0;");
1966                                 }
1967                         }
1968                 }
1969         }
1970         
1971         
1972         /**
1973          * HELPER: writeInputCountVarStructSkeleton() writes input counter variable of struct for skeleton
1974          */
1975         private boolean writeInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
1976
1977                 List<String> methParams = intDecl.getMethodParams(method);
1978                 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
1979                 boolean structExist = false;
1980                 // Check for params with structs
1981                 for (int i = 0; i < methParams.size(); i++) {
1982                         String paramType = methPrmTypes.get(i);
1983                         String param = methParams.get(i);
1984                         String simpleType = getGenericType(paramType);
1985                         boolean begin = true;
1986                         if (isStructClass(simpleType)) {
1987                                 structExist = true;
1988                                 if (!begin) {
1989                                         print(", "); begin = false;
1990                                 }
1991                                 int methodNumId = intDecl.getMethodNumId(method);
1992                                 print("struct" + methodNumId + "Size" + i);
1993                         }
1994                 }
1995                 return structExist;
1996         }
1997
1998
1999         /**
2000          * HELPER: writeMethodCallStructSkeleton() writes method call for wait invoke in skeleton
2001          */
2002         private void writeMethodCallStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2003
2004                 // Use this set to handle two same methodIds
2005                 for (String method : methods) {
2006
2007                         List<String> methParams = intDecl.getMethodParams(method);
2008                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2009                         // Check for params with structs
2010                         for (int i = 0; i < methParams.size(); i++) {
2011                                 String paramType = methPrmTypes.get(i);
2012                                 String param = methParams.get(i);
2013                                 String simpleType = getGenericType(paramType);
2014                                 if (isStructClass(simpleType)) {
2015                                         int methodNumId = intDecl.getMethodNumId(method);
2016                                         print("case ");
2017                                         String helperMethod = methodNumId + "struct" + i;
2018                                         String tempVar = "struct" + methodNumId + "Size" + i;
2019                                         print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2020                                         print(tempVar + " = ___");
2021                                         println(helperMethod + "(); break;");
2022                                 }
2023                         }
2024                 }
2025         }
2026
2027
2028         /**
2029          * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
2030          */
2031         private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
2032
2033                 // Use this set to handle two same methodIds
2034                 for (String method : methods) {
2035
2036                         List<String> methParams = intDecl.getMethodParams(method);
2037                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2038                         // Check for params with structs
2039                         for (int i = 0; i < methParams.size(); i++) {
2040                                 String paramType = methPrmTypes.get(i);
2041                                 String param = methParams.get(i);
2042                                 String simpleType = getGenericType(paramType);
2043                                 if (isStructClass(simpleType)) {
2044                                         int methodNumId = intDecl.getMethodNumId(method);
2045                                         print("case ");
2046                                         String helperMethod = methodNumId + "struct" + i;
2047                                         String tempVar = "struct" + methodNumId + "Size" + i;
2048                                         print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
2049                                         print(tempVar + " = ___");
2050                                         println(helperMethod + "(rmiObj); break;");
2051                                 }
2052                         }
2053                 }
2054         }
2055
2056
2057         /**
2058          * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
2059          */
2060         private void writeJavaMethodPermission(String intface) {
2061
2062                 // Get all the different stubs
2063                 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2064                 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2065                         String newIntface = intMeth.getKey();
2066                         int newObjectId = getNewIntfaceObjectId(newIntface);
2067                         println("if (_objectId == object" + newObjectId + "Id) {");
2068                         println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
2069                         println("throw new Error(\"Object with object Id: \" + _objectId + \"  is not allowed to access method: \" + methodId);");
2070                         println("}");
2071                         println("}");
2072                         println("else {");
2073                         println("throw new Error(\"Object Id: \" + _objectId + \" not recognized!\");");
2074                         println("}");
2075                 }
2076         }
2077
2078
2079         /**
2080          * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
2081          */
2082         private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist, String intface) {
2083
2084                 // Use this set to handle two same methodIds
2085                 Set<String> uniqueMethodIds = new HashSet<String>();
2086                 println("private void ___waitRequestInvokeMethod() throws IOException {");
2087                 // Write variables here if we have callbacks or enums or structs
2088                 writeCountVarStructSkeleton(methods, intDecl);
2089                 println("while (true) {");
2090                 println("rmiObj.getMethodBytes();");
2091                 println("int _objectId = rmiObj.getObjectId();");
2092                 println("int methodId = rmiObj.getMethodId();");
2093                 // Generate permission check
2094                 writeJavaMethodPermission(intface);
2095                 println("switch (methodId) {");
2096                 // Print methods and method Ids
2097                 for (String method : methods) {
2098                         String methodId = intDecl.getMethodId(method);
2099                         int methodNumId = intDecl.getMethodNumId(method);
2100                         print("case " + methodNumId + ": ___");
2101                         String helperMethod = methodId;
2102                         if (uniqueMethodIds.contains(methodId))
2103                                 helperMethod = helperMethod + methodNumId;
2104                         else
2105                                 uniqueMethodIds.add(methodId);
2106                         print(helperMethod + "(");
2107                         writeInputCountVarStructSkeleton(method, intDecl);
2108                         println("); break;");
2109                 }
2110                 String method = "___initCallBack()";
2111                 // Print case -9999 (callback handler) if callback exists
2112                 if (callbackExist) {
2113                         int methodId = intDecl.getHelperMethodNumId(method);
2114                         println("case " + methodId + ": ___regCB(); break;");
2115                 }
2116                 writeMethodCallStructSkeleton(methods, intDecl);
2117                 println("default: ");
2118                 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2119                 println("}");
2120                 println("}");
2121                 println("}\n");
2122         }
2123
2124
2125         /**
2126          * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
2127          */
2128         public void generateJavaSkeletonClass() throws IOException {
2129
2130                 // Create a new directory
2131                 String path = createDirectories(dir, subdir);
2132                 for (String intface : mapIntfacePTH.keySet()) {
2133                         // Open a new file to write into
2134                         String newSkelClass = intface + "_Skeleton";
2135                         FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2136                         pw = new PrintWriter(new BufferedWriter(fw));
2137                         // Pass in set of methods and get import classes
2138                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2139                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2140                         List<String> methods = intDecl.getMethods();
2141                         Set<String> importClasses = getImportClasses(methods, intDecl);
2142                         List<String> stdImportClasses = getStandardJavaImportClasses();
2143                         List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2144                         printImportStatements(allImportClasses);
2145                         // Find out if there are callback objects
2146                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2147                         boolean callbackExist = !callbackClasses.isEmpty();
2148                         // Write class header
2149                         println("");
2150                         println("public class " + newSkelClass  + " implements " + intface + " {\n");
2151                         // Write properties
2152                         writePropertiesJavaSkeleton(intface, callbackExist, intDecl);
2153                         // Write constructor
2154                         writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
2155                         // Write methods
2156                         writeMethodJavaSkeleton(methods, intDecl, callbackClasses, false);
2157                         // Write method helper
2158                         writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
2159                         // Write waitRequestInvokeMethod() - main loop
2160                         writeJavaWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface);
2161                         println("}");
2162                         pw.close();
2163                         System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
2164                 }
2165         }
2166
2167
2168         /**
2169          * HELPER: writePropertiesJavaCallbackSkeleton() writes the properties of the callback skeleton class
2170          */
2171         private void writePropertiesJavaCallbackSkeleton(String intface, boolean callbackExist) {
2172
2173                 println("private " + intface + " mainObj;");
2174                 // For callback skeletons, this is its own object Id
2175                 println("private static int objectId = 0;");
2176                 // Callback
2177                 if (callbackExist) {
2178                         println("private static int objIdCnt = 0;");
2179                         println("private IoTRMICall rmiCall;");
2180                 }
2181                 println("\n");
2182         }
2183
2184
2185         /**
2186          * HELPER: writeConstructorJavaCallbackSkeleton() writes the constructor of the skeleton class
2187          */
2188         private void writeConstructorJavaCallbackSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, Collection<String> methods) {
2189
2190                 println("public " + newSkelClass + "(" + intface + " _mainObj, int _objectId) throws Exception {");
2191                 println("mainObj = _mainObj;");
2192                 println("objectId = _objectId;");
2193                 println("}\n");
2194         }
2195
2196
2197         /**
2198          * HELPER: writeMethodHelperJavaCallbackSkeleton() writes the method helper of the callback skeleton class
2199          */
2200         private void writeMethodHelperJavaCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
2201
2202                 // Use this set to handle two same methodIds
2203                 Set<String> uniqueMethodIds = new HashSet<String>();
2204                 for (String method : methods) {
2205
2206                         List<String> methParams = intDecl.getMethodParams(method);
2207                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2208                         if (isStructPresent(methParams, methPrmTypes)) {        // Treat struct differently
2209                                 String methodId = intDecl.getMethodId(method);
2210                                 print("public void ___");
2211                                 String helperMethod = methodId;
2212                                 if (uniqueMethodIds.contains(methodId))
2213                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
2214                                 else
2215                                         uniqueMethodIds.add(methodId);
2216                                 String retType = intDecl.getMethodType(method);
2217                                 print(helperMethod + "(");
2218                                 boolean begin = true;
2219                                 for (int i = 0; i < methParams.size(); i++) { // Print size variables
2220                                         String paramType = methPrmTypes.get(i);
2221                                         String param = methParams.get(i);
2222                                         String simpleType = getGenericType(paramType);
2223                                         if (isStructClass(simpleType)) {
2224                                                 if (!begin) {   // Generate comma for not the beginning variable
2225                                                         print(", "); begin = false;
2226                                                 }
2227                                                 int methodNumId = intDecl.getMethodNumId(method);
2228                                                 print("int struct" + methodNumId + "Size" + i);
2229                                         }
2230                                 }
2231                                 // Check if this is "void"
2232                                 if (retType.equals("void"))
2233                                         println(", IoTRMIObject rmiObj) {");
2234                                 else
2235                                         println(", IoTRMIObject rmiObj) throws IOException {");
2236                                 writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
2237                                 println("}\n");
2238                         } else {
2239                                 String methodId = intDecl.getMethodId(method);
2240                                 print("public void ___");
2241                                 String helperMethod = methodId;
2242                                 if (uniqueMethodIds.contains(methodId))
2243                                         helperMethod = helperMethod + intDecl.getMethodNumId(method);
2244                                 else
2245                                         uniqueMethodIds.add(methodId);
2246                                 // Check if this is "void"
2247                                 String retType = intDecl.getMethodType(method);
2248                                 if (retType.equals("void"))
2249                                         println(helperMethod + "(IoTRMIObject rmiObj) {");
2250                                 else
2251                                         println(helperMethod + "(IoTRMIObject rmiObj) throws IOException {");
2252                                 // Now, write the helper body of skeleton!
2253                                 writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
2254                                 println("}\n");
2255                         }
2256                 }
2257                 // Write method helper for structs
2258                 writeMethodHelperStructSetupJavaCallbackSkeleton(methods, intDecl);
2259         }
2260
2261
2262         /**
2263          * HELPER: writeJavaCallbackWaitRequestInvokeMethod() writes the request invoke method of the callback skeleton class
2264          */
2265         private void writeJavaCallbackWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist) {
2266
2267                 // Use this set to handle two same methodIds
2268                 Set<String> uniqueMethodIds = new HashSet<String>();
2269                 println("public void invokeMethod(IoTRMIObject rmiObj) throws IOException {");
2270                 // Write variables here if we have callbacks or enums or structs
2271                 writeCountVarStructSkeleton(methods, intDecl);
2272                 // Write variables here if we have callbacks or enums or structs
2273                 println("int methodId = rmiObj.getMethodId();");
2274                 // TODO: code the permission check here!
2275                 println("switch (methodId) {");
2276                 // Print methods and method Ids
2277                 for (String method : methods) {
2278                         String methodId = intDecl.getMethodId(method);
2279                         int methodNumId = intDecl.getMethodNumId(method);
2280                         print("case " + methodNumId + ": ___");
2281                         String helperMethod = methodId;
2282                         if (uniqueMethodIds.contains(methodId))
2283                                 helperMethod = helperMethod + methodNumId;
2284                         else
2285                                 uniqueMethodIds.add(methodId);
2286                         print(helperMethod + "(");
2287                         if (writeInputCountVarStructSkeleton(method, intDecl))
2288                                 println(", rmiObj); break;");
2289                         else
2290                                 println("rmiObj); break;");
2291                 }
2292                 String method = "___initCallBack()";
2293                 // Print case -9999 (callback handler) if callback exists
2294                 if (callbackExist) {
2295                         int methodId = intDecl.getHelperMethodNumId(method);
2296                         println("case " + methodId + ": ___regCB(rmiObj); break;");
2297                 }
2298                 writeMethodCallStructCallbackSkeleton(methods, intDecl);
2299                 println("default: ");
2300                 println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
2301                 println("}");
2302                 println("}\n");
2303         }
2304
2305
2306         /**
2307          * generateJavaCallbackSkeletonClass() generate callback skeletons based on the methods list in Java
2308          */
2309         public void generateJavaCallbackSkeletonClass() throws IOException {
2310
2311                 // Create a new directory
2312                 String path = createDirectories(dir, subdir);
2313                 for (String intface : mapIntfacePTH.keySet()) {
2314                         // Open a new file to write into
2315                         String newSkelClass = intface + "_CallbackSkeleton";
2316                         FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".java");
2317                         pw = new PrintWriter(new BufferedWriter(fw));
2318                         // Pass in set of methods and get import classes
2319                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2320                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2321                         List<String> methods = intDecl.getMethods();
2322                         Set<String> importClasses = getImportClasses(methods, intDecl);
2323                         List<String> stdImportClasses = getStandardJavaImportClasses();
2324                         List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
2325                         printImportStatements(allImportClasses);
2326                         // Find out if there are callback objects
2327                         Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
2328                         boolean callbackExist = !callbackClasses.isEmpty();
2329                         // Write class header
2330                         println("");
2331                         println("public class " + newSkelClass  + " implements " + intface + " {\n");
2332                         // Write properties
2333                         writePropertiesJavaCallbackSkeleton(intface, callbackExist);
2334                         // Write constructor
2335                         writeConstructorJavaCallbackSkeleton(newSkelClass, intface, intDecl, methods);
2336                         // Write methods
2337                         writeMethodJavaSkeleton(methods, intDecl, callbackClasses, true);
2338                         // Write method helper
2339                         writeMethodHelperJavaCallbackSkeleton(methods, intDecl, callbackClasses);
2340                         // Write waitRequestInvokeMethod() - main loop
2341                         writeJavaCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist);
2342                         println("}");
2343                         pw.close();
2344                         System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".java...");
2345                 }
2346         }
2347
2348
2349         /**
2350          * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
2351          */
2352         private void writeMethodCplusLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
2353
2354                 for (String method : methods) {
2355
2356                         List<String> methParams = intDecl.getMethodParams(method);
2357                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2358                         print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2359                                 intDecl.getMethodId(method) + "(");
2360                         for (int i = 0; i < methParams.size(); i++) {
2361                                 // Check for params with driver class types and exchange it 
2362                                 //              with its remote interface
2363                                 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
2364                                 paramType = checkAndGetCplusType(paramType);
2365                                 // Check for arrays - translate into vector in C++
2366                                 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2367                                 print(paramComplete);
2368                                 // Check if this is the last element (don't print a comma)
2369                                 if (i != methParams.size() - 1) {
2370                                         print(", ");
2371                                 }
2372                         }
2373                         println(") = 0;");
2374                 }
2375         }
2376
2377
2378         /**
2379          * HELPER: writeMethodCplusInterface() writes the method of the interface
2380          */
2381         private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
2382
2383                 for (String method : methods) {
2384
2385                         List<String> methParams = intDecl.getMethodParams(method);
2386                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2387                         print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2388                                 intDecl.getMethodId(method) + "(");
2389                         for (int i = 0; i < methParams.size(); i++) {
2390                                 // Check for params with driver class types and exchange it 
2391                                 //              with its remote interface
2392                                 String paramType = methPrmTypes.get(i);
2393                                 paramType = checkAndGetCplusType(paramType);
2394                                 // Check for arrays - translate into vector in C++
2395                                 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
2396                                 print(paramComplete);
2397                                 // Check if this is the last element (don't print a comma)
2398                                 if (i != methParams.size() - 1) {
2399                                         print(", ");
2400                                 }
2401                         }
2402                         println(") = 0;");
2403                 }
2404         }
2405
2406
2407         /**
2408          * HELPER: generateEnumCplus() writes the enumeration declaration
2409          */
2410         public void generateEnumCplus() throws IOException {
2411
2412                 // Create a new directory
2413                 createDirectory(dir);
2414                 for (String intface : mapIntfacePTH.keySet()) {
2415                         // Get the right StructDecl
2416                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2417                         EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
2418                         Set<String> enumTypes = enumDecl.getEnumDeclarations();
2419                         // Iterate over enum declarations
2420                         for (String enType : enumTypes) {
2421                                 // Open a new file to write into
2422                                 FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp");
2423                                 pw = new PrintWriter(new BufferedWriter(fw));
2424                                 // Write file headers
2425                                 println("#ifndef _" + enType.toUpperCase() + "_HPP__");
2426                                 println("#define _" + enType.toUpperCase() + "_HPP__");
2427                                 println("enum " + enType + " {");
2428                                 List<String> enumMembers = enumDecl.getMembers(enType);
2429                                 for (int i = 0; i < enumMembers.size(); i++) {
2430
2431                                         String member = enumMembers.get(i);
2432                                         print(member);
2433                                         // Check if this is the last element (don't print a comma)
2434                                         if (i != enumMembers.size() - 1)
2435                                                 println(",");
2436                                         else
2437                                                 println("");
2438                                 }
2439                                 println("};\n");
2440                                 println("#endif");
2441                                 pw.close();
2442                                 System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
2443                         }
2444                 }
2445         }
2446
2447
2448         /**
2449          * HELPER: generateStructCplus() writes the struct declaration
2450          */
2451         public void generateStructCplus() throws IOException {
2452
2453                 // Create a new directory
2454                 createDirectory(dir);
2455                 for (String intface : mapIntfacePTH.keySet()) {
2456                         // Get the right StructDecl
2457                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2458                         StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
2459                         List<String> structTypes = structDecl.getStructTypes();
2460                         // Iterate over enum declarations
2461                         for (String stType : structTypes) {
2462                                 // Open a new file to write into
2463                                 FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp");
2464                                 pw = new PrintWriter(new BufferedWriter(fw));
2465                                 // Write file headers
2466                                 println("#ifndef _" + stType.toUpperCase() + "_HPP__");
2467                                 println("#define _" + stType.toUpperCase() + "_HPP__");
2468                                 println("using namespace std;");
2469                                 println("struct " + stType + " {");
2470                                 List<String> structMemberTypes = structDecl.getMemberTypes(stType);
2471                                 List<String> structMembers = structDecl.getMembers(stType);
2472                                 for (int i = 0; i < structMembers.size(); i++) {
2473
2474                                         String memberType = structMemberTypes.get(i);
2475                                         String member = structMembers.get(i);
2476                                         String structTypeC = checkAndGetCplusType(memberType);
2477                                         String structComplete = checkAndGetCplusArray(structTypeC, member);
2478                                         println(structComplete + ";");
2479                                 }
2480                                 println("};\n");
2481                                 println("#endif");
2482                                 pw.close();
2483                                 System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
2484                         }
2485                 }
2486         }
2487
2488
2489         /**
2490          * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
2491          * <p>
2492          * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
2493          * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
2494          * The local interface has to be the input parameter for the stub and the stub 
2495          * interface has to be the input parameter for the local class.
2496          */
2497         public void generateCplusLocalInterfaces() throws IOException {
2498
2499                 // Create a new directory
2500                 createDirectory(dir);
2501                 for (String intface : mapIntfacePTH.keySet()) {
2502                         // Open a new file to write into
2503                         FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
2504                         pw = new PrintWriter(new BufferedWriter(fw));
2505                         // Write file headers
2506                         println("#ifndef _" + intface.toUpperCase() + "_HPP__");
2507                         println("#define _" + intface.toUpperCase() + "_HPP__");
2508                         println("#include <iostream>");
2509                         // Pass in set of methods and get include classes
2510                         DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2511                         InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2512                         List<String> methods = intDecl.getMethods();
2513                         Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
2514                         printIncludeStatements(includeClasses); println("");
2515                         println("using namespace std;\n");
2516                         //writeStructCplus(structDecl);
2517                         println("class " + intface); println("{");
2518                         println("public:");
2519                         // Write methods
2520                         writeMethodCplusLocalInterface(methods, intDecl);
2521                         println("};");
2522                         println("#endif");
2523                         pw.close();
2524                         System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
2525                 }
2526         }
2527
2528
2529         /**
2530          * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
2531          * <p>
2532          * For C++ we use virtual classe as interface
2533          */
2534         public void generateCPlusInterfaces() throws IOException {
2535
2536                 // Create a new directory
2537                 String path = createDirectories(dir, subdir);
2538                 for (String intface : mapIntfacePTH.keySet()) {
2539
2540                         Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
2541                         for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
2542
2543                                 // Open a new file to write into
2544                                 String newIntface = intMeth.getKey();
2545                                 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
2546                                 pw = new PrintWriter(new BufferedWriter(fw));
2547                                 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
2548                                 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
2549                                 // Write file headers
2550                                 println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
2551                                 println("#define _" + newIntface.toUpperCase() + "_HPP__");
2552                                 println("#include <iostream>");
2553                                 // Pass in set of methods and get import classes
2554                                 Set<String> includeClasses = getIncludeClasses(intMeth.getValue(), intDecl, intface, false);
2555                                 List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
2556                                 List<String> allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses);
2557                                 printIncludeStatements(allIncludeClasses); println("");                 
2558                                 println("using namespace std;\n");
2559                                 println("class " + newIntface);
2560                                 println("{");
2561                                 println("public:");
2562                                 // Write methods
2563                                 writeMethodCplusInterface(intMeth.getValue(), intDecl);
2564                                 println("};");
2565                                 println("#endif");
2566                                 pw.close();
2567                                 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
2568                         }
2569                 }
2570         }
2571
2572
2573         /**
2574          * HELPER: writeMethodCplusStub() writes the methods of the stub
2575          */
2576         private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
2577
2578                 boolean isDefined = false;
2579                 for (String method : methods) {
2580
2581                         List<String> methParams = intDecl.getMethodParams(method);
2582                         List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
2583                         print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
2584                                 intDecl.getMethodId(method) + "(");
2585                         boolean isCallbackMethod = false;
2586                         String callbackType = null;
2587                         for (int i = 0; i < methParams.size(); i++) {
2588
2589                                 String paramType = returnGenericCallbackType(methPrmTypes.get(i));
2590                                 // Check if this has callback object
2591                                 if (callbackClasses.contains(paramType)) {
2592                                         isCallbackMethod = true;
2593                                         callbackType = paramType;       
2594                                         // Even if there're 2 callback arguments, we expect them to be of the same interface
2595                                 }
2596                                 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
2597                                 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
2598                                 print(methParamComplete);
2599                                 // Check if this is the last element (don't print a comma)
2600                                 if (i != methParams.size() - 1) {
2601                                         print(", ");
2602                                 }
2603                         }
2604                         println(") { ");
2605                         if (isCallbackMethod)
2606                                 writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
2607                         else
2608                                 writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackClasses);
2609                         println("}\n");
2610                         // Write the init callback helper method
2611                         if (isCallbackMethod && !isDefined) {
2612                                 writeInitCallbackCplusStub(callbackType, intDecl);
2613                                 writeInitCallbackSendInfoCplusStub(intDecl);
2614                                 isDefined = true;
2615                         }
2616                 }
2617         }
2618
2619
2620         /**
2621          * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
2622          */
2623         private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
2624                         List<String> methPrmTypes, String method, String callbackType) {
2625
2626                 // Check if this is single object, array, or list of objects
2627                 boolean isArrayOrList = false;
2628                 String callbackParam = null;
2629                 for (int i = 0; i < methParams.size(); i++) {
2630
2631                         String paramType = methPrmTypes.get(i);
2632                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2633                                 String param = methParams.get(i);
2634                                 if (isArrayOrList(paramType, param)) {  // Generate loop
2635                                         println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
2636                                         println(callbackType + "_CallbackSkeleton* skel = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);");
2637                                         isArrayOrList = true;
2638                                         callbackParam = getSimpleIdentifier(param);
2639                                 } else
2640                                         println(callbackType + "_CallbackSkeleton* skel = new " + callbackType + "_CallbackSkeleton(" +
2641                                                 getSimpleIdentifier(param) + ", objIdCnt++);");
2642                                 println("vecCallbackObj.push_back(skel);");
2643                                 if (isArrayOrList)
2644                                         println("}");
2645                         }
2646                 }
2647                 println("int numParam = " + methParams.size() + ";");
2648                 println("int methodId = " + intDecl.getMethodNumId(method) + ";");
2649                 String retType = intDecl.getMethodType(method);
2650                 //String retTypeC = checkAndGetCplusType(retType);
2651                 //println("string retType = \"" + checkAndGetCplusArrayType(getStructType(getEnumType(retTypeC))) + "\";");
2652                 println("string retType = \"" + checkAndGetCplusRetClsType(getStructType(getEnumType(retType))) + "\";");
2653                 // Generate array of parameter types
2654                 print("string paramCls[] = { ");
2655                 for (int i = 0; i < methParams.size(); i++) {
2656                         String paramType = methPrmTypes.get(i);
2657                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2658                                 print("\"int\"");
2659                         } else { // Generate normal classes if it's not a callback object
2660                                 String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2661                                 print("\"" + paramTypeC + "\"");
2662                         }
2663                         if (i != methParams.size() - 1) // Check if this is the last element
2664                                 print(", ");
2665                 }
2666                 println(" };");
2667                 print("int ___paramCB = ");
2668                 if (isArrayOrList)
2669                         println(callbackParam + ".size();");
2670                 else
2671                         println("1;");
2672                 // Generate array of parameter objects
2673                 print("void* paramObj[] = { ");
2674                 for (int i = 0; i < methParams.size(); i++) {
2675                         String paramType = methPrmTypes.get(i);
2676                         if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
2677                                 print("&___paramCB");
2678                         } else
2679                                 print(getSimpleIdentifier(methParams.get(i)));
2680                         if (i != methParams.size() - 1)
2681                                 print(", ");
2682                 }
2683                 println(" };");
2684                 // Check if this is "void"
2685                 if (retType.equals("void")) {
2686                         println("void* retObj = NULL;");
2687                         println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
2688                 } else { // We do have a return value
2689                         if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2690                                 println(checkAndGetCplusType(retType) + " retVal;");
2691                         else
2692                                 println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
2693                         println("void* retObj = &retVal;");
2694                         println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
2695                         println("return retVal;");
2696                 }
2697         }
2698
2699
2700         /**
2701          * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
2702          */
2703         private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
2704
2705                 // Iterate and find enum declarations
2706                 for (int i = 0; i < methParams.size(); i++) {
2707                         String paramType = methPrmTypes.get(i);
2708                         String param = methParams.get(i);
2709                         if (isEnumClass(getGenericType(paramType))) {
2710                         // Check if this is enum type
2711                                 if (isArrayOrList(paramType, param)) {  // An array or vector
2712                                         println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
2713                                         println("vector<int> paramEnum" + i + "(len" + i + ");");
2714                                         println("for (int i = 0; i < len" + i + "; i++) {");
2715                                         println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
2716                                         println("}");
2717                                 } else {        // Just one element
2718                                         println("vector<int> paramEnum" + i + "(1);");
2719                                         println("paramEnum" + i + "[0] = (int) " + param + ";");
2720                                 }
2721                         }
2722                 }
2723         }
2724
2725
2726         /**
2727          * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
2728          */
2729         private void checkAndWriteEnumRetTypeCplusStub(String retType) {
2730
2731                 // Strips off array "[]" for return type
2732                 String pureType = getSimpleArrayType(getGenericType(retType));
2733                 // Take the inner type of generic
2734                 if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
2735                         pureType = getGenericType(retType);
2736                 if (isEnumClass(pureType)) {
2737                 // Check if this is enum type
2738                         println("vector<int> retEnumInt;");
2739                         println("void* retObj = &retEnumInt;");
2740                         println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
2741                         if (isArrayOrList(retType, retType)) {  // An array or vector
2742                                 println("int retLen = retEnumInt.size();");
2743                                 println("vector<" + pureType + "> retVal(retLen);");
2744                                 println("for (int i = 0; i < retLen; i++) {");
2745                                 println("retVal[i] = (" + pureType + ") retEnumInt[i];");
2746                                 println("}");
2747                         } else {        // Just one element
2748                                 println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
2749                         }
2750                         println("return retVal;");
2751                 }
2752         }
2753
2754
2755         /**
2756          * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
2757          */
2758         private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes, 
2759                         InterfaceDecl intDecl, String method) {
2760                 
2761                 // Iterate and find struct declarations
2762                 for (int i = 0; i < methParams.size(); i++) {
2763                         String paramType = methPrmTypes.get(i);
2764                         String param = methParams.get(i);
2765                         String simpleType = getGenericType(paramType);
2766                         if (isStructClass(simpleType)) {
2767                         // Check if this is enum type
2768                                 println("int numParam" + i + " = 1;");
2769                                 int methodNumId = intDecl.getMethodNumId(method);
2770                                 String helperMethod = methodNumId + "struct" + i;
2771                                 println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
2772                                 println("string retTypeStruct" + i + " = \"void\";");
2773                                 println("string paramClsStruct" + i + "[] = { \"int\" };");
2774                                 print("int structLen" + i + " = ");
2775                                 if (isArrayOrList(paramType, param)) {  // An array
2776                                         println(getSimpleArrayType(param) + ".size();");
2777                                 } else {        // Just one element
2778                                         println("1;");
2779                                 }
2780                                 println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
2781                                 println("void* retStructLen" + i + " = NULL;");
2782                                 println("rmiCall->remoteCall(objectId, methodIdStruct" + i + 
2783                                                 ", retTypeStruct" + i + ", paramClsStruct" + i + ", paramObjStruct" + i + 
2784                                                 ", numParam" + i + ", retStructLen" + i + ");\n");
2785                         }
2786                 }
2787         }
2788
2789
2790         /**
2791          * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
2792          */
2793         private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2794
2795                 // Iterate and find struct declarations - count number of params
2796                 for (int i = 0; i < methParams.size(); i++) {
2797                         String paramType = methPrmTypes.get(i);
2798                         String param = methParams.get(i);
2799                         String simpleType = getGenericType(paramType);
2800                         if (isStructClass(simpleType)) {
2801                                 int members = getNumOfMembers(simpleType);
2802                                 if (isArrayOrList(paramType, param)) {  // An array or list
2803                                         String structLen = getSimpleIdentifier(param) + ".size()";
2804                                         print(members + "*" + structLen);
2805                                 } else
2806                                         print(Integer.toString(members));
2807                         } else
2808                                 print("1");
2809                         if (i != methParams.size() - 1) {
2810                                 print("+");
2811                         }
2812                 }
2813         }
2814
2815
2816         /**
2817          * HELPER: writeStructMembersCplusStub() writes member parameters of struct
2818          */
2819         private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
2820
2821                 // Get the struct declaration for this struct and generate initialization code
2822                 StructDecl structDecl = getStructDecl(simpleType);
2823                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2824                 List<String> members = structDecl.getMembers(simpleType);
2825                 if (isArrayOrList(paramType, param)) {  // An array or list
2826                         println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
2827                 }
2828                 if (isArrayOrList(paramType, param)) {  // An array or list
2829                         for (int i = 0; i < members.size(); i++) {
2830                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2831                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
2832                                 print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
2833                                 print(getSimpleIdentifier(members.get(i)));
2834                                 println(";");
2835                         }
2836                         println("}");
2837                 } else {        // Just one struct element
2838                         for (int i = 0; i < members.size(); i++) {
2839                                 String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
2840                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
2841                                 print("paramObj[pos++] = &" + param + ".");
2842                                 print(getSimpleIdentifier(members.get(i)));
2843                                 println(";");
2844                         }
2845                 }
2846         }
2847
2848
2849         /**
2850          * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
2851          */
2852         private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
2853
2854                 print("int numParam = ");
2855                 writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
2856                 println(";");
2857                 println("void* paramObj[numParam];");
2858                 println("string paramCls[numParam];");
2859                 println("int pos = 0;");
2860                 // Iterate again over the parameters
2861                 for (int i = 0; i < methParams.size(); i++) {
2862                         String paramType = methPrmTypes.get(i);
2863                         String param = methParams.get(i);
2864                         String simpleType = getGenericType(paramType);
2865                         if (isStructClass(simpleType)) {
2866                                 writeStructMembersCplusStub(simpleType, paramType, param);
2867                         } else {
2868                                 String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
2869                                 println("paramCls[pos] = \"" + prmTypeC + "\";");
2870                                 print("paramObj[pos++] = &");
2871                                 print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
2872                                 println(";");
2873                         }
2874                 }
2875                 
2876         }
2877
2878
2879         /**
2880          * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
2881          */
2882         private void writeStructRetMembersCplusStub(String simpleType, String retType) {
2883
2884                 // Get the struct declaration for this struct and generate initialization code
2885                 StructDecl structDecl = getStructDecl(simpleType);
2886                 List<String> memTypes = structDecl.getMemberTypes(simpleType);
2887                 List<String> members = structDecl.getMembers(simpleType);
2888                 if (isArrayOrList(retType, retType)) {  // An array or list
2889                         println("for(int i = 0; i < retLen; i++) {");
2890                 }
2891                 if (isArrayOrList(retType, retType)) {  // An array or list
2892                         for (int i = 0; i < members.size(); i++) {
2893                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2894                                 print("structRet[i]." + getSimpleIdentifier(members.get(i)));
2895                                 println(" = retParam" + i + "[i];");
2896                         }
2897                         println("}");
2898                 } else {        // Just one struct element
2899                         for (int i = 0; i < members.size(); i++) {
2900                                 String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
2901                                 print("structRet." + getSimpleIdentifier(members.get(i)));
2902                                 println(" = retParam" + i + ";");
2903                         }
2904                 }
2905                 println("return structRet;");
2906         }
2907
2908
2909         /**
2910          * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
2911          */
2912         private void writeStructReturnCplusStub(String simpleType, String retType) {
2913
2914                 // Minimum retLen is 1 if this is a single struct object
2915                 println("int retLen = 0;");
2916                 println("void* retLenObj = { &retLen };");
2917                 // Handle the returned struct!!!
2918                 println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retLenObj);");
2919                 int numMem = getNumOfMembers(simpleType);
2920                 println("int numRet = " + numMem + "*retLen;");
2921                 println("string retCls[numRet];");
2922