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