Adding config file for sharing.
[iot2.git] / iotjava / iotpolicy / IoTCompiler.java
index 58538c9c00d4455840045e03ac306452c36c4795..027ea07670c77433c6e030ff6f984f26893de84c 100644 (file)
@@ -49,6 +49,7 @@ public class IoTCompiler {
        private Map<String,DeclarationHandler> mapIntDeclHand;
        private Map<String,Map<String,Set<String>>> mapInt2NewInts;
        private Map<String,String> mapInt2NewIntName;
+       private Map<String,List<String>> mapInt2Drv;
        // Data structure to store our types (primitives and non-primitives) for compilation
        private Map<String,String> mapPrimitives;
        private Map<String,String> mapNonPrimitivesJava;
@@ -63,12 +64,20 @@ public class IoTCompiler {
        private static int portCount = 0;
        private static int countObjId = 1;                      // Always increment object Id for a new stub/skeleton
        private String mainClass;
+       private String controllerClass;
 
 
        /**
         * Class constants
         */
        private final static String OUTPUT_DIRECTORY = "output_files";
+       private final static String INTERFACES_DIRECTORY = "interfaces";
+       private final static String VIRTUALS_DIRECTORY = "virtuals";
+       private final static String DRIVERS_DIRECTORY = "drivers";
+       private final static String CONTROLLER_DIRECTORY = "controller";
+       private final static String CODE_PREFIX = "iotcode";
+       private final static String INTERFACE_PACKAGE = "iotcode.interfaces";
+
 
        private enum ParamCategory {
 
@@ -89,6 +98,7 @@ public class IoTCompiler {
                mapIntDeclHand = new HashMap<String,DeclarationHandler>();
                mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
                mapInt2NewIntName = new HashMap<String,String>();
+               mapInt2Drv = new HashMap<String,List<String>>();
                mapIntfaceObjId = new HashMap<String,Integer>();
                mapNewIntfaceObjId = new HashMap<String,Integer>();
                mapPrimitives = new HashMap<String,String>();
@@ -102,6 +112,29 @@ public class IoTCompiler {
                dir = OUTPUT_DIRECTORY;
                subdir = null;
                mainClass = null;
+               controllerClass = null;
+       }
+
+
+       /**
+        * setDriverClass() sets the name of the driver class.
+        */
+       public void setDriverClass(String intface, String driverClass) {
+               
+               List<String> drvList = mapInt2Drv.get(intface);
+               if(drvList == null)
+                       drvList = new ArrayList<String>();
+               drvList.add(driverClass);
+               mapInt2Drv.put(intface, drvList);
+       }
+       
+       
+       /**
+        * setControllerClass() sets the name of the controller class.
+        */
+       public void setControllerClass(String _controllerClass) {
+               
+               controllerClass = _controllerClass;
        }
 
 
@@ -146,6 +179,17 @@ public class IoTCompiler {
                // Set object Id counter to 0 for each interface
                mapIntfaceObjId.put(origInt, countObjId++);
        }
+       
+       
+       /**
+        * setObjectId() updates the object Id. This option is useful
+        * when the stub/skeleton are also used in other apps, so that
+        * we can set a single object Id for the stub/skeleton.
+        */
+       private void setObjectId(String intface, String objectId) {
+
+               mapIntfaceObjId.put(intface, Integer.parseInt(objectId));
+       }
 
 
        /**
@@ -259,6 +303,7 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, INTERFACES_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Get the right EnumDecl
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -267,8 +312,9 @@ public class IoTCompiler {
                        // Iterate over enum declarations
                        for (String enType : enumTypes) {
                                // Open a new file to write into
-                               FileWriter fw = new FileWriter(dir + "/" + enType + ".java");
+                               FileWriter fw = new FileWriter(path + "/" + enType + ".java");
                                pw = new PrintWriter(new BufferedWriter(fw));
+                               println("package " + INTERFACE_PACKAGE + ";\n");
                                println("public enum " + enType + " {");
                                List<String> enumMembers = enumDecl.getMembers(enType);
                                for (int i = 0; i < enumMembers.size(); i++) {
@@ -296,6 +342,7 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, INTERFACES_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Get the right StructDecl
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -304,8 +351,9 @@ public class IoTCompiler {
                        // Iterate over enum declarations
                        for (String stType : structTypes) {
                                // Open a new file to write into
-                               FileWriter fw = new FileWriter(dir + "/" + stType + ".java");
+                               FileWriter fw = new FileWriter(path + "/" + stType + ".java");
                                pw = new PrintWriter(new BufferedWriter(fw));
+                               println("package " + INTERFACE_PACKAGE + ";\n");
                                println("public class " + stType + " {");
                                List<String> structMemberTypes = structDecl.getMemberTypes(stType);
                                List<String> structMembers = structDecl.getMembers(stType);
@@ -335,9 +383,10 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, INTERFACES_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Open a new file to write into
-                       FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
+                       FileWriter fw = new FileWriter(path + "/" + intface + ".java");
                        pw = new PrintWriter(new BufferedWriter(fw));
                        // Pass in set of methods and get import classes
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -346,6 +395,7 @@ public class IoTCompiler {
                        Set<String> importClasses = getImportClasses(methods, intDecl);
                        List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
                        List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
+                       println("package " + INTERFACE_PACKAGE + ";\n");
                        printImportStatements(allImportClasses);
                        // Write interface header
                        println("");
@@ -377,6 +427,7 @@ public class IoTCompiler {
 
                // Create a new directory
                String path = createDirectories(dir, subdir);
+               path = createDirectories(dir + "/" + subdir, INTERFACES_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
 
                        Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
@@ -393,6 +444,7 @@ public class IoTCompiler {
                                Set<String> importClasses = getImportClasses(methods, intDecl);
                                List<String> stdImportClasses = getStandardJavaIntfaceImportClasses();
                                List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
+                       println("package " + INTERFACE_PACKAGE + ";\n");
                                printImportStatements(allImportClasses);
                                // Write interface header
                                println("");
@@ -1109,38 +1161,55 @@ public class IoTCompiler {
                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> methods = intMeth.getValue();
-                               Set<String> importClasses = getImportClasses(methods, intDecl);
-                               List<String> stdImportClasses = getStandardJavaImportClasses();
-                               List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
-                               printImportStatements(allImportClasses); println("");
-                               // Find out if there are callback objects
-                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                               boolean callbackExist = !callbackClasses.isEmpty();
-                               // Write class header
-                               println("public class " + newStubClass + " implements " + newIntface + " {\n");
-                               // Write properties
-                               writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
-                               // Write constructor
-                               writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
-                               // Write callback constructor (used if this stub is treated as a callback stub)
-                               writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
-                               // Write methods
-                               writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
-                               println("}");
-                               pw.close();
-                               System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               String driverClass = drvList.get(i);
+                               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";
+                                       String packageClass = null;
+                                       // Check if this interface is a callback class
+                                       if(isCallbackClass(intface)) {
+                                               packageClass = CODE_PREFIX + "." + driverClass;
+                                               path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                                       } else {
+                                               packageClass = controllerClass;
+                                               path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                                       }
+                                       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> methods = intMeth.getValue();
+                                       Set<String> importClasses = getImportClasses(methods, intDecl);
+                                       List<String> stdImportClasses = getStandardJavaImportClasses();
+                                       List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
+                                       // Find out if there are callback objects
+                                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);                     
+                                       boolean callbackExist = !callbackClasses.isEmpty();
+                                       println("package " + packageClass + ";\n");
+                                       printImportStatements(allImportClasses); 
+                                       println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
+                                       // Write class header
+                                       println("public class " + newStubClass + " implements " + newIntface + " {\n");
+                                       // Write properties
+                                       writePropertiesJavaStub(intface, intMeth.getValue(), intDecl);
+                                       // Write constructor
+                                       writeConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
+                                       // Write callback constructor (used if this stub is treated as a callback stub)
+                                       writeCallbackConstructorJavaStub(intface, newStubClass, intMeth.getValue(), intDecl);
+                                       // Write methods
+                                       writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses, newStubClass);
+                                       println("}");
+                                       pw.close();
+                                       System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
+                               }
                        }
                }
        }
@@ -2224,41 +2293,59 @@ public class IoTCompiler {
                // Create a new directory
                String path = createDirectories(dir, subdir);
                for (String intface : mapIntfacePTH.keySet()) {
-                       // Open a new file to write into
-                       String newSkelClass = intface + "_Skeleton";
-                       FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".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);
-                       List<String> stdImportClasses = getStandardJavaImportClasses();
-                       List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
-                       printImportStatements(allImportClasses);
-                       // Find out if there are callback objects
-                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                       boolean callbackExist = !callbackClasses.isEmpty();
-                       // Write class header
-                       println("");
-                       println("public class " + newSkelClass  + " implements " + intface + " {\n");
-                       // Write properties
-                       writePropertiesJavaSkeleton(intface, intDecl);
-                       // Write constructor
-                       writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
-                       // Write constructor that is called when this object is a callback object
-                       writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
-                       // Write function to return didAlreadyInitWaitInvoke
-                       writeReturnDidAlreadyInitWaitInvoke();
-                       // Write methods
-                       writeMethodJavaSkeleton(methods, intDecl);
-                       // Write method helper
-                       writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
-                       // Write waitRequestInvokeMethod() - main loop
-                       writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
-                       println("}");
-                       pw.close();
-                       System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
+               
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               // Get driver class
+                               String driverClass = drvList.get(i);
+                               // Open a new file to write into
+                               String newSkelClass = intface + "_Skeleton";
+                               String packageClass = null;
+                               // Check if this interface is a callback class
+                               if(isCallbackClass(intface)) {
+                                       packageClass = controllerClass;
+                                       path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                               } else {
+                                       packageClass = CODE_PREFIX + "." + driverClass;
+                                       path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                               }
+                               FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".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);
+                               List<String> stdImportClasses = getStandardJavaImportClasses();
+                               List<String> allImportClasses = getAllLibClasses(stdImportClasses, importClasses);
+                               // Find out if there are callback objects
+                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                               boolean callbackExist = !callbackClasses.isEmpty();
+                               println("package " + packageClass + ";\n");
+                               printImportStatements(allImportClasses);
+                               println("\nimport " + INTERFACE_PACKAGE + ".*;\n");
+                               // Write class header
+                               println("public class " + newSkelClass  + " implements " + intface + " {\n");
+                               // Write properties
+                               writePropertiesJavaSkeleton(intface, intDecl);
+                               // Write constructor
+                               writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
+                               // Write constructor that is called when this object is a callback object
+                               writeCallbackConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
+                               // Write function to return didAlreadyInitWaitInvoke
+                               writeReturnDidAlreadyInitWaitInvoke();
+                               // Write methods
+                               writeMethodJavaSkeleton(methods, intDecl);
+                               // Write method helper
+                               writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
+                               // Write waitRequestInvokeMethod() - main loop
+                               writeJavaWaitRequestInvokeMethod(methods, intDecl, intface);
+                               println("}");
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
+                       }
                }
        }
 
@@ -2334,6 +2421,7 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, VIRTUALS_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Get the right StructDecl
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -2342,7 +2430,7 @@ public class IoTCompiler {
                        // Iterate over enum declarations
                        for (String enType : enumTypes) {
                                // Open a new file to write into
-                               FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp");
+                               FileWriter fw = new FileWriter(path + "/" + enType + ".hpp");
                                pw = new PrintWriter(new BufferedWriter(fw));
                                // Write file headers
                                println("#ifndef _" + enType.toUpperCase() + "_HPP__");
@@ -2375,6 +2463,7 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, VIRTUALS_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Get the right StructDecl
                        DeclarationHandler decHandler = mapIntDeclHand.get(intface);
@@ -2383,7 +2472,7 @@ public class IoTCompiler {
                        // Iterate over enum declarations
                        for (String stType : structTypes) {
                                // Open a new file to write into
-                               FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp");
+                               FileWriter fw = new FileWriter(path + "/" + stType + ".hpp");
                                pw = new PrintWriter(new BufferedWriter(fw));
                                // Write file headers
                                println("#ifndef _" + stType.toUpperCase() + "_HPP__");
@@ -2421,9 +2510,10 @@ public class IoTCompiler {
 
                // Create a new directory
                createDirectory(dir);
+               String path = createDirectories(dir, VIRTUALS_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
                        // Open a new file to write into
-                       FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
+                       FileWriter fw = new FileWriter(path + "/" + intface + ".hpp");
                        pw = new PrintWriter(new BufferedWriter(fw));
                        // Write file headers
                        println("#ifndef _" + intface.toUpperCase() + "_HPP__");
@@ -2487,6 +2577,7 @@ public class IoTCompiler {
 
                // Create a new directory
                String path = createDirectories(dir, subdir);
+               path = createDirectories(dir + "/" + subdir, VIRTUALS_DIRECTORY);
                for (String intface : mapIntfacePTH.keySet()) {
 
                        Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
@@ -2610,8 +2701,8 @@ public class IoTCompiler {
                println(callbackType + "_Skeleton* skel" + counter + " = new " + callbackType + "_Skeleton(" + paramIdent + ", rmiComm, newObjIdSent);");
                println("IoTRMIUtil::mapSkel->insert(make_pair(" + paramIdent + ", skel" + counter + "));");
                println("IoTRMIUtil::mapSkelId->insert(make_pair(" + paramIdent + ", newObjIdSent));");
-               println("thread th" + counter + " (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, std::ref(skel" + counter + 
-                       "), std::ref(skel" + counter +"));");
+               println("thread th" + counter + " (&" + callbackType + "_Skeleton::___waitRequestInvokeMethod, skel" + counter + 
+                       ", skel" + counter +");");
                println("th" + counter + ".detach();");
                println("while(!skel" + counter + "->didInitWaitInvoke());");
                println("}");
@@ -3116,45 +3207,56 @@ public class IoTCompiler {
                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>");
-                               // Find out if there are callback objects
-                               Set<String> methods = intMeth.getValue();
-                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
-                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
-                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                               boolean callbackExist = !callbackClasses.isEmpty();
-                               println("#include <thread>");
-                               println("#include <mutex>");
-                               List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
-                               printIncludeStatements(stdIncludeClasses); println("");
-                               println("#include \"" + newIntface + ".hpp\""); println("");            
-                               println("using namespace std;"); println("");
-                               println("class " + newStubClass + " : public " + newIntface); println("{");
-                               println("private:\n");
-                               writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
-                               println("public:\n");
-                               // Add default constructor and destructor
-                               println(newStubClass + "();");
-                               // Declarations
-                               println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
-                               println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
-                               println("~" + newStubClass + "();");
-                               // Write methods
-                               writeMethodDeclCplusStub(methods, intDecl);
-                               print("}"); println(";");
-                               println("#endif");
-                               pw.close();
-                               System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               String driverClass = drvList.get(i);
+                               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";
+                                       // Check if this interface is a callback class
+                                       if(isCallbackClass(intface))
+                                               path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                                       else
+                                               path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                                       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>");
+                                       // Find out if there are callback objects
+                                       Set<String> methods = intMeth.getValue();
+                                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                                       boolean callbackExist = !callbackClasses.isEmpty();
+                                       println("#include <thread>");
+                                       println("#include <mutex>");
+                                       List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
+                                       printIncludeStatements(stdIncludeClasses); println("");
+                                       println("#include \"" + newIntface + ".hpp\""); println("");            
+                                       println("using namespace std;"); println("");
+                                       println("class " + newStubClass + " : public " + newIntface); println("{");
+                                       println("private:\n");
+                                       writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses, methods, intDecl);
+                                       println("public:\n");
+                                       // Add default constructor and destructor
+                                       println(newStubClass + "();");
+                                       // Declarations
+                                       println(newStubClass + "(int _portSend, int _portRecv, const char* _skeletonAddress, int _rev, bool* _bResult);");
+                                       println(newStubClass + "(IoTRMIComm* _rmiComm, int _objectId);");
+                                       println("~" + newStubClass + "();");
+                                       // Write methods
+                                       writeMethodDeclCplusStub(methods, intDecl);
+                                       print("}"); println(";");
+                                       println("#endif");
+                                       pw.close();
+                                       System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
+                               }
                        }
                }
        }
@@ -3188,45 +3290,56 @@ public class IoTCompiler {
                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 + ".cpp");
-                               pw = new PrintWriter(new BufferedWriter(fw));
-                               // Write file headers
-                               println("#include <iostream>");
-                               // Find out if there are callback objects
-                               Set<String> methods = intMeth.getValue();
-                               DeclarationHandler decHandler = mapIntDeclHand.get(intface);
-                               InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
-                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                               boolean callbackExist = !callbackClasses.isEmpty();
-                               println("#include \"" + newStubClass + ".hpp\""); println("");
-                               for(String str: callbackClasses) {
-                                       if (intface.equals(mainClass))
-                                               println("#include \"" + str + "_Skeleton.cpp\"\n");
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               String driverClass = drvList.get(i);
+                               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";
+                                       // Check if this interface is a callback class
+                                       if(isCallbackClass(intface))
+                                               path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
                                        else
-                                               println("#include \"" + str + "_Skeleton.hpp\"\n");
-                               }
-                               println("using namespace std;"); println("");
-                               // Add default constructor and destructor
-                               writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
-                               writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
-                               writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
-                               // Write methods
-                               writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
-                               // Write external functions for .so file
-                               writeStubExternalCFunctions(newStubClass);
-                               // TODO: Remove this later
-                               if (intface.equals(mainClass)) {
-                                       println("int main() {");
-                                       println("return 0;");
-                                       println("}");
+                                               path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                                       FileWriter fw = new FileWriter(path + "/" + newStubClass + ".cpp");
+                                       pw = new PrintWriter(new BufferedWriter(fw));
+                                       // Write file headers
+                                       println("#include <iostream>");
+                                       // Find out if there are callback objects
+                                       Set<String> methods = intMeth.getValue();
+                                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                                       boolean callbackExist = !callbackClasses.isEmpty();
+                                       println("#include \"" + newStubClass + ".hpp\""); println("");
+                                       for(String str: callbackClasses) {
+                                               if (intface.equals(mainClass))
+                                                       println("#include \"" + str + "_Skeleton.cpp\"\n");
+                                               else
+                                                       println("#include \"" + str + "_Skeleton.hpp\"\n");
+                                       }
+                                       println("using namespace std;"); println("");
+                                       // Add default constructor and destructor
+                                       writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
+                                       writeCallbackConstructorCplusStub(newStubClass, callbackExist, callbackClasses, methods, intDecl);
+                                       writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
+                                       // Write methods
+                                       writeMethodCplusStub(methods, intDecl, callbackClasses, newStubClass);
+                                       // Write external functions for .so file
+                                       writeStubExternalCFunctions(newStubClass);
+                                       // TODO: Remove this later
+                                       if (intface.equals(mainClass)) {
+                                               println("int main() {");
+                                               println("return 0;");
+                                               println("}");
+                                       }
+                                       pw.close();
+                                       System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
                                }
-                               pw.close();
-                               System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".cpp...");
                        }
                }
        }
@@ -4175,7 +4288,7 @@ public class IoTCompiler {
                                helperMethod = helperMethod + methodNumId;
                        else
                                uniqueMethodIds.add(methodId);
-                       print(helperMethod + ", std::ref(skel), ");
+                       print(helperMethod + ", skel, ");
                        boolean structExists = writeInputCountVarStructCplusSkeleton(method, intDecl);
                        if (structExists)
                                print(", ");
@@ -4201,49 +4314,62 @@ public class IoTCompiler {
                // Create a new directory
                String path = createDirectories(dir, subdir);
                for (String intface : mapIntfacePTH.keySet()) {
-                       // Open a new file to write into
-                       String newSkelClass = intface + "_Skeleton";
-                       FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
-                       pw = new PrintWriter(new BufferedWriter(fw));
-                       // Write file headers
-                       println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
-                       println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
-                       println("#include <iostream>");
-                       println("#include \"" + intface + ".hpp\"\n");
-                       // 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();
-                       List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
-                       printIncludeStatements(stdIncludeClasses); println("");
-                       println("using namespace std;\n");
-                       // Find out if there are callback objects
-                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                       boolean callbackExist = !callbackClasses.isEmpty();
-                       // Write class header
-                       println("class " + newSkelClass + " : public " + intface); println("{");
-                       println("private:\n");
-                       // Write properties
-                       writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
-                       println("public:\n");
-                       // Write constructors
-                       println(newSkelClass + "();");
-                       println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
-                       println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
-                       // Write deconstructor
-                       println("~" + newSkelClass + "();");
-                       // Write method declarations
-                       println("bool didInitWaitInvoke();");
-                       writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
-                       // Write method helper declarations
-                       writeMethodHelperDeclCplusSkeleton(methods, intDecl, newSkelClass);
-                       // Write waitRequestInvokeMethod() declaration - main loop
-                       println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
-                       println("};");
-                       writePermissionInitializationCplus(intface, newSkelClass, intDecl);
-                       println("#endif");
-                       pw.close();
-                       System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
+               
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               // Open a new file to write into
+                               String newSkelClass = intface + "_Skeleton";
+                               // Get driver class
+                               String driverClass = drvList.get(i);
+                               // Check if this interface is a callback class
+                               if(isCallbackClass(intface))
+                                       path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
+                               else
+                                       path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                               FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp");
+                               pw = new PrintWriter(new BufferedWriter(fw));
+                               // Write file headers
+                               println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__");
+                               println("#define _" + newSkelClass.toUpperCase() + "_HPP__");
+                               println("#include <iostream>");
+                               println("#include \"" + intface + ".hpp\"\n");
+                               // 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();
+                               List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
+                               printIncludeStatements(stdIncludeClasses); println("");
+                               println("using namespace std;\n");
+                               // Find out if there are callback objects
+                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                               boolean callbackExist = !callbackClasses.isEmpty();
+                               // Write class header
+                               println("class " + newSkelClass + " : public " + intface); println("{");
+                               println("private:\n");
+                               // Write properties
+                               writePropertiesCplusSkeleton(intface, callbackExist, callbackClasses);
+                               println("public:\n");
+                               // Write constructors
+                               println(newSkelClass + "();");
+                               println(newSkelClass + "(" + intface + "*_mainObj, int _portSend, int _portRecv);");
+                               println(newSkelClass + "(" + intface + "*_mainObj, IoTRMIComm *rmiComm, int _objectId);");
+                               // Write deconstructor
+                               println("~" + newSkelClass + "();");
+                               // Write method declarations
+                               println("bool didInitWaitInvoke();");
+                               writeMethodDeclCplusSkeleton(methods, intDecl, callbackClasses);
+                               // Write method helper declarations
+                               writeMethodHelperDeclCplusSkeleton(methods, intDecl, newSkelClass);
+                               // Write waitRequestInvokeMethod() declaration - main loop
+                               println("void ___waitRequestInvokeMethod(" + newSkelClass + "* skel);");
+                               println("};");
+                               writePermissionInitializationCplus(intface, newSkelClass, intDecl);
+                               println("#endif");
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
+                       }
                }
        }
 
@@ -4284,51 +4410,64 @@ public class IoTCompiler {
                // Create a new directory
                String path = createDirectories(dir, subdir);
                for (String intface : mapIntfacePTH.keySet()) {
-                       // Open a new file to write into
-                       String newSkelClass = intface + "_Skeleton";
-                       FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
-                       pw = new PrintWriter(new BufferedWriter(fw));
-                       // Write file headers
-                       println("#include <iostream>");
-                       println("#include \"" + newSkelClass + ".hpp\"\n");
-                       // 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();
-                       // Find out if there are callback objects
-                       Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
-                       boolean callbackExist = !callbackClasses.isEmpty();
-                       for(String str: callbackClasses) {
-                               if (intface.equals(mainClass))
-                                       println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
+
+                       // Check if there is more than 1 class that uses the same interface
+                       List<String> drvList = mapInt2Drv.get(intface);
+                       for(int i = 0; i < drvList.size(); i++) {
+
+                               // Open a new file to write into
+                               String newSkelClass = intface + "_Skeleton";
+                               // Get driver class
+                               String driverClass = drvList.get(i);
+                               // Check if this interface is a callback class
+                               if(isCallbackClass(intface))
+                                       path = createDirectories(dir + "/" + subdir + "/" + CONTROLLER_DIRECTORY, controllerClass);
                                else
-                                       println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
-                       }
-                       println("using namespace std;\n");
-                       // Write constructor
-                       writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
-                       // Write callback constructor
-                       writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
-                       // Write deconstructor
-                       writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
-                       // Write didInitWaitInvoke() to return bool
-                       writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
-                       // Write methods
-                       writeMethodCplusSkeleton(methods, intDecl, newSkelClass);
-                       // Write method helper
-                       writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
-                       // Write waitRequestInvokeMethod() - main loop
-                       writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
-                       // Write external functions for .so file
-                       writeSkelExternalCFunctions(newSkelClass, intface);
-                       // TODO: Remove this later
-                       if (intface.equals(mainClass)) {
-                               println("int main() {");
-                               println("return 0;");
-                               println("}");
+                                       path = createDirectories(dir + "/" + subdir + "/" + DRIVERS_DIRECTORY, driverClass);
+                               FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".cpp");
+                               pw = new PrintWriter(new BufferedWriter(fw));
+                               // Write file headers
+                               println("#include <iostream>");
+                               println("#include \"" + newSkelClass + ".hpp\"\n");
+                               // 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();
+                               // Find out if there are callback objects
+                               Set<String> callbackClasses = getCallbackClasses(methods, intDecl);
+                               boolean callbackExist = !callbackClasses.isEmpty();
+                               for(String str: callbackClasses) {
+                                       if (intface.equals(mainClass))
+                                               println("#include \"" + getStubInterface(str) + "_Stub.cpp\"\n");
+                                       else
+                                               println("#include \"" + getStubInterface(str) + "_Stub.hpp\"\n");
+                               }
+                               println("using namespace std;\n");
+                               // Write constructor
+                               writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
+                               // Write callback constructor
+                               writeCallbackConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
+                               // Write deconstructor
+                               writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
+                               // Write didInitWaitInvoke() to return bool
+                               writeReturnDidAlreadyInitWaitInvoke(newSkelClass);
+                               // Write methods
+                               writeMethodCplusSkeleton(methods, intDecl, newSkelClass);
+                               // Write method helper
+                               writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses, newSkelClass);
+                               // Write waitRequestInvokeMethod() - main loop
+                               writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface, newSkelClass);
+                               // Write external functions for .so file
+                               writeSkelExternalCFunctions(newSkelClass, intface);
+                               // TODO: Remove this later
+                               if (intface.equals(mainClass)) {
+                                       println("int main() {");
+                                       println("return 0;");
+                                       println("}");
+                               }
+                               pw.close();
+                               System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
                        }
-                       pw.close();
-                       System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".cpp...");
                }
        }
 
@@ -4388,8 +4527,14 @@ public class IoTCompiler {
                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");
+               System.out.println("\t-cont\t<controller-class>\tSpecify controller class name");
+               System.out.println("\t-drv\t<driver-class>\t\tSpecify driver class name");
+               System.out.println("\t\t(place this option right after a pair of .pol and .req files)");
+               System.out.println("\t-objid\t<object-id>\t\tSpecify object Id for stub/skeleton used in multiple apps");
+               System.out.println("\t\t(place this option right after -drv option)");
+               System.out.println("\t-cplus\t<directory>\t\tGenerate C++ stub files");
+               System.out.println("\t-java\t<directory>\t\tGenerate Java stub files\n");
+               System.out.println("\t\tNote: The options -cont and -drv have to be defined before -cplus and -java");
                System.out.println();
        }
 
@@ -4526,7 +4671,7 @@ public class IoTCompiler {
        // Basically the compiler needs to parse the policy (and requires) files for callback class first
        private int getNewIntfaceObjectId(String newIntface) {
 
-               int retObjId = mapNewIntfaceObjId.get(newIntface);
+               int retObjId = mapNewIntfaceObjId.get(newIntface);      
                return retObjId;
        }
 
@@ -4865,6 +5010,45 @@ public class IoTCompiler {
                }
                return callbackClasses;
        }
+       
+
+       // Check if this is a callback class
+       private boolean isCallbackClass(String className) {
+
+               Set<String> intfaceSet = mapIntDeclHand.keySet();
+               for(String intface : intfaceSet) {
+
+                       DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+                       InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
+                       Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+                       for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+                               Set<String> methods = intMeth.getValue();
+                               for (String method : methods) {
+
+                                       List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+                                       List<String> methParams = intDecl.getMethodParams(method);
+                                       for (int i = 0; i < methPrmTypes.size(); i++) {
+
+                                               String type = methPrmTypes.get(i);
+                                               if (getParamCategory(type) == ParamCategory.USERDEFINED) {
+                                                       // Final check to see if this is the searched class
+                                                       if (type.equals(className))
+                                                               return true;
+                                               } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) {
+                                               // Can be a List<...> of callback objects ...
+                                                       String genericType = getTypeOfGeneric(type)[0];
+                                                       if (getParamCategory(type) == ParamCategory.USERDEFINED) {
+                                                               if (type.equals(className))
+                                                                       return true;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
+
+               return false;
+       }
 
 
        // Print import statements into file
@@ -5169,32 +5353,53 @@ public class IoTCompiler {
        public static void main(String[] args) throws Exception {
 
                // If there is no argument or just "--help" or "-h", then invoke printUsage()
-               if ((args[0].equals("-help") ||
+               if ((args.length == 0        ||
+                        args[0].equals("-help") ||
                         args[0].equals("--help")||
-                        args[0].equals("-h"))   ||
-                       (args.length == 0)) {
+                        args[0].equals("-h"))) {
 
                        IoTCompiler.printUsage();
 
                } else if (args.length > 1) {
 
                        IoTCompiler comp = new IoTCompiler();
-                       int i = 0;                              
+                       int i = 0;
+                       boolean controllerDefined = false;
                        do {
-                               // Parse main policy file
-                               ParseNode pnPol = IoTCompiler.parseFile(args[i]);
-                               // Parse "requires" policy file
-                               ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
-                               // Get interface name
-                               String intface = ParseTreeHandler.getOrigIntface(pnPol);
-                               comp.setDataStructures(intface, pnPol, pnReq);
-                               comp.getMethodsForIntface(intface);
+                               if (!controllerDefined && args[i].equals("-cont")) {
+                                       comp.setControllerClass(args[i+1]);
+                                       controllerDefined = true;
+                                       i = i + 2;
+                               }
+                           // Parse main policy file
+                           ParseNode pnPol = IoTCompiler.parseFile(args[i]);
+                           // Parse "requires" policy file
+                           ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
+                           // Get interface name
+                           String intface = ParseTreeHandler.getOrigIntface(pnPol);
+                           comp.setDataStructures(intface, pnPol, pnReq);
+                           comp.getMethodsForIntface(intface);
                                i = i + 2;
+                               // Driver name
+                               if (args[i].equals("-drv")) {
+                                       comp.setDriverClass(intface, args[i+1]);
+                                       i = i + 2;
+                               } else
+                                       throw new Error("IoTCompiler: ERROR - driver class name is needed for the interface: " + intface + "\n");
+                               // Object ID (for a stub/skeleton pair that is also used in other applications)
+                               if (args[i].equals("-objid")) {
+                                       comp.setObjectId(intface, args[i+1]);
+                                       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")
+                       // 2) Check if this is really the last option
                        } while(!args[i].equals("-java") &&
                                        !args[i].equals("-cplus") &&
                                        (i < args.length));
+                       // Controller class name needs to be defined at least once
+                       if (!controllerDefined)
+                               throw new Error("IoTCompiler: ERROR - controller class name has not been specified!\n");
 
                        // Generate everything if we don't see "-java" or "-cplus"
                        if (i == args.length) {
@@ -5255,3 +5460,4 @@ public class IoTCompiler {
 }
 
 
+