}
+ /**
+ * HELPER: writeMethodJavaLocalInterface() writes the method of the interface
+ */
+ private void writeMethodJavaLocalInterface(Collection<String> methods, InterfaceDecl intDecl) {
+
+ for (String method : methods) {
+
+ List<String> methParams = intDecl.getMethodParams(method);
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ print("public " + intDecl.getMethodType(method) + " " +
+ intDecl.getMethodId(method) + "(");
+ for (int i = 0; i < methParams.size(); i++) {
+ // 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
*/
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) {
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...");
/**
* 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<String> callbackClasses) {
println("private IoTRMICall rmiCall;");
- //println("private IoTRMIObject rmiObj;");
println("private String address;");
println("private int[] ports;\n");
// Get the object Id
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");
}
/**
* HELPER: writeConstructorJavaStub() writes the constructor of the stub class
*/
- private void writeConstructorJavaStub(String intface) {
+ private void writeConstructorJavaStub(String intface, boolean callbackExist, Set<String> 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");
}
}
+ /**
+ * 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<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 (" + 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<String> methods, InterfaceDecl intDecl) {
+ private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
for (String method : methods) {
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 = 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) {
}
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);
}
}
DeclarationHandler decHandler = mapIntDeclHand.get(intface);
InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
// Pass in set of methods and get import classes
- Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
+ Set<String> methods = intMeth.getValue();
+ Set<String> importClasses = getImportClasses(methods, intDecl);
List<String> stdImportClasses = getStandardJavaImportClasses();
List<String> allImportClasses = getAllImportClasses(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);
+ 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...");
}
+ /**
+ * 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;");
+ // 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<String> 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
+ * <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 = getAllImportClasses(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(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<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
}
+ /**
+ * 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<String> methods, InterfaceDecl intDecl) {
+ private void writeMethodJavaSkeleton(Collection<String> methods, InterfaceDecl intDecl, Set<String> callbackClasses) {
for (String method : methods) {
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++) {
- 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(", ");
// 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<Integer,String> writeCallbackStubGeneration(List<String> methParams, List<String> methPrmTypes, String callbackType) {
+
+ Map<Integer,String> mapStubParam = new HashMap<Integer,String>();
+ // 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;
}
* 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) {
+ 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 = 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(", ");
}
print(", ");
}
println(" });");
+ Map<Integer,String> mapStubParam = null;
+ if (isCallbackMethod)
+ mapStubParam = writeCallbackStubGeneration(methParams, methPrmTypes, callbackType);
// Check if this is "void"
String retType = intDecl.getMethodType(method);
if (retType.equals("void")) {
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<String> methods, InterfaceDecl intDecl) {
+ 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>();
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");
}
}
/**
* HELPER: writeJavaWaitRequestInvokeMethod() writes the main loop of the skeleton class
*/
- private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl) {
+ private void writeJavaWaitRequestInvokeMethod(Collection<String> methods, InterfaceDecl intDecl, boolean callbackExist) {
// Use this set to handle two same methodIds
Set<String> uniqueMethodIds = new HashSet<String>();
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("}");
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);
List<String> stdImportClasses = getStandardJavaImportClasses();
List<String> allImportClasses = getAllImportClasses(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);
+ 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...");
}
+ /**
+ * 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<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);
+ 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<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
+ 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<String> methods = intDecl.getMethods();
+ Set<String> importClasses = getImportClasses(methods, intDecl);
+ List<String> stdImportClasses = getStandardJavaImportClasses();
+ List<String> allImportClasses = getAllImportClasses(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);
+ // 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
*/
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));
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)
*/
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<int>\t\t\tports;\n");
+ println("string address;");
+ println("vector<int> 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");
}
+ /**
+ * 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<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));
+ // Write file headers
+ println("#ifndef _" + newStubClass.toUpperCase() + "_HPP__");
+ println("#define _" + newStubClass.toUpperCase() + "_HPP__");
+ println("#include <iostream>");
+ println("#include \"" + newIntface + ".hpp\""); println("");
+ println("using namespace std;"); println("");
+ println("class " + newStubClass + " : public " + newIntface); println("{");
+ println("private:\n");
+ 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
*/
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)
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__");
}
+ /**
+ * 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<String> methods, InterfaceDecl intDecl) {
+
+ // 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);
+ 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<String> methods, InterfaceDecl intDecl) {
+
+ // Use this set to handle two same methodIds
+ Set<String> uniqueMethodIds = new HashSet<String>();
+ 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 <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);
+ List<String> stdIncludeClasses = getStandardCplusIncludeClasses();
+ List<String> 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
*/
}
+ // Generate a set of callback classes
+ private Set<String> getCallbackClasses(Collection<String> methods, InterfaceDecl intDecl) {
+
+ Set<String> callbackClasses = new HashSet<String>();
+ for (String method : methods) {
+
+ List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
+ List<String> methParams = intDecl.getMethodParams(method);
+ for (int i = 0; i < methPrmTypes.size(); i++) {
+
+ String type = methPrmTypes.get(i);
+ if (getParamCategory(type) == ParamCategory.USERDEFINED) {
+ 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<String> importClasses) {
for(String cls : importClasses) {
}
- // 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
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) {
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;