From 7c4edd552766ca89566cf033bc2320483204c625 Mon Sep 17 00:00:00 2001 From: rtrimana Date: Wed, 16 Nov 2016 09:02:27 -0800 Subject: [PATCH] Adding Java callback support in compiler --- config/iotpolicy/camerapolicy.pol | 2 + iotjava/Makefile | 4 +- iotjava/iotpolicy/IoTCompiler.java | 894 +++++++++++++++++++++- iotjava/iotpolicy/tree/InterfaceDecl.java | 19 + 4 files changed, 876 insertions(+), 43 deletions(-) diff --git a/config/iotpolicy/camerapolicy.pol b/config/iotpolicy/camerapolicy.pol index 0afb5a0..809f12d 100644 --- a/config/iotpolicy/camerapolicy.pol +++ b/config/iotpolicy/camerapolicy.pol @@ -6,6 +6,7 @@ public interface Camera { public String MethodC(String E, List F); public float MethodD(List G, float H); public boolean MethodE(String I, boolean J); + public void MethodF(LightBulb K); capability ImageCapture { description = "The quick brown fox jumps over the smart dog"; @@ -13,6 +14,7 @@ public interface Camera { method = "MethodA(int A, int B)"; method = "MethodB(int C, String D[])"; method = "MethodC(String E, List F)"; + method = "MethodF(LightBulb K)"; } capability VideoRecording { diff --git a/iotjava/Makefile b/iotjava/Makefile index 50792f4..e748017 100644 --- a/iotjava/Makefile +++ b/iotjava/Makefile @@ -32,8 +32,8 @@ PHONY += compile compile: cd $(BIN_DIR)/iotpolicy/output_files; cp *.java ./Java cd $(BIN_DIR)/iotpolicy/output_files; cp *.hpp ./Cplus - #cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) *.java - cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./*.hpp --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ + cd $(BIN_DIR)/iotpolicy/output_files/Java; $(JAVAC) -cp .:..:../../../$(BIN_DIR) *.java +# cd $(BIN_DIR)/iotpolicy/output_files/Cplus; $(G++) ./*.hpp --std=c++11 -pthread -pg -I../../../../iotjava/iotrmi/C++/ PHONY += clean clean: diff --git a/iotjava/iotpolicy/IoTCompiler.java b/iotjava/iotpolicy/IoTCompiler.java index f3a1ce1..9c6a16a 100644 --- a/iotjava/iotpolicy/IoTCompiler.java +++ b/iotjava/iotpolicy/IoTCompiler.java @@ -180,6 +180,32 @@ public class IoTCompiler { } + /** + * HELPER: writeMethodJavaLocalInterface() writes the method of the interface + */ + private void writeMethodJavaLocalInterface(Collection methods, InterfaceDecl intDecl) { + + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + print("public " + 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), false); + print(paramType + " " + methParams.get(i)); + // Check if this is the last element (don't print a comma) + if (i != methParams.size() - 1) { + print(", "); + } + } + println(");"); + } + } + + /** * HELPER: writeMethodJavaInterface() writes the method of the interface */ @@ -194,7 +220,7 @@ public class IoTCompiler { for (int i = 0; i < methParams.size(); i++) { // Check for params with driver class types and exchange it // with its remote interface - String paramType = checkAndGetParamClass(methPrmTypes.get(i), false); + String paramType = methPrmTypes.get(i); print(paramType + " " + methParams.get(i)); // Check if this is the last element (don't print a comma) if (i != methParams.size() - 1) { @@ -287,7 +313,7 @@ public class IoTCompiler { StructDecl structDecl = (StructDecl) decHandler.getStructDecl(intface); writeStructJava(structDecl); // Write methods - writeMethodJavaInterface(methods, intDecl); + writeMethodJavaLocalInterface(methods, intDecl); println("}"); pw.close(); System.out.println("IoTCompiler: Generated local interface " + intface + ".java..."); @@ -332,10 +358,9 @@ public class IoTCompiler { /** * HELPER: writePropertiesJavaStub() writes the properties of the stub class */ - private void writePropertiesJavaStub(String intface, String newIntface) { + private void writePropertiesJavaStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { println("private IoTRMICall rmiCall;"); - //println("private IoTRMIObject rmiObj;"); println("private String address;"); println("private int[] ports;\n"); // Get the object Id @@ -343,6 +368,15 @@ public class IoTCompiler { println("private final 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("private IoTRMIObject rmiObj;"); + println("List<" + callbackType + "> listCallbackObj;"); + println("private static int objIdCnt = 0;"); + } println("\n"); } @@ -350,12 +384,57 @@ public class IoTCompiler { /** * HELPER: writeConstructorJavaStub() writes the constructor of the stub class */ - private void writeConstructorJavaStub(String intface) { + private void writeConstructorJavaStub(String intface, boolean callbackExist, Set callbackClasses) { println("public " + intface + "(int _port, String _address, int _rev, int[] _ports) throws Exception {"); println("address = _address;"); println("ports = _ports;"); println("rmiCall = new IoTRMICall(_port, _address, _rev);"); + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + println("listCallbackObj = new ArrayList<" + callbackType + ">();"); + println("___initCallBack();"); + } + println("}\n"); + } + + + /** + * HELPER: writeConstructorJavaStub() writes the constructor of the stub class + */ + private void writeInitCallbackJavaStub(String intface, InterfaceDecl intDecl) { + + println("public void ___initCallBack() {"); + // Generate main thread for callbacks + println("Thread thread = new Thread() {"); + println("public void run() {"); + println("try {"); + println("rmiObj = new IoTRMIObject(ports[0]);"); + println("while (true) {"); + println("byte[] method = rmiObj.getMethodBytes();"); + println("int objId = IoTRMIObject.getObjectId(method);"); + println(intface + "_CallbackSkeleton skel = (" + intface + "_CallbackSkeleton) listCallbackObj.get(objId);"); + println("if (skel != null) {"); + println("skel.invokeMethod(rmiObj);"); + println("} else {"); + println("throw new Error(\"" + intface + ": Object with Id \" + objId + \" not found!\");"); + println("}"); + println("}"); + println("} catch (Exception ex) {"); + println("ex.printStackTrace();"); + println("throw new Error(\"Error instantiating class " + intface + "_CallbackSkeleton!\");"); + println("}"); + println("}"); + println("};"); + println("thread.start();\n"); + // Generate info sending part + String method = "___initCallBack()"; + println("int methodId = " + intDecl.getHelperMethodNumId(method) + ";"); + println("Class retType = void.class;"); + println("Class[] paramCls = new Class[] { int.class, String.class, int.class };"); + println("Object[] paramObj = new Object[] { ports[0], address, 0 };"); + println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); println("}\n"); } @@ -408,10 +487,101 @@ public class IoTCompiler { } + /** + * HELPER: checkCallbackType() checks the callback type + */ + private boolean checkCallbackType(String paramType, String callbackType) { + + if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) + paramType = getTypeOfGeneric(paramType)[0]; + return callbackType.equals(paramType); + } + + + /** + * HELPER: writeCallbackMethodBodyJavaStub() writes the callback method of the stub class + */ + private void writeCallbackMethodBodyJavaStub(InterfaceDecl intDecl, List methParams, + List 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 (" + paramType + " cb : " + getSimpleIdentifier(param) + ") {"); + println(callbackType + "_CallbackSkeleton skel = new " + callbackType + "_CallbackSkeleton(cb, objIdCnt++);"); + } else + println(callbackType + "_CallbackSkeleton skel = new " + callbackType + "_CallbackSkeleton(" + + getSimpleIdentifier(param) + ", objIdCnt++);"); + println("listCallbackObj.add(skel);"); + if (isArrayOrList(paramType, param)) + println("}"); + } + } + println("} catch (Exception ex) {"); + println("ex.printStackTrace();"); + println("throw new Error(\"Exception when generating skeleton objects!\");"); + println("}\n"); + println("int methodId = " + intDecl.getMethodNumId(method) + ";"); + String retType = intDecl.getMethodType(method); + println("Class retType = " + getSimpleType(retType) + ".class;"); + // Generate array of parameter types + print("Class[] paramCls = new Class[] { "); + for (int i = 0; i < methParams.size(); i++) { + String paramType = methPrmTypes.get(i); + if (checkCallbackType(paramType, callbackType)) { // Check if this has callback object + 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(prmType) + ".class"); + } + if (i != methParams.size() - 1) // Check if this is the last element + 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))) + print(getSimpleIdentifier(methParams.get(i)) + ".length"); + else if (isList(methPrmTypes.get(i), methParams.get(i))) + print(getSimpleIdentifier(methParams.get(i)) + ".size()"); + else + print("new Integer(1)"); + } else + print(getSimpleIdentifier(methParams.get(i))); + if (i != methParams.size() - 1) + print(", "); + } + println(" };"); + // Check if this is "void" + if (retType.equals("void")) { + println("rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + } else { // We do have a return value + // Check if the return value NONPRIMITIVES + if (getParamCategory(retType) == ParamCategory.NONPRIMITIVES) { + String[] retGenValType = getTypeOfGeneric(retType); + println("Class retGenValType = " + retGenValType[0] + ".class;"); + println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, retGenValType, paramCls, paramObj);"); + println("return (" + retType + ")retObj;"); + } else { + println("Object retObj = rmiCall.remoteCall(objectId, methodId, retType, null, paramCls, paramObj);"); + println("return (" + retType + ")retObj;"); + } + } + } + + /** * HELPER: writeMethodJavaStub() writes the method of the stub class */ - private void writeMethodJavaStub(Collection methods, InterfaceDecl intDecl) { + private void writeMethodJavaStub(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { for (String method : methods) { @@ -419,8 +589,21 @@ public class IoTCompiler { List 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 = methPrmTypes.get(i); + if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) + paramType = getTypeOfGeneric(paramType)[0]; + // Check if this has callback object + if (callbackClasses != null) { + 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) { @@ -429,8 +612,14 @@ public class IoTCompiler { } println(") {"); // Now, write the body of stub! - writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method); + if (isCallbackMethod) + writeCallbackMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method, callbackType); + else + writeStdMethodBodyJavaStub(intDecl, methParams, methPrmTypes, method); println("}\n"); + // Write the init callback helper method + if (isCallbackMethod) + writeInitCallbackJavaStub(callbackType, intDecl); } } @@ -455,18 +644,22 @@ public class IoTCompiler { DeclarationHandler decHandler = mapIntDeclHand.get(intface); InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); // Pass in set of methods and get import classes - Set importClasses = getImportClasses(intMeth.getValue(), intDecl); + Set methods = intMeth.getValue(); + Set importClasses = getImportClasses(methods, intDecl); List stdImportClasses = getStandardJavaImportClasses(); List allImportClasses = getAllImportClasses(stdImportClasses, importClasses); printImportStatements(allImportClasses); println(""); + // Find out if there are callback objects + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); // Write class header println("public class " + newStubClass + " implements " + newIntface + " {\n"); // Write properties - writePropertiesJavaStub(intface, newIntface); + writePropertiesJavaStub(intface, newIntface, callbackExist, callbackClasses); // Write constructor - writeConstructorJavaStub(newStubClass); + writeConstructorJavaStub(newStubClass, callbackExist, callbackClasses); // Write methods - writeMethodJavaStub(intMeth.getValue(), intDecl); + writeMethodJavaStub(intMeth.getValue(), intDecl, callbackClasses); println("}"); pw.close(); System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java..."); @@ -475,15 +668,107 @@ public class IoTCompiler { } + /** + * HELPER: writePropertiesJavaCallbackStub() writes the properties of the callback stub class + */ + private void writePropertiesJavaCallbackStub(String intface, String newIntface, boolean callbackExist, Set callbackClasses) { + + println("private IoTRMICall rmiCall;"); + // Get the object Id + println("private static 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;"); + } + println("\n"); + } + + + /** + * HELPER: writeConstructorJavaCallbackStub() writes the constructor of the callback stub class + */ + private void writeConstructorJavaCallbackStub(String intface, boolean callbackExist, Set callbackClasses) { + + println("public " + intface + "(IoTRMICall _rmiCall, int _objectId) throws Exception {"); + println("objectId = _objectId;"); + println("rmiCall = _rmiCall;"); + if (callbackExist) { + Iterator it = callbackClasses.iterator(); + String callbackType = (String) it.next(); + println("listCallbackObj = new ArrayList<" + callbackType + ">();"); + println("___initCallBack();"); + } + println("}\n"); + } + + + /** + * generateJavaCallbackStubClasses() generate callback stubs based on the methods list in Java + *

+ * 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> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> 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 methods = intMeth.getValue(); + Set importClasses = getImportClasses(methods, intDecl); + List stdImportClasses = getStandardJavaImportClasses(); + List allImportClasses = getAllImportClasses(stdImportClasses, importClasses); + printImportStatements(allImportClasses); println(""); + // Find out if there are callback objects + Set 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(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) { + private void writePropertiesJavaSkeleton(String intface, boolean callbackExist) { println("private " + intface + " mainObj;"); //println("private int ports;"); - //println("private IoTRMICall rmiCall;"); println("private IoTRMIObject rmiObj;\n"); + // Callback + if (callbackExist) { + println("private static int objIdCnt = 0;"); + println("private IoTRMICall rmiCall;"); + } // Keep track of object Ids of all stubs registered to this interface Map> mapNewIntMethods = mapInt2NewInts.get(intface); for (Map.Entry> intMeth : mapNewIntMethods.entrySet()) { @@ -531,10 +816,23 @@ public class IoTCompiler { } + /** + * HELPER: writeInitCallbackJavaSkeleton() writes the init callback method for skeleton class + */ + private void writeInitCallbackJavaSkeleton() { + + println("public void ___regCB() throws IOException {"); + println("Object[] paramObj = rmiObj.getMethodParams(new Class[] { int.class, String.class, int.class },"); + println("\tnew 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 methods, InterfaceDecl intDecl) { + private void writeMethodJavaSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { for (String method : methods) { @@ -542,9 +840,19 @@ public class IoTCompiler { List 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++) { - print(methPrmTypes.get(i) + " " + methParams.get(i)); + String origParamType = methPrmTypes.get(i); + String paramType = checkAndGetParamClass(origParamType, false); + if (callbackClasses != null) { // Check if this has callback object + if (callbackClasses.contains(origParamType)) { + 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(", "); @@ -554,7 +862,56 @@ public class IoTCompiler { // Now, write the body of skeleton! writeStdMethodBodyJavaSkeleton(methParams, methodId, intDecl.getMethodType(method)); println("}\n"); + if (isCallbackMethod) + writeInitCallbackJavaSkeleton(); + } + } + + + /** + * HELPER: writeCallbackStubGeneration() writes the callback stub generation part + */ + private Map writeCallbackStubGeneration(List methParams, List methPrmTypes, String callbackType) { + + Map mapStubParam = new HashMap(); + // Iterate over callback objects + 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("try {"); + String exchParamType = checkAndGetParamClass(paramType, false); + // Print array if this is array or list if this is a list of callback objects + if (isArray(paramType, param)) { + println("int numStubs" + i + " = (int) paramObj[" + i + "];"); + println(exchParamType + "[] stub" + i + " = new " + exchParamType + "[numStubs" + i + "];"); + } else if (isList(paramType, param)) { + println("int numStubs" + i + " = (int) paramObj[" + 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(paramType, false); + if (isArray(paramType, 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, param)) { + 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; } @@ -562,13 +919,28 @@ public class IoTCompiler { * HELPER: writeStdMethodHelperBodyJavaSkeleton() writes the standard method body helper in the skeleton class */ private void writeStdMethodHelperBodyJavaSkeleton(InterfaceDecl intDecl, List methParams, - List methPrmTypes, String method) { + List methPrmTypes, String method, Set 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 = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); - print(getSimpleType(paramType) + ".class"); - // Check if this is the last element (don't print a comma) + String paramType = methPrmTypes.get(i); + if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) + paramType = getTypeOfGeneric(paramType)[0]; + if (callbackClasses != null) { + if (callbackClasses.contains(paramType)) { + isCallbackMethod = true; + callbackType = paramType; + print("int.class"); + } else { + String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + print(getSimpleType(prmType) + ".class"); + } + } else { // Generate normal classes if it's not a callback object + String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + print(getSimpleType(prmType) + ".class"); + } if (i != methParams.size() - 1) print(", "); } @@ -585,6 +957,9 @@ public class IoTCompiler { print(", "); } println(" });"); + Map mapStubParam = null; + if (isCallbackMethod) + mapStubParam = writeCallbackStubGeneration(methParams, methPrmTypes, callbackType); // Check if this is "void" String retType = intDecl.getMethodType(method); if (retType.equals("void")) { @@ -593,21 +968,32 @@ public class IoTCompiler { print("Object retObj = " + intDecl.getMethodId(method) + "("); } for (int i = 0; i < methParams.size(); i++) { - String paramType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); - print("(" + paramType + ") paramObj[" + i + "]"); + + if (isCallbackMethod) { + print(mapStubParam.get(i)); // Get the callback parameter + } else { + String prmType = checkAndGetArray(methPrmTypes.get(i), methParams.get(i)); + print("(" + prmType + ") paramObj[" + i + "]"); + } if (i != methParams.size() - 1) print(", "); } println(");"); if (!retType.equals("void")) println("rmiObj.sendReturnObj(retObj);"); + if (isCallbackMethod) { // Catch exception if this is callback + println("} catch(Exception ex) {"); + println("ex.printStackTrace();"); + println("throw new Error(\"Exception from callback object instantiation!\");"); + println("}"); + } } /** * HELPER: writeMethodHelperJavaSkeleton() writes the method helper of the skeleton class */ - private void writeMethodHelperJavaSkeleton(Collection methods, InterfaceDecl intDecl) { + private void writeMethodHelperJavaSkeleton(Collection methods, InterfaceDecl intDecl, Set callbackClasses) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); @@ -629,7 +1015,7 @@ public class IoTCompiler { else println(helperMethod + "() throws IOException {"); // Now, write the helper body of skeleton! - writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method); + writeStdMethodHelperBodyJavaSkeleton(intDecl, methParams, methPrmTypes, method, callbackClasses); println("}\n"); } } @@ -638,7 +1024,7 @@ public class IoTCompiler { /** * HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class */ - private void writeJavaWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl) { + private void writeJavaWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, boolean callbackExist) { // Use this set to handle two same methodIds Set uniqueMethodIds = new HashSet(); @@ -662,6 +1048,12 @@ public class IoTCompiler { uniqueMethodIds.add(methodId); println(helperMethod + "(); break;"); } + String method = "___initCallBack()"; + // Print case -9999 (callback handler) if callback exists + if (callbackExist) { + int methodId = intDecl.getHelperMethodNumId(method); + println("case " + methodId + ": ___regCB(); break;"); + } println("default: "); println("throw new Error(\"Method Id \" + methodId + \" not recognized!\");"); println("}"); @@ -676,11 +1068,11 @@ public class IoTCompiler { public void generateJavaSkeletonClass() throws IOException { // Create a new directory - createDirectory(dir); + 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(dir + "/" + newSkelClass + ".java"); + 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); @@ -690,19 +1082,22 @@ public class IoTCompiler { List stdImportClasses = getStandardJavaImportClasses(); List allImportClasses = getAllImportClasses(stdImportClasses, importClasses); printImportStatements(allImportClasses); + // Find out if there are callback objects + Set callbackClasses = getCallbackClasses(methods, intDecl); + boolean callbackExist = !callbackClasses.isEmpty(); // Write class header println(""); println("public class " + newSkelClass + " implements " + intface + " {\n"); // Write properties - writePropertiesJavaSkeleton(intface); + writePropertiesJavaSkeleton(intface, callbackExist); // Write constructor writeConstructorJavaSkeleton(newSkelClass, intface); // Write methods - writeMethodJavaSkeleton(methods, intDecl); + writeMethodJavaSkeleton(methods, intDecl, callbackClasses); // Write method helper - writeMethodHelperJavaSkeleton(methods, intDecl); + writeMethodHelperJavaSkeleton(methods, intDecl, callbackClasses); // Write waitRequestInvokeMethod() - main loop - writeJavaWaitRequestInvokeMethod(methods, intDecl); + writeJavaWaitRequestInvokeMethod(methods, intDecl, callbackExist); println("}"); pw.close(); System.out.println("IoTCompiler: Generated skeleton class " + newSkelClass + ".java..."); @@ -710,6 +1105,146 @@ public class IoTCompiler { } + /** + * 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 static 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) { + + 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 methods, InterfaceDecl intDecl, Set callbackClasses) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + 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"); + } + } + + + /** + * HELPER: writeJavaCallbackWaitRequestInvokeMethod() writes the main loop of the skeleton class + */ + private void writeJavaCallbackWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl, boolean callbackExist) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + println("public void invokeMethod(IoTRMIObject rmiObj) throws IOException {"); + // 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); + println(helperMethod + "(rmiObj); break;"); + } + String method = "___initCallBack()"; + // Print case -9999 (callback handler) if callback exists + if (callbackExist) { + int methodId = intDecl.getHelperMethodNumId(method); + println("case " + methodId + ": ___regCB(); break;"); + } + 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 methods = intDecl.getMethods(); + Set importClasses = getImportClasses(methods, intDecl); + List stdImportClasses = getStandardJavaImportClasses(); + List allImportClasses = getAllImportClasses(stdImportClasses, importClasses); + printImportStatements(allImportClasses); + // Find out if there are callback objects + Set 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); + // Write methods + writeMethodJavaSkeleton(methods, intDecl, callbackClasses); + // 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: writeMethodCplusInterface() writes the method of the interface */ @@ -724,7 +1259,8 @@ public class IoTCompiler { for (int i = 0; i < methParams.size(); i++) { // Check for params with driver class types and exchange it // with its remote interface - String paramType = checkAndGetParamClass(methPrmTypes.get(i), true); + //String paramType = checkAndGetParamClass(methPrmTypes.get(i), true); + String paramType = methPrmTypes.get(i); paramType = checkAndGetCplusType(paramType); // Check for arrays - translate into vector in C++ String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i)); @@ -891,7 +1427,10 @@ public class IoTCompiler { print(checkAndGetCplusType(intDecl.getMethodType(method)) + " " + intDecl.getMethodId(method) + "("); for (int i = 0; i < methParams.size(); i++) { - String methPrmType = checkAndGetCplusType(methPrmTypes.get(i)); + + //String paramType = checkAndGetParamClass(methPrmTypes.get(i), true); + String paramType = 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) @@ -960,13 +1499,13 @@ public class IoTCompiler { */ private void writePropertiesCplusStub(String intface, String newIntface) { - println("IoTRMICall\t\t\t*rmiCall;"); + println("IoTRMICall *rmiCall;"); //println("IoTRMIObject\t\t\t*rmiObj;"); - println("string\t\t\t\taddress;"); - println("vector\t\t\tports;\n"); + println("string address;"); + println("vector ports;\n"); // Get the object Id Integer objId = mapIntfaceObjId.get(intface); - println("const static int\tobjectId = " + objId + ";"); + println("const static int objectId = " + objId + ";"); mapNewIntfaceObjId.put(newIntface, objId); mapIntfaceObjId.put(intface, objId++); println("\n"); @@ -1046,6 +1585,73 @@ public class IoTCompiler { } + /** + * HELPER: writePropertiesCplusCallbackStub() writes the properties of the stub class + */ + private void writePropertiesCplusCallbackStub(String intface, String newIntface) { + + println("IoTRMICall *rmiCall;"); + // Get the object Id + println("static int objectId;"); + println("\n"); + } + + + /** + * HELPER: writeConstructorCplusCallbackStub() writes the constructor of the stub class + */ + private void writeConstructorCplusCallbackStub(String newStubClass) { + + println(newStubClass + "(IoTRMICall* _rmiCall, int _objectId) {"); + println("objectId = _objectId;"); + println("rmiCall = _rmiCall;"); + 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> mapNewIntMethods = mapInt2NewInts.get(intface); + for (Map.Entry> 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)); + // Write file headers + println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__"); + println("#define _" + newStubClass.toUpperCase() + "_HPP__"); + println("#include "); + println("#include \"" + newIntface + ".hpp\""); println(""); + println("using namespace std;"); println(""); + println("class " + newStubClass + " : public " + newIntface); println("{"); + println("private:\n"); + writePropertiesCplusCallbackStub(intface, newIntface); + println("public:\n"); + // Add default constructor and destructor + println(newStubClass + "() { }"); println(""); + writeConstructorCplusCallbackStub(newStubClass); + writeDeconstructorCplusStub(newStubClass); + DeclarationHandler decHandler = mapIntDeclHand.get(intface); + InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface); + // Write methods + writeMethodCplusStub(intMeth.getValue(), intDecl); + print("}"); println(";"); + println("#endif"); + pw.close(); + System.out.println("IoTCompiler: Generated callback stub class " + newIntface + ".hpp..."); + } + } + } + + /** * HELPER: writePropertiesCplusSkeleton() writes the properties of the skeleton class */ @@ -1134,7 +1740,9 @@ public class IoTCompiler { String methodType = checkAndGetCplusType(intDecl.getMethodType(method)); print(methodType + " " + methodId + "("); for (int i = 0; i < methParams.size(); i++) { - String methPrmType = checkAndGetCplusType(methPrmTypes.get(i)); + + String paramType = checkAndGetParamClass(methPrmTypes.get(i), true); + 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) @@ -1281,11 +1889,11 @@ public class IoTCompiler { public void generateCplusSkeletonClass() throws IOException { // Create a new directory - createDirectory(dir); + 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(dir + "/" + newSkelClass + ".hpp"); + FileWriter fw = new FileWriter(path + "/" + newSkelClass + ".hpp"); pw = new PrintWriter(new BufferedWriter(fw)); // Write file headers println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__"); @@ -1325,6 +1933,142 @@ public class IoTCompiler { } + /** + * HELPER: writePropertiesCplusCallbackSkeleton() writes the properties of the callback skeleton class + */ + private void writePropertiesCplusCallbackSkeleton(String intface) { + + println(intface + " *mainObj;"); + //println("IoTRMIObject *rmiObj;\n"); + // Keep track of object Ids of all stubs registered to this interface + println("static int objectId;"); + println("\n"); + } + + + /** + * HELPER: writeConstructorCplusCallbackSkeleton() writes the constructor of the skeleton class + */ + private void writeConstructorCplusCallbackSkeleton(String newSkelClass, String intface) { + + println(newSkelClass + "(" + intface + " *_mainObj, int _objectId) {"); + println("mainObj = _mainObj;"); + println("objectId = _objectId;"); + println("}\n"); + } + + + /** + * HELPER: writeMethodHelperCplusCallbackSkeleton() writes the method helper of the callback skeleton class + */ + private void writeMethodHelperCplusCallbackSkeleton(Collection methods, InterfaceDecl intDecl) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + for (String method : methods) { + + List methParams = intDecl.getMethodParams(method); + List methPrmTypes = intDecl.getMethodParamTypes(method); + 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 + "(IoTRMIObject* rmiObj) {"); + // Now, write the helper body of skeleton! + writeStdMethodHelperBodyCplusSkeleton(intDecl, methParams, methPrmTypes, method, methodId); + println("}\n"); + } + } + + + /** + * HELPER: writeCplusCallbackWaitRequestInvokeMethod() writes the main loop of the skeleton class + */ + private void writeCplusCallbackWaitRequestInvokeMethod(Collection methods, InterfaceDecl intDecl) { + + // Use this set to handle two same methodIds + Set uniqueMethodIds = new HashSet(); + println("void invokeMethod(IoTRMIObject* rmiObj) {"); + // 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); + println(helperMethod + "(rmiObj); break;"); + } + println("default: "); + println("cerr << \"Method Id \" << methodId << \" not recognized!\" << endl;"); + println("throw exception();"); + println("}"); + println("}\n"); + } + + + + /** + * generateCplusCallbackSkeletonClass() generate callback skeletons based on the methods list in C++ + */ + public void generateCplusCallbackSkeletonClass() 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 + ".hpp"); + pw = new PrintWriter(new BufferedWriter(fw)); + // Write file headers + println("#ifndef _" + newSkelClass.toUpperCase() + "_HPP__"); + println("#define _" + newSkelClass.toUpperCase() + "_HPP__"); + println("#include "); + 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 methods = intDecl.getMethods(); + Set includeClasses = getIncludeClasses(methods, intDecl); + List stdIncludeClasses = getStandardCplusIncludeClasses(); + List allIncludeClasses = getAllImportClasses(stdIncludeClasses, includeClasses); + printIncludeStatements(allIncludeClasses); println(""); + println("using namespace std;\n"); + // Write class header + println("class " + newSkelClass + " : public " + intface); println("{"); + println("private:\n"); + // Write properties + writePropertiesCplusCallbackSkeleton(intface); + println("public:\n"); + // Write constructor + writeConstructorCplusCallbackSkeleton(newSkelClass, intface); + // Write deconstructor + //writeDeconstructorCplusSkeleton(newSkelClass); + // Write methods + writeMethodCplusSkeleton(methods, intDecl); + // Write method helper + writeMethodHelperCplusCallbackSkeleton(methods, intDecl); + // Write waitRequestInvokeMethod() - main loop + writeCplusCallbackWaitRequestInvokeMethod(methods, intDecl); + println("};"); + println("#endif"); + pw.close(); + System.out.println("IoTCompiler: Generated callback skeleton class " + newSkelClass + ".hpp..."); + } + } + + /** * generateInitializer() generate initializer based on type */ @@ -1665,6 +2409,32 @@ public class IoTCompiler { } + // Generate a set of callback classes + private Set getCallbackClasses(Collection methods, InterfaceDecl intDecl) { + + Set callbackClasses = new HashSet(); + for (String method : methods) { + + List methPrmTypes = intDecl.getMethodParamTypes(method); + List methParams = intDecl.getMethodParams(method); + for (int i = 0; i < methPrmTypes.size(); i++) { + + String type = methPrmTypes.get(i); + if (getParamCategory(type) == ParamCategory.USERDEFINED) { + callbackClasses.add(type); + } else if (getParamCategory(type) == ParamCategory.NONPRIMITIVES) { + // Can be a List<...> of callback objects ... + String genericType = getTypeOfGeneric(type)[0]; + if (getParamCategory(type) == ParamCategory.USERDEFINED) { + callbackClasses.add(type); + } + } + } + } + return callbackClasses; + } + + private void printImportStatements(Collection importClasses) { for(String cls : importClasses) { @@ -1804,8 +2574,42 @@ public class IoTCompiler { } - // Get simple types, e.g. HashSet for HashSet<...> - // Basically strip off the "<...>" + // Is array or list? + private boolean isArrayOrList(String paramType, String param) { + + // Check for array declaration + if (isArray(paramType, param)) + return true; + else if (isList(paramType, param)) + return true; + else + return false; + } + + + // Is array or list? + private boolean isArray(String paramType, String param) { + + // Check for array declaration + if (param.contains("[]")) + return true; + else + return false; + } + + + // Is array or list? + private boolean isList(String paramType, String param) { + + // Check for array declaration + if (paramType.contains("List")) + return true; + else + return false; + } + + + // Get the right type for a callback object private String checkAndGetParamClass(String paramType, boolean needPtr) { // Check if this is generics @@ -1887,11 +2691,15 @@ public class IoTCompiler { comp.generateJavaLocalInterfaces(); comp.generateJavaInterfaces(); comp.generateJavaStubClasses(); + comp.generateJavaCallbackStubClasses(); comp.generateJavaSkeletonClass(); + comp.generateJavaCallbackSkeletonClass(); comp.generateCplusLocalInterfaces(); comp.generateCPlusInterfaces(); comp.generateCPlusStubClasses(); + comp.generateCPlusCallbackStubClasses(); comp.generateCplusSkeletonClass(); + comp.generateCplusCallbackSkeletonClass(); } else { // Check other options while(i < args.length) { @@ -1909,12 +2717,16 @@ public class IoTCompiler { comp.generateJavaLocalInterfaces(); comp.generateJavaInterfaces(); comp.generateJavaStubClasses(); + comp.generateJavaCallbackStubClasses(); comp.generateJavaSkeletonClass(); + comp.generateJavaCallbackSkeletonClass(); } else { comp.generateCplusLocalInterfaces(); comp.generateCPlusInterfaces(); comp.generateCPlusStubClasses(); + comp.generateCPlusCallbackStubClasses(); comp.generateCplusSkeletonClass(); + comp.generateCplusCallbackSkeletonClass(); } } i = i + 2; diff --git a/iotjava/iotpolicy/tree/InterfaceDecl.java b/iotjava/iotpolicy/tree/InterfaceDecl.java index 69ad796..30dd3ce 100644 --- a/iotjava/iotpolicy/tree/InterfaceDecl.java +++ b/iotjava/iotpolicy/tree/InterfaceDecl.java @@ -38,6 +38,9 @@ public class InterfaceDecl extends Declaration { private List listMethodTypes; // Method types, e.g. void private List> listMethodParams; // Method parameter names, e.g. A, B private List> listMethodParamTypes; // Method parameter types, e.g. int, int + private Map mapHelperNumMethodId; // Helper method Id, e.g. for callbacks, structs. + + private static int helperMethodIdNum = -9999; /** * Class constructors @@ -50,6 +53,7 @@ public class InterfaceDecl extends Declaration { listMethodTypes = new ArrayList(); listMethodParams = new ArrayList>(); listMethodParamTypes = new ArrayList>(); + mapHelperNumMethodId = new HashMap(); } @@ -61,6 +65,7 @@ public class InterfaceDecl extends Declaration { listMethodTypes = new ArrayList(); listMethodParams = new ArrayList>(); listMethodParamTypes = new ArrayList>(); + mapHelperNumMethodId = new HashMap(); } @@ -108,6 +113,20 @@ public class InterfaceDecl extends Declaration { } + /** + * getHelperMethodNumId() gets Id number for a method + */ + public int getHelperMethodNumId(String method) { + + if (!mapHelperNumMethodId.containsKey(method)) { + mapHelperNumMethodId.put(method, helperMethodIdNum++); + return mapHelperNumMethodId.get(method); + } else { + return mapHelperNumMethodId.get(method); + } + } + + /** * getMethodIds() gets method identifiers */ -- 2.34.1