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