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