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