3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
6 import java.util.Collection;
7 import java.util.Collections;
8 import java.util.HashMap;
9 import java.util.HashSet;
10 import java.util.Iterator;
11 import java.util.List;
15 import iotpolicy.parser.Lexer;
16 import iotpolicy.parser.Parser;
17 import iotpolicy.tree.ParseNode;
18 import iotpolicy.tree.ParseNodeVector;
19 import iotpolicy.tree.ParseTreeHandler;
20 import iotpolicy.tree.Declaration;
21 import iotpolicy.tree.DeclarationHandler;
22 import iotpolicy.tree.CapabilityDecl;
23 import iotpolicy.tree.InterfaceDecl;
24 import iotpolicy.tree.RequiresDecl;
26 import iotrmi.Java.IoTRMITypes;
29 /** Class IoTCompiler is the main interface/stub compiler for
30 * files generation. This class calls helper classes
31 * such as Parser, Lexer, InterfaceDecl, CapabilityDecl,
32 * RequiresDecl, ParseTreeHandler, etc.
34 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
38 public class IoTCompiler {
43 // Maps multiple interfaces to multiple objects of ParseTreeHandler
44 private Map<String,ParseTreeHandler> mapIntfacePTH;
45 private Map<String,DeclarationHandler> mapIntDeclHand;
46 private Map<String,Map<String,Set<String>>> mapInt2NewInts;
47 // Data structure to store our types (primitives and non-primitives) for compilation
48 private Map<String,String> mapPrimitives;
49 private Map<String,String> mapNonPrimitivesJava;
50 private Map<String,String> mapNonPrimitivesCplus;
51 private PrintWriter pw;
53 private String subdir;
58 private final static String OUTPUT_DIRECTORY = "output_files";
60 private enum ParamCategory {
62 PRIMITIVES, // All the primitive types, e.g. byte, short, int, long, etc.
63 NONPRIMITIVES, // Non-primitive types, e.g. Set, Map, List, etc.
64 USERDEFINED // Non-supported type by default; assumed as driver classes
70 public IoTCompiler() {
72 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
73 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
74 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
75 mapPrimitives = new HashMap<String,String>();
76 arraysToMap(mapPrimitives, IoTRMITypes.primitivesJava, IoTRMITypes.primitivesCplus);
77 mapNonPrimitivesJava = new HashMap<String,String>();
78 arraysToMap(mapNonPrimitivesJava, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitiveJavaLibs);
79 mapNonPrimitivesCplus = new HashMap<String,String>();
80 arraysToMap(mapNonPrimitivesCplus, IoTRMITypes.nonPrimitivesJava, IoTRMITypes.nonPrimitivesCplus);
82 dir = OUTPUT_DIRECTORY;
88 * setParseTree() sets parse tree based on policy files.
90 * It also generates parse tree (ParseTreeHandler) and
91 * copies useful information from parse tree into
92 * InterfaceDecl, CapabilityDecl, and RequiresDecl
94 * Additionally, the data structure handles are
95 * returned from tree-parsing for further process.
98 public void setParseTree(String origInt, ParseNode pnPol, ParseNode pnReq) {
100 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
101 DeclarationHandler decHandler = new DeclarationHandler();
103 // Process ParseNode and generate Declaration objects
104 ptHandler.processInterfaceDecl();
105 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
106 decHandler.addInterfaceDecl(origInt, intDecl);
107 ptHandler.processCapabilityDecl();
108 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
109 decHandler.addCapabilityDecl(origInt, capDecl);
110 ptHandler.processRequiresDecl();
111 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
112 decHandler.addRequiresDecl(origInt, reqDecl);
114 mapIntfacePTH.put(origInt, ptHandler);
115 mapIntDeclHand.put(origInt, decHandler);
120 * getMethodsForIntface() reads for methods in the data structure
122 * It is going to give list of methods for a certain interface
123 * based on the declaration of capabilities.
125 public void getMethodsForIntface(String origInt) {
127 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
128 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
129 // Get set of new interfaces, e.g. CameraWithCaptureAndData
130 // Generate this new interface with all the methods it needs
131 // from different capabilities it declares
132 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
133 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
134 Set<String> setIntfaces = reqDecl.getInterfaces();
135 for (String strInt : setIntfaces) {
137 // Initialize a set of methods
138 Set<String> setMethods = new HashSet<String>();
139 // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
140 List<String> listCapab = reqDecl.getCapabList(strInt);
141 for (String strCap : listCapab) {
143 // Get list of methods for each capability
144 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
145 List<String> listCapabMeth = capDecl.getMethods(strCap);
146 for (String strMeth : listCapabMeth) {
148 // Add methods into setMethods
149 // This is to also handle redundancies (say two capabilities
150 // share the same methods)
151 setMethods.add(strMeth);
154 // Add interface and methods information into map
155 mapNewIntMethods.put(strInt, setMethods);
157 // Map the map of interface-methods to the original interface
158 mapInt2NewInts.put(origInt, mapNewIntMethods);
163 * HELPER: writeMethodJavaInterface() writes the method of the interface
165 private void writeMethodJavaInterface(Collection<String> methods, InterfaceDecl intDecl) {
167 for (String method : methods) {
169 List<String> methParams = intDecl.getMethodParams(method);
170 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
171 print("public " + intDecl.getMethodType(method) + " " +
172 intDecl.getMethodId(method) + "(");
173 for (int i = 0; i < methParams.size(); i++) {
174 // Check for params with driver class types and exchange it
175 // with its remote interface
176 String paramType = checkAndGetParamClass(methPrmTypes.get(i), false);
177 print(paramType + " " + methParams.get(i));
178 // Check if this is the last element (don't print a comma)
179 if (i != methParams.size() - 1) {
189 * generateJavaLocalInterface() writes the local interface and provides type-checking.
191 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
192 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
193 * The local interface has to be the input parameter for the stub and the stub
194 * interface has to be the input parameter for the local class.
196 public void generateJavaLocalInterfaces() throws IOException {
198 // Create a new directory
199 createDirectory(dir);
200 for (String intface : mapIntfacePTH.keySet()) {
201 // Open a new file to write into
202 FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
203 pw = new PrintWriter(new BufferedWriter(fw));
204 // Pass in set of methods and get import classes
205 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
206 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
207 List<String> methods = intDecl.getMethods();
208 Set<String> importClasses = getImportClasses(methods, intDecl);
209 printImportStatements(importClasses);
210 // Write interface header
212 println("public interface " + intface + " {");
214 writeMethodJavaInterface(methods, intDecl);
217 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
223 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
225 public void generateJavaInterfaces() throws IOException {
227 // Create a new directory
228 String path = createDirectories(dir, subdir);
229 for (String intface : mapIntfacePTH.keySet()) {
231 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
232 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
234 // Open a new file to write into
235 String newIntface = intMeth.getKey();
236 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
237 pw = new PrintWriter(new BufferedWriter(fw));
238 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
239 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
240 // Pass in set of methods and get import classes
241 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
242 printImportStatements(importClasses);
243 // Write interface header
245 println("public interface " + newIntface + " {");
247 writeMethodJavaInterface(intMeth.getValue(), intDecl);
250 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
257 * HELPER: writeMethodJavaStub() writes the method of the stub class
259 private void writeMethodJavaStub(Collection<String> methods, InterfaceDecl intDecl) {
261 for (String method : methods) {
263 List<String> methParams = intDecl.getMethodParams(method);
264 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
265 print("public " + intDecl.getMethodType(method) + " " +
266 intDecl.getMethodId(method) + "(");
267 for (int i = 0; i < methParams.size(); i++) {
269 print(methPrmTypes.get(i) + " " + methParams.get(i));
270 // Check if this is the last element (don't print a comma)
271 if (i != methParams.size() - 1) {
276 // Check if this is not "void"
277 if (!intDecl.getMethodType(method).equals("void")) {
278 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
279 println("return " + retStmt + ";");
281 println("}"); println("");
287 * generateJavaStubClasses() generate stubs based on the methods list in Java
289 public void generateJavaStubClasses() throws IOException {
291 // Create a new directory
292 String path = createDirectories(dir, subdir);
293 for (String intface : mapIntfacePTH.keySet()) {
295 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
296 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
298 // Open a new file to write into
299 String newIntface = intMeth.getKey();
300 String newStubClass = newIntface + "_Stub";
301 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
302 pw = new PrintWriter(new BufferedWriter(fw));
303 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
304 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
305 // Pass in set of methods and get import classes
306 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
307 printImportStatements(importClasses);
308 // Write interface header
310 println("public class " + newStubClass + " implements " + newIntface + " {");
313 writeMethodJavaStub(intMeth.getValue(), intDecl);
316 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
323 * HELPER: writeMethodCplusInterface() writes the method of the interface
325 private void writeMethodCplusInterface(Collection<String> methods, InterfaceDecl intDecl) {
327 for (String method : methods) {
329 List<String> methParams = intDecl.getMethodParams(method);
330 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
331 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
332 intDecl.getMethodId(method) + "(");
333 for (int i = 0; i < methParams.size(); i++) {
334 // Check for params with driver class types and exchange it
335 // with its remote interface
336 String paramType = checkAndGetParamClass(methPrmTypes.get(i), true);
337 paramType = checkAndGetCplusType(paramType);
338 // Check for arrays - translate into vector in C++
339 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
340 print(paramComplete);
341 // Check if this is the last element (don't print a comma)
342 if (i != methParams.size() - 1) {
352 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
354 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
355 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
356 * The local interface has to be the input parameter for the stub and the stub
357 * interface has to be the input parameter for the local class.
359 public void generateCplusLocalInterfaces() throws IOException {
361 // Create a new directory
362 createDirectory(dir);
363 for (String intface : mapIntfacePTH.keySet()) {
364 // Open a new file to write into
365 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
366 pw = new PrintWriter(new BufferedWriter(fw));
367 // Write file headers
368 println("#include <iostream>");
369 // Pass in set of methods and get include classes
370 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
371 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
372 List<String> methods = intDecl.getMethods();
373 Set<String> includeClasses = getIncludeClasses(methods, intDecl);
374 printIncludeStatements(includeClasses);
376 println("using namespace std;");
378 println("class " + intface);
382 writeMethodCplusInterface(methods, intDecl);
386 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
392 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
394 * For C++ we use virtual classe as interface
396 public void generateCPlusInterfaces() throws IOException {
398 // Create a new directory
399 String path = createDirectories(dir, subdir);
400 for (String intface : mapIntfacePTH.keySet()) {
402 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
403 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
405 // Open a new file to write into
406 String newIntface = intMeth.getKey();
407 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
408 pw = new PrintWriter(new BufferedWriter(fw));
409 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
410 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
411 // Write file headers
412 println("#include <iostream>");
413 // Pass in set of methods and get import classes
414 Set<String> includeClasses = getIncludeClasses(intMeth.getValue(), intDecl);
415 printIncludeStatements(includeClasses);
417 println("using namespace std;");
419 println("class " + newIntface);
423 writeMethodCplusInterface(intMeth.getValue(), intDecl);
427 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
434 * HELPER: writeMethodCplusStub() writes the method of the stub
436 private void writeMethodCplusStub(Collection<String> methods, InterfaceDecl intDecl) {
438 for (String method : methods) {
440 List<String> methParams = intDecl.getMethodParams(method);
441 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
442 print(convertType(intDecl.getMethodType(method)) + " " +
443 intDecl.getMethodId(method) + "(");
444 for (int i = 0; i < methParams.size(); i++) {
445 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
446 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
447 print(methParamComplete);
448 // Check if this is the last element (don't print a comma)
449 if (i != methParams.size() - 1) {
454 // Check if this is not "void"
455 if (!intDecl.getMethodType(method).equals("void")) {
456 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
457 if (retStmt.equals("null")) { // null = NULL in C++
460 println("return " + retStmt + ";");
462 println("}"); println("");
468 * generateCPlusStubClasses() generate stubs based on the methods list in C++
470 public void generateCPlusStubClasses() throws IOException {
472 // Create a new directory
473 String path = createDirectories(dir, subdir);
474 for (String intface : mapIntfacePTH.keySet()) {
476 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
477 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
478 // Open a new file to write into
479 String newIntface = intMeth.getKey();
480 String newStubClass = newIntface + "_Stub";
481 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
482 pw = new PrintWriter(new BufferedWriter(fw));
483 // Write file headers
484 println("#include <iostream>");
485 println("#include \"" + newIntface + ".hpp\""); println("");
486 println("using namespace std;"); println("");
487 println("class " + newStubClass + " : public " + newIntface); println("{");
488 println("public:"); println("");
489 // Add default constructor and destructor
490 println(newStubClass + "() { }"); println("");
491 println("~" + newStubClass + "() { }"); println("");
492 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
493 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
495 writeMethodCplusStub(intMeth.getValue(), intDecl);
496 print("}"); println(";");
498 System.out.println("IoTCompiler: Generated stub class " + newIntface + ".hpp...");
505 * generateReturnStmt() generate return statement based on methType
507 public String generateReturnStmt(String methType) {
509 // Generate dummy returns for now
510 if (methType.equals("short")||
511 methType.equals("int") ||
512 methType.equals("long") ||
513 methType.equals("float")||
514 methType.equals("double")) {
517 } else if ( methType.equals("String")) {
520 } else if ( methType.equals("char") ||
521 methType.equals("byte")) {
524 } else if ( methType.equals("boolean")) {
534 * setDirectory() sets a new directory for stub files
536 public void setDirectory(String _subdir) {
543 * printUsage() prints the usage of this compiler
545 public static void printUsage() {
547 System.out.println();
548 System.out.println("Sentinel interface and stub compiler version 1.0");
549 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
550 System.out.println("All rights reserved.");
551 System.out.println("Usage:");
552 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
553 System.out.println("\t\tDisplay this help texts\n\n");
554 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
555 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
556 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
557 System.out.println("Options:");
558 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
559 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
560 System.out.println();
565 * parseFile() prepares Lexer and Parser objects, then parses the file
567 public static ParseNode parseFile(String file) {
571 ComplexSymbolFactory csf = new ComplexSymbolFactory();
572 ScannerBuffer lexer =
573 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
574 Parser parse = new Parser(lexer,csf);
575 pn = (ParseNode) parse.parse().value;
576 } catch (Exception e) {
578 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file);
589 boolean newline=true;
592 private void print(String str) {
597 for(int i=0; i<tab; i++)
606 * This function converts Java to C++ type for compilation
608 private String convertType(String jType) {
610 return mapPrimitives.get(jType);
614 private void println(String str) {
619 for(int i=0; i<tab; i++)
628 private void updatetabbing(String str) {
629 tablevel+=count(str,'{')-count(str,'}');
633 private int count(String str, char key) {
634 char[] array = str.toCharArray();
636 for(int i=0; i<array.length; i++) {
644 private void createDirectory(String dirName) {
646 File file = new File(dirName);
647 if (!file.exists()) {
649 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
651 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
654 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
659 // Create a directory and possibly a sub directory
660 private String createDirectories(String dir, String subdir) {
663 createDirectory(path);
664 if (subdir != null) {
665 path = path + "/" + subdir;
666 createDirectory(path);
672 // Inserting array members into a Map object
673 // that maps arrKey to arrVal objects
674 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
676 for(int i = 0; i < arrKey.length; i++) {
678 map.put(arrKey[i], arrVal[i]);
683 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, or USERDEFINED
684 private ParamCategory getParamCategory(String paramType) {
686 if (mapPrimitives.containsKey(paramType)) {
687 return ParamCategory.PRIMITIVES;
688 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
689 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
690 return ParamCategory.NONPRIMITIVES;
692 return ParamCategory.USERDEFINED;
696 // Return full class name for non-primitives to generate Java import statements
697 // e.g. java.util.Set for Set, java.util.Map for Map
698 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
700 return mapNonPrimitivesJava.get(paramNonPrimitives);
704 // Return full class name for non-primitives to generate Cplus include statements
705 // e.g. #include <set> for Set, #include <map> for Map
706 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
708 return mapNonPrimitivesCplus.get(paramNonPrimitives);
712 // Get simple types, e.g. HashSet for HashSet<...>
713 // Basically strip off the "<...>"
714 private String getSimpleType(String paramType) {
716 // Check if this is generics
717 if(paramType.contains("<")) {
718 String[] type = paramType.split("<");
725 // Generate a set of classes for import statements
726 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
728 Set<String> importClasses = new HashSet<String>();
729 for (String method : methods) {
730 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
731 for (String paramType : methPrmTypes) {
733 String simpleType = getSimpleType(paramType);
734 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
735 importClasses.add(getNonPrimitiveJavaClass(simpleType));
739 return importClasses;
743 // Generate a set of classes for include statements
744 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl) {
746 Set<String> includeClasses = new HashSet<String>();
747 for (String method : methods) {
749 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
750 List<String> methParams = intDecl.getMethodParams(method);
751 for (int i = 0; i < methPrmTypes.size(); i++) {
753 String simpleType = getSimpleType(methPrmTypes.get(i));
754 String param = methParams.get(i);
755 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
756 includeClasses.add("<" + getNonPrimitiveCplusClass(simpleType) + ">");
757 } else if (getParamCategory(simpleType) == ParamCategory.USERDEFINED) {
758 includeClasses.add("\"" + exchangeParamType(simpleType) + ".hpp\"");
759 } else if (param.contains("[]")) {
760 // Check if this is array for C++; translate into vector
761 includeClasses.add("<vector>");
765 return includeClasses;
769 private void printImportStatements(Set<String> importClasses) {
771 for(String cls : importClasses) {
772 println("import " + cls + ";");
777 private void printIncludeStatements(Set<String> includeClasses) {
779 for(String cls : includeClasses) {
780 println("#include " + cls);
785 // Get the C++ version of a non-primitive type
786 // e.g. set for Set and map for Map
787 // Input nonPrimitiveType has to be generics in format
788 private String[] getTypeOfGeneric(String nonPrimitiveType) {
790 // Handle <, >, and , for 2-type generic/template
791 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
796 private String checkAndGetCplusType(String paramType) {
798 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
799 return convertType(paramType);
800 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
802 // Check for generic/template format
803 if (paramType.contains("<") && paramType.contains(">")) {
805 String genericClass = getSimpleType(paramType);
806 String[] genericType = getTypeOfGeneric(paramType);
807 String cplusTemplate = null;
808 if (genericType.length == 1) // Generic/template with one type
809 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
810 "<" + convertType(genericType[0]) + ">";
811 else // Generic/template with two types
812 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
813 "<" + convertType(genericType[0]) + "," + convertType(genericType[1]) + ">";
814 return cplusTemplate;
816 return getNonPrimitiveCplusClass(paramType);
818 // Just return it as is if it's not non-primitives
823 // Detect array declaration, e.g. int A[],
824 // then generate "int A[]" in C++ as "vector<int> A"
825 private String checkAndGetCplusArray(String paramType, String param) {
827 String paramComplete = null;
828 // Check for array declaration
829 if (param.contains("[]")) {
830 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
832 // Just return it as is if it's not an array
833 paramComplete = paramType + " " + param;
835 return paramComplete;
839 // Get simple types, e.g. HashSet for HashSet<...>
840 // Basically strip off the "<...>"
841 private String checkAndGetParamClass(String paramType, boolean needPtr) {
843 // Check if this is generics
844 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
845 // If true then return with pointer (C++)
847 return exchangeParamType(paramType) + "*";
848 else // Java, so no pointer needed
849 return exchangeParamType(paramType);
855 // Returns the other interface for type-checking purposes for USERDEFINED
856 // classes based on the information provided in multiple policy files
857 // e.g. return CameraWithXXX instead of Camera
858 private String exchangeParamType(String intface) {
860 // Param type that's passed is the interface name we need to look for
861 // in the map of interfaces, based on available policy files.
862 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
863 if (decHandler != null) {
864 // We've found the required interface policy files
865 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
866 Set<String> setExchInt = reqDecl.getInterfaces();
867 if (setExchInt.size() == 1) {
868 Iterator iter = setExchInt.iterator();
869 return (String) iter.next();
871 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
872 ". Only one new interface can be declared if the object " + intface +
873 " needs to be passed in as an input parameter!");
876 // NULL value - this means policy files missing
877 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
878 "... Please provide the necessary policy files for user-defined types." +
879 " If this is an array please type the brackets after the variable name," +
880 " e.g. \"String str[]\", not \"String[] str\"." +
881 " If this is a Collections (Java) / STL (C++) type, this compiler only" +
882 " supports List/ArrayList (Java) or list (C++).");
887 public static void main(String[] args) throws Exception {
889 // If there is no argument or just "--help" or "-h", then invoke printUsage()
890 if ((args[0].equals("-help") ||
891 args[0].equals("--help")||
892 args[0].equals("-h")) ||
893 (args.length == 0)) {
895 IoTCompiler.printUsage();
897 } else if (args.length > 1) {
899 IoTCompiler comp = new IoTCompiler();
902 // Parse main policy file
903 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
904 // Parse "requires" policy file
905 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
906 // Get interface name
907 String intface = ParseTreeHandler.getOrigIntface(pnPol);
908 comp.setParseTree(intface, pnPol, pnReq);
909 comp.getMethodsForIntface(intface);
911 // 1) Check if this is the last option before "-java" or "-cplus"
912 // 2) Check if this is really the last option (no "-java" or "-cplus")
913 } while(!args[i].equals("-java") &&
914 !args[i].equals("-cplus") &&
917 // Generate everything if we don't see "-java" or "-cplus"
918 if (i == args.length) {
919 comp.generateJavaLocalInterfaces();
920 comp.generateJavaInterfaces();
921 comp.generateJavaStubClasses();
922 comp.generateCplusLocalInterfaces();
923 comp.generateCPlusInterfaces();
924 comp.generateCPlusStubClasses();
926 // Check other options
927 while(i < args.length) {
929 if (!args[i].equals("-java") &&
930 !args[i].equals("-cplus")) {
931 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]);
933 if (i + 1 < args.length) {
934 comp.setDirectory(args[i+1]);
936 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i]);
938 if (args[i].equals("-java")) {
939 comp.generateJavaLocalInterfaces();
940 comp.generateJavaInterfaces();
941 comp.generateJavaStubClasses();
943 comp.generateCplusLocalInterfaces();
944 comp.generateCPlusInterfaces();
945 comp.generateCPlusStubClasses();
952 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
953 IoTCompiler.printUsage();
954 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!");