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;
27 /** Class IoTCompiler is the main interface/stub compiler for
28 * files generation. This class calls helper classes
29 * such as Parser, Lexer, InterfaceDecl, CapabilityDecl,
30 * RequiresDecl, ParseTreeHandler, etc.
32 * @author Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
36 public class IoTCompiler {
41 // Maps multiple interfaces to multiple objects of ParseTreeHandler
42 private Map<String,ParseTreeHandler> mapIntfacePTH;
43 private Map<String,DeclarationHandler> mapIntDeclHand;
44 private Map<String,Map<String,Set<String>>> mapInt2NewInts;
45 // Data structure to store our types (primitives and non-primitives) for compilation
46 private Map<String,String> mapPrimitives;
47 private Map<String,String> mapNonPrimitivesJava;
48 private Map<String,String> mapNonPrimitivesCplus;
49 private PrintWriter pw;
51 private String subdir;
56 private final static String OUTPUT_DIRECTORY = "output_files";
59 * Primitive data types
61 private final static String[] primitives = new String[] {
85 * Primitive data types in C++ to map the primitives list
87 private final static String[] primitivesCplus = new String[] {
111 * Non-primitive data types supported by this compiler
113 private final static String[] nonPrimitives = new String[] {
124 * Non-primitive Java libraries based on the list above
126 private final static String[] nonPrimitiveJavaLibs = new String[] {
133 "java.util.ArrayList"
137 * Non-primitive C++ libraries based on the list above
139 private final static String[] nonPrimitiveCplusLibs = new String[] {
149 private enum ParamCategory {
151 PRIMITIVES, // All the primitive types, e.g. byte, short, int, long, etc.
152 NONPRIMITIVES, // Non-primitive types, e.g. Set, Map, List, etc.
153 USERDEFINED // Non-supported type by default; assumed as driver classes
159 public IoTCompiler() {
161 mapIntfacePTH = new HashMap<String,ParseTreeHandler>();
162 mapIntDeclHand = new HashMap<String,DeclarationHandler>();
163 mapInt2NewInts = new HashMap<String,Map<String,Set<String>>>();
164 mapPrimitives = new HashMap<String,String>();
165 arraysToMap(mapPrimitives, primitives, primitivesCplus);
166 mapNonPrimitivesJava = new HashMap<String,String>();
167 arraysToMap(mapNonPrimitivesJava, nonPrimitives, nonPrimitiveJavaLibs);
168 mapNonPrimitivesCplus = new HashMap<String,String>();
169 arraysToMap(mapNonPrimitivesCplus, nonPrimitives, nonPrimitiveCplusLibs);
171 dir = OUTPUT_DIRECTORY;
177 * setParseTree() sets parse tree based on policy files.
179 * It also generates parse tree (ParseTreeHandler) and
180 * copies useful information from parse tree into
181 * InterfaceDecl, CapabilityDecl, and RequiresDecl
183 * Additionally, the data structure handles are
184 * returned from tree-parsing for further process.
187 public void setParseTree(String origInt, ParseNode pnPol, ParseNode pnReq) {
189 ParseTreeHandler ptHandler = new ParseTreeHandler(origInt, pnPol, pnReq);
190 DeclarationHandler decHandler = new DeclarationHandler();
192 // Process ParseNode and generate Declaration objects
193 ptHandler.processInterfaceDecl();
194 InterfaceDecl intDecl = ptHandler.getInterfaceDecl();
195 decHandler.addInterfaceDecl(origInt, intDecl);
196 ptHandler.processCapabilityDecl();
197 CapabilityDecl capDecl = ptHandler.getCapabilityDecl();
198 decHandler.addCapabilityDecl(origInt, capDecl);
199 ptHandler.processRequiresDecl();
200 RequiresDecl reqDecl = ptHandler.getRequiresDecl();
201 decHandler.addRequiresDecl(origInt, reqDecl);
203 mapIntfacePTH.put(origInt, ptHandler);
204 mapIntDeclHand.put(origInt, decHandler);
209 * getMethodsForIntface() reads for methods in the data structure
211 * It is going to give list of methods for a certain interface
212 * based on the declaration of capabilities.
214 public void getMethodsForIntface(String origInt) {
216 ParseTreeHandler ptHandler = mapIntfacePTH.get(origInt);
217 Map<String,Set<String>> mapNewIntMethods = new HashMap<String,Set<String>>();
218 // Get set of new interfaces, e.g. CameraWithCaptureAndData
219 // Generate this new interface with all the methods it needs
220 // from different capabilities it declares
221 DeclarationHandler decHandler = mapIntDeclHand.get(origInt);
222 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(origInt);
223 Set<String> setIntfaces = reqDecl.getInterfaces();
224 for (String strInt : setIntfaces) {
226 // Initialize a set of methods
227 Set<String> setMethods = new HashSet<String>();
228 // Get list of capabilities, e.g. ImageCapture, VideoRecording, etc.
229 List<String> listCapab = reqDecl.getCapabList(strInt);
230 for (String strCap : listCapab) {
232 // Get list of methods for each capability
233 CapabilityDecl capDecl = (CapabilityDecl) decHandler.getCapabilityDecl(origInt);
234 List<String> listCapabMeth = capDecl.getMethods(strCap);
235 for (String strMeth : listCapabMeth) {
237 // Add methods into setMethods
238 // This is to also handle redundancies (say two capabilities
239 // share the same methods)
240 setMethods.add(strMeth);
243 // Add interface and methods information into map
244 mapNewIntMethods.put(strInt, setMethods);
246 // Map the map of interface-methods to the original interface
247 mapInt2NewInts.put(origInt, mapNewIntMethods);
249 /* for (String origint : mapInt2NewInts.keySet()) {
251 System.out.println("Original Interface: " + origint);
252 Map<String,Set<String>> mapNewInt = mapInt2NewInts.get(origint);
253 for (String intf : mapNewInt.keySet()) {
255 System.out.println("\tNew Interface: " + intf);
256 Set<String> methods = mapNewInt.get(intf);
257 for (String meth : methods) {
259 System.out.println("\t\tMethod: " + meth);
267 * generateJavaLocalInterface() writes the local interface and provides type-checking.
269 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
270 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
271 * The local interface has to be the input parameter for the stub and the stub
272 * interface has to be the input parameter for the local class.
274 public void generateJavaLocalInterfaces() throws IOException {
276 // Create a new directory
277 createDirectory(dir);
278 for (String intface : mapIntfacePTH.keySet()) {
279 // Open a new file to write into
280 FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
281 pw = new PrintWriter(new BufferedWriter(fw));
282 // Pass in set of methods and get import classes
283 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
284 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
285 List<String> methods = intDecl.getMethods();
286 Set<String> importClasses = getImportClasses(methods, intDecl);
287 printImportStatements(importClasses);
288 // Write interface header
290 println("public interface " + intface + " {");
292 for (String method : methods) {
294 List<String> methParams = intDecl.getMethodParams(method);
295 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
296 print("public " + intDecl.getMethodType(method) + " " +
297 intDecl.getMethodId(method) + "(");
298 for (int i = 0; i < methParams.size(); i++) {
299 // Check for params with driver class types and exchange it
300 // with its remote interface
301 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
302 print(paramType + " " + methParams.get(i));
303 // Check if this is the last element (don't print a comma)
304 if (i != methParams.size() - 1) {
312 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
318 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
320 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
321 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
322 * The local interface has to be the input parameter for the stub and the stub
323 * interface has to be the input parameter for the local class.
325 public void generateCplusLocalInterfaces() throws IOException {
327 // Create a new directory
328 createDirectory(dir);
329 for (String intface : mapIntfacePTH.keySet()) {
330 // Open a new file to write into
331 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
332 pw = new PrintWriter(new BufferedWriter(fw));
333 // Write file headers
334 println("#include <iostream>");
335 // Pass in set of methods and get include classes
336 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
337 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
338 List<String> methods = intDecl.getMethods();
339 Set<String> includeClasses = getIncludeClasses(methods, intDecl);
340 printIncludeStatements(includeClasses);
342 println("using namespace std;");
344 println("class " + intface);
348 for (String method : methods) {
350 List<String> methParams = intDecl.getMethodParams(method);
351 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
352 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
353 intDecl.getMethodId(method) + "(");
354 for (int i = 0; i < methParams.size(); i++) {
355 // Check for params with driver class types and exchange it
356 // with its remote interface
357 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
358 paramType = checkAndGetCplusType(paramType);
359 print(paramType + " " + methParams.get(i));
360 // Check if this is the last element (don't print a comma)
361 if (i != methParams.size() - 1) {
370 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
376 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
378 public void generateJavaInterfaces() throws IOException {
380 // Create a new directory
381 String path = createDirectories(dir, subdir);
382 for (String intface : mapIntfacePTH.keySet()) {
384 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
385 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
387 // Open a new file to write into
388 String newIntface = intMeth.getKey();
389 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
390 pw = new PrintWriter(new BufferedWriter(fw));
391 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
392 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
393 // Pass in set of methods and get import classes
394 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
395 printImportStatements(importClasses);
396 // Write interface header
398 println("public interface " + newIntface + " {");
399 List<String> meths = intDecl.getMethods();
401 for (String method : intMeth.getValue()) {
403 List<String> methParams = intDecl.getMethodParams(method);
404 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
405 print("public " + intDecl.getMethodType(method) + " " +
406 intDecl.getMethodId(method) + "(");
407 for (int i = 0; i < methParams.size(); i++) {
408 print(methPrmTypes.get(i) + " " + methParams.get(i));
409 // Check if this is the last element (don't print a comma)
410 if (i != methParams.size() - 1) {
418 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
425 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
427 * For C++ we use virtual classe as interface
429 public void generateCPlusInterfaces() throws IOException {
431 // Create a new directory
432 String path = createDirectories(dir, subdir);
433 for (String intface : mapIntfacePTH.keySet()) {
435 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
436 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
438 // Open a new file to write into
439 String newIntface = intMeth.getKey();
440 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
441 pw = new PrintWriter(new BufferedWriter(fw));
442 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
443 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
444 // Write file headers
445 println("#include <iostream>");
446 // Pass in set of methods and get import classes
447 Set<String> includeClasses = getIncludeClasses(intMeth.getValue(), intDecl);
448 printIncludeStatements(includeClasses);
450 println("using namespace std;");
452 println("class " + newIntface);
456 for (String method : intMeth.getValue()) {
458 List<String> methParams = intDecl.getMethodParams(method);
459 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
460 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
461 intDecl.getMethodId(method) + "(");
462 for (int i = 0; i < methParams.size(); i++) {
464 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
465 print(methPrmType + " " + methParams.get(i));
466 // Check if this is the last element (don't print a comma)
467 if (i != methParams.size() - 1) {
476 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
483 * generateJavaStubClasses() generate stubs based on the methods list in Java
485 public void generateJavaStubClasses() throws IOException {
487 // Create a new directory
488 String path = createDirectories(dir, subdir);
489 for (String intface : mapIntfacePTH.keySet()) {
491 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
492 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
494 // Open a new file to write into
495 String newIntface = intMeth.getKey();
496 String newStubClass = newIntface + "_Stub";
497 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
498 pw = new PrintWriter(new BufferedWriter(fw));
499 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
500 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
501 // Pass in set of methods and get import classes
502 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
503 printImportStatements(importClasses);
504 // Write interface header
506 println("public class " + newStubClass + " implements " + newIntface + " {");
509 for (String method : intMeth.getValue()) {
511 List<String> methParams = intDecl.getMethodParams(method);
512 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
513 print("public " + intDecl.getMethodType(method) + " " +
514 intDecl.getMethodId(method) + "(");
515 for (int i = 0; i < methParams.size(); i++) {
517 print(methPrmTypes.get(i) + " " + methParams.get(i));
518 // Check if this is the last element (don't print a comma)
519 if (i != methParams.size() - 1) {
524 // Check if this is not "void"
525 if (!intDecl.getMethodType(method).equals("void")) {
526 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
527 println("return " + retStmt + ";");
529 println("}"); println("");
533 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
540 * generateCPlusStubClasses() generate stubs based on the methods list in C++
542 public void generateCPlusStubClasses() throws IOException {
544 // Create a new directory
545 String path = createDirectories(dir, subdir);
546 for (String intface : mapIntfacePTH.keySet()) {
548 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
549 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
550 // Open a new file to write into
551 String newIntface = intMeth.getKey();
552 String newStubClass = newIntface + "_Stub";
553 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
554 pw = new PrintWriter(new BufferedWriter(fw));
555 // Write file headers
556 println("#include <iostream>");
557 println("#include \"" + newIntface + ".hpp\""); println("");
558 println("using namespace std;"); println("");
559 println("class " + newStubClass + " : public " + newIntface); println("{");
560 println("public:"); println("");
561 // Add default constructor and destructor
562 println(newStubClass + "() { }"); println("");
563 println("~" + newStubClass + "() { }"); println("");
564 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
565 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
567 for (String method : intMeth.getValue()) {
569 List<String> methParams = intDecl.getMethodParams(method);
570 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
571 print(convertType(intDecl.getMethodType(method)) + " " +
572 intDecl.getMethodId(method) + "(");
573 for (int i = 0; i < methParams.size(); i++) {
575 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
576 print(methPrmType + " " + methParams.get(i));
577 // Check if this is the last element (don't print a comma)
578 if (i != methParams.size() - 1) {
583 // Check if this is not "void"
584 if (!intDecl.getMethodType(method).equals("void")) {
585 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
586 if (retStmt.equals("null")) { // null = NULL in C++
589 println("return " + retStmt + ";");
591 println("}"); println("");
593 print("}"); println(";");
595 System.out.println("IoTCompiler: Generated stub class " + newIntface + ".hpp...");
602 * generateReturnStmt() generate return statement based on methType
604 public String generateReturnStmt(String methType) {
606 // Generate dummy returns for now
607 if (methType.equals("short")||
608 methType.equals("int") ||
609 methType.equals("long") ||
610 methType.equals("float")||
611 methType.equals("double")) {
614 } else if ( methType.equals("String") ||
615 methType.equals("byte")) {
618 } else if ( methType.equals("char")) {
621 } else if ( methType.equals("boolean")) {
631 * setDirectory() sets a new directory for stub files
633 public void setDirectory(String _subdir) {
640 * printUsage() prints the usage of this compiler
642 public static void printUsage() {
644 System.out.println();
645 System.out.println("Sentinel interface and stub compiler version 1.0");
646 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
647 System.out.println("All rights reserved.");
648 System.out.println("Usage:");
649 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
650 System.out.println("\t\tDisplay this help texts\n\n");
651 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
652 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
653 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
654 System.out.println("Options:");
655 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
656 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
657 System.out.println();
662 * parseFile() prepares Lexer and Parser objects, then parses the file
664 public static ParseNode parseFile(String file) {
668 ComplexSymbolFactory csf = new ComplexSymbolFactory();
669 ScannerBuffer lexer =
670 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
671 Parser parse = new Parser(lexer,csf);
672 pn = (ParseNode) parse.parse().value;
673 } catch (Exception e) {
675 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file);
682 /**================================================
683 * Helper functions to write stub codes into files
684 **================================================
686 boolean newline=true;
689 private void print(String str) {
694 for(int i=0; i<tab; i++)
703 * This function converts Java to C++ type for compilation
705 private String convertType(String jType) {
707 return mapPrimitives.get(jType);
711 private void println(String str) {
716 for(int i=0; i<tab; i++)
725 private void updatetabbing(String str) {
726 tablevel+=count(str,'{')-count(str,'}');
730 private int count(String str, char key) {
731 char[] array = str.toCharArray();
733 for(int i=0; i<array.length; i++) {
741 private void createDirectory(String dirName) {
743 File file = new File(dirName);
744 if (!file.exists()) {
746 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
748 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
751 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
756 // Create a directory and possibly a sub directory
757 private String createDirectories(String dir, String subdir) {
760 createDirectory(path);
761 if (subdir != null) {
762 path = path + "/" + subdir;
763 createDirectory(path);
769 // Inserting array members into a Map object
770 // that maps arrKey to arrVal objects
771 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
773 for(int i = 0; i < arrKey.length; i++) {
775 map.put(arrKey[i], arrVal[i]);
780 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, or USERDEFINED
781 private ParamCategory getParamCategory(String paramType) {
783 if (mapPrimitives.containsKey(paramType)) {
784 return ParamCategory.PRIMITIVES;
785 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
786 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
787 return ParamCategory.NONPRIMITIVES;
789 return ParamCategory.USERDEFINED;
793 // Return full class name for non-primitives to generate Java import statements
794 // e.g. java.util.Set for Set, java.util.Map for Map
795 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
797 return mapNonPrimitivesJava.get(paramNonPrimitives);
801 // Return full class name for non-primitives to generate Cplus include statements
802 // e.g. #include <set> for Set, #include <map> for Map
803 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
805 return mapNonPrimitivesCplus.get(paramNonPrimitives);
809 // Get simple types, e.g. HashSet for HashSet<...>
810 // Basically strip off the "<...>"
811 private String getSimpleType(String paramType) {
813 // Check if this is generics
814 if(paramType.contains("<")) {
815 String[] type = paramType.split("<");
822 // Generate a set of classes for import statements
823 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
825 Set<String> importClasses = new HashSet<String>();
826 for (String method : methods) {
827 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
828 for (String paramType : methPrmTypes) {
830 String simpleType = getSimpleType(paramType);
831 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
832 importClasses.add(getNonPrimitiveJavaClass(simpleType));
836 return importClasses;
840 // Generate a set of classes for include statements
841 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl) {
843 Set<String> includeClasses = new HashSet<String>();
844 for (String method : methods) {
846 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
847 for (String paramType : methPrmTypes) {
849 String simpleType = getSimpleType(paramType);
850 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
851 includeClasses.add(getNonPrimitiveCplusClass(simpleType));
855 return includeClasses;
859 private void printImportStatements(Set<String> importClasses) {
861 for(String cls : importClasses) {
862 println("import " + cls + ";");
867 private void printIncludeStatements(Set<String> includeClasses) {
869 for(String cls : includeClasses) {
870 println("#include <" + cls + ">");
875 // Get the C++ version of a non-primitive type
876 // e.g. set for Set and map for Map
877 // Input nonPrimitiveType has to be generics in format
878 private String[] getTypeOfGeneric(String nonPrimitiveType) {
880 // Handle <, >, and , for 2-type generic/template
881 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
886 private String checkAndGetCplusType(String paramType) {
888 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
889 return convertType(paramType);
890 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
892 // Check for generic/template format
893 if (paramType.contains("<") && paramType.contains(">")) {
895 String genericClass = getSimpleType(paramType);
896 String[] genericType = getTypeOfGeneric(paramType);
897 String cplusTemplate = null;
898 if (genericType.length == 1) // Generic/template with one type
899 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
900 "<" + convertType(genericType[0]) + ">";
901 else // Generic/template with two types
902 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
903 "<" + convertType(genericType[0]) + "," + convertType(genericType[1]) + ">";
904 return cplusTemplate;
906 return getNonPrimitiveCplusClass(paramType);
908 // Just return it as is if it's not non-primitives
913 // Get simple types, e.g. HashSet for HashSet<...>
914 // Basically strip off the "<...>"
915 private String checkAndGetParamClass(String paramType) {
917 // Check if this is generics
918 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
919 return exchangeParamType(paramType);
925 // Returns the other interface for type-checking purposes for USERDEFINED
926 // classes based on the information provided in multiple policy files
927 // e.g. return CameraWithXXX instead of Camera
928 private String exchangeParamType(String intface) {
930 // Param type that's passed is the interface name we need to look for
931 // in the map of interfaces, based on available policy files.
932 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
933 if (decHandler != null) {
934 // We've found the required interface policy files
935 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
936 Set<String> setExchInt = reqDecl.getInterfaces();
937 if (setExchInt.size() == 1) {
938 Iterator iter = setExchInt.iterator();
939 return (String) iter.next();
941 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
942 ". Only one new interface can be declared if the object " + intface +
943 " needs to be passed in as an input parameter!");
946 // NULL value - this means policy files missing
947 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
948 "... Please provide the necessary policy files for user-defined types.");
953 public static void main(String[] args) throws Exception {
955 // If there is no argument or just "--help" or "-h", then invoke printUsage()
956 if ((args[0].equals("-help") ||
957 args[0].equals("--help")||
958 args[0].equals("-h")) ||
959 (args.length == 0)) {
961 IoTCompiler.printUsage();
963 } else if (args.length > 1) {
965 IoTCompiler comp = new IoTCompiler();
968 // Parse main policy file
969 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
970 // Parse "requires" policy file
971 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
972 // Get interface name
973 String intface = ParseTreeHandler.getOrigIntface(pnPol);
974 comp.setParseTree(intface, pnPol, pnReq);
975 comp.getMethodsForIntface(intface);
977 // 1) Check if this is the last option before "-java" or "-cplus"
978 // 2) Check if this is really the last option (no "-java" or "-cplus")
979 } while(!args[i].equals("-java") &&
980 !args[i].equals("-cplus") &&
983 // Generate everything if we don't see "-java" or "-cplus"
984 if (i == args.length) {
985 comp.generateJavaLocalInterfaces();
986 comp.generateJavaInterfaces();
987 comp.generateJavaStubClasses();
988 comp.generateCplusLocalInterfaces();
989 comp.generateCPlusInterfaces();
990 comp.generateCPlusStubClasses();
992 // Check other options
993 while(i < args.length) {
995 if (!args[i].equals("-java") &&
996 !args[i].equals("-cplus")) {
997 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]);
999 if (i + 1 < args.length) {
1000 comp.setDirectory(args[i+1]);
1002 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i]);
1004 if (args[i].equals("-java")) {
1005 comp.generateJavaLocalInterfaces();
1006 comp.generateJavaInterfaces();
1007 comp.generateJavaStubClasses();
1009 comp.generateCplusLocalInterfaces();
1010 comp.generateCPlusInterfaces();
1011 comp.generateCPlusStubClasses();
1018 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
1019 IoTCompiler.printUsage();
1020 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!");