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 * generateJavaLocalInterface() writes the local interface and provides type-checking.
165 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
166 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
167 * The local interface has to be the input parameter for the stub and the stub
168 * interface has to be the input parameter for the local class.
170 public void generateJavaLocalInterfaces() throws IOException {
172 // Create a new directory
173 createDirectory(dir);
174 for (String intface : mapIntfacePTH.keySet()) {
175 // Open a new file to write into
176 FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
177 pw = new PrintWriter(new BufferedWriter(fw));
178 // Pass in set of methods and get import classes
179 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
180 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
181 List<String> methods = intDecl.getMethods();
182 Set<String> importClasses = getImportClasses(methods, intDecl);
183 printImportStatements(importClasses);
184 // Write interface header
186 println("public interface " + intface + " {");
188 for (String method : methods) {
190 List<String> methParams = intDecl.getMethodParams(method);
191 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
192 print("public " + intDecl.getMethodType(method) + " " +
193 intDecl.getMethodId(method) + "(");
194 for (int i = 0; i < methParams.size(); i++) {
195 // Check for params with driver class types and exchange it
196 // with its remote interface
197 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
198 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
199 //print(paramType + " " + methParams.get(i));
200 print(paramComplete);
201 // Check if this is the last element (don't print a comma)
202 if (i != methParams.size() - 1) {
210 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
216 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
218 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
219 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
220 * The local interface has to be the input parameter for the stub and the stub
221 * interface has to be the input parameter for the local class.
223 public void generateCplusLocalInterfaces() throws IOException {
225 // Create a new directory
226 createDirectory(dir);
227 for (String intface : mapIntfacePTH.keySet()) {
228 // Open a new file to write into
229 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
230 pw = new PrintWriter(new BufferedWriter(fw));
231 // Write file headers
232 println("#include <iostream>");
233 // Pass in set of methods and get include classes
234 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
235 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
236 List<String> methods = intDecl.getMethods();
237 Set<String> includeClasses = getIncludeClasses(methods, intDecl);
238 printIncludeStatements(includeClasses);
240 println("using namespace std;");
242 println("class " + intface);
246 for (String method : methods) {
248 List<String> methParams = intDecl.getMethodParams(method);
249 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
250 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
251 intDecl.getMethodId(method) + "(");
252 for (int i = 0; i < methParams.size(); i++) {
253 // Check for params with driver class types and exchange it
254 // with its remote interface
255 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
256 paramType = checkAndGetCplusType(paramType);
257 // Check for arrays - translate into vector in C++
258 String paramComplete = checkAndGetCplusArray(paramType, methParams.get(i));
259 //print(paramType + " " + param);
260 print(paramComplete);
261 // Check if this is the last element (don't print a comma)
262 if (i != methParams.size() - 1) {
271 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
277 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
279 public void generateJavaInterfaces() throws IOException {
281 // Create a new directory
282 String path = createDirectories(dir, subdir);
283 for (String intface : mapIntfacePTH.keySet()) {
285 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
286 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
288 // Open a new file to write into
289 String newIntface = intMeth.getKey();
290 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
291 pw = new PrintWriter(new BufferedWriter(fw));
292 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
293 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
294 // Pass in set of methods and get import classes
295 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
296 printImportStatements(importClasses);
297 // Write interface header
299 println("public interface " + newIntface + " {");
300 List<String> meths = intDecl.getMethods();
302 for (String method : intMeth.getValue()) {
304 List<String> methParams = intDecl.getMethodParams(method);
305 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
306 print("public " + intDecl.getMethodType(method) + " " +
307 intDecl.getMethodId(method) + "(");
308 for (int i = 0; i < methParams.size(); i++) {
309 print(methPrmTypes.get(i) + " " + methParams.get(i));
310 // Check if this is the last element (don't print a comma)
311 if (i != methParams.size() - 1) {
319 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
326 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
328 * For C++ we use virtual classe as interface
330 public void generateCPlusInterfaces() throws IOException {
332 // Create a new directory
333 String path = createDirectories(dir, subdir);
334 for (String intface : mapIntfacePTH.keySet()) {
336 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
337 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
339 // Open a new file to write into
340 String newIntface = intMeth.getKey();
341 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
342 pw = new PrintWriter(new BufferedWriter(fw));
343 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
344 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
345 // Write file headers
346 println("#include <iostream>");
347 // Pass in set of methods and get import classes
348 Set<String> includeClasses = getIncludeClasses(intMeth.getValue(), intDecl);
349 printIncludeStatements(includeClasses);
351 println("using namespace std;");
353 println("class " + newIntface);
357 for (String method : intMeth.getValue()) {
359 List<String> methParams = intDecl.getMethodParams(method);
360 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
361 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
362 intDecl.getMethodId(method) + "(");
363 for (int i = 0; i < methParams.size(); i++) {
365 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
366 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
367 //print(methPrmType + " " + methParam);
368 print(methParamComplete);
369 // Check if this is the last element (don't print a comma)
370 if (i != methParams.size() - 1) {
379 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
386 * generateJavaStubClasses() generate stubs based on the methods list in Java
388 public void generateJavaStubClasses() throws IOException {
390 // Create a new directory
391 String path = createDirectories(dir, subdir);
392 for (String intface : mapIntfacePTH.keySet()) {
394 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
395 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
397 // Open a new file to write into
398 String newIntface = intMeth.getKey();
399 String newStubClass = newIntface + "_Stub";
400 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
401 pw = new PrintWriter(new BufferedWriter(fw));
402 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
403 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
404 // Pass in set of methods and get import classes
405 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
406 printImportStatements(importClasses);
407 // Write interface header
409 println("public class " + newStubClass + " implements " + newIntface + " {");
412 for (String method : intMeth.getValue()) {
414 List<String> methParams = intDecl.getMethodParams(method);
415 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
416 print("public " + intDecl.getMethodType(method) + " " +
417 intDecl.getMethodId(method) + "(");
418 for (int i = 0; i < methParams.size(); i++) {
420 print(methPrmTypes.get(i) + " " + methParams.get(i));
421 // Check if this is the last element (don't print a comma)
422 if (i != methParams.size() - 1) {
427 // Check if this is not "void"
428 if (!intDecl.getMethodType(method).equals("void")) {
429 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
430 println("return " + retStmt + ";");
432 println("}"); println("");
436 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
443 * generateCPlusStubClasses() generate stubs based on the methods list in C++
445 public void generateCPlusStubClasses() throws IOException {
447 // Create a new directory
448 String path = createDirectories(dir, subdir);
449 for (String intface : mapIntfacePTH.keySet()) {
451 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
452 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
453 // Open a new file to write into
454 String newIntface = intMeth.getKey();
455 String newStubClass = newIntface + "_Stub";
456 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
457 pw = new PrintWriter(new BufferedWriter(fw));
458 // Write file headers
459 println("#include <iostream>");
460 println("#include \"" + newIntface + ".hpp\""); println("");
461 println("using namespace std;"); println("");
462 println("class " + newStubClass + " : public " + newIntface); println("{");
463 println("public:"); println("");
464 // Add default constructor and destructor
465 println(newStubClass + "() { }"); println("");
466 println("~" + newStubClass + "() { }"); println("");
467 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
468 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
470 for (String method : intMeth.getValue()) {
472 List<String> methParams = intDecl.getMethodParams(method);
473 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
475 //System.out.println("\n\nMethod param: " + intDecl.getMethodParams(method));
476 //System.out.println("\n\nMethod param type: " + intDecl.getMethodParamTypes(method));
477 //System.out.println("\n\n");
479 print(convertType(intDecl.getMethodType(method)) + " " +
480 intDecl.getMethodId(method) + "(");
481 for (int i = 0; i < methParams.size(); i++) {
482 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
483 String methParamComplete = checkAndGetCplusArray(methPrmType, methParams.get(i));
484 //print(methPrmType + " " + methParam);
485 print(methParamComplete);
486 // Check if this is the last element (don't print a comma)
487 if (i != methParams.size() - 1) {
492 // Check if this is not "void"
493 if (!intDecl.getMethodType(method).equals("void")) {
494 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
495 if (retStmt.equals("null")) { // null = NULL in C++
498 println("return " + retStmt + ";");
500 println("}"); println("");
502 print("}"); println(";");
504 System.out.println("IoTCompiler: Generated stub class " + newIntface + ".hpp...");
511 * generateReturnStmt() generate return statement based on methType
513 public String generateReturnStmt(String methType) {
515 // Generate dummy returns for now
516 if (methType.equals("short")||
517 methType.equals("int") ||
518 methType.equals("long") ||
519 methType.equals("float")||
520 methType.equals("double")) {
523 } else if ( methType.equals("String") ||
524 methType.equals("byte")) {
527 } else if ( methType.equals("char")) {
530 } else if ( methType.equals("boolean")) {
540 * setDirectory() sets a new directory for stub files
542 public void setDirectory(String _subdir) {
549 * printUsage() prints the usage of this compiler
551 public static void printUsage() {
553 System.out.println();
554 System.out.println("Sentinel interface and stub compiler version 1.0");
555 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
556 System.out.println("All rights reserved.");
557 System.out.println("Usage:");
558 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
559 System.out.println("\t\tDisplay this help texts\n\n");
560 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
561 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
562 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
563 System.out.println("Options:");
564 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
565 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
566 System.out.println();
571 * parseFile() prepares Lexer and Parser objects, then parses the file
573 public static ParseNode parseFile(String file) {
577 ComplexSymbolFactory csf = new ComplexSymbolFactory();
578 ScannerBuffer lexer =
579 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
580 Parser parse = new Parser(lexer,csf);
581 pn = (ParseNode) parse.parse().value;
582 } catch (Exception e) {
584 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file);
595 boolean newline=true;
598 private void print(String str) {
603 for(int i=0; i<tab; i++)
612 * This function converts Java to C++ type for compilation
614 private String convertType(String jType) {
616 return mapPrimitives.get(jType);
620 private void println(String str) {
625 for(int i=0; i<tab; i++)
634 private void updatetabbing(String str) {
635 tablevel+=count(str,'{')-count(str,'}');
639 private int count(String str, char key) {
640 char[] array = str.toCharArray();
642 for(int i=0; i<array.length; i++) {
650 private void createDirectory(String dirName) {
652 File file = new File(dirName);
653 if (!file.exists()) {
655 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
657 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
660 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
665 // Create a directory and possibly a sub directory
666 private String createDirectories(String dir, String subdir) {
669 createDirectory(path);
670 if (subdir != null) {
671 path = path + "/" + subdir;
672 createDirectory(path);
678 // Inserting array members into a Map object
679 // that maps arrKey to arrVal objects
680 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
682 for(int i = 0; i < arrKey.length; i++) {
684 map.put(arrKey[i], arrVal[i]);
689 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, or USERDEFINED
690 private ParamCategory getParamCategory(String paramType) {
692 if (mapPrimitives.containsKey(paramType)) {
693 return ParamCategory.PRIMITIVES;
694 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
695 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
696 return ParamCategory.NONPRIMITIVES;
698 return ParamCategory.USERDEFINED;
702 // Return full class name for non-primitives to generate Java import statements
703 // e.g. java.util.Set for Set, java.util.Map for Map
704 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
706 return mapNonPrimitivesJava.get(paramNonPrimitives);
710 // Return full class name for non-primitives to generate Cplus include statements
711 // e.g. #include <set> for Set, #include <map> for Map
712 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
714 return mapNonPrimitivesCplus.get(paramNonPrimitives);
718 // Get simple types, e.g. HashSet for HashSet<...>
719 // Basically strip off the "<...>"
720 private String getSimpleType(String paramType) {
722 // Check if this is generics
723 if(paramType.contains("<")) {
724 String[] type = paramType.split("<");
731 // Generate a set of classes for import statements
732 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
734 Set<String> importClasses = new HashSet<String>();
735 for (String method : methods) {
736 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
737 for (String paramType : methPrmTypes) {
739 String simpleType = getSimpleType(paramType);
740 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
741 importClasses.add(getNonPrimitiveJavaClass(simpleType));
745 return importClasses;
749 // Generate a set of classes for include statements
750 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl) {
752 Set<String> includeClasses = new HashSet<String>();
753 for (String method : methods) {
755 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
756 List<String> methParams = intDecl.getMethodParams(method);
757 for (int i = 0; i < methPrmTypes.size(); i++) {
759 String simpleType = getSimpleType(methPrmTypes.get(i));
760 String param = methParams.get(i);
761 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
762 includeClasses.add(getNonPrimitiveCplusClass(simpleType));
763 } else if (param.contains("[]")) {
764 // Check if this is array for C++; translate into vector
765 includeClasses.add("vector");
769 return includeClasses;
773 private void printImportStatements(Set<String> importClasses) {
775 for(String cls : importClasses) {
776 println("import " + cls + ";");
781 private void printIncludeStatements(Set<String> includeClasses) {
783 for(String cls : includeClasses) {
784 println("#include <" + cls + ">");
789 // Get the C++ version of a non-primitive type
790 // e.g. set for Set and map for Map
791 // Input nonPrimitiveType has to be generics in format
792 private String[] getTypeOfGeneric(String nonPrimitiveType) {
794 // Handle <, >, and , for 2-type generic/template
795 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
800 private String checkAndGetCplusType(String paramType) {
802 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
803 return convertType(paramType);
804 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
806 // Check for generic/template format
807 if (paramType.contains("<") && paramType.contains(">")) {
809 String genericClass = getSimpleType(paramType);
810 String[] genericType = getTypeOfGeneric(paramType);
811 String cplusTemplate = null;
812 if (genericType.length == 1) // Generic/template with one type
813 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
814 "<" + convertType(genericType[0]) + ">";
815 else // Generic/template with two types
816 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
817 "<" + convertType(genericType[0]) + "," + convertType(genericType[1]) + ">";
818 return cplusTemplate;
820 return getNonPrimitiveCplusClass(paramType);
822 // Just return it as is if it's not non-primitives
827 // Detect array declaration, e.g. int A[],
828 // then generate "int A[]" in C++ as "vector<int> A"
829 private String checkAndGetCplusArray(String paramType, String param) {
831 String paramComplete = null;
832 // Check for array declaration
833 if (param.contains("[]")) {
834 paramComplete = "vector<" + paramType + "> " + param.replace("[]","");
836 // Just return it as is if it's not an array
837 paramComplete = paramType + " " + param;
839 return paramComplete;
843 // Get simple types, e.g. HashSet for HashSet<...>
844 // Basically strip off the "<...>"
845 private String checkAndGetParamClass(String paramType) {
847 // Check if this is generics
848 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
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!");