Adding permission checks for Java; fixing type translations for return and parameter...
[iot2.git] / iotjava / iotpolicy / IoTCompiler.java
index e79bea68700701b043b03c44eb90832e8bb5b244..90734e3f5dde470427cbd19757be160c3be9086a 100644 (file)
@@ -3,10 +3,13 @@ package iotpolicy;
 import java_cup.runtime.ComplexSymbolFactory;
 import java_cup.runtime.ScannerBuffer;
 import java.io.*;
+import java.util.Arrays;
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -16,10 +19,15 @@ import iotpolicy.parser.Parser;
 import iotpolicy.tree.ParseNode;
 import iotpolicy.tree.ParseNodeVector;
 import iotpolicy.tree.ParseTreeHandler;
+import iotpolicy.tree.Declaration;
+import iotpolicy.tree.DeclarationHandler;
 import iotpolicy.tree.CapabilityDecl;
 import iotpolicy.tree.InterfaceDecl;
 import iotpolicy.tree.RequiresDecl;
 
+import iotrmi.Java.IoTRMITypes;
+
+
 /** Class IoTCompiler is the main interface/stub compiler for
  *  files generation. This class calls helper classes
  *  such as Parser, Lexer, InterfaceDecl, CapabilityDecl,
@@ -34,16 +42,16 @@ public class IoTCompiler {
        /**
         * Class properties
         */
-       private ParseTreeHandler ptHandler;
-       private InterfaceDecl intDecl;
-       private CapabilityDecl capDecl;
-       private RequiresDecl reqDecl;
-       private Map<String,Set<String>> mapCapabMethods;
+       // Maps multiple interfaces to multiple objects of ParseTreeHandler
+       private Map<String,ParseTreeHandler> mapIntfacePTH;
+       private Map<String,DeclarationHandler> mapIntDeclHand;
+       private Map<String,Map<String,Set<String>>> mapInt2NewInts;
        // Data structure to store our types (primitives and non-primitives) for compilation
-       //private Set<String> setPrimitives;
        private Map<String,String> mapPrimitives;
        private Map<String,String> mapNonPrimitivesJava;
        private Map<String,String> mapNonPrimitivesCplus;
+       // Other data structures
+       private Map<String,Integer> mapIntfaceObjId;    // Maps interface name to object Id
        private PrintWriter pw;
        private String dir;
        private String subdir;
@@ -53,97 +61,6 @@ public class IoTCompiler {
         */
        private final static String OUTPUT_DIRECTORY = "output_files";
 
-       /**
-        * Primitive data types
-        */
-       private final static String[] primitives = new String[] {
-
-               "byte",
-               "Byte",
-               "short",
-               "Short",
-               "int",
-               "Integer",
-               "long",
-               "Long",
-               "float",
-               "Float",
-               "double",
-               "Double",
-               "boolean",
-               "Boolean",
-               "char",
-               "Character",
-               "string",
-               "String",
-               "void"
-       };
-
-       /**
-        * Primitive data types in C++ to map the primitives list
-        */
-       private final static String[] primitivesCplus = new String[] {
-
-               "char",
-               "char",
-               "short",
-               "short",
-               "int",
-               "int",
-               "long",
-               "long",
-               "float",
-               "float",
-               "double",
-               "double",
-               "bool",
-               "bool",
-               "char",
-               "char",
-               "string",
-               "string",
-               "void"
-       };
-
-       /**
-        * Non-primitive data types supported by this compiler
-        */
-       private final static String[] nonPrimitives = new String[] {
-
-               "Set",
-               "HashSet",
-               "Map",
-               "HashMap",
-               "List",
-               "ArrayList"
-       };
-
-       /**
-        * Non-primitive Java libraries based on the list above
-        */
-       private final static String[] nonPrimitiveJavaLibs = new String[] {
-
-               "java.util.Set",
-               "java.util.HashSet",
-               "java.util.Map",
-               "java.util.HashMap",
-               "java.util.List",
-               "java.util.ArrayList"
-       };
-
-       /**
-        * Non-primitive C++ libraries based on the list above
-        */
-       private final static String[] nonPrimitiveCplusLibs = new String[] {
-
-               "set",
-               "unordered_set",
-               "map",
-               "unordered_map",
-               "list",
-               "list"
-       };
-
        private enum ParamCategory {
 
                PRIMITIVES,             // All the primitive types, e.g. byte, short, int, long, etc.
@@ -156,36 +73,16 @@ public class IoTCompiler {
         */
        public IoTCompiler() {
 
-               ptHandler = new ParseTreeHandler();
-               intDecl = null;
-               capDecl = null;
-               capDecl = null;
-               mapCapabMethods = new HashMap<String,Set<String>>();
-               mapPrimitives = new HashMap<String,String>();
-                       arraysToMap(mapPrimitives, primitives, primitivesCplus);
-               mapNonPrimitivesJava = new HashMap<String,String>();
-                       arraysToMap(mapNonPrimitivesJava, nonPrimitives, nonPrimitiveJavaLibs);
-               mapNonPrimitivesCplus = new HashMap<String,String>();
-                       arraysToMap(mapNonPrimitivesCplus, nonPrimitives, nonPrimitiveCplusLibs);
-               pw = null;
-               dir = OUTPUT_DIRECTORY;
-               subdir = null;
-       }
-
-
-       public IoTCompiler(String _intface, ParseNode _pnPol, ParseNode _pnReq) {
-
-               ptHandler = new ParseTreeHandler(_intface, _pnPol, _pnReq);
-               intDecl = null;
-               capDecl = null;
-               reqDecl = null;
-               mapCapabMethods = new HashMap<String,Set<String>>();
+               mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
+               mapIntDeclHand = new HashMap<String,DeclarationHandler>();
+               mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
+               mapIntfaceObjId = new HashMap<String,Integer>();
                mapPrimitives = new HashMap<String,String>();
-                       arraysToMap(mapPrimitives, primitives, primitivesCplus);
+                       arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
                mapNonPrimitivesJava = new HashMap<String,String>();
-                       arraysToMap(mapNonPrimitivesJava, nonPrimitives, nonPrimitiveJavaLibs);
+                       arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
                mapNonPrimitivesCplus = new HashMap<String,String>();
-                       arraysToMap(mapNonPrimitivesCplus, nonPrimitives, nonPrimitiveCplusLibs);
+                       arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
                pw = null;
                dir = OUTPUT_DIRECTORY;
                subdir = null;
@@ -193,9 +90,9 @@ public class IoTCompiler {
 
 
        /**
-        * parsePolicyFile() parses policy file
+        * setDataStructures() sets parse tree and other data structures based on policy files.
         * <p>
-        * It also generates parse tree and
+        * It also generates parse tree (ParseTreeHandler) and
         * copies useful information from parse tree into
         * InterfaceDecl, CapabilityDecl, and RequiresDecl 
         * data structures.
@@ -203,16 +100,26 @@ public class IoTCompiler {
         * returned from tree-parsing for further process.
         *
         */
-       public void parsePolicyFile() {
+       public void setDataStructures(String origInt, ParseNode pnPol, ParseNode pnReq) {
 
+               ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
+               DeclarationHandler decHandler = new DeclarationHandler();
+               // Process ParseNode and generate Declaration objects
                ptHandler.processInterfaceDecl();
-               intDecl = ptHandler.getInterfaceDecl();
-
+               InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
+               decHandler.addInterfaceDecl(origInt, intDecl);
                ptHandler.processCapabilityDecl();
-               capDecl = ptHandler.getCapabilityDecl();
-
+               CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
+               decHandler.addCapabilityDecl(origInt, capDecl);
                ptHandler.processRequiresDecl();
-               reqDecl = ptHandler.getRequiresDecl();
+               RequiresDecl reqDecl = ptHandler.getRequiresDecl();
+               decHandler.addRequiresDecl(origInt, reqDecl);
+
+               mapIntfacePTH.put(origInt, ptHandler);
+               mapIntDeclHand.put(origInt, decHandler);
+               // Set object Id counter to 0 for each interface
+               mapIntfaceObjId.put(origInt, new Integer(0));
+               //System.out.println("\nInterface: " + origInt + "\n\n");
        }
 
 
@@ -222,11 +129,15 @@ public class IoTCompiler {
         * It is going to give list of methods for a certain interface
         *              based on the declaration of capabilities.
         */
-       public void getMethodsForIntface() {
+       public void getMethodsForIntface(String origInt) {
 
+               ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
+               Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
                // Get set of new interfaces, e.g. CameraWithCaptureAndData
                // Generate this new interface with all the methods it needs
                //              from different capabilities it declares
+               DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
+               RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
                Set<String> setIntfaces = reqDecl.getInterfaces();
                for (String strInt : setIntfaces) {
 
@@ -237,6 +148,7 @@ public class IoTCompiler {
                        for (String strCap : listCapab) {
 
                                // Get list of methods for each capability
+                               CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
                                List<String> listCapabMeth = capDecl.getMethods(strCap);
                                for (String strMeth : listCapabMeth) {
 
@@ -247,35 +159,18 @@ public class IoTCompiler {
                                }
                        }
                        // Add interface and methods information into map
-                       mapCapabMethods.put(strInt, setMethods);
+                       mapNewIntMethods.put(strInt, setMethods);
                }
+               // Map the map of interface-methods to the original interface
+               mapInt2NewInts.put(origInt, mapNewIntMethods);
        }
 
 
        /**
-        * generateJavaLocalInterface() writes the local interface to provide type-checking
-        * <p>
-        * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
-        * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
-        * The local interface has to be the input parameter for the stub and the stub 
-        * interface has to be the input parameter for the local class.
+        * HELPER: writeMethodJavaInterface() writes the method of the interface
         */
-       public void generateJavaLocalInterface(String _intface) throws IOException {
+       private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
 
-               // Create a new directory
-               createDirectory(dir);
-               // Open a new file to write into
-               String intface = _intface;
-               FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
-               pw = new PrintWriter(new BufferedWriter(fw));
-               // Pass in set of methods and get import classes
-               List<String> methods = intDecl.getMethods();
-               Set<String> importClasses = getImportClasses(methods);
-               printImportStatements(importClasses);
-               // Write interface header
-               println("");
-               println("public interface " + intface + " {");
-               // Write methods
                for (String method : methods) {
 
                        List<String> methParams = intDecl.getMethodParams(method);
@@ -285,7 +180,7 @@ public class IoTCompiler {
                        for (int i = 0; i < methParams.size(); i++) {
                                // Check for params with driver class types and exchange it 
                                //              with its remote interface
-                               String paramType = checkAndGetParamClass(methPrmTypes.get(i));
+                               String paramType = checkAndGetParamClass(methPrmTypes.get(i), false);
                                print(paramType + " " + methParams.get(i));
                                // Check if this is the last element (don't print a comma)
                                if (i != methParams.size() - 1) {
@@ -294,53 +189,241 @@ public class IoTCompiler {
                        }
                        println(");");
                }
-               println("}");
-               pw.close();
-               System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
        }
 
 
        /**
-        * generateCplusLocalInterface() writes the local interface to provide type-checking
+        * generateJavaLocalInterface() writes the local interface and provides type-checking.
         * <p>
         * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
         * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
         * The local interface has to be the input parameter for the stub and the stub 
         * interface has to be the input parameter for the local class.
         */
-       public void generateCplusLocalInterface(String _intface) throws IOException {
+       public void generateJavaLocalInterfaces() throws IOException {
 
                // Create a new directory
                createDirectory(dir);
-               // Open a new file to write into
-               String intface = _intface;
-               FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
-               pw = new PrintWriter(new BufferedWriter(fw));
-               // Write file headers
-               println("#include <iostream>");
-               // Pass in set of methods and get import classes
-               List<String> methods = intDecl.getMethods();
-               Set<String> includeClasses = getIncludeClasses(methods);
-               printIncludeStatements(includeClasses);
-               println("");
-               println("using namespace std;");
-               println("");
-               println("class " + intface);
-               println("{");
-               println("public:");
-               // Write methods
+               for (String intface : mapIntfacePTH.keySet()) {
+                       // Open a new file to write into
+                       FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
+                       pw = new PrintWriter(new BufferedWriter(fw));
+                       // Pass in set of methods and get import classes
+                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                       List<String> methods = intDecl.getMethods();
+                       Set<String> importClasses = getImportClasses(methods, intDecl);
+                       printImportStatements(importClasses);
+                       // Write interface header
+                       println("");
+                       println("public interface " + intface + " {");
+                       // Write methods
+                       writeMethodJavaInterface(methods, intDecl);
+                       println("}");
+                       pw.close();
+                       System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
+               }
+       }
+
+
+       /**
+        * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
+        */
+       public void generateJavaInterfaces() throws IOException {
+
+               // Create a new directory
+               String path = createDirectories(dir, subdir);
+               for (String intface : mapIntfacePTH.keySet()) {
+
+                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+
+                               // Open a new file to write into
+                               String newIntface = intMeth.getKey();
+                               FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
+                               pw = new PrintWriter(new BufferedWriter(fw));
+                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                               // Pass in set of methods and get import classes
+                               Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
+                               printImportStatements(importClasses);
+                               // Write interface header
+                               println("");
+                               println("public interface " + newIntface + " {");
+                               // Write methods
+                               writeMethodJavaInterface(intMeth.getValue(), intDecl);
+                               println("}");
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
+                       }
+               }
+       }
+
+
+       /**
+        * HELPER: writePropertiesJavaStub() writes the properties of the stub class
+        */
+       private void writePropertiesJavaStub(String intface) {
+
+               println("private IoTRMICall rmiCall;");
+               //println("private IoTRMIObject rmiObj;");
+               println("private String address;");
+               println("private int[] ports;\n");
+               // Get the object Id
+               Integer objId = mapIntfaceObjId.get(intface);
+               println("private final static int objectId = " + objId + ";");
+               mapIntfaceObjId.put(intface, objId++);
+               println("\n");
+       }
+
+
+       /**
+        * HELPER: writeConstructorJavaStub() writes the constructor of the stub class
+        */
+       private void writeConstructorJavaStub(String intface) {
+
+               println("public " + intface + "(int _port, String _address, int _rev, int[] _ports) throws Exception {");
+               println("address = _address;");
+               println("ports = _ports;");
+               println("rmiCall = new IoTRMICall(_port, _address, _rev);");
+               println("}\n");
+       }
+
+
+       /**
+        * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
+        */
+       private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
+                       List<String> methPrmTypes, String method) {
+
+               println("int methodId = " + intDecl.getMethodNumId(method) + ";");
+               String retType = intDecl.getMethodType(method);
+               println("Class<?> retType = " + getSimpleType(retType) + ".class;");
+               // Generate array of parameter types
+               print("Class<?>[] paramCls = new Class<?>[] { ");
+               for (int i = 0; i < methParams.size(); i++) {
+                       String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
+                       print(getSimpleType(paramType) + ".class");
+                       // Check if this is the last element (don't print a comma)
+                       if (i != methParams.size() - 1) {
+                               print(", ");
+                       }
+               }
+               println(" };");
+               // Generate array of parameter objects
+               print("Object[] paramObj = new Object[] { ");
+               for (int i = 0; i < methParams.size(); i++) {
+                       print(getSimpleIdentifier(methParams.get(i)));
+                       // Check if this is the last element (don't print a comma)
+                       if (i != methParams.size() - 1) {
+                               print(", ");
+                       }
+               }
+               println(" };");
+               // Check if this is "void"
+               if (retType.equals("void")) {
+                       println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
+               } else { // We do have a return value
+               // Check if the return value NONPRIMITIVES
+                       if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
+                               String[] retGenValType = getTypeOfGeneric(retType);
+                               println("Class<?> retGenValType = " + retGenValType[0] + ".class;");
+                               println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);");
+                               println("return (" + retType + ")retObj;");
+                       } else {
+                               println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
+                               println("return (" + retType + ")retObj;");
+                       }
+               }
+       }
+
+
+       /**
+        * HELPER: writeMethodJavaStub() writes the method of the stub class
+        */
+       private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl) {
+
                for (String method : methods) {
 
                        List<String> methParams = intDecl.getMethodParams(method);
                        List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
-                       print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
+                       print("public " + intDecl.getMethodType(method) + " " +
+                               intDecl.getMethodId(method) + "(");
+                       for (int i = 0; i < methParams.size(); i++) {
+
+                               print(methPrmTypes.get(i) + " " + methParams.get(i));
+                               // Check if this is the last element (don't print a comma)
+                               if (i != methParams.size() - 1) {
+                                       print(", ");
+                               }
+                       }
+                       println(") {");
+                       // Now, write the body of stub!
+                       writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method);
+                       println("}\n");
+               }
+       }
+
+
+       /**
+        * generateJavaStubClasses() generate stubs based on the methods list in Java
+        */
+       public void generateJavaStubClasses() throws IOException {
+
+               // Create a new directory
+               String path = createDirectories(dir, subdir);
+               for (String intface : mapIntfacePTH.keySet()) {
+
+                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+
+                               // Open a new file to write into
+                               String newIntface = intMeth.getKey();
+                               String newStubClass = newIntface + "_Stub";
+                               FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
+                               pw = new PrintWriter(new BufferedWriter(fw));
+                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                               // Pass in set of methods and get import classes
+                               Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
+                               List<String> stdImportClasses = getStandardJavaImportClasses();
+                               List<String> allImportClasses = getAllImportClasses(stdImportClasses, importClasses);
+                               printImportStatements(allImportClasses); println("");
+                               // Write interface header
+                               println("public class " + newStubClass + " implements " + newIntface + " {\n");
+                               // Write properties
+                               writePropertiesJavaStub(intface);
+                               // Write constructor
+                               writeConstructorJavaStub(newStubClass);
+                               // Write methods
+                               writeMethodJavaStub(intMeth.getValue(), intDecl);
+                               println("}");
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
+                       }
+               }
+       }
+
+
+       /**
+        * HELPER: writeMethodCplusInterface() writes the method of the interface
+        */
+       private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
+
+               for (String method : methods) {
+
+                       List<String> methParams = intDecl.getMethodParams(method);
+                       List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+                       print("virtual " + checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
                                intDecl.getMethodId(method) + "(");
                        for (int i = 0; i < methParams.size(); i++) {
                                // Check for params with driver class types and exchange it 
                                //              with its remote interface
-                               String paramType = checkAndGetParamClass(methPrmTypes.get(i));
+                               String paramType = checkAndGetParamClass(methPrmTypes.get(i), true);
                                paramType = checkAndGetCplusType(paramType);
-                               print(paramType + " " + methParams.get(i));
+                               // Check for arrays - translate into vector in C++
+                               String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
+                               print(paramComplete);
                                // Check if this is the last element (don't print a comma)
                                if (i != methParams.size() - 1) {
                                        print(", ");
@@ -348,52 +431,44 @@ public class IoTCompiler {
                        }
                        println(") = 0;");
                }
-               print("}");
-               println(";");
-               pw.close();
-               System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
        }
 
 
        /**
-        * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
+        * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
+        * <p>
+        * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
+        * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
+        * The local interface has to be the input parameter for the stub and the stub 
+        * interface has to be the input parameter for the local class.
         */
-       public void generateJavaInterfaces() throws IOException {
+       public void generateCplusLocalInterfaces() throws IOException {
 
                // Create a new directory
-               createDirectories(dir, subdir);
-               for (Map.Entry<String,Set<String>> intMeth : mapCapabMethods.entrySet()) {
-
+               createDirectory(dir);
+               for (String intface : mapIntfacePTH.keySet()) {
                        // Open a new file to write into
-                       String newIntface = intMeth.getKey();
-                       FileWriter fw = new FileWriter(dir + "/" + subdir + "/" + newIntface + ".java");
+                       FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
                        pw = new PrintWriter(new BufferedWriter(fw));
-                       // Pass in set of methods and get import classes
-                       Set<String> importClasses = getImportClasses(intMeth.getValue());
-                       printImportStatements(importClasses);
-                       // Write interface header
-                       println("");
-                       println("public interface " + newIntface + " {");
-                       List<String> meths = intDecl.getMethods();
+                       // Write file headers
+                       println("#ifndef _" + intface.toUpperCase() + "_HPP__");
+                       println("#define _" + intface.toUpperCase() + "_HPP__");
+                       println("#include <iostream>");
+                       // Pass in set of methods and get include classes
+                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                       List<String> methods = intDecl.getMethods();
+                       Set<String> includeClasses = getIncludeClasses(methods, intDecl);
+                       printIncludeStatements(includeClasses); println("");
+                       println("using namespace std;\n");
+                       println("class " + intface); println("{");
+                       println("public:");
                        // Write methods
-                       for (String method : intMeth.getValue()) {
-
-                               List<String> methParams = intDecl.getMethodParams(method);
-                               List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
-                               print("public " + intDecl.getMethodType(method) + " " +
-                                       intDecl.getMethodId(method) + "(");
-                               for (int i = 0; i < methParams.size(); i++) {
-                                       print(methPrmTypes.get(i) + " " + methParams.get(i));
-                                       // Check if this is the last element (don't print a comma)
-                                       if (i != methParams.size() - 1) {
-                                               print(", ");
-                                       }
-                               }
-                               println(");");
-                       }
-                       println("}");
+                       writeMethodCplusInterface(methods, intDecl);
+                       println("};");
+                       println("#endif");
                        pw.close();
-                       System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
+                       System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
                }
        }
 
@@ -406,155 +481,232 @@ public class IoTCompiler {
        public void generateCPlusInterfaces() throws IOException {
 
                // Create a new directory
-               createDirectories(dir, subdir);
-               for (Map.Entry<String,Set<String>> intMeth : mapCapabMethods.entrySet()) {
-
-                       // Open a new file to write into
-                       String newIntface = intMeth.getKey();
-                       FileWriter fw = new FileWriter(dir + "/" + subdir + "/" + newIntface + ".hpp");
-                       pw = new PrintWriter(new BufferedWriter(fw));
-                       // Write file headers
-                       println("#include <iostream>");
-                       // Pass in set of methods and get import classes
-                       Set<String> includeClasses = getIncludeClasses(intMeth.getValue());
-                       printIncludeStatements(includeClasses);
-                       println("");
-                       println("using namespace std;");
-                       println("");
-                       println("class " + newIntface);
-                       println("{");
-                       println("public:");
-                       // Write methods
-                       for (String method : intMeth.getValue()) {
-
-                               List<String> methParams = intDecl.getMethodParams(method);
-                               List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
-                               print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
-                                       intDecl.getMethodId(method) + "(");
-                               for (int i = 0; i < methParams.size(); i++) {
-
-                                       String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
-                                       print(methPrmType + " " + methParams.get(i));
-                                       // Check if this is the last element (don't print a comma)
-                                       if (i != methParams.size() - 1) {
-                                               print(", ");
-                                       }
-                               }
-                               println(") = 0;");
+               String path = createDirectories(dir, subdir);
+               for (String intface : mapIntfacePTH.keySet()) {
+
+                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+
+                               // Open a new file to write into
+                               String newIntface = intMeth.getKey();
+                               FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
+                               pw = new PrintWriter(new BufferedWriter(fw));
+                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                               // Write file headers
+                               println("#ifndef _" + newIntface.toUpperCase() + "_HPP__");
+                               println("#define _" + newIntface.toUpperCase() + "_HPP__");
+                               println("#include <iostream>");
+                               // Pass in set of methods and get import classes
+                               Set<String> includeClasses = getIncludeClasses(intMeth.getValue(), intDecl);
+                               List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
+                               List<String> allIncludeClasses = getAllImportClasses(stdIncludeClasses, includeClasses);
+                               printIncludeStatements(allIncludeClasses); println("");                 
+                               println("using namespace std;\n");
+                               println("class " + newIntface);
+                               println("{");
+                               println("public:");
+                               // Write methods
+                               writeMethodCplusInterface(intMeth.getValue(), intDecl);
+                               println("};");
+                               println("#endif");
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
                        }
-                       print("}");
-                       println(";");
-                       pw.close();
-                       System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
                }
        }
 
 
        /**
-        * generateJavaStubClasses() generate stubs based on the methods list in Java
+        * HELPER: writeMethodCplusStub() writes the method of the stub
         */
-       public void generateJavaStubClasses() throws IOException {
+       private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
 
-               // Create a new directory
-               createDirectories(dir, subdir);
-               for (Map.Entry<String,Set<String>> intMeth : mapCapabMethods.entrySet()) {
+               for (String method : methods) {
 
-                       // Open a new file to write into
-                       String newIntface = intMeth.getKey();
-                       String newStubClass = newIntface + "_Stub";
-                       FileWriter fw = new FileWriter(dir + "/" + subdir + "/" + newStubClass + ".java");
-                       pw = new PrintWriter(new BufferedWriter(fw));
-                       // Pass in set of methods and get import classes
-                       Set<String> importClasses = getImportClasses(intMeth.getValue());
-                       printImportStatements(importClasses);
-                       // Write interface header
-                       println("");
-                       println("public class " + newStubClass + " implements " + newIntface + " {");
-                       println("");
-                       // Write methods
-                       for (String method : intMeth.getValue()) {
-
-                               List<String> methParams = intDecl.getMethodParams(method);
-                               List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
-                               print("public " + intDecl.getMethodType(method) + " " +
-                                       intDecl.getMethodId(method) + "(");
-                               for (int i = 0; i < methParams.size(); i++) {
-
-                                       print(methPrmTypes.get(i) + " " + methParams.get(i));
-                                       // Check if this is the last element (don't print a comma)
-                                       if (i != methParams.size() - 1) {
-                                               print(", ");
-                                       }
-                               }
-                               println(") {");
-                               // Check if this is not "void"
-                               if (!intDecl.getMethodType(method).equals("void")) {
-                                       String retStmt = generateReturnStmt(intDecl.getMethodType(method));
-                                       println("return " + retStmt + ";");
+                       List<String> methParams = intDecl.getMethodParams(method);
+                       List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+                       print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
+                               intDecl.getMethodId(method) + "(");
+                       for (int i = 0; i < methParams.size(); i++) {
+                               String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
+                               String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
+                               print(methParamComplete);
+                               // Check if this is the last element (don't print a comma)
+                               if (i != methParams.size() - 1) {
+                                       print(", ");
                                }
-                               println("}"); println("");
                        }
-                       println("}");
-                       pw.close();
-                       System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
+                       println(") { ");
+                       writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method);
+                       println("}\n");
+               }
+       }
+
+
+       /**
+        * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
+        */
+       private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
+                       List<String> methPrmTypes, String method) {
+
+               println("int numParam = " + methParams.size() + ";");
+               println("int methodId = " + intDecl.getMethodNumId(method) + ";");
+               String retType = intDecl.getMethodType(method);
+               println("string retType = \"" + checkAndGetCplusType(retType) + "\";");
+               // Generate array of parameter types
+               print("string paramCls[] = { ");
+               for (int i = 0; i < methParams.size(); i++) {
+                       String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
+                       print("\"" + getSimpleType(paramType) + "\"");
+                       // Check if this is the last element (don't print a comma)
+                       if (i != methParams.size() - 1) {
+                               print(", ");
+                       }
+               }
+               println(" };");
+               // Generate array of parameter objects
+               print("void* paramObj[] = { ");
+               for (int i = 0; i < methParams.size(); i++) {
+                       print("&" + checkAndGetCplusType(getSimpleIdentifier(methParams.get(i))));
+                       // Check if this is the last element (don't print a comma)
+                       if (i != methParams.size() - 1) {
+                               print(", ");
+                       }
+               }
+               println(" };");
+               // Check if this is "void"
+               if (retType.equals("void")) {
+                       println("void* retObj = NULL;");
+                       println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
+               } else { // We do have a return value
+                       if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
+                               println(checkAndGetCplusType(retType) + " retVal;");
+                       else
+                               println(checkAndGetCplusType(retType) + " retVal = " + generateCplusInitializer(retType) + ";");
+                       println("void* retObj = &retVal;");
+                       println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
+                       println("return retVal;");
                }
        }
 
 
+       /**
+        * HELPER: writePropertiesCplusStub() writes the properties of the stub class
+        */
+       private void writePropertiesCplusStub(String intface) {
+
+               println("IoTRMICall\t\t\t*rmiCall;");
+               //println("IoTRMIObject\t\t\t*rmiObj;");
+               println("string\t\t\t\taddress;");
+               println("vector<int>\t\t\tports;\n");
+               // Get the object Id
+               Integer objId = mapIntfaceObjId.get(intface);
+               println("const static int\tobjectId = " + objId + ";");
+               mapIntfaceObjId.put(intface, objId++);
+               println("\n");
+       }
+
+
+       /**
+        * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
+        */
+       private void writeConstructorCplusStub(String newStubClass) {
+
+               println(newStubClass + 
+                       "(int _port, const char* _address, int _rev, bool* _bResult, vector<int> _ports) {");
+               println("address = _address;");
+               println("ports = _ports;");
+               println("rmiCall = new IoTRMICall(_port, _address, _rev, _bResult);");
+               println("}\n");
+       }
+
+
+       /**
+        * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
+        */
+       private void writeDeconstructorCplusStub(String newStubClass) {
+
+               println("~" + newStubClass + "() {");
+               println("if (rmiCall != NULL) {");
+               println("delete rmiCall;");
+               println("rmiCall = NULL;");
+               println("}");
+               println("}");
+               println("");
+               // Check if this is callback!!! and print "delete rmiObj and vecCBObj"
+       }
+
+
        /**
         * generateCPlusStubClasses() generate stubs based on the methods list in C++
         */
        public void generateCPlusStubClasses() throws IOException {
 
                // Create a new directory
-               createDirectories(dir, subdir);
-               for (Map.Entry<String,Set<String>> intMeth : mapCapabMethods.entrySet()) {
-
-                       // Open a new file to write into
-                       String newIntface = intMeth.getKey();
-                       String newStubClass = newIntface + "_Stub";
-                       FileWriter fw = new FileWriter(dir + "/" + subdir + "/" + newStubClass + ".hpp");
-                       pw = new PrintWriter(new BufferedWriter(fw));
-                       // Write file headers
-                       println("#include <iostream>");
-                       println("#include \"" + newIntface + ".hpp\""); println("");            
-                       println("using namespace std;"); println("");
-                       println("class " + newStubClass + " : public " + newIntface);
-                       println("{");
-                       println("public:"); println("");
-                       // Add default constructor and destructor
-                       println(newStubClass + "() { }"); println("");
-                       println("~" + newStubClass + "() { }"); println("");            
-                       // Write methods
-                       for (String method : intMeth.getValue()) {
-
-                               List<String> methParams = intDecl.getMethodParams(method);
-                               List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
-                               print(convertType(intDecl.getMethodType(method)) + " " +
-                                       intDecl.getMethodId(method) + "(");
-                               for (int i = 0; i < methParams.size(); i++) {
-
-                                       String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
-                                       print(methPrmType + " " + methParams.get(i));
-                                       // Check if this is the last element (don't print a comma)
-                                       if (i != methParams.size() - 1) {
-                                               print(", ");
-                                       }
-                               }
-                               println(") { ");
-                               // Check if this is not "void"
-                               if (!intDecl.getMethodType(method).equals("void")) {
-                                       String retStmt = generateReturnStmt(intDecl.getMethodType(method));
-                                       if (retStmt.equals("null")) { // null = NULL in C++
-                                               retStmt = "NULL";
-                                       }
-                                       println("return " + retStmt + ";");
-                               }
-                               println("}"); println("");
+               String path = createDirectories(dir, subdir);
+               for (String intface : mapIntfacePTH.keySet()) {
+
+                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+                               // Open a new file to write into
+                               String newIntface = intMeth.getKey();
+                               String newStubClass = newIntface + "_Stub";
+                               FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
+                               pw = new PrintWriter(new BufferedWriter(fw));
+                               // Write file headers
+                               println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
+                               println("#define _" + newStubClass.toUpperCase() + "_HPP__");
+                               println("#include <iostream>");
+                               println("#include \"" + newIntface + ".hpp\""); println("");            
+                               println("using namespace std;"); println("");
+                               println("class " + newStubClass + " : public " + newIntface); println("{");
+                               println("private:\n");
+                               writePropertiesCplusStub(intface);
+                               println("public:\n");
+                               // Add default constructor and destructor
+                               println(newStubClass + "() { }"); println("");
+                               writeConstructorCplusStub(newStubClass);
+                               writeDeconstructorCplusStub(newStubClass);
+                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                               // Write methods
+                               writeMethodCplusStub(intMeth.getValue(), intDecl);
+                               print("}"); println(";");
+                               println("#endif");
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated stub class " + newIntface + ".hpp...");
                        }
-                       print("}"); println(";");
-                       pw.close();
-                       System.out.println("IoTCompiler: Generated stub class " + newIntface + ".hpp...");
+               }
+       }
+
+
+       /**
+        * generateInitializer() generate initializer based on type
+        */
+       public String generateCplusInitializer(String type) {
+
+               // Generate dummy returns for now
+               if (type.equals("short")||
+                       type.equals("int")      ||
+                       type.equals("long") ||
+                       type.equals("float")||
+                       type.equals("double")) {
+
+                       return "0";
+               } else if ( type.equals("String") ||
+                                       type.equals("string")) {
+  
+                       return "\"\"";
+               } else if ( type.equals("char") ||
+                                       type.equals("byte")) {
+
+                       return "\' \'";
+               } else if ( type.equals("boolean")) {
+
+                       return "false";
+               } else {
+                       return "NULL";
                }
        }
 
@@ -572,11 +724,11 @@ public class IoTCompiler {
                        methType.equals("double")) {
 
                        return "1";
-               } else if ( methType.equals("String") ||
-                                       methType.equals("byte")) {
+               } else if ( methType.equals("String")) {
   
                        return "\"a\"";
-               } else if ( methType.equals("char")) {
+               } else if ( methType.equals("char") ||
+                                       methType.equals("byte")) {
 
                        return "\'a\'";
                } else if ( methType.equals("boolean")) {
@@ -589,7 +741,7 @@ public class IoTCompiler {
 
 
        /**
-        * setDirectory() set a new directory for stub files
+        * setDirectory() sets a new directory for stub files
         */
        public void setDirectory(String _subdir) {
 
@@ -607,9 +759,11 @@ public class IoTCompiler {
                System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
                System.out.println("All rights reserved.");
                System.out.println("Usage:");
-               System.out.println("\tjava IoTCompiler --help / -h\t\t\t\t\tDisplay this help texts");
-               System.out.println("\tjava IoTCompiler <main-policy-file> <req-policy-file>\t\tGenerate both Java and C++ stub files");
-               System.out.println("\tjava IoTCompiler <main-policy-file> <req-policy-file> [options]");
+               System.out.println("\tjava IoTCompiler -help / --help / -h\n");
+               System.out.println("\t\tDisplay this help texts\n\n");
+               System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
+               System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
+               System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
                System.out.println("Options:");
                System.out.println("\t-java\t<directory>\tGenerate Java stub files");
                System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
@@ -630,17 +784,17 @@ public class IoTCompiler {
                        Parser parse = new Parser(lexer,csf);
                        pn = (ParseNode) parse.parse().value;
                } catch (Exception e) {
-                       System.out.println("IoTCompiler: ERROR parsing policy file!");
                        e.printStackTrace();
+                       throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file);
                }
 
                return pn;
        }
 
 
-       /**================================================
-        * Helper functions to write stub codes into files
-        **================================================
+       /**================
+        * Helper functions
+        **================
         */
        boolean newline=true;
        int tablevel=0;
@@ -658,6 +812,7 @@ public class IoTCompiler {
                newline=false;
        }
 
+
        /**
         * This function converts Java to C++ type for compilation
         */
@@ -713,12 +868,15 @@ public class IoTCompiler {
 
 
        // Create a directory and possibly a sub directory
-       private void createDirectories(String dir, String subdir) {
+       private String createDirectories(String dir, String subdir) {
 
-               createDirectory(dir);
+               String path = dir;
+               createDirectory(path);
                if (subdir != null) {
-                       createDirectory(dir + "/" + subdir);
+                       path = path + "/" + subdir;
+                       createDirectory(path);
                }
+               return path;
        }
 
 
@@ -775,8 +933,52 @@ public class IoTCompiler {
        }
 
 
+       // Generate a set of standard classes for import statements
+       private List<String> getStandardJavaImportClasses() {
+
+               List<String> importClasses = new ArrayList<String>();
+               // Add the standard list first
+               importClasses.add("java.io.IOException");
+               importClasses.add("java.util.List");
+               importClasses.add("java.util.ArrayList");
+               importClasses.add("iotrmi.Java.IoTRMICall");
+               importClasses.add("iotrmi.Java.IoTRMIObject");
+
+               return importClasses;
+       }
+
+
+       // Generate a set of standard classes for import statements
+       private List<String> getStandardCplusIncludeClasses() {
+
+               List<String> importClasses = new ArrayList<String>();
+               // Add the standard list first
+               importClasses.add("<vector>");
+               importClasses.add("\"IoTRMICall.hpp\"");
+               importClasses.add("\"IoTRMIObject.hpp\"");
+
+               return importClasses;
+       }
+
+
+       // Generate a set of standard classes for import statements
+       private List<String> getAllImportClasses(Collection<String> stdImportClasses, Collection<String> importClasses) {
+
+               List<String> allImportClasses = new ArrayList<String>(stdImportClasses);
+               // Iterate over the list of import classes
+               for (String str : importClasses) {
+                       if (!stdImportClasses.contains(str)) {
+                               stdImportClasses.add(str);
+                       }
+               }
+
+               return allImportClasses;
+       }
+
+
+
        // Generate a set of classes for import statements
-       private Set<String> getImportClasses(Collection<String> methods) {
+       private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
 
                Set<String> importClasses = new HashSet<String>();
                for (String method : methods) {
@@ -794,17 +996,24 @@ public class IoTCompiler {
 
 
        // Generate a set of classes for include statements
-       private Set<String> getIncludeClasses(Collection<String> methods) {
+       private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl) {
 
                Set<String> includeClasses = new HashSet<String>();
                for (String method : methods) {
 
                        List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
-                       for (String paramType : methPrmTypes) {
+                       List<String> methParams = intDecl.getMethodParams(method);
+                       for (int i = 0; i < methPrmTypes.size(); i++) {
 
-                               String simpleType = getSimpleType(paramType);
+                               String simpleType = getSimpleType(methPrmTypes.get(i));
+                               String param = methParams.get(i);
                                if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
-                                       includeClasses.add(getNonPrimitiveCplusClass(simpleType));
+                                       includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
+                               } else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
+                                       includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
+                               } else if (param.contains("[]")) {
+                               // Check if this is array for C++; translate into vector
+                                       includeClasses.add("<vector>");
                                }
                        }
                }
@@ -812,7 +1021,7 @@ public class IoTCompiler {
        }
 
 
-       private void printImportStatements(Set<String> importClasses) {
+       private void printImportStatements(Collection<String> importClasses) {
 
                for(String cls : importClasses) {
                        println("import " + cls + ";");
@@ -820,10 +1029,10 @@ public class IoTCompiler {
        }
 
 
-       private void printIncludeStatements(Set<String> includeClasses) {
+       private void printIncludeStatements(Collection<String> includeClasses) {
 
                for(String cls : includeClasses) {
-                       println("#include <" + cls + ">");
+                       println("#include " + cls);
                }
        }
 
@@ -839,6 +1048,18 @@ public class IoTCompiler {
        }
 
 
+       // This helper function strips off array declaration, e.g. D[] becomes D
+       private String getSimpleIdentifier(String ident) {
+
+               // Handle [ for array declaration
+               String substr = ident;
+               if (ident.contains("[]")) {
+                       substr = ident.split("\\[\\]")[0];
+               }
+               return substr;
+       }
+
+
        private String checkAndGetCplusType(String paramType) {
 
                if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
@@ -866,71 +1087,152 @@ public class IoTCompiler {
        }
 
 
+       // Detect array declaration, e.g. int A[],
+       //              then generate "int A[]" in C++ as "vector<int> A"
+       private String checkAndGetCplusArray(String paramType, String param) {
+
+               String paramComplete = null;
+               // Check for array declaration
+               if (param.contains("[]")) {
+                       paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
+               } else
+                       // Just return it as is if it's not an array
+                       paramComplete = paramType + " " + param;
+
+               return paramComplete;
+       }
+
+
+       // Detect array declaration, e.g. int A[],
+       //              then generate type "int[]"
+       private String checkAndGetArray(String paramType, String param) {
+
+               String paramTypeRet = null;
+               // Check for array declaration
+               if (param.contains("[]")) {
+                       paramTypeRet = paramType + "[]";
+               } else
+                       // Just return it as is if it's not an array
+                       paramTypeRet = paramType;
+
+               return paramTypeRet;
+       }
+
+
        // Get simple types, e.g. HashSet for HashSet<...>
        // Basically strip off the "<...>"
-       private String checkAndGetParamClass(String paramType) {
+       private String checkAndGetParamClass(String paramType, boolean needPtr) {
 
                // Check if this is generics
                if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
-                       // TODO: replace this with the proper stub interface name
-                       return paramType + "Remote";
+                       // If true then return with pointer (C++)
+                       if (needPtr)
+                               return exchangeParamType(paramType) + "*";
+                       else    // Java, so no pointer needed
+                               return exchangeParamType(paramType);
                } else
                        return paramType;
        }
 
 
+       // Returns the other interface for type-checking purposes for USERDEFINED
+       //              classes based on the information provided in multiple policy files
+       // e.g. return CameraWithXXX instead of Camera
+       private String exchangeParamType(String intface) {
+
+               // Param type that's passed is the interface name we need to look for
+               //              in the map of interfaces, based on available policy files.
+               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+               if (decHandler != null) {
+               // We've found the required interface policy files
+                       RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
+                       Set<String> setExchInt = reqDecl.getInterfaces();
+                       if (setExchInt.size() == 1) {
+                               Iterator iter = setExchInt.iterator();
+                               return (String) iter.next();
+                       } else {
+                               throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() + 
+                                       ". Only one new interface can be declared if the object " + intface +
+                                       " needs to be passed in as an input parameter!");
+                       }
+               } else {
+               // NULL value - this means policy files missing
+                       throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
+                               "... Please provide the necessary policy files for user-defined types." +
+                               " If this is an array please type the brackets after the variable name," +
+                               " e.g. \"String str[]\", not \"String[] str\"." +
+                               " If this is a Collections (Java) / STL (C++) type, this compiler only" +
+                               " supports List/ArrayList (Java) or list (C++).");
+               }
+       }
+
+
        public static void main(String[] args) throws Exception {
 
-               // Runtime options
-               if (args.length > 1) {
-                       // Display help
-                       if ((args[0].equals("--help") ||
-                               (args[0].equals("-h")))) {
-                               IoTCompiler.printUsage();
-                       } else {
+               // If there is no argument or just "--help" or "-h", then invoke printUsage()
+               if ((args[0].equals("-help") ||
+                        args[0].equals("--help")||
+                        args[0].equals("-h"))   ||
+                       (args.length == 0)) {
+
+                       IoTCompiler.printUsage();
+
+               } else if (args.length > 1) {
+
+                       IoTCompiler comp = new IoTCompiler();
+                       int i = 0;                              
+                       do {
                                // Parse main policy file
-                               ParseNode pnPol = IoTCompiler.parseFile(args[0]);
+                               ParseNode pnPol = IoTCompiler.parseFile(args[i]);
                                // Parse "requires" policy file
-                               ParseNode pnReq = IoTCompiler.parseFile(args[1]);
+                               ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
                                // Get interface name
                                String intface = ParseTreeHandler.getOrigIntface(pnPol);
-                               IoTCompiler comp = new IoTCompiler(intface, pnPol, pnReq);
-                               // Generate all policy files if just policy file is provided
-                               comp.parsePolicyFile();
-                               comp.getMethodsForIntface();
-                               if (args.length == 2) {
-                                       comp.generateJavaLocalInterface(intface);
-                                       comp.generateJavaInterfaces();
-                                       comp.generateJavaStubClasses();
-                                       comp.generateCplusLocalInterface(intface);
-                                       comp.generateCPlusInterfaces();
-                                       comp.generateCPlusStubClasses();
-                               } else {
-                               // Check other options
-                                       int i = 2;
-                                       while(i < args.length) {
-                                               // Check whether <directory> is provided
-                                               if ((i + 1) < args.length) {
+                               comp.setDataStructures(intface, pnPol, pnReq);
+                               comp.getMethodsForIntface(intface);
+                               i = i + 2;
+                       // 1) Check if this is the last option before "-java" or "-cplus"
+                       // 2) Check if this is really the last option (no "-java" or "-cplus")
+                       } while(!args[i].equals("-java") &&
+                                       !args[i].equals("-cplus") &&
+                                       (i < args.length));
+
+                       // Generate everything if we don't see "-java" or "-cplus"
+                       if (i == args.length) {
+                               comp.generateJavaLocalInterfaces();
+                               comp.generateJavaInterfaces();
+                               comp.generateJavaStubClasses();
+                               comp.generateCplusLocalInterfaces();
+                               comp.generateCPlusInterfaces();
+                               comp.generateCPlusStubClasses();
+                       } else {
+                       // Check other options
+                               while(i < args.length) {
+                                       // Error checking
+                                       if (!args[i].equals("-java") &&
+                                               !args[i].equals("-cplus")) {
+                                               throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]);
+                                       } else {
+                                               if (i + 1 < args.length) {
                                                        comp.setDirectory(args[i+1]);
                                                } else
                                                        throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i]);
+
                                                if (args[i].equals("-java")) {
-                                                       comp.generateJavaLocalInterface(intface);
+                                                       comp.generateJavaLocalInterfaces();
                                                        comp.generateJavaInterfaces();
                                                        comp.generateJavaStubClasses();
-                                               } else if (args[i].equals("-cplus")) {
-                                                       comp.generateCplusLocalInterface(intface);
+                                               } else {
+                                                       comp.generateCplusLocalInterfaces();
                                                        comp.generateCPlusInterfaces();
                                                        comp.generateCPlusStubClasses();
-                                               } else
-                                                       throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]);
-                                               i = i + 2;
+                                               }
                                        }
+                                       i = i + 2;
                                }
                        }
-
                } else {
-               // Need at least the policy file name
+               // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
                        IoTCompiler.printUsage();
                        throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!");
                }