+ /**
+ * HELPER: writeStructRetMembersJavaStub() writes parameters of struct for return statement
+ */
+ private void writeStructRetMembersJavaStub(String simpleType, String retType) {
+
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ if (isArrayOrList(retType, retType)) { // An array or list
+ println("for(int i = 0; i < retLen; i++) {");
+ }
+ if (isArray(retType)) { // An array
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ print("structRet[i]." + getSimpleIdentifier(members.get(i)));
+ println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];");
+ }
+ println("}");
+ } else if (isList(retType)) { // A list
+ println(simpleType + " structRetMem = new " + simpleType + "();");
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ print("structRetMem." + getSimpleIdentifier(members.get(i)));
+ println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];");
+ }
+ println("structRet.add(structRetMem);");
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ print("structRet." + getSimpleIdentifier(members.get(i)));
+ println(" = (" + getSimpleType(getEnumType(prmType)) + ") retObj[retObjPos++];");
+ }
+ }
+ println("return structRet;");
+ }
+
+
+ /**
+ * HELPER: writeStructReturnJavaStub() writes parameters if struct is present for return statement
+ */
+ private void writeStructReturnJavaStub(String simpleType, String retType) {
+
+ // Handle the returned struct!!!
+ println("Object retLenObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
+ // Minimum retLen is 1 if this is a single struct object
+ println("int retLen = (int) retLenObj;");
+ int numMem = getNumOfMembers(simpleType);
+ println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
+ println("Class<?>[] retClsVal = new Class<?>[" + numMem + "*retLen];");
+ println("int retPos = 0;");
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ if (isArrayOrList(retType, retType)) { // An array or list
+ println("for(int i = 0; i < retLen; i++) {");
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
+ println("retClsVal[retPos++] = null;");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
+ println("retClsVal[retPos++] = null;");
+ }
+ }
+ println("Object[] retObj = rmiCall.getStructObjects(retCls, retClsVal);");
+ if (isArray(retType)) { // An array
+ println(simpleType + "[] structRet = new " + simpleType + "[retLen];");
+ println("for(int i = 0; i < retLen; i++) {");
+ println("structRet[i] = new " + simpleType + "();");
+ println("}");
+ } else if (isList(retType)) { // A list
+ println("List<" + simpleType + "> structRet = new ArrayList<" + simpleType + ">();");
+ } else
+ println(simpleType + " structRet = new " + simpleType + "();");
+ println("int retObjPos = 0;");
+ writeStructRetMembersJavaStub(simpleType, retType);
+ }
+
+
+ /**
+ * HELPER: writeStdMethodBodyJavaStub() writes the standard method body in the stub class
+ */
+ private void writeStdMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, String callbackType) {
+
+ checkAndWriteStructSetupJavaStub(methParams, methPrmTypes, intDecl, method);
+ println("int methodId = " + intDecl.getMethodNumId(method) + ";");
+ String retType = intDecl.getMethodType(method);
+ println("Class<?> retType = " + getSimpleType(getStructType(getEnumType(retType))) + ".class;");
+ checkAndWriteEnumTypeJavaStub(methParams, methPrmTypes);
+ // Generate array of parameter types
+ if (isStructPresent(methParams, methPrmTypes)) {
+ writeStructParamClassJavaStub(methParams, methPrmTypes, callbackType);
+ } else {
+ print("Class<?>[] paramCls = new Class<?>[] { ");
+ for (int i = 0; i < methParams.size(); i++) {
+ String prmType = methPrmTypes.get(i);
+ if (checkCallbackType(prmType, callbackType)) { // Check if this has callback object
+ print("int.class");
+ } else { // Generate normal classes if it's not a callback object
+ String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
+ print(getSimpleType(getEnumType(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++) {
+ String paramType = methPrmTypes.get(i);
+ if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+ //if (isArray(methPrmTypes.get(i), methParams.get(i)))
+ if (isArray(methParams.get(i)))
+ print(getSimpleIdentifier(methParams.get(i)) + ".length");
+ else if (isList(methPrmTypes.get(i)))
+ print(getSimpleIdentifier(methParams.get(i)) + ".size()");
+ else
+ print("new Integer(1)");
+ } else
+ print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), 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
+ // Generate array of parameter types
+ if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
+ writeStructReturnJavaStub(getGenericType(getSimpleArrayType(retType)), retType);
+ } else {
+ // This is an enum type
+ if (getParamCategory(getGenericType(getSimpleArrayType(retType))) == ParamCategory.ENUM) {
+ println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);");
+ checkAndWriteEnumRetTypeJavaStub(retType);
+ } else if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) {
+ // Check if the return value NONPRIMITIVES
+ String retGenValType = getGenericType(retType);
+ println("Class<?> retGenValType = " + retGenValType + ".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: returnGenericCallbackType() returns the callback type
+ */
+ private String returnGenericCallbackType(String paramType) {
+
+ if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES)
+ return getGenericType(paramType);
+ else
+ return paramType;
+ }
+
+
+ /**
+ * HELPER: checkCallbackType() checks the callback type
+ */
+ private boolean checkCallbackType(String paramType, String callbackType) {
+
+ String prmType = returnGenericCallbackType(paramType);
+ if (callbackType == null) // If there is no callbackType it means not a callback method
+ return false;
+ else
+ return callbackType.equals(prmType);
+ }
+
+
+ /**
+ * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class
+ */
+ private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, String callbackType) {
+
+ println("try {");
+ // Check if this is single object, array, or list of objects
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+ String param = methParams.get(i);
+ if (isArrayOrList(paramType, param)) { // Generate loop
+ println("for (" + getGenericType(paramType) + " cb : " + getSimpleIdentifier(param) + ") {");
+ println(callbackType + "_CallbackSkeleton skel" + i + " = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);");
+ } else
+ println(callbackType + "_CallbackSkeleton skel" + i + " = new " + callbackType + "_CallbackSkeleton(" +
+ getSimpleIdentifier(param) + ", objIdCnt++);");
+ println("listCallbackObj.add(skel" + i + ");");
+ if (isArrayOrList(paramType, param))
+ println("}");
+ }
+ }
+ print("}");
+ println(" catch (Exception ex) {");
+ println("ex.printStackTrace();");
+ println("throw new Error(\"Exception when generating skeleton objects!\");");
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeMethodJavaStub() writes the methods of the stub class
+ */
+ private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
+
+ boolean isDefined = false;
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ print("public " + intDecl.getMethodType(method) + " " +
+ intDecl.getMethodId(method) + "(");
+ boolean isCallbackMethod = false;
+ String callbackType = null;
+ for (int i = 0; i < methParams.size(); i++) {
+
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ // Check if this has callback object
+ if (callbackClasses.contains(paramType)) {
+ isCallbackMethod = true;
+ callbackType = paramType;
+ // Even if there're 2 callback arguments, we expect them to be of the same interface
+ }
+ 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!
+ if (isCallbackMethod)
+ writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
+ //else
+ writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType);
+ println("}\n");
+ // Write the init callback helper method
+ if (isCallbackMethod && !isDefined) {
+ writeInitCallbackJavaStub(callbackType, intDecl);
+ isDefined = true;
+ }
+ }
+ }
+
+
+ /**
+ * 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> 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, newIntface, callbackExist, callbackClasses);
+ // Write constructor
+ writeConstructorJavaStub(intface, newStubClass, callbackExist, callbackClasses);
+ // Write methods
+ writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
+ println("}");
+ pw.close();
+ System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writePropertiesJavaCallbackStub() writes the properties of the callback stub class
+ */
+ private void writePropertiesJavaCallbackStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
+
+ println("private IoTRMICall rmiCall;");
+ println("private String address;");
+ println("private int[] ports;\n");
+ // Get the object Id
+ println("private int objectId = 0;");
+ if (callbackExist) {
+ // We assume that each class only has one callback interface for now
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ println("// Callback properties");
+ println("private IoTRMIObject rmiObj;");
+ println("List<" + callbackType + "> listCallbackObj;");
+ println("private static int objIdCnt = 0;");
+ // Generate permission stuff for callback stubs
+ DeclarationHandler decHandler = mapIntDeclHand.get(callbackType);
+ InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(callbackType);
+ writePropertiesJavaPermission(callbackType, intDecl);
+ }
+ println("\n");
+ }
+
+
+ /**
+ * HELPER: writeConstructorJavaCallbackStub() writes the constructor of the callback stub class
+ */
+ private void writeConstructorJavaCallbackStub(String intface, String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
+
+ // TODO: If we want callback in callback, then we need to add address and port initializations
+ println("public " + newStubClass + "(IoTRMICall _rmiCall, int _objectId) throws Exception {");
+ println("objectId = _objectId;");
+ println("rmiCall = _rmiCall;");
+ if (callbackExist) {
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ writeConstructorJavaPermission(intface);
+ println("listCallbackObj = new ArrayList<" + callbackType + ">();");
+ println("___initCallBack();");
+ println("// TODO: Add address and port initialization here if we want callback in callback!");
+ }
+ println("}\n");
+ }
+
+
+ /**
+ * generateJavaCallbackStubClasses() generate callback stubs based on the methods list in Java
+ * <p>
+ * Callback stubs gets the IoTRMICall objects from outside of the class as contructor input
+ * because all these stubs are populated by the class that takes in this object as a callback
+ * object. In such a class, we only use one socket, hence one IoTRMICall, for all callback objects.
+ */
+ public void generateJavaCallbackStubClasses() 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 + "_CallbackStub";
+ 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
+ writePropertiesJavaCallbackStub(intface, newIntface, callbackExist, callbackClasses);
+ // Write constructor
+ writeConstructorJavaCallbackStub(intface, newStubClass, callbackExist, callbackClasses);
+ // Write methods
+ // TODO: perhaps need to generate callback for callback
+ writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses);
+ println("}");
+ pw.close();
+ System.out.println("IoTCompiler: Generated callback stub class " + newStubClass + ".java...");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writePropertiesJavaSkeleton() writes the properties of the skeleton class
+ */
+ private void writePropertiesJavaSkeleton(String intface, boolean callbackExist, InterfaceDecl intDecl) {
+
+ println("private " + intface + " mainObj;");
+ //println("private int ports;");
+ println("private IoTRMIObject rmiObj;\n");
+ // Callback
+ if (callbackExist) {
+ println("private static int objIdCnt = 0;");
+ println("private IoTRMICall rmiCall;");
+ }
+ writePropertiesJavaPermission(intface, intDecl);
+ println("\n");
+ }
+
+
+ /**
+ * HELPER: writeStructPermissionJavaSkeleton() writes permission for struct helper
+ */
+ private void writeStructPermissionJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ String helperMethod = methodNumId + "struct" + i;
+ int methodHelperNumId = intDecl.getHelperMethodNumId(helperMethod);
+ // Iterate over interfaces to give permissions to
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ println("set" + newObjectId + "Allowed.add(" + methodHelperNumId + ");");
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeConstructorJavaSkeleton() writes the constructor of the skeleton class
+ */
+ private void writeConstructorJavaSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, Collection<String> methods, boolean callbackExist) {
+
+ println("public " + newSkelClass + "(" + intface + " _mainObj, int _port) throws Exception {");
+ println("mainObj = _mainObj;");
+ println("rmiObj = new IoTRMIObject(_port);");
+ // Generate permission control initialization
+ writeConstructorJavaPermission(intface);
+ writeJavaInitCallbackPermission(intface, intDecl, callbackExist);
+ writeStructPermissionJavaSkeleton(methods, intDecl, intface);
+ println("___waitRequestInvokeMethod();");
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeStdMethodBodyJavaSkeleton() writes the standard method body in the skeleton class
+ */
+ private void writeStdMethodBodyJavaSkeleton(List<String> methParams, String methodId, String methodType) {
+
+ if (methodType.equals("void"))
+ print("mainObj." + methodId + "(");
+ else
+ print("return mainObj." + methodId + "(");
+ 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(");");
+ }
+
+
+ /**
+ * HELPER: writeInitCallbackJavaSkeleton() writes the init callback method for skeleton class
+ */
+ private void writeInitCallbackJavaSkeleton(boolean callbackSkeleton) {
+
+ // This is a callback skeleton generation
+ if (callbackSkeleton)
+ println("public void ___regCB(IoTRMIObject rmiObj) throws IOException {");
+ else
+ println("public void ___regCB() throws IOException {");
+ print("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class, String.class, int.class },");
+ println("new Class<?>[] { null, null, null });");
+ println("rmiCall = new IoTRMICall((int) paramObj[0], (String) paramObj[1], (int) paramObj[2]);");
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeMethodJavaSkeleton() writes the method of the skeleton class
+ */
+ private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses,
+ boolean callbackSkeleton) {
+
+ boolean isDefined = false;
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ String methodId = intDecl.getMethodId(method);
+ print("public " + intDecl.getMethodType(method) + " " + methodId + "(");
+ boolean isCallbackMethod = false;
+ String callbackType = null;
+ for (int i = 0; i < methParams.size(); i++) {
+
+ String origParamType = methPrmTypes.get(i);
+ String paramType = checkAndGetParamClass(origParamType);
+ if (callbackClasses.contains(origParamType)) { // Check if this has callback object
+ isCallbackMethod = true;
+ callbackType = origParamType;
+ }
+ print(paramType + " " + 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 skeleton!
+ writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method));
+ println("}\n");
+ if (isCallbackMethod && !isDefined) { // Make sure that this function is only defined once!
+ writeInitCallbackJavaSkeleton(callbackSkeleton);
+ isDefined = true;
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeCallbackJavaStubGeneration() writes the callback stub generation part
+ */
+ private Map<Integer,String> writeCallbackJavaStubGeneration(List<String> methParams, List<String> methPrmTypes,
+ String callbackType, boolean isStructMethod) {
+
+ Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
+ String offsetPfx = "";
+ if (isStructMethod)
+ offsetPfx = "offset";
+ // Iterate over callback objects
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+ String exchParamType = checkAndGetParamClass(getGenericType(paramType));
+ // Print array if this is array or list if this is a list of callback objects
+ if (isArray(param)) {
+ println("int numStubs" + i + " = (int) paramObj[" + offsetPfx + i + "];");
+ println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];");
+ } else if (isList(paramType)) {
+ println("int numStubs" + i + " = (int) paramObj[" + offsetPfx + i + "];");
+ println("List<" + exchParamType + "> stub" + i + " = new ArrayList<" + exchParamType + ">();");
+ } else {
+ println(exchParamType + " stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
+ println("objIdCnt++;");
+ }
+ }
+ // Generate a loop if needed
+ if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+ String exchParamType = checkAndGetParamClass(getGenericType(paramType));
+ if (isArray(param)) {
+ println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
+ println("stub" + i + "[objId] = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
+ println("objIdCnt++;");
+ println("}");
+ } else if (isList(paramType)) {
+ println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
+ println("stub" + i + ".add(new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt));");
+ println("objIdCnt++;");
+ println("}");
+ }
+ mapStubParam.put(i, "stub" + i); // List of all stub parameters
+ }
+ }
+ return mapStubParam;
+ }
+
+
+ /**
+ * HELPER: checkAndWriteEnumTypeJavaSkeleton() writes the enum type (convert from enum to int)
+ */
+ private void checkAndWriteEnumTypeJavaSkeleton(List<String> methParams, List<String> methPrmTypes, boolean isStructMethod) {
+
+ String offsetPfx = "";
+ if (isStructMethod)
+ offsetPfx = "offset";
+ // Iterate and find enum declarations
+ boolean printed = false;
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isEnumClass(simpleType)) {
+ // Check if this is enum type
+ println("int paramInt" + i + "[] = (int[]) paramObj[" + offsetPfx + i + "];");
+ if (!printed) {
+ println(simpleType + "[] enumVals = " + simpleType + ".values();");
+ printed = true;
+ }
+ if (isArray(param)) { // An array
+ println("int len" + i + " = paramInt" + i + ".length;");
+ println(simpleType + "[] paramEnum" + i + " = new " + simpleType + "[len" + i + "];");
+ println("for (int i = 0; i < len" + i + "; i++) {");
+ println("paramEnum" + i + "[i] = enumVals[paramInt" + i + "[i]];");
+ println("}");
+ } else if (isList(paramType)) { // A list
+ println("int len" + i + " = paramInt" + i + ".length;");
+ println("List<" + simpleType + "> paramEnum" + i + " = new ArrayList<" + simpleType + ">();");
+ println("for (int i = 0; i < len" + i + "; i++) {");
+ println("paramEnum" + i + ".add(enumVals[paramInt" + i + "[i]]);");
+ println("}");
+ } else { // Just one element
+ println(simpleType + " paramEnum" + i + " = enumVals[paramInt" + i + "[0]];");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteEnumRetTypeJavaSkeleton() writes the enum return type (convert from enum to int)
+ */
+ private void checkAndWriteEnumRetTypeJavaSkeleton(String retType, String methodId) {
+
+ // Strips off array "[]" for return type
+ String pureType = getSimpleArrayType(getGenericType(retType));
+ // Take the inner type of generic
+ if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
+ pureType = getGenericType(retType);
+ if (isEnumClass(pureType)) {
+ // Check if this is enum type
+ // Enum decoder
+ if (isArray(retType)) { // An array
+ print(pureType + "[] retEnum = " + methodId + "(");
+ } else if (isList(retType)) { // A list
+ print("List<" + pureType + "> retEnum = " + methodId + "(");
+ } else { // Just one element
+ print(pureType + " retEnum = " + methodId + "(");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteEnumRetConvJavaSkeleton() writes the enum return type (convert from enum to int)
+ */
+ private void checkAndWriteEnumRetConvJavaSkeleton(String retType) {
+
+ // Strips off array "[]" for return type
+ String pureType = getSimpleArrayType(getGenericType(retType));
+ // Take the inner type of generic
+ if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
+ pureType = getGenericType(retType);
+ if (isEnumClass(pureType)) {
+ // Check if this is enum type
+ if (isArray(retType)) { // An array
+ println("int retLen = retEnum.length;");
+ println("int[] retEnumVal = new int[retLen];");
+ println("for (int i = 0; i < retLen; i++) {");
+ println("retEnumVal[i] = retEnum[i].ordinal();");
+ println("}");
+ } else if (isList(retType)) { // A list
+ println("int retLen = retEnum.size();");
+ println("int[] retEnumVal = new int[retLen];");
+ println("for (int i = 0; i < retLen; i++) {");
+ println("retEnumVal[i] = retEnum.get(i).ordinal();");
+ println("}");
+ } else { // Just one element
+ println("int[] retEnumVal = new int[1];");
+ println("retEnumVal[0] = retEnum.ordinal();");
+ }
+ println("Object retObj = retEnumVal;");
+ }
+ }
+
+
+ /**
+ * HELPER: writeLengthStructParamClassSkeleton() writes lengths of params
+ */
+ private void writeLengthStructParamClassSkeleton(List<String> methParams, List<String> methPrmTypes,
+ String method, InterfaceDecl intDecl) {
+
+ // Iterate and find struct declarations - count number of params
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int members = getNumOfMembers(simpleType);
+ print(Integer.toString(members) + "*");
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("struct" + methodNumId + "Size" + i);
+ } else
+ print("1");
+ if (i != methParams.size() - 1) {
+ print("+");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructMembersJavaSkeleton() writes member parameters of struct
+ */
+ private void writeStructMembersJavaSkeleton(String simpleType, String paramType,
+ String param, String method, InterfaceDecl intDecl, int iVar) {
+
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ if (isArrayOrList(paramType, param)) { // An array or list
+ int methodNumId = intDecl.getMethodNumId(method);
+ String counter = "struct" + methodNumId + "Size" + iVar;
+ println("for(int i = 0; i < " + counter + "; i++) {");
+ }
+ if (isArrayOrList(paramType, param)) { // An array or list
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
+ println("paramClsGen[pos++] = null;");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ println("paramCls[pos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
+ println("paramClsGen[pos++] = null;");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructMembersInitJavaSkeleton() writes member parameters initialization of struct
+ */
+ private void writeStructMembersInitJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method) {
+
+ println("int objPos = 0;");
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ String counter = "struct" + methodNumId + "Size" + i;
+ // Declaration
+ if (isArray(param)) { // An array
+ println(simpleType + "[] paramStruct" + i + " = new " + simpleType + "[" + counter + "];");
+ println("for(int i = 0; i < " + counter + "; i++) {");
+ println("paramStruct" + i + "[i] = new " + simpleType + "();");
+ println("}");
+ } else if (isList(paramType)) { // A list
+ println("List<" + simpleType + "> paramStruct" + i + " = new ArrayList<" + simpleType + ">();");
+ } else
+ println(simpleType + " paramStruct" + i + " = new " + simpleType + "();");
+ // Initialize members
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ if (isArrayOrList(paramType, param)) { // An array or list
+ println("for(int i = 0; i < " + counter + "; i++) {");
+ }
+ if (isArray(param)) { // An array
+ for (int j = 0; j < members.size(); j++) {
+ String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
+ print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
+ println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
+ }
+ println("}");
+ } else if (isList(paramType)) { // A list
+ println(simpleType + " paramStructMem = new " + simpleType + "();");
+ for (int j = 0; j < members.size(); j++) {
+ String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
+ print("paramStructMem." + getSimpleIdentifier(members.get(j)));
+ println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
+ }
+ println("paramStruct" + i + ".add(paramStructMem);");
+ println("}");
+ } else { // Just one struct element
+ for (int j = 0; j < members.size(); j++) {
+ String prmType = checkAndGetArray(memTypes.get(j), members.get(j));
+ print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
+ println(" = (" + getSimpleType(getEnumType(prmType)) + ") paramObj[objPos++];");
+ }
+ }
+ } else {
+ // Take offsets of parameters
+ println("int offset" + i +" = objPos++;");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructReturnJavaSkeleton() writes struct for return statement
+ */
+ private void writeStructReturnJavaSkeleton(String simpleType, String retType) {
+
+ // Minimum retLen is 1 if this is a single struct object
+ if (isArray(retType))
+ println("int retLen = retStruct.length;");
+ else if (isList(retType))
+ println("int retLen = retStruct.size();");
+ else // Just single struct object
+ println("int retLen = 1;");
+ println("Object retLenObj = retLen;");
+ println("rmiObj.sendReturnObj(retLenObj);");
+ int numMem = getNumOfMembers(simpleType);
+ println("Class<?>[] retCls = new Class<?>[" + numMem + "*retLen];");
+ println("Object[] retObj = new Object[" + numMem + "*retLen];");
+ println("int retPos = 0;");
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ if (isArray(retType)) { // An array or list
+ println("for(int i = 0; i < retLen; i++) {");
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
+ print("retObj[retPos++] = retStruct[i].");
+ print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
+ println(";");
+ }
+ println("}");
+ } else if (isList(retType)) { // An array or list
+ println("for(int i = 0; i < retLen; i++) {");
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
+ print("retObj[retPos++] = retStruct.get(i).");
+ print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
+ println(";");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = " + getSimpleType(getEnumType(prmType)) + ".class;");
+ print("retObj[retPos++] = retStruct.");
+ print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
+ println(";");
+ }
+ }
+
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperReturnJavaSkeleton() writes return statement part in skeleton
+ */
+ private void writeMethodHelperReturnJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, boolean isCallbackMethod, String callbackType,
+ boolean isStructMethod) {
+
+ checkAndWriteEnumTypeJavaSkeleton(methParams, methPrmTypes, isStructMethod);
+ Map<Integer,String> mapStubParam = null;
+ if (isCallbackMethod) {
+ println("try {");
+ mapStubParam = writeCallbackJavaStubGeneration(methParams, methPrmTypes, callbackType, isStructMethod);
+ }
+ // Check if this is "void"
+ String retType = intDecl.getMethodType(method);
+ if (retType.equals("void")) {
+ print(intDecl.getMethodId(method) + "(");
+ } else if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
+ checkAndWriteEnumRetTypeJavaSkeleton(retType, intDecl.getMethodId(method));
+ } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
+ print(retType + " retStruct = " + intDecl.getMethodId(method) + "(");
+ } else { // We do have a return value
+ print("Object retObj = " + intDecl.getMethodId(method) + "(");
+ }
+ for (int i = 0; i < methParams.size(); i++) {
+
+ String paramType = methPrmTypes.get(i);
+ if (isCallbackMethod && checkCallbackType(paramType, callbackType)) {
+ print(mapStubParam.get(i)); // Get the callback parameter
+ } else if (isEnumClass(getGenericType(paramType))) { // Enum class
+ print(getEnumParam(paramType, methParams.get(i), i));
+ } else if (isStructClass(getGenericType(paramType))) {
+ print("paramStruct" + i);
+ } else {
+ String prmType = checkAndGetArray(paramType, methParams.get(i));
+ if (isStructMethod)
+ print("(" + prmType + ") paramObj[offset" + i + "]");
+ else
+ print("(" + prmType + ") paramObj[" + i + "]");
+ }
+ if (i != methParams.size() - 1)
+ print(", ");
+ }
+ println(");");
+ if (!retType.equals("void")) {
+ if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) { // Enum type
+ checkAndWriteEnumRetConvJavaSkeleton(retType);
+ println("rmiObj.sendReturnObj(retObj);");
+ } else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) { // Struct type
+ writeStructReturnJavaSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
+ println("rmiObj.sendReturnObj(retCls, retObj);");
+ } else
+ println("rmiObj.sendReturnObj(retObj);");
+ }
+ if (isCallbackMethod) { // Catch exception if this is callback
+ print("}");
+ println(" catch(Exception ex) {");
+ println("ex.printStackTrace();");
+ println("throw new Error(\"Exception from callback object instantiation!\");");
+ println("}");
+ }
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperStructJavaSkeleton() writes the struct in skeleton
+ */
+ private void writeMethodHelperStructJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, Set<String> callbackClasses) {
+
+ // Generate array of parameter objects
+ boolean isCallbackMethod = false;
+ String callbackType = null;
+ print("int paramLen = ");
+ writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
+ println(";");
+ println("Class<?>[] paramCls = new Class<?>[paramLen];");
+ println("Class<?>[] paramClsGen = new Class<?>[paramLen];");
+ println("int pos = 0;");
+ // Iterate again over the parameters
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ writeStructMembersJavaSkeleton(simpleType, paramType, param, method, intDecl, i);
+ } else {
+ String prmType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (callbackClasses.contains(prmType)) {
+ isCallbackMethod = true;
+ callbackType = prmType;
+ println("paramCls[pos] = int.class;");
+ println("paramClsGen[pos++] = null;");
+ } else { // Generate normal classes if it's not a callback object
+ String paramTypeOth = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
+ println("paramCls[pos] = " + getSimpleType(getEnumType(paramTypeOth)) + ".class;");
+ print("paramClsGen[pos++] = ");
+ String prmTypeOth = methPrmTypes.get(i);
+ if (getParamCategory(prmTypeOth) == ParamCategory.NONPRIMITIVES)
+ println(getTypeOfGeneric(prmType)[0] + ".class;");
+ else
+ println("null;");
+ }
+ }
+ }
+ println("Object[] paramObj = rmiObj.getMethodParams(paramCls, paramClsGen);");
+ writeStructMembersInitJavaSkeleton(intDecl, methParams, methPrmTypes, method);
+ // Write the return value part
+ writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, true);
+ }
+
+
+ /**
+ * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class
+ */
+ private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, Set<String> callbackClasses) {
+
+ // Generate array of parameter objects
+ boolean isCallbackMethod = false;
+ String callbackType = null;
+ print("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { ");
+ for (int i = 0; i < methParams.size(); i++) {
+
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (callbackClasses.contains(paramType)) {
+ isCallbackMethod = true;
+ callbackType = paramType;
+ print("int.class");
+ } else { // Generate normal classes if it's not a callback object
+ String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i));
+ print(getSimpleType(getEnumType(prmType)) + ".class");
+ }
+ if (i != methParams.size() - 1)
+ print(", ");
+ }
+ println(" }, ");
+ // Generate generic class if it's a generic type.. null otherwise
+ print("new Class<?>[] { ");
+ for (int i = 0; i < methParams.size(); i++) {
+ String prmType = methPrmTypes.get(i);
+ if ((getParamCategory(prmType) == ParamCategory.NONPRIMITIVES) &&
+ !isEnumClass(getGenericType(prmType)) &&
+ !callbackClasses.contains(getGenericType(prmType)))
+ print(getGenericType(prmType) + ".class");
+ else
+ print("null");
+ if (i != methParams.size() - 1)
+ print(", ");
+ }
+ println(" });");
+ // Write the return value part
+ writeMethodHelperReturnJavaSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod, callbackType, false);
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class
+ */
+ private void writeMethodHelperJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
+
+ // Use this set to handle two same methodIds
+ Set<String> uniqueMethodIds = new HashSet<String>();
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
+ String methodId = intDecl.getMethodId(method);
+ print("public void ___");
+ String helperMethod = methodId;
+ if (uniqueMethodIds.contains(methodId))
+ helperMethod = helperMethod + intDecl.getMethodNumId(method);
+ else
+ uniqueMethodIds.add(methodId);
+ String retType = intDecl.getMethodType(method);
+ print(helperMethod + "(");
+ boolean begin = true;
+ for (int i = 0; i < methParams.size(); i++) { // Print size variables
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ if (!begin) // Generate comma for not the beginning variable
+ print(", ");
+ else
+ begin = false;
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("int struct" + methodNumId + "Size" + i);
+ }
+ }
+ // Check if this is "void"
+ if (retType.equals("void"))
+ println(") {");
+ else
+ println(") throws IOException {");
+ writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
+ println("}\n");
+ } else {
+ String methodId = intDecl.getMethodId(method);
+ print("public void ___");
+ String helperMethod = methodId;
+ if (uniqueMethodIds.contains(methodId))
+ helperMethod = helperMethod + intDecl.getMethodNumId(method);
+ else
+ uniqueMethodIds.add(methodId);
+ // Check if this is "void"
+ String retType = intDecl.getMethodType(method);
+ if (retType.equals("void"))
+ println(helperMethod + "() {");
+ else
+ println(helperMethod + "() throws IOException {");
+ // Now, write the helper body of skeleton!
+ writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
+ println("}\n");
+ }
+ }
+ // Write method helper for structs
+ writeMethodHelperStructSetupJavaSkeleton(methods, intDecl);
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperStructSetupJavaSkeleton() writes the method helper of struct setup in skeleton class
+ */
+ private void writeMethodHelperStructSetupJavaSkeleton(Collection<String> methods,
+ InterfaceDecl intDecl) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("public int ___");
+ String helperMethod = methodNumId + "struct" + i;
+ println(helperMethod + "() {");
+ // Now, write the helper body of skeleton!
+ println("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
+ println("return (int) paramObj[0];");
+ println("}\n");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperStructSetupJavaCallbackSkeleton() writes the method helper of struct setup in callback skeleton class
+ */
+ private void writeMethodHelperStructSetupJavaCallbackSkeleton(Collection<String> methods,
+ InterfaceDecl intDecl) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("public int ___");
+ String helperMethod = methodNumId + "struct" + i;
+ println(helperMethod + "(IoTRMIObject rmiObj) {");
+ // Now, write the helper body of skeleton!
+ println("Object[] paramObj = rmiObj.getMethodParams(new Class<?>[] { int.class }, new Class<?>[] { null });");
+ println("return (int) paramObj[0];");
+ println("}\n");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeCountVarStructSkeleton() writes counter variable of struct for skeleton
+ */
+ private void writeCountVarStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ println("int struct" + methodNumId + "Size" + i + " = 0;");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeInputCountVarStructSkeleton() writes input counter variable of struct for skeleton
+ */
+ private boolean writeInputCountVarStructSkeleton(String method, InterfaceDecl intDecl) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ boolean structExist = false;
+ boolean begin = true;
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ structExist = true;
+ if (!begin)
+ print(", ");
+ else
+ begin = false;
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("struct" + methodNumId + "Size" + i);
+ }
+ }
+ return structExist;
+ }
+
+
+ /**
+ * HELPER: writeMethodCallStructSkeleton() writes method call for wait invoke in skeleton
+ */
+ private void writeMethodCallStructSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("case ");
+ String helperMethod = methodNumId + "struct" + i;
+ String tempVar = "struct" + methodNumId + "Size" + i;
+ print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
+ print(tempVar + " = ___");
+ println(helperMethod + "(); break;");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeMethodCallStructCallbackSkeleton() writes method call for wait invoke in skeleton
+ */
+ private void writeMethodCallStructCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("case ");
+ String helperMethod = methodNumId + "struct" + i;
+ String tempVar = "struct" + methodNumId + "Size" + i;
+ print(intDecl.getHelperMethodNumId(helperMethod) + ": ");
+ print(tempVar + " = ___");
+ println(helperMethod + "(rmiObj); break;");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeJavaMethodPermission() writes permission checks in skeleton
+ */
+ private void writeJavaMethodPermission(String intface) {
+
+ // Get all the different stubs
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ println("if (_objectId == object" + newObjectId + "Id) {");
+ println("if (!set" + newObjectId + "Allowed.contains(methodId)) {");
+ println("throw new Error(\"Object with object Id: \" + _objectId + \" is not allowed to access method: \" + methodId);");
+ println("}");
+ println("}");
+ println("else {");
+ println("throw new Error(\"Object Id: \" + _objectId + \" not recognized!\");");
+ println("}");
+ }
+ }
+
+
+ /**
+ * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
+ */
+ private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist, String intface) {
+
+ // Use this set to handle two same methodIds
+ Set<String> uniqueMethodIds = new HashSet<String>();
+ println("private void ___waitRequestInvokeMethod() throws IOException {");
+ // Write variables here if we have callbacks or enums or structs
+ writeCountVarStructSkeleton(methods, intDecl);
+ println("while (true) {");
+ println("rmiObj.getMethodBytes();");
+ println("int _objectId = rmiObj.getObjectId();");
+ println("int methodId = rmiObj.getMethodId();");
+ // Generate permission check
+ writeJavaMethodPermission(intface);
+ println("switch (methodId) {");
+ // Print methods and method Ids
+ for (String method : methods) {
+ String methodId = intDecl.getMethodId(method);
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("case " + methodNumId + ": ___");
+ String helperMethod = methodId;
+ if (uniqueMethodIds.contains(methodId))
+ helperMethod = helperMethod + methodNumId;
+ else
+ uniqueMethodIds.add(methodId);
+ print(helperMethod + "(");
+ writeInputCountVarStructSkeleton(method, intDecl);
+ println("); break;");
+ }
+ String method = "___initCallBack()";
+ // Print case -9999 (callback handler) if callback exists
+ if (callbackExist) {
+ int methodId = intDecl.getHelperMethodNumId(method);
+ println("case " + methodId + ": ___regCB(); break;");
+ }
+ writeMethodCallStructSkeleton(methods, intDecl);
+ println("default: ");
+ println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
+ println("}");
+ println("}");
+ println("}\n");
+ }
+
+
+ /**
+ * generateJavaSkeletonClass() generate skeletons based on the methods list in Java
+ */
+ public void generateJavaSkeletonClass() throws IOException {
+
+ // 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, callbackExist, intDecl);
+ // Write constructor
+ writeConstructorJavaSkeleton(newSkelClass, intface, intDecl, methods, callbackExist);
+ // Write methods
+ writeMethodJavaSkeleton(methods, intDecl, callbackClasses, false);
+ // Write method helper
+ writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses);
+ // Write waitRequestInvokeMethod() - main loop
+ writeJavaWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface);
+ println("}");
+ pw.close();
+ System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java...");
+ }
+ }
+
+
+ /**
+ * HELPER: writePropertiesJavaCallbackSkeleton() writes the properties of the callback skeleton class
+ */
+ private void writePropertiesJavaCallbackSkeleton(String intface, boolean callbackExist) {
+
+ println("private " + intface + " mainObj;");
+ // For callback skeletons, this is its own object Id
+ println("private int objectId = 0;");
+ // Callback
+ if (callbackExist) {
+ println("private static int objIdCnt = 0;");
+ println("private IoTRMICall rmiCall;");
+ }
+ println("\n");
+ }
+
+
+ /**
+ * HELPER: writeConstructorJavaCallbackSkeleton() writes the constructor of the skeleton class
+ */
+ private void writeConstructorJavaCallbackSkeleton(String newSkelClass, String intface, InterfaceDecl intDecl, Collection<String> methods) {
+
+ println("public " + newSkelClass + "(" + intface + " _mainObj, int _objectId) throws Exception {");
+ println("mainObj = _mainObj;");
+ println("objectId = _objectId;");
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperJavaCallbackSkeleton() writes the method helper of the callback skeleton class
+ */
+ private void writeMethodHelperJavaCallbackSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
+
+ // Use this set to handle two same methodIds
+ Set<String> uniqueMethodIds = new HashSet<String>();
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
+ String methodId = intDecl.getMethodId(method);
+ print("public void ___");
+ String helperMethod = methodId;
+ if (uniqueMethodIds.contains(methodId))
+ helperMethod = helperMethod + intDecl.getMethodNumId(method);
+ else
+ uniqueMethodIds.add(methodId);
+ String retType = intDecl.getMethodType(method);
+ print(helperMethod + "(");
+ boolean begin = true;
+ for (int i = 0; i < methParams.size(); i++) { // Print size variables
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ if (!begin) // Generate comma for not the beginning variable
+ print(", ");
+ else
+ begin = false;
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("int struct" + methodNumId + "Size" + i);
+ }
+ }
+ // Check if this is "void"
+ if (retType.equals("void"))
+ println(", IoTRMIObject rmiObj) {");
+ else
+ println(", IoTRMIObject rmiObj) throws IOException {");
+ writeMethodHelperStructJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
+ println("}\n");
+ } else {
+ String methodId = intDecl.getMethodId(method);
+ print("public void ___");
+ String helperMethod = methodId;
+ if (uniqueMethodIds.contains(methodId))
+ helperMethod = helperMethod + intDecl.getMethodNumId(method);
+ else
+ uniqueMethodIds.add(methodId);
+ // Check if this is "void"
+ String retType = intDecl.getMethodType(method);
+ if (retType.equals("void"))
+ println(helperMethod + "(IoTRMIObject rmiObj) {");
+ else
+ println(helperMethod + "(IoTRMIObject rmiObj) throws IOException {");
+ // Now, write the helper body of skeleton!
+ writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses);
+ println("}\n");
+ }
+ }
+ // Write method helper for structs
+ writeMethodHelperStructSetupJavaCallbackSkeleton(methods, intDecl);
+ }
+
+
+ /**
+ * HELPER: writeJavaCallbackWaitRequestInvokeMethod() writes the request invoke method of the callback skeleton class
+ */
+ private void writeJavaCallbackWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist) {
+
+ // Use this set to handle two same methodIds
+ Set<String> uniqueMethodIds = new HashSet<String>();
+ println("public void invokeMethod(IoTRMIObject rmiObj) throws IOException {");
+ // Write variables here if we have callbacks or enums or structs
+ writeCountVarStructSkeleton(methods, intDecl);
+ // Write variables here if we have callbacks or enums or structs
+ println("int methodId = rmiObj.getMethodId();");
+ // TODO: code the permission check here!
+ println("switch (methodId) {");
+ // Print methods and method Ids
+ for (String method : methods) {
+ String methodId = intDecl.getMethodId(method);
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("case " + methodNumId + ": ___");
+ String helperMethod = methodId;
+ if (uniqueMethodIds.contains(methodId))
+ helperMethod = helperMethod + methodNumId;
+ else
+ uniqueMethodIds.add(methodId);
+ print(helperMethod + "(");
+ if (writeInputCountVarStructSkeleton(method, intDecl))
+ println(", rmiObj); break;");
+ else
+ println("rmiObj); break;");
+ }
+ String method = "___initCallBack()";
+ // Print case -9999 (callback handler) if callback exists
+ if (callbackExist) {
+ int methodId = intDecl.getHelperMethodNumId(method);
+ println("case " + methodId + ": ___regCB(rmiObj); break;");
+ }
+ writeMethodCallStructCallbackSkeleton(methods, intDecl);
+ println("default: ");
+ println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");");
+ println("}");
+ println("}\n");
+ }
+
+
+ /**
+ * generateJavaCallbackSkeletonClass() generate callback skeletons based on the methods list in Java
+ */
+ public void generateJavaCallbackSkeletonClass() throws IOException {
+
+ // Create a new directory
+ String path = createDirectories(dir, subdir);
+ for (String intface : mapIntfacePTH.keySet()) {
+ // Open a new file to write into
+ String newSkelClass = intface + "_CallbackSkeleton";
+ 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
+ writePropertiesJavaCallbackSkeleton(intface, callbackExist);
+ // Write constructor
+ writeConstructorJavaCallbackSkeleton(newSkelClass, intface, intDecl, methods);
+ // Write methods
+ writeMethodJavaSkeleton(methods, intDecl, callbackClasses, true);
+ // Write method helper
+ writeMethodHelperJavaCallbackSkeleton(methods, intDecl, callbackClasses);
+ // Write waitRequestInvokeMethod() - main loop
+ writeJavaCallbackWaitRequestInvokeMethod(methods, intDecl, callbackExist);
+ println("}");
+ pw.close();
+ System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".java...");
+ }
+ }
+
+
+ /**
+ * HELPER: writeMethodCplusLocalInterface() writes the method of the local interface
+ */
+ private void writeMethodCplusLocalInterface(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));
+ paramType = checkAndGetCplusType(paramType);
+ // 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(", ");
+ }
+ }
+ println(") = 0;");
+ }
+ }
+
+
+ /**
+ * 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 = methPrmTypes.get(i);
+ paramType = checkAndGetCplusType(paramType);
+ // 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(", ");
+ }
+ }
+ println(") = 0;");
+ }
+ }
+
+
+ /**
+ * HELPER: generateEnumCplus() writes the enumeration declaration
+ */
+ public void generateEnumCplus() throws IOException {
+
+ // Create a new directory
+ createDirectory(dir);
+ for (String intface : mapIntfacePTH.keySet()) {
+ // Get the right StructDecl
+ DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+ EnumDecl enumDecl = (EnumDecl) decHandler.getEnumDecl(intface);
+ Set<String> enumTypes = enumDecl.getEnumDeclarations();
+ // Iterate over enum declarations
+ for (String enType : enumTypes) {
+ // Open a new file to write into
+ FileWriter fw = new FileWriter(dir + "/" + enType + ".hpp");
+ pw = new PrintWriter(new BufferedWriter(fw));
+ // Write file headers
+ println("#ifndef _" + enType.toUpperCase() + "_HPP__");
+ println("#define _" + enType.toUpperCase() + "_HPP__");
+ println("enum " + enType + " {");
+ List<String> enumMembers = enumDecl.getMembers(enType);
+ for (int i = 0; i < enumMembers.size(); i++) {
+
+ String member = enumMembers.get(i);
+ print(member);
+ // Check if this is the last element (don't print a comma)
+ if (i != enumMembers.size() - 1)
+ println(",");
+ else
+ println("");
+ }
+ println("};\n");
+ println("#endif");
+ pw.close();
+ System.out.println("IoTCompiler: Generated enum " + enType + ".hpp...");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: generateStructCplus() writes the struct declaration
+ */
+ public void generateStructCplus() throws IOException {
+
+ // Create a new directory
+ createDirectory(dir);
+ for (String intface : mapIntfacePTH.keySet()) {
+ // Get the right StructDecl
+ DeclarationHandler decHandler = mapIntDeclHand.get(intface);
+ StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface);
+ List<String> structTypes = structDecl.getStructTypes();
+ // Iterate over enum declarations
+ for (String stType : structTypes) {
+ // Open a new file to write into
+ FileWriter fw = new FileWriter(dir + "/" + stType + ".hpp");
+ pw = new PrintWriter(new BufferedWriter(fw));
+ // Write file headers
+ println("#ifndef _" + stType.toUpperCase() + "_HPP__");
+ println("#define _" + stType.toUpperCase() + "_HPP__");
+ println("using namespace std;");
+ println("struct " + stType + " {");
+ List<String> structMemberTypes = structDecl.getMemberTypes(stType);
+ List<String> structMembers = structDecl.getMembers(stType);
+ for (int i = 0; i < structMembers.size(); i++) {
+
+ String memberType = structMemberTypes.get(i);
+ String member = structMembers.get(i);
+ String structTypeC = checkAndGetCplusType(memberType);
+ String structComplete = checkAndGetCplusArray(structTypeC, member);
+ println(structComplete + ";");
+ }
+ println("};\n");
+ println("#endif");
+ pw.close();
+ System.out.println("IoTCompiler: Generated struct " + stType + ".hpp...");
+ }
+ }
+ }
+
+
+ /**
+ * 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 generateCplusLocalInterfaces() throws IOException {
+
+ // Create a new directory
+ createDirectory(dir);
+ for (String intface : mapIntfacePTH.keySet()) {
+ // Open a new file to write into
+ FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
+ pw = new PrintWriter(new BufferedWriter(fw));
+ // 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, intface, true);
+ printIncludeStatements(includeClasses); println("");
+ println("using namespace std;\n");
+ //writeStructCplus(structDecl);
+ println("class " + intface); println("{");
+ println("public:");
+ // Write methods
+ writeMethodCplusLocalInterface(methods, intDecl);
+ println("};");
+ println("#endif");
+ pw.close();
+ System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
+ }
+ }
+
+
+ /**
+ * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
+ * <p>
+ * For C++ we use virtual classe as interface
+ */
+ public void generateCPlusInterfaces() 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 + ".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, intface, false);
+ List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
+ List<String> allIncludeClasses = getAllLibClasses(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...");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeMethodCplusStub() writes the methods of the stub
+ */
+ private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
+
+ boolean isDefined = false;
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " +
+ intDecl.getMethodId(method) + "(");
+ boolean isCallbackMethod = false;
+ String callbackType = null;
+ for (int i = 0; i < methParams.size(); i++) {
+
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ // Check if this has callback object
+ if (callbackClasses.contains(paramType)) {
+ isCallbackMethod = true;
+ callbackType = paramType;
+ // Even if there're 2 callback arguments, we expect them to be of the same interface
+ }
+ 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(") { ");
+ if (isCallbackMethod)
+ writeCallbackMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType);
+ writeStdMethodBodyCplusStub(intDecl, methParams, methPrmTypes, method, callbackType, isCallbackMethod);
+ println("}\n");
+ // Write the init callback helper method
+ if (isCallbackMethod && !isDefined) {
+ writeInitCallbackCplusStub(callbackType, intDecl);
+ writeInitCallbackSendInfoCplusStub(intDecl);
+ isDefined = true;
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeCallbackMethodBodyCplusStub() writes the callback method of the stub class
+ */
+ private void writeCallbackMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, String callbackType) {
+
+ // Check if this is single object, array, or list of objects
+ boolean isArrayOrList = false;
+ String callbackParam = null;
+ for (int i = 0; i < methParams.size(); i++) {
+
+ String paramType = methPrmTypes.get(i);
+ if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+ String param = methParams.get(i);
+ if (isArrayOrList(paramType, param)) { // Generate loop
+ println("for (" + getGenericType(paramType) + "* cb : " + getSimpleIdentifier(param) + ") {");
+ println(callbackType + "_CallbackSkeleton* skel" + i + " = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);");
+ isArrayOrList = true;
+ callbackParam = getSimpleIdentifier(param);
+ } else
+ println(callbackType + "_CallbackSkeleton* skel" + i + " = new " + callbackType + "_CallbackSkeleton(" +
+ getSimpleIdentifier(param) + ", objIdCnt++);");
+ println("vecCallbackObj.push_back(skel" + i + ");");
+ if (isArrayOrList)
+ println("}");
+ print("int ___paramCB" + i + " = ");
+ if (isArrayOrList)
+ println(callbackParam + ".size();");
+ else
+ println("1;");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteEnumTypeCplusStub() writes the enum type (convert from enum to int)
+ */
+ private void checkAndWriteEnumTypeCplusStub(List<String> methParams, List<String> methPrmTypes) {
+
+ // Iterate and find enum declarations
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ if (isEnumClass(getGenericType(paramType))) {
+ // Check if this is enum type
+ if (isArrayOrList(paramType, param)) { // An array or vector
+ println("int len" + i + " = " + getSimpleIdentifier(param) + ".size();");
+ println("vector<int> paramEnum" + i + "(len" + i + ");");
+ println("for (int i = 0; i < len" + i + "; i++) {");
+ println("paramEnum" + i + "[i] = (int) " + getSimpleIdentifier(param) + "[i];");
+ println("}");
+ } else { // Just one element
+ println("vector<int> paramEnum" + i + "(1);");
+ println("paramEnum" + i + "[0] = (int) " + param + ";");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteEnumRetTypeCplusStub() writes the enum return type (convert from enum to int)
+ */
+ private void checkAndWriteEnumRetTypeCplusStub(String retType) {
+
+ // Strips off array "[]" for return type
+ String pureType = getSimpleArrayType(getGenericType(retType));
+ // Take the inner type of generic
+ if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
+ pureType = getGenericType(retType);
+ if (isEnumClass(pureType)) {
+ // Check if this is enum type
+ println("vector<int> retEnumInt;");
+ println("void* retObj = &retEnumInt;");
+ println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
+ if (isArrayOrList(retType, retType)) { // An array or vector
+ println("int retLen = retEnumInt.size();");
+ println("vector<" + pureType + "> retVal(retLen);");
+ println("for (int i = 0; i < retLen; i++) {");
+ println("retVal[i] = (" + pureType + ") retEnumInt[i];");
+ println("}");
+ } else { // Just one element
+ println(pureType + " retVal = (" + pureType + ") retEnumInt[0];");
+ }
+ println("return retVal;");
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteStructSetupCplusStub() writes the struct type setup
+ */
+ private void checkAndWriteStructSetupCplusStub(List<String> methParams, List<String> methPrmTypes,
+ InterfaceDecl intDecl, String method) {
+
+ // Iterate and find struct declarations
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ // Check if this is enum type
+ println("int numParam" + i + " = 1;");
+ int methodNumId = intDecl.getMethodNumId(method);
+ String helperMethod = methodNumId + "struct" + i;
+ println("int methodIdStruct" + i + " = " + intDecl.getHelperMethodNumId(helperMethod) + ";");
+ println("string retTypeStruct" + i + " = \"void\";");
+ println("string paramClsStruct" + i + "[] = { \"int\" };");
+ print("int structLen" + i + " = ");
+ if (isArrayOrList(paramType, param)) { // An array
+ println(getSimpleArrayType(param) + ".size();");
+ } else { // Just one element
+ println("1;");
+ }
+ println("void* paramObjStruct" + i + "[] = { &structLen" + i + " };");
+ println("void* retStructLen" + i + " = NULL;");
+ println("rmiCall->remoteCall(objectId, methodIdStruct" + i +
+ ", retTypeStruct" + i + ", paramClsStruct" + i + ", paramObjStruct" + i +
+ ", numParam" + i + ", retStructLen" + i + ");\n");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeLengthStructParamClassCplusStub() writes lengths of params
+ */
+ private void writeLengthStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes) {
+
+ // Iterate and find struct declarations - count number of params
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int members = getNumOfMembers(simpleType);
+ if (isArrayOrList(paramType, param)) { // An array or list
+ String structLen = getSimpleIdentifier(param) + ".size()";
+ print(members + "*" + structLen);
+ } else
+ print(Integer.toString(members));
+ } else
+ print("1");
+ if (i != methParams.size() - 1) {
+ print("+");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructMembersCplusStub() writes member parameters of struct
+ */
+ private void writeStructMembersCplusStub(String simpleType, String paramType, String param) {
+
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ if (isArrayOrList(paramType, param)) { // An array or list
+ println("for(int i = 0; i < " + getSimpleIdentifier(param) + ".size(); i++) {");
+ }
+ if (isArrayOrList(paramType, param)) { // An array or list
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("paramCls[pos] = \"" + prmTypeC + "\";");
+ print("paramObj[pos++] = &" + getSimpleIdentifier(param) + "[i].");
+ print(getSimpleIdentifier(members.get(i)));
+ println(";");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("paramCls[pos] = \"" + prmTypeC + "\";");
+ print("paramObj[pos++] = &" + param + ".");
+ print(getSimpleIdentifier(members.get(i)));
+ println(";");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructParamClassCplusStub() writes member parameters of struct
+ */
+ private void writeStructParamClassCplusStub(List<String> methParams, List<String> methPrmTypes, String callbackType) {
+
+ print("int numParam = ");
+ writeLengthStructParamClassCplusStub(methParams, methPrmTypes);
+ println(";");
+ println("void* paramObj[numParam];");
+ println("string paramCls[numParam];");
+ println("int pos = 0;");
+ // Iterate again over the parameters
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ writeStructMembersCplusStub(simpleType, paramType, param);
+ } else if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+ println("paramCls[pos] = \"int\";");
+ println("paramObj[pos++] = &___paramCB" + i + ";");
+ } else {
+ String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
+ println("paramCls[pos] = \"" + prmTypeC + "\";");
+ print("paramObj[pos++] = &");
+ print(getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), i));
+ println(";");
+ }
+ }
+
+ }
+
+
+ /**
+ * HELPER: writeStructRetMembersCplusStub() writes member parameters of struct for return statement
+ */
+ private void writeStructRetMembersCplusStub(String simpleType, String retType) {
+
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ if (isArrayOrList(retType, retType)) { // An array or list
+ println("for(int i = 0; i < retLen; i++) {");
+ }
+ if (isArrayOrList(retType, retType)) { // An array or list
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ print("structRet[i]." + getSimpleIdentifier(members.get(i)));
+ println(" = retParam" + i + "[i];");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmType = checkAndGetArray(memTypes.get(i), members.get(i));
+ print("structRet." + getSimpleIdentifier(members.get(i)));
+ println(" = retParam" + i + ";");
+ }
+ }
+ println("return structRet;");
+ }
+
+
+ /**
+ * HELPER: writeStructReturnCplusStub() writes member parameters of struct for return statement
+ */
+ private void writeStructReturnCplusStub(String simpleType, String retType) {
+
+ // Minimum retLen is 1 if this is a single struct object
+ println("int retLen = 0;");
+ println("void* retLenObj = { &retLen };");
+ // Handle the returned struct!!!
+ println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retLenObj);");
+ int numMem = getNumOfMembers(simpleType);
+ println("int numRet = " + numMem + "*retLen;");
+ println("string retCls[numRet];");
+ println("void* retObj[numRet];");
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ // Set up variables
+ if (isArrayOrList(retType, retType)) { // An array or list
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusType(memTypes.get(i));
+ String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
+ println(getSimpleType(getEnumType(prmType)) + " retParam" + i + "[retLen];");
+ }
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusType(memTypes.get(i));
+ String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
+ println(getSimpleType(getEnumType(prmType)) + " retParam" + i + ";");
+ }
+ }
+ println("int retPos = 0;");
+ // Get the struct declaration for this struct and generate initialization code
+ if (isArrayOrList(retType, retType)) { // An array or list
+ println("for(int i = 0; i < retLen; i++) {");
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = \"" + prmTypeC + "\";");
+ println("retObj[retPos++] = &retParam" + i + "[i];");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = \"" + prmTypeC + "\";");
+ println("retObj[retPos++] = &retParam" + i + ";");
+ }
+ }
+ println("rmiCall->getStructObjects(retCls, numRet, retObj);");
+ if (isArrayOrList(retType, retType)) { // An array or list
+ println("vector<" + simpleType + "> structRet(retLen);");
+ } else
+ println(simpleType + " structRet;");
+ writeStructRetMembersCplusStub(simpleType, retType);
+ }
+
+
+ /**
+ * HELPER: writeStdMethodBodyCplusStub() writes the standard method body in the stub class
+ */
+ private void writeStdMethodBodyCplusStub(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, String callbackType, boolean isCallbackMethod) {
+
+ checkAndWriteStructSetupCplusStub(methParams, methPrmTypes, intDecl, method);
+ println("int methodId = " + intDecl.getMethodNumId(method) + ";");
+ String retType = intDecl.getMethodType(method);
+ println("string retType = \"" + checkAndGetCplusRetClsType(getStructType(getEnumType(retType))) + "\";");
+ checkAndWriteEnumTypeCplusStub(methParams, methPrmTypes);
+ // Generate array of parameter types
+ if (isStructPresent(methParams, methPrmTypes)) {
+ writeStructParamClassCplusStub(methParams, methPrmTypes, callbackType);
+ } else {
+ println("int numParam = " + methParams.size() + ";");
+ print("string paramCls[] = { ");
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (checkCallbackType(paramType, callbackType)) {
+ print("\"int\"");
+ } else {
+ String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
+ print("\"" + paramTypeC + "\"");
+ }
+ // 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++) {
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
+ print("&___paramCB" + i);
+ else
+ print("&" + getEnumParam(methPrmTypes.get(i), getSimpleIdentifier(methParams.get(i)), 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
+ // Generate array of parameter types
+ if (isStructClass(getGenericType(getSimpleArrayType(retType)))) {
+ writeStructReturnCplusStub(getGenericType(getSimpleArrayType(retType)), retType);
+ } else {
+ // Check if the return value NONPRIMITIVES
+ if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) {
+ checkAndWriteEnumRetTypeCplusStub(retType);
+ } else {
+ //if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
+ if (isArrayOrList(retType,retType))
+ 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 writePropertiesCplusPermission(String intface) {
+
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ println("const static int object" + newObjectId + "Id = " + newObjectId + ";\t//" + newIntface);
+ println("static set<int> set" + newObjectId + "Allowed;");
+ }
+ }
+
+ /**
+ * HELPER: writePropertiesCplusStub() writes the properties of the stub class
+ */
+ private void writePropertiesCplusStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
+
+ println("IoTRMICall *rmiCall;");
+ println("string callbackAddress;");
+ println("vector<int> ports;\n");
+ // Get the object Id
+ Integer objId = mapIntfaceObjId.get(intface);
+ println("const static int objectId = " + objId + ";");
+ mapNewIntfaceObjId.put(newIntface, objId);
+ mapIntfaceObjId.put(intface, objId++);
+ if (callbackExist) {
+ // We assume that each class only has one callback interface for now
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ println("// Callback properties");
+ println("IoTRMIObject *rmiObj;");
+ println("vector<" + callbackType + "*> vecCallbackObj;");
+ println("static int objIdCnt;");
+ // Generate permission stuff for callback stubs
+ writePropertiesCplusPermission(callbackType);
+ }
+ println("\n");
+ }
+
+
+ /**
+ * HELPER: writeConstructorCplusStub() writes the constructor of the stub class
+ */
+ private void writeConstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
+
+ println(newStubClass +
+ "(int _port, const char* _skeletonAddress, const char* _callbackAddress, int _rev, bool* _bResult, vector<int> _ports) {");
+ println("callbackAddress = _callbackAddress;");
+ println("ports = _ports;");
+ println("rmiCall = new IoTRMICall(_port, _skeletonAddress, _rev, _bResult);");
+ if (callbackExist) {
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ println("thread th1 (&" + newStubClass + "::___initCallBack, this);");
+ println("th1.detach();");
+ println("___regCB();");
+ }
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
+ */
+ private void writeDeconstructorCplusStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
+
+ println("~" + newStubClass + "() {");
+ println("if (rmiCall != NULL) {");
+ println("delete rmiCall;");
+ println("rmiCall = NULL;");
+ println("}");
+ if (callbackExist) {
+ // We assume that each class only has one callback interface for now
+ println("if (rmiObj != NULL) {");
+ println("delete rmiObj;");
+ println("rmiObj = NULL;");
+ println("}");
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ println("for(" + callbackType + "* cb : vecCallbackObj) {");
+ println("delete cb;");
+ println("cb = NULL;");
+ println("}");
+ }
+ println("}");
+ println("");
+ }
+
+
+ /**
+ * HELPER: writeCplusMethodCallbackPermission() writes permission checks in stub for callbacks
+ */
+ private void writeCplusMethodCallbackPermission(String intface) {
+
+ println("int methodId = IoTRMIObject::getMethodId(method);");
+ // Get all the different stubs
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
+ println("cerr << \"Callback object for " + intface + " is not allowed to access method: \" << methodId;");
+ println("return;");
+ println("}");
+ }
+ }
+
+
+ /**
+ * HELPER: writeInitCallbackCplusStub() writes the initialization of callback
+ */
+ private void writeInitCallbackCplusStub(String intface, InterfaceDecl intDecl) {
+
+ println("void ___initCallBack() {");
+ println("bool bResult = false;");
+ println("rmiObj = new IoTRMIObject(ports[0], &bResult);");
+ println("while (true) {");
+ println("char* method = rmiObj->getMethodBytes();");
+ writeCplusMethodCallbackPermission(intface);
+ println("int objId = IoTRMIObject::getObjectId(method);");
+ println("if (objId < vecCallbackObj.size()) { // Check if still within range");
+ println(intface + "_CallbackSkeleton* skel = dynamic_cast<" + intface +
+ "_CallbackSkeleton*> (vecCallbackObj.at(objId));");
+ println("skel->invokeMethod(rmiObj);");
+ print("}");
+ println(" else {");
+ println("cerr << \"Illegal object Id: \" << to_string(objId);");
+ // TODO: perhaps need to change this into "throw" to make it cleaner (allow stack unfolding)
+ println("return;");
+ println("}");
+ println("}");
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeCplusInitCallbackPermission() writes the permission for callback
+ */
+ private void writeCplusInitCallbackPermission(String intface, InterfaceDecl intDecl, boolean callbackExist) {
+
+ if (callbackExist) {
+ String method = "___initCallBack()";
+ int methodNumId = intDecl.getHelperMethodNumId(method);
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ println("set" + newObjectId + "Allowed.insert(" + methodNumId + ");");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeInitCallbackSendInfoCplusStub() writes the initialization (send info part) of callback
+ */
+ private void writeInitCallbackSendInfoCplusStub(InterfaceDecl intDecl) {
+
+ // Generate info sending part
+ println("void ___regCB() {");
+ println("int numParam = 3;");
+ String method = "___initCallBack()";
+ int methodNumId = intDecl.getHelperMethodNumId(method);
+ println("int methodId = " + methodNumId + ";");
+ println("string retType = \"void\";");
+ println("string paramCls[] = { \"int\", \"String\", \"int\" };");
+ println("int rev = 0;");
+ println("void* paramObj[] = { &ports[0], &callbackAddress, &rev };");
+ println("void* retObj = NULL;");
+ println("rmiCall->remoteCall(objectId, methodId, retType, paramCls, paramObj, numParam, retObj);");
+ println("}\n");
+ }
+
+
+ /**
+ * generateCPlusStubClasses() generate stubs based on the methods list in C++
+ */
+ public void generateCPlusStubClasses() 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 + ".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();
+ if (callbackExist) // Need thread library if this has callback
+ println("#include <thread>");
+ println("#include \"" + newIntface + ".hpp\""); println("");
+ println("using namespace std;"); println("");
+ println("class " + newStubClass + " : public " + newIntface); println("{");
+ println("private:\n");
+ writePropertiesCplusStub(intface, newIntface, callbackExist, callbackClasses);
+ println("public:\n");
+ // Add default constructor and destructor
+ println(newStubClass + "() { }"); println("");
+ writeConstructorCplusStub(newStubClass, callbackExist, callbackClasses);
+ writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
+ // Write methods
+ writeMethodCplusStub(methods, intDecl, callbackClasses);
+ print("}"); println(";");
+ if (callbackExist) {
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ // Generate permission stuff for callback stubs
+ DeclarationHandler decHandlerCallback = mapIntDeclHand.get(callbackType);
+ InterfaceDecl intDeclCallback = (InterfaceDecl) decHandlerCallback.getInterfaceDecl(callbackType);
+ writePermissionInitializationCplus(callbackType, newStubClass, intDeclCallback);
+ }
+ writeObjectIdCountInitializationCplus(newStubClass, callbackExist);
+ println("#endif");
+ pw.close();
+ System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".hpp...");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writePropertiesCplusCallbackStub() writes the properties of the stub class
+ */
+ private void writePropertiesCplusCallbackStub(String intface, String newIntface, boolean callbackExist, Set<String> callbackClasses) {
+
+ println("IoTRMICall *rmiCall;");
+ // Get the object Id
+ println("int objectId;");
+ if (callbackExist) {
+ // We assume that each class only has one callback interface for now
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ println("// Callback properties");
+ println("IoTRMIObject *rmiObj;");
+ println("vector<" + callbackType + "*> vecCallbackObj;");
+ println("static int objIdCnt;");
+ // TODO: Need to initialize address and ports if we want to have callback-in-callback
+ println("string address;");
+ println("vector<int> ports;\n");
+ writePropertiesCplusPermission(callbackType);
+ }
+ println("\n");
+ }
+
+
+ /**
+ * HELPER: writeConstructorCplusCallbackStub() writes the constructor of the stub class
+ */
+ private void writeConstructorCplusCallbackStub(String newStubClass, boolean callbackExist, Set<String> callbackClasses) {
+
+ println(newStubClass + "(IoTRMICall* _rmiCall, int _objectId) {");
+ println("objectId = _objectId;");
+ println("rmiCall = _rmiCall;");
+ if (callbackExist) {
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ println("thread th1 (&" + newStubClass + "::___initCallBack, this);");
+ println("th1.detach();");
+ println("___regCB();");
+ }
+ println("}\n");
+ }
+
+
+ /**
+ * generateCPlusCallbackStubClasses() generate callback stubs based on the methods list in C++
+ */
+ public void generateCPlusCallbackStubClasses() 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 + "_CallbackStub";
+ FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
+ pw = new PrintWriter(new BufferedWriter(fw));
+ // 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();
+ // Write file headers
+ println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
+ println("#define _" + newStubClass.toUpperCase() + "_HPP__");
+ println("#include <iostream>");
+ if (callbackExist)
+ println("#include <thread>");
+ println("#include \"" + newIntface + ".hpp\""); println("");
+ println("using namespace std;"); println("");
+ println("class " + newStubClass + " : public " + newIntface); println("{");
+ println("private:\n");
+ writePropertiesCplusCallbackStub(intface, newIntface, callbackExist, callbackClasses);
+ println("public:\n");
+ // Add default constructor and destructor
+ println(newStubClass + "() { }"); println("");
+ writeConstructorCplusCallbackStub(newStubClass, callbackExist, callbackClasses);
+ writeDeconstructorCplusStub(newStubClass, callbackExist, callbackClasses);
+ // Write methods
+ writeMethodCplusStub(methods, intDecl, callbackClasses);
+ println("};");
+ if (callbackExist) {
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ // Generate permission stuff for callback stubs
+ DeclarationHandler decHandlerCallback = mapIntDeclHand.get(callbackType);
+ InterfaceDecl intDeclCallback = (InterfaceDecl) decHandlerCallback.getInterfaceDecl(callbackType);
+ writePermissionInitializationCplus(callbackType, newStubClass, intDeclCallback);
+ }
+ writeObjectIdCountInitializationCplus(newStubClass, callbackExist);
+ println("#endif");
+ pw.close();
+ System.out.println("IoTCompiler: Generated callback stub class " + newIntface + ".hpp...");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class
+ */
+ private void writePropertiesCplusSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
+
+ println(intface + " *mainObj;");
+ // Callback
+ if (callbackExist) {
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ String exchangeType = checkAndGetParamClass(callbackType);
+ println("// Callback properties");
+ println("static int objIdCnt;");
+ println("vector<" + exchangeType + "*> vecCallbackObj;");
+ println("IoTRMICall *rmiCall;");
+ }
+ println("IoTRMIObject *rmiObj;\n");
+ // Keep track of object Ids of all stubs registered to this interface
+ writePropertiesCplusPermission(intface);
+ println("\n");
+ }
+
+
+ /**
+ * HELPER: writeObjectIdCountInitializationCplus() writes the initialization of objIdCnt variable
+ */
+ private void writeObjectIdCountInitializationCplus(String newSkelClass, boolean callbackExist) {
+
+ if (callbackExist)
+ println("int " + newSkelClass + "::objIdCnt = 0;");
+ }
+
+
+ /**
+ * HELPER: writePermissionInitializationCplus() writes the initialization of permission set
+ */
+ private void writePermissionInitializationCplus(String intface, String newSkelClass, InterfaceDecl intDecl) {
+
+ // Keep track of object Ids of all stubs registered to this interface
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ print("set<int> " + newSkelClass + "::set" + newObjectId + "Allowed { ");
+ Set<String> methodIds = intMeth.getValue();
+ int i = 0;
+ for (String methodId : methodIds) {
+ int methodNumId = intDecl.getMethodNumId(methodId);
+ print(Integer.toString(methodNumId));
+ // Check if this is the last element (don't print a comma)
+ if (i != methodIds.size() - 1) {
+ print(", ");
+ }
+ i++;
+ }
+ println(" };");
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructPermissionCplusSkeleton() writes permission for struct helper
+ */
+ private void writeStructPermissionCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, String intface) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ String helperMethod = methodNumId + "struct" + i;
+ int helperMethodNumId = intDecl.getHelperMethodNumId(helperMethod);
+ // Iterate over interfaces to give permissions to
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ println("set" + newObjectId + "Allowed.insert(" + helperMethodNumId + ");");
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeConstructorCplusSkeleton() writes the constructor of the skeleton class
+ */
+ private void writeConstructorCplusSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
+
+ println(newSkelClass + "(" + intface + " *_mainObj, int _port) {");
+ println("bool _bResult = false;");
+ println("mainObj = _mainObj;");
+ println("rmiObj = new IoTRMIObject(_port, &_bResult);");
+ writeCplusInitCallbackPermission(intface, intDecl, callbackExist);
+ writeStructPermissionCplusSkeleton(methods, intDecl, intface);
+ println("___waitRequestInvokeMethod();");
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeDeconstructorCplusSkeleton() writes the deconstructor of the skeleton class
+ */
+ private void writeDeconstructorCplusSkeleton(String newSkelClass, boolean callbackExist, Set<String> callbackClasses) {
+
+ println("~" + newSkelClass + "() {");
+ println("if (rmiObj != NULL) {");
+ println("delete rmiObj;");
+ println("rmiObj = NULL;");
+ println("}");
+ if (callbackExist) {
+ // We assume that each class only has one callback interface for now
+ println("if (rmiCall != NULL) {");
+ println("delete rmiCall;");
+ println("rmiCall = NULL;");
+ println("}");
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ String exchangeType = checkAndGetParamClass(callbackType);
+ println("for(" + exchangeType + "* cb : vecCallbackObj) {");
+ println("delete cb;");
+ println("cb = NULL;");
+ println("}");
+ }
+ println("}");
+ println("");
+ }
+
+
+ /**
+ * HELPER: writeStdMethodBodyCplusSkeleton() writes the standard method body in the skeleton class
+ */
+ private void writeStdMethodBodyCplusSkeleton(List<String> methParams, String methodId, String methodType) {
+
+ if (methodType.equals("void"))
+ print("mainObj->" + methodId + "(");
+ else
+ print("return mainObj->" + methodId + "(");
+ 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(");");
+ }
+
+
+ /**
+ * HELPER: writeInitCallbackCplusSkeleton() writes the init callback method for skeleton class
+ */
+ private void writeInitCallbackCplusSkeleton(boolean callbackSkeleton) {
+
+ // This is a callback skeleton generation
+ if (callbackSkeleton)
+ println("void ___regCB(IoTRMIObject* rmiObj) {");
+ else
+ println("void ___regCB() {");
+ println("int numParam = 3;");
+ println("int param1 = 0;");
+ println("string param2 = \"\";");
+ println("int param3 = 0;");
+ println("string paramCls[] = { \"int\", \"String\", \"int\" };");
+ println("void* paramObj[] = { ¶m1, ¶m2, ¶m3 };");
+ println("rmiObj->getMethodParams(paramCls, numParam, paramObj);");
+ println("bool bResult = false;");
+ println("rmiCall = new IoTRMICall(param1, param2.c_str(), param3, &bResult);");
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeMethodCplusSkeleton() writes the method of the skeleton class
+ */
+ private void writeMethodCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl,
+ Set<String> callbackClasses, boolean callbackSkeleton) {
+
+ boolean isDefined = false;
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ String methodId = intDecl.getMethodId(method);
+ String methodType = checkAndGetCplusType(intDecl.getMethodType(method));
+ print(methodType + " " + methodId + "(");
+ boolean isCallbackMethod = false;
+ String callbackType = null;
+ for (int i = 0; i < methParams.size(); i++) {
+
+ String origParamType = methPrmTypes.get(i);
+ if (callbackClasses.contains(origParamType)) { // Check if this has callback object
+ isCallbackMethod = true;
+ callbackType = origParamType;
+ }
+ String paramType = checkAndGetParamClass(methPrmTypes.get(i));
+ String methPrmType = checkAndGetCplusType(paramType);
+ 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(") {");
+ // Now, write the body of skeleton!
+ writeStdMethodBodyCplusSkeleton(methParams, methodId, intDecl.getMethodType(method));
+ println("}\n");
+ if (isCallbackMethod && !isDefined) {
+ writeInitCallbackCplusSkeleton(callbackSkeleton);
+ isDefined = true;
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeCallbackCplusNumStubs() writes the numStubs variable
+ */
+ private void writeCallbackCplusNumStubs(List<String> methParams, List<String> methPrmTypes, String callbackType) {
+
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ //if (callbackType.equals(paramType)) {
+ if (checkCallbackType(paramType, callbackType)) // Check if this has callback object
+ println("int numStubs" + i + " = 0;");
+ }
+ }
+
+
+ /**
+ * HELPER: writeCallbackCplusStubGeneration() writes the callback stub generation part
+ */
+ private void writeCallbackCplusStubGeneration(List<String> methParams, List<String> methPrmTypes, String callbackType) {
+
+ // Iterate over callback objects
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ // Generate a loop if needed
+ if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object
+ String exchParamType = checkAndGetParamClass(getGenericType(paramType));
+ if (isArrayOrList(paramType, param)) {
+ println("vector<" + exchParamType + "*> stub" + i + ";");
+ println("for (int objId = 0; objId < numStubs" + i + "; objId++) {");
+ println(exchParamType + "* cb" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
+ println("stub" + i + ".push_back(cb" + i + ");");
+ println("vecCallbackObj.push_back(cb" + i + ");");
+ println("objIdCnt++;");
+ println("}");
+ } else {
+ println(exchParamType + "* stub" + i + " = new " + exchParamType + "_CallbackStub(rmiCall, objIdCnt);");
+ println("vecCallbackObj.push_back(stub" + i + ");");
+ println("objIdCnt++;");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteEnumTypeCplusSkeleton() writes the enum type (convert from enum to int)
+ */
+ private void checkAndWriteEnumTypeCplusSkeleton(List<String> methParams, List<String> methPrmTypes) {
+
+ // Iterate and find enum declarations
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isEnumClass(simpleType)) {
+ // Check if this is enum type
+ if (isArrayOrList(paramType, param)) { // An array
+ println("int len" + i + " = paramEnumInt" + i + ".size();");
+ println("vector<" + simpleType + "> paramEnum" + i + "(len" + i + ");");
+ println("for (int i=0; i < len" + i + "; i++) {");
+ println("paramEnum" + i + "[i] = (" + simpleType + ") paramEnumInt" + i + "[i];");
+ println("}");
+ } else { // Just one element
+ println(simpleType + " paramEnum" + i + ";");
+ println("paramEnum" + i + " = (" + simpleType + ") paramEnumInt" + i + "[0];");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: checkAndWriteEnumRetTypeCplusSkeleton() writes the enum return type (convert from enum to int)
+ */
+ private void checkAndWriteEnumRetTypeCplusSkeleton(String retType) {
+
+ // Strips off array "[]" for return type
+ String pureType = getSimpleArrayType(getGenericType(retType));
+ // Take the inner type of generic
+ if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES)
+ pureType = getGenericType(retType);
+ if (isEnumClass(pureType)) {
+ // Check if this is enum type
+ // Enum decoder
+ if (isArrayOrList(retType, retType)) { // An array
+ println("int retLen = retEnum.size();");
+ println("vector<int> retEnumInt(retLen);");
+ println("for (int i=0; i < retLen; i++) {");
+ println("retEnumInt[i] = (int) retEnum[i];");
+ println("}");
+ } else { // Just one element
+ println("vector<int> retEnumInt(1);");
+ println("retEnumInt[0] = (int) retEnum;");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeMethodInputParameters() writes the parameter variables for C++ skeleton
+ */
+ private void writeMethodInputParameters(List<String> methParams, List<String> methPrmTypes,
+ Set<String> callbackClasses, String methodId) {
+
+ print(methodId + "(");
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (callbackClasses.contains(paramType))
+ print("stub" + i);
+ else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
+ print("paramEnum" + i);
+ else if (isStructClass(getGenericType(paramType))) // Struct type
+ print("paramStruct" + i);
+ else
+ print(getSimpleIdentifier(methParams.get(i)));
+ if (i != methParams.size() - 1) {
+ print(", ");
+ }
+ }
+ println(");");
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperReturnCplusSkeleton() writes the return statement part in skeleton
+ */
+ private void writeMethodHelperReturnCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, boolean isCallbackMethod, String callbackType,
+ String methodId, Set<String> callbackClasses) {
+
+ println("rmiObj->getMethodParams(paramCls, numParam, paramObj);");
+ if (isCallbackMethod)
+ writeCallbackCplusStubGeneration(methParams, methPrmTypes, callbackType);
+ checkAndWriteEnumTypeCplusSkeleton(methParams, methPrmTypes);
+ writeStructMembersInitCplusSkeleton(intDecl, methParams, methPrmTypes, method);
+ // Check if this is "void"
+ String retType = intDecl.getMethodType(method);
+ // Check if this is "void"
+ if (retType.equals("void")) {
+ writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
+ } else { // We do have a return value
+ if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
+ print(checkAndGetCplusType(retType) + " retEnum = ");
+ else if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
+ print(checkAndGetCplusType(retType) + " retStruct = ");
+ else
+ print(checkAndGetCplusType(retType) + " retVal = ");
+ writeMethodInputParameters(methParams, methPrmTypes, callbackClasses, methodId);
+ checkAndWriteEnumRetTypeCplusSkeleton(retType);
+ if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
+ writeStructReturnCplusSkeleton(getSimpleArrayType(getGenericType(retType)), retType);
+ if (isEnumClass(getSimpleArrayType(getGenericType(retType)))) // Enum type
+ println("void* retObj = &retEnumInt;");
+ else
+ if (!isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
+ println("void* retObj = &retVal;");
+ String retTypeC = checkAndGetCplusType(retType);
+ if (isStructClass(getSimpleArrayType(getGenericType(retType)))) // Struct type
+ println("rmiObj->sendReturnObj(retObj, retCls, numRetObj);");
+ else
+ println("rmiObj->sendReturnObj(retObj, \"" + checkAndGetCplusRetClsType(getEnumType(retType)) + "\");");
+ }
+ }
+
+
+ /**
+ * HELPER: writeStdMethodHelperBodyCplusSkeleton() writes the standard method body helper in the skeleton class
+ */
+ private void writeStdMethodHelperBodyCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
+
+ // Generate array of parameter types
+ boolean isCallbackMethod = false;
+ String callbackType = null;
+ print("string paramCls[] = { ");
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (callbackClasses.contains(paramType)) {
+ isCallbackMethod = true;
+ callbackType = paramType;
+ print("\"int\"");
+ } else { // Generate normal classes if it's not a callback object
+ String paramTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
+ print("\"" + paramTypeC + "\"");
+ }
+ if (i != methParams.size() - 1) {
+ print(", ");
+ }
+ }
+ println(" };");
+ println("int numParam = " + methParams.size() + ";");
+ if (isCallbackMethod)
+ writeCallbackCplusNumStubs(methParams, methPrmTypes, callbackType);
+ // Generate parameters
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (!callbackClasses.contains(paramType)) {
+ String methParamType = methPrmTypes.get(i);
+ if (isEnumClass(getSimpleArrayType(getGenericType(methParamType)))) {
+ // Check if this is enum type
+ println("vector<int> paramEnumInt" + i + ";");
+ } else {
+ String methPrmType = checkAndGetCplusType(methParamType);
+ String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
+ println(methParamComplete + ";");
+ }
+ }
+ }
+ // Generate array of parameter objects
+ print("void* paramObj[] = { ");
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (callbackClasses.contains(paramType))
+ print("&numStubs" + i);
+ else if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
+ print("¶mEnumInt" + i);
+ else
+ print("&" + getSimpleIdentifier(methParams.get(i)));
+ if (i != methParams.size() - 1) {
+ print(", ");
+ }
+ }
+ println(" };");
+ // Write the return value part
+ writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
+ callbackType, methodId, callbackClasses);
+ }
+
+
+ /**
+ * HELPER: writeStructMembersCplusSkeleton() writes member parameters of struct
+ */
+ private void writeStructMembersCplusSkeleton(String simpleType, String paramType,
+ String param, String method, InterfaceDecl intDecl, int iVar) {
+
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ int methodNumId = intDecl.getMethodNumId(method);
+ String counter = "struct" + methodNumId + "Size" + iVar;
+ // Set up variables
+ if (isArrayOrList(paramType, param)) { // An array or list
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusType(memTypes.get(i));
+ String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
+ println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + "[" + counter + "];");
+ }
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusType(memTypes.get(i));
+ String prmType = checkAndGetCplusArrayType(prmTypeC, members.get(i));
+ println(getSimpleType(getEnumType(prmType)) + " param" + iVar + i + ";");
+ }
+ }
+ if (isArrayOrList(paramType, param)) { // An array or list
+ println("for(int i = 0; i < " + counter + "; i++) {");
+ }
+ if (isArrayOrList(paramType, param)) { // An array or list
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("paramCls[pos] = \"" + prmTypeC + "\";");
+ println("paramObj[pos++] = ¶m" + iVar + i + "[i];");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("paramCls[pos] = \"" + prmTypeC + "\";");
+ println("paramObj[pos++] = ¶m" + iVar + i + ";");
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructMembersInitCplusSkeleton() writes member parameters initialization of struct
+ */
+ private void writeStructMembersInitCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method) {
+
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ String counter = "struct" + methodNumId + "Size" + i;
+ // Declaration
+ if (isArrayOrList(paramType, param)) { // An array or list
+ println("vector<" + simpleType + "> paramStruct" + i + "(" + counter + ");");
+ } else
+ println(simpleType + " paramStruct" + i + ";");
+ // Initialize members
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ if (isArrayOrList(paramType, param)) { // An array or list
+ println("for(int i = 0; i < " + counter + "; i++) {");
+ for (int j = 0; j < members.size(); j++) {
+ print("paramStruct" + i + "[i]." + getSimpleIdentifier(members.get(j)));
+ println(" = param" + i + j + "[i];");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int j = 0; j < members.size(); j++) {
+ print("paramStruct" + i + "." + getSimpleIdentifier(members.get(j)));
+ println(" = param" + i + j + ";");
+ }
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeStructReturnCplusSkeleton() writes parameters of struct for return statement
+ */
+ private void writeStructReturnCplusSkeleton(String simpleType, String retType) {
+
+ // Minimum retLen is 1 if this is a single struct object
+ if (isArrayOrList(retType, retType))
+ println("int retLen = retStruct.size();");
+ else // Just single struct object
+ println("int retLen = 1;");
+ println("void* retLenObj = &retLen;");
+ println("rmiObj->sendReturnObj(retLenObj, \"int\");");
+ int numMem = getNumOfMembers(simpleType);
+ println("int numRetObj = " + numMem + "*retLen;");
+ println("string retCls[numRetObj];");
+ println("void* retObj[numRetObj];");
+ println("int retPos = 0;");
+ // Get the struct declaration for this struct and generate initialization code
+ StructDecl structDecl = getStructDecl(simpleType);
+ List<String> memTypes = structDecl.getMemberTypes(simpleType);
+ List<String> members = structDecl.getMembers(simpleType);
+ if (isArrayOrList(retType, retType)) { // An array or list
+ println("for(int i = 0; i < retLen; i++) {");
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = \"" + prmTypeC + "\";");
+ print("retObj[retPos++] = &retStruct[i].");
+ print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
+ println(";");
+ }
+ println("}");
+ } else { // Just one struct element
+ for (int i = 0; i < members.size(); i++) {
+ String prmTypeC = checkAndGetCplusArgClsType(memTypes.get(i), members.get(i));
+ println("retCls[retPos] = \"" + prmTypeC + "\";");
+ print("retObj[retPos++] = &retStruct.");
+ print(getEnumParam(memTypes.get(i), getSimpleIdentifier(members.get(i)), i));
+ println(";");
+ }
+ }
+
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperStructCplusSkeleton() writes the struct in skeleton
+ */
+ private void writeMethodHelperStructCplusSkeleton(InterfaceDecl intDecl, List<String> methParams,
+ List<String> methPrmTypes, String method, String methodId, Set<String> callbackClasses) {
+
+ // Generate array of parameter objects
+ boolean isCallbackMethod = false;
+ String callbackType = null;
+ print("int numParam = ");
+ writeLengthStructParamClassSkeleton(methParams, methPrmTypes, method, intDecl);
+ println(";");
+ println("string paramCls[numParam];");
+ println("void* paramObj[numParam];");
+ println("int pos = 0;");
+ // Iterate again over the parameters
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ writeStructMembersCplusSkeleton(simpleType, paramType, param, method, intDecl, i);
+ } else {
+ String prmType = returnGenericCallbackType(methPrmTypes.get(i));
+ if (callbackClasses.contains(prmType)) {
+ isCallbackMethod = true;
+ callbackType = prmType;
+ println("int numStubs" + i + " = 0;");
+ println("paramCls[pos] = \"int\";");
+ println("paramObj[pos++] = &numStubs" + i + ";");
+ } else { // Generate normal classes if it's not a callback object
+ String paramTypeC = checkAndGetCplusType(methPrmTypes.get(i));
+ if (isEnumClass(getGenericType(paramTypeC))) { // Check if this is enum type
+ println("vector<int> paramEnumInt" + i + ";");
+ } else {
+ String methParamComplete = checkAndGetCplusArray(paramTypeC, methParams.get(i));
+ println(methParamComplete + ";");
+ }
+ String prmTypeC = checkAndGetCplusArgClsType(methPrmTypes.get(i), methParams.get(i));
+ println("paramCls[pos] = \"" + prmTypeC + "\";");
+ if (isEnumClass(getGenericType(paramType))) // Check if this is enum type
+ println("paramObj[pos++] = ¶mEnumInt" + i + ";");
+ else
+ println("paramObj[pos++] = &" + getSimpleIdentifier(methParams.get(i)) + ";");
+ }
+ }
+ }
+ // Write the return value part
+ writeMethodHelperReturnCplusSkeleton(intDecl, methParams, methPrmTypes, method, isCallbackMethod,
+ callbackType, methodId, callbackClasses);
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperCplusSkeleton() writes the method helper of the skeleton class
+ */
+ private void writeMethodHelperCplusSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
+
+ // Use this set to handle two same methodIds
+ Set<String> uniqueMethodIds = new HashSet<String>();
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ if (isStructPresent(methParams, methPrmTypes)) { // Treat struct differently
+ String methodId = intDecl.getMethodId(method);
+ print("void ___");
+ String helperMethod = methodId;
+ if (uniqueMethodIds.contains(methodId))
+ helperMethod = helperMethod + intDecl.getMethodNumId(method);
+ else
+ uniqueMethodIds.add(methodId);
+ String retType = intDecl.getMethodType(method);
+ print(helperMethod + "(");
+ boolean begin = true;
+ for (int i = 0; i < methParams.size(); i++) { // Print size variables
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ if (!begin) // Generate comma for not the beginning variable
+ print(", ");
+ else
+ begin = false;
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("int struct" + methodNumId + "Size" + i);
+ }
+ }
+ println(") {");
+ writeMethodHelperStructCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
+ println("}\n");
+ } else {
+ String methodId = intDecl.getMethodId(method);
+ print("void ___");
+ String helperMethod = methodId;
+ if (uniqueMethodIds.contains(methodId))
+ helperMethod = helperMethod + intDecl.getMethodNumId(method);
+ else
+ uniqueMethodIds.add(methodId);
+ // Check if this is "void"
+ String retType = intDecl.getMethodType(method);
+ println(helperMethod + "() {");
+ // Now, write the helper body of skeleton!
+ writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId, callbackClasses);
+ println("}\n");
+ }
+ }
+ // Write method helper for structs
+ writeMethodHelperStructSetupCplusSkeleton(methods, intDecl);
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperStructSetupCplusSkeleton() writes the method helper of struct in skeleton class
+ */
+ private void writeMethodHelperStructSetupCplusSkeleton(Collection<String> methods,
+ InterfaceDecl intDecl) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("int ___");
+ String helperMethod = methodNumId + "struct" + i;
+ println(helperMethod + "() {");
+ // Now, write the helper body of skeleton!
+ println("string paramCls[] = { \"int\" };");
+ println("int numParam = 1;");
+ println("int param0 = 0;");
+ println("void* paramObj[] = { ¶m0 };");
+ println("rmiObj->getMethodParams(paramCls, numParam, paramObj);");
+ println("return param0;");
+ println("}\n");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeMethodHelperStructSetupCplusCallbackSkeleton() writes the method helper of struct in skeleton class
+ */
+ private void writeMethodHelperStructSetupCplusCallbackSkeleton(Collection<String> methods,
+ InterfaceDecl intDecl) {
+
+ // Use this set to handle two same methodIds
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ // Check for params with structs
+ for (int i = 0; i < methParams.size(); i++) {
+ String paramType = methPrmTypes.get(i);
+ String param = methParams.get(i);
+ String simpleType = getGenericType(paramType);
+ if (isStructClass(simpleType)) {
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("int ___");
+ String helperMethod = methodNumId + "struct" + i;
+ println(helperMethod + "(IoTRMIObject* rmiObj) {");
+ // Now, write the helper body of skeleton!
+ println("string paramCls[] = { \"int\" };");
+ println("int numParam = 1;");
+ println("int param0 = 0;");
+ println("void* paramObj[] = { ¶m0 };");
+ println("rmiObj->getMethodParams(paramCls, numParam, paramObj);");
+ println("return param0;");
+ println("}\n");
+ }
+ }
+ }
+ }
+
+
+ /**
+ * HELPER: writeCplusMethodPermission() writes permission checks in skeleton
+ */
+ private void writeCplusMethodPermission(String intface) {
+
+ // Get all the different stubs
+ Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
+ for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
+ String newIntface = intMeth.getKey();
+ int newObjectId = getNewIntfaceObjectId(newIntface);
+ println("if (_objectId == object" + newObjectId + "Id) {");
+ println("if (set" + newObjectId + "Allowed.find(methodId) == set" + newObjectId + "Allowed.end()) {");
+ println("cerr << \"Object with object Id: \" << _objectId << \" is not allowed to access method: \" << methodId << endl;");
+ println("return;");
+ println("}");
+ println("}");
+ println("else {");
+ println("cerr << \"Object Id: \" << _objectId << \" not recognized!\" << endl;");
+ println("return;");
+ println("}");
+ }
+ }
+
+
+ /**
+ * HELPER: writeCplusWaitRequestInvokeMethod() writes the main loop of the skeleton class
+ */
+ private void writeCplusWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist, String intface) {
+
+ // Use this set to handle two same methodIds
+ Set<String> uniqueMethodIds = new HashSet<String>();
+ println("void ___waitRequestInvokeMethod() {");
+ // Write variables here if we have callbacks or enums or structs
+ writeCountVarStructSkeleton(methods, intDecl);
+ println("while (true) {");
+ println("rmiObj->getMethodBytes();");
+ println("int _objectId = rmiObj->getObjectId();");
+ println("int methodId = rmiObj->getMethodId();");
+ // Generate permission check
+ writeCplusMethodPermission(intface);
+ println("switch (methodId) {");
+ // Print methods and method Ids
+ for (String method : methods) {
+ String methodId = intDecl.getMethodId(method);
+ int methodNumId = intDecl.getMethodNumId(method);
+ print("case " + methodNumId + ": ___");
+ String helperMethod = methodId;
+ if (uniqueMethodIds.contains(methodId))
+ helperMethod = helperMethod + methodNumId;
+ else
+ uniqueMethodIds.add(methodId);
+ print(helperMethod + "(");
+ writeInputCountVarStructSkeleton(method, intDecl);
+ println("); break;");
+ }
+ String method = "___initCallBack()";
+ // Print case -9999 (callback handler) if callback exists
+ if (callbackExist) {
+ int methodId = intDecl.getHelperMethodNumId(method);
+ println("case " + methodId + ": ___regCB(); break;");
+ }
+ writeMethodCallStructSkeleton(methods, intDecl);
+ println("default: ");
+ println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;");
+ println("throw exception();");
+ println("}");
+ println("}");
+ println("}\n");
+ }
+
+
+ /**
+ * generateCplusSkeletonClass() generate skeletons based on the methods list in C++
+ */
+ public void generateCplusSkeletonClass() throws IOException {
+
+ // 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();
+ Set<String> includeClasses = getIncludeClasses(methods, intDecl, intface, true);
+ List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
+ List<String> allIncludeClasses = getAllLibClasses(stdIncludeClasses, includeClasses);
+ printIncludeStatements(allIncludeClasses); 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 constructor
+ writeConstructorCplusSkeleton(newSkelClass, intface, callbackExist, intDecl, methods);
+ // Write deconstructor
+ writeDeconstructorCplusSkeleton(newSkelClass, callbackExist, callbackClasses);
+ // Write methods
+ writeMethodCplusSkeleton(methods, intDecl, callbackClasses, false);
+ // Write method helper
+ writeMethodHelperCplusSkeleton(methods, intDecl, callbackClasses);
+ // Write waitRequestInvokeMethod() - main loop
+ writeCplusWaitRequestInvokeMethod(methods, intDecl, callbackExist, intface);
+ println("};");
+ writePermissionInitializationCplus(intface, newSkelClass, intDecl);
+ writeObjectIdCountInitializationCplus(newSkelClass, callbackExist);
+ println("#endif");
+ pw.close();
+ System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".hpp...");
+ }
+ }
+
+
+ /**
+ * HELPER: writePropertiesCplusCallbackSkeleton() writes the properties of the callback skeleton class
+ */
+ private void writePropertiesCplusCallbackSkeleton(String intface, boolean callbackExist, Set<String> callbackClasses) {
+
+ println(intface + " *mainObj;");
+ // Keep track of object Ids of all stubs registered to this interface
+ println("int objectId;");
+ // Callback
+ if (callbackExist) {
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ String exchangeType = checkAndGetParamClass(callbackType);
+ println("// Callback properties");
+ println("IoTRMICall* rmiCall;");
+ println("vector<" + exchangeType + "*> vecCallbackObj;");
+ println("static int objIdCnt;");
+ }
+ println("\n");
+ }
+
+
+ /**
+ * HELPER: writeConstructorCplusCallbackSkeleton() writes the constructor of the skeleton class
+ */
+ private void writeConstructorCplusCallbackSkeleton(String newSkelClass, String intface, boolean callbackExist, InterfaceDecl intDecl, Collection<String> methods) {
+
+ println(newSkelClass + "(" + intface + " *_mainObj, int _objectId) {");
+ println("mainObj = _mainObj;");
+ println("objectId = _objectId;");
+ println("}\n");
+ }
+
+
+ /**
+ * HELPER: writeDeconstructorCplusStub() writes the deconstructor of the stub class
+ */
+ private void writeDeconstructorCplusCallbackSkeleton(String newStubClass, boolean callbackExist,
+ Set<String> callbackClasses) {
+
+ println("~" + newStubClass + "() {");
+ if (callbackExist) {
+ // We assume that each class only has one callback interface for now
+ println("if (rmiCall != NULL) {");
+ println("delete rmiCall;");
+ println("rmiCall = NULL;");
+ println("}");
+ Iterator it = callbackClasses.iterator();
+ String callbackType = (String) it.next();
+ String exchangeType = checkAndGetParamClass(callbackType);
+ println("for(" + exchangeType + "* cb : vecCallbackObj) {");
+ println("delete cb;");
+ println("cb = NULL;");
+ println("}");
+ }
+ println("}");
+ println("");
+ }
+