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);
252 * generateJavaLocalInterface() writes the local interface and provides type-checking.
254 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
255 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
256 * The local interface has to be the input parameter for the stub and the stub
257 * interface has to be the input parameter for the local class.
259 public void generateJavaLocalInterfaces() throws IOException {
261 // Create a new directory
262 createDirectory(dir);
263 for (String intface : mapIntfacePTH.keySet()) {
264 // Open a new file to write into
265 FileWriter fw = new FileWriter(dir + "/" + intface + ".java");
266 pw = new PrintWriter(new BufferedWriter(fw));
267 // Pass in set of methods and get import classes
268 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
269 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
270 List<String> methods = intDecl.getMethods();
271 Set<String> importClasses = getImportClasses(methods, intDecl);
272 printImportStatements(importClasses);
273 // Write interface header
275 println("public interface " + intface + " {");
277 for (String method : methods) {
279 List<String> methParams = intDecl.getMethodParams(method);
280 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
281 print("public " + intDecl.getMethodType(method) + " " +
282 intDecl.getMethodId(method) + "(");
283 for (int i = 0; i < methParams.size(); i++) {
284 // Check for params with driver class types and exchange it
285 // with its remote interface
286 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
287 print(paramType + " " + methParams.get(i));
288 // Check if this is the last element (don't print a comma)
289 if (i != methParams.size() - 1) {
297 System.out.println("IoTCompiler: Generated local interface " + intface + ".java...");
303 * generateCplusLocalInterfaces() writes the local interfaces and provides type-checking.
305 * It needs to rewrite and exchange USERDEFINED types in input parameters of stub
306 * and original interfaces, e.g. exchange Camera and CameraWithVideoAndRecording.
307 * The local interface has to be the input parameter for the stub and the stub
308 * interface has to be the input parameter for the local class.
310 public void generateCplusLocalInterfaces() throws IOException {
312 // Create a new directory
313 createDirectory(dir);
314 for (String intface : mapIntfacePTH.keySet()) {
315 // Open a new file to write into
316 FileWriter fw = new FileWriter(dir + "/" + intface + ".hpp");
317 pw = new PrintWriter(new BufferedWriter(fw));
318 // Write file headers
319 println("#include <iostream>");
320 // Pass in set of methods and get include classes
321 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
322 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
323 List<String> methods = intDecl.getMethods();
324 Set<String> includeClasses = getIncludeClasses(methods, intDecl);
325 printIncludeStatements(includeClasses);
327 println("using namespace std;");
329 println("class " + intface);
333 for (String method : methods) {
335 List<String> methParams = intDecl.getMethodParams(method);
336 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
337 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
338 intDecl.getMethodId(method) + "(");
339 for (int i = 0; i < methParams.size(); i++) {
340 // Check for params with driver class types and exchange it
341 // with its remote interface
342 String paramType = checkAndGetParamClass(methPrmTypes.get(i));
343 paramType = checkAndGetCplusType(paramType);
344 print(paramType + " " + methParams.get(i));
345 // Check if this is the last element (don't print a comma)
346 if (i != methParams.size() - 1) {
355 System.out.println("IoTCompiler: Generated local interface " + intface + ".hpp...");
361 * generateJavaInterfaces() generate stub interfaces based on the methods list in Java
363 public void generateJavaInterfaces() throws IOException {
365 // Create a new directory
366 String path = createDirectories(dir, subdir);
367 for (String intface : mapIntfacePTH.keySet()) {
369 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
370 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
372 // Open a new file to write into
373 String newIntface = intMeth.getKey();
374 FileWriter fw = new FileWriter(path + "/" + newIntface + ".java");
375 pw = new PrintWriter(new BufferedWriter(fw));
376 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
377 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
378 // Pass in set of methods and get import classes
379 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
380 printImportStatements(importClasses);
381 // Write interface header
383 println("public interface " + newIntface + " {");
384 List<String> meths = intDecl.getMethods();
386 for (String method : intMeth.getValue()) {
388 List<String> methParams = intDecl.getMethodParams(method);
389 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
390 print("public " + intDecl.getMethodType(method) + " " +
391 intDecl.getMethodId(method) + "(");
392 for (int i = 0; i < methParams.size(); i++) {
393 print(methPrmTypes.get(i) + " " + methParams.get(i));
394 // Check if this is the last element (don't print a comma)
395 if (i != methParams.size() - 1) {
403 System.out.println("IoTCompiler: Generated interface " + newIntface + ".java...");
410 * generateCPlusInterfaces() generate stub interfaces based on the methods list in C++
412 * For C++ we use virtual classe as interface
414 public void generateCPlusInterfaces() throws IOException {
416 // Create a new directory
417 String path = createDirectories(dir, subdir);
418 for (String intface : mapIntfacePTH.keySet()) {
420 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
421 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
423 // Open a new file to write into
424 String newIntface = intMeth.getKey();
425 FileWriter fw = new FileWriter(path + "/" + newIntface + ".hpp");
426 pw = new PrintWriter(new BufferedWriter(fw));
427 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
428 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
429 // Write file headers
430 println("#include <iostream>");
431 // Pass in set of methods and get import classes
432 Set<String> includeClasses = getIncludeClasses(intMeth.getValue(), intDecl);
433 printIncludeStatements(includeClasses);
435 println("using namespace std;");
437 println("class " + newIntface);
441 for (String method : intMeth.getValue()) {
443 List<String> methParams = intDecl.getMethodParams(method);
444 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
445 print("virtual " + convertType(intDecl.getMethodType(method)) + " " +
446 intDecl.getMethodId(method) + "(");
447 for (int i = 0; i < methParams.size(); i++) {
449 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
450 print(methPrmType + " " + methParams.get(i));
451 // Check if this is the last element (don't print a comma)
452 if (i != methParams.size() - 1) {
461 System.out.println("IoTCompiler: Generated interface " + newIntface + ".hpp...");
468 * generateJavaStubClasses() generate stubs based on the methods list in Java
470 public void generateJavaStubClasses() 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()) {
479 // Open a new file to write into
480 String newIntface = intMeth.getKey();
481 String newStubClass = newIntface + "_Stub";
482 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".java");
483 pw = new PrintWriter(new BufferedWriter(fw));
484 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
485 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
486 // Pass in set of methods and get import classes
487 Set<String> importClasses = getImportClasses(intMeth.getValue(), intDecl);
488 printImportStatements(importClasses);
489 // Write interface header
491 println("public class " + newStubClass + " implements " + newIntface + " {");
494 for (String method : intMeth.getValue()) {
496 List<String> methParams = intDecl.getMethodParams(method);
497 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
498 print("public " + intDecl.getMethodType(method) + " " +
499 intDecl.getMethodId(method) + "(");
500 for (int i = 0; i < methParams.size(); i++) {
502 print(methPrmTypes.get(i) + " " + methParams.get(i));
503 // Check if this is the last element (don't print a comma)
504 if (i != methParams.size() - 1) {
509 // Check if this is not "void"
510 if (!intDecl.getMethodType(method).equals("void")) {
511 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
512 println("return " + retStmt + ";");
514 println("}"); println("");
518 System.out.println("IoTCompiler: Generated stub class " + newStubClass + ".java...");
525 * generateCPlusStubClasses() generate stubs based on the methods list in C++
527 public void generateCPlusStubClasses() throws IOException {
529 // Create a new directory
530 String path = createDirectories(dir, subdir);
531 for (String intface : mapIntfacePTH.keySet()) {
533 Map<String,Set<String>> mapNewIntMethods = mapInt2NewInts.get(intface);
534 for (Map.Entry<String,Set<String>> intMeth : mapNewIntMethods.entrySet()) {
535 // Open a new file to write into
536 String newIntface = intMeth.getKey();
537 String newStubClass = newIntface + "_Stub";
538 FileWriter fw = new FileWriter(path + "/" + newStubClass + ".hpp");
539 pw = new PrintWriter(new BufferedWriter(fw));
540 // Write file headers
541 println("#include <iostream>");
542 println("#include \"" + newIntface + ".hpp\""); println("");
543 println("using namespace std;"); println("");
544 println("class " + newStubClass + " : public " + newIntface); println("{");
545 println("public:"); println("");
546 // Add default constructor and destructor
547 println(newStubClass + "() { }"); println("");
548 println("~" + newStubClass + "() { }"); println("");
549 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
550 InterfaceDecl intDecl = (InterfaceDecl) decHandler.getInterfaceDecl(intface);
552 for (String method : intMeth.getValue()) {
554 List<String> methParams = intDecl.getMethodParams(method);
555 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
556 print(convertType(intDecl.getMethodType(method)) + " " +
557 intDecl.getMethodId(method) + "(");
558 for (int i = 0; i < methParams.size(); i++) {
560 String methPrmType = checkAndGetCplusType(methPrmTypes.get(i));
561 print(methPrmType + " " + methParams.get(i));
562 // Check if this is the last element (don't print a comma)
563 if (i != methParams.size() - 1) {
568 // Check if this is not "void"
569 if (!intDecl.getMethodType(method).equals("void")) {
570 String retStmt = generateReturnStmt(intDecl.getMethodType(method));
571 if (retStmt.equals("null")) { // null = NULL in C++
574 println("return " + retStmt + ";");
576 println("}"); println("");
578 print("}"); println(";");
580 System.out.println("IoTCompiler: Generated stub class " + newIntface + ".hpp...");
587 * generateReturnStmt() generate return statement based on methType
589 public String generateReturnStmt(String methType) {
591 // Generate dummy returns for now
592 if (methType.equals("short")||
593 methType.equals("int") ||
594 methType.equals("long") ||
595 methType.equals("float")||
596 methType.equals("double")) {
599 } else if ( methType.equals("String") ||
600 methType.equals("byte")) {
603 } else if ( methType.equals("char")) {
606 } else if ( methType.equals("boolean")) {
616 * setDirectory() sets a new directory for stub files
618 public void setDirectory(String _subdir) {
625 * printUsage() prints the usage of this compiler
627 public static void printUsage() {
629 System.out.println();
630 System.out.println("Sentinel interface and stub compiler version 1.0");
631 System.out.println("Copyright (c) 2015-2016 University of California, Irvine - Programming Language Group.");
632 System.out.println("All rights reserved.");
633 System.out.println("Usage:");
634 System.out.println("\tjava IoTCompiler -help / --help / -h\n");
635 System.out.println("\t\tDisplay this help texts\n\n");
636 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>]");
637 System.out.println("\tjava IoTCompiler [<main-policy-file> <req-policy-file>] [options]\n");
638 System.out.println("\t\tTake one or more pairs of main-req policy files, and generate Java and/or C++ files\n");
639 System.out.println("Options:");
640 System.out.println("\t-java\t<directory>\tGenerate Java stub files");
641 System.out.println("\t-cplus\t<directory>\tGenerate C++ stub files");
642 System.out.println();
647 * parseFile() prepares Lexer and Parser objects, then parses the file
649 public static ParseNode parseFile(String file) {
653 ComplexSymbolFactory csf = new ComplexSymbolFactory();
654 ScannerBuffer lexer =
655 new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(file)),csf));
656 Parser parse = new Parser(lexer,csf);
657 pn = (ParseNode) parse.parse().value;
658 } catch (Exception e) {
660 throw new Error("IoTCompiler: ERROR parsing policy file or wrong command line option: " + file);
667 /**================================================
668 * Helper functions to write stub codes into files
669 **================================================
671 boolean newline=true;
674 private void print(String str) {
679 for(int i=0; i<tab; i++)
688 * This function converts Java to C++ type for compilation
690 private String convertType(String jType) {
692 return mapPrimitives.get(jType);
696 private void println(String str) {
701 for(int i=0; i<tab; i++)
710 private void updatetabbing(String str) {
711 tablevel+=count(str,'{')-count(str,'}');
715 private int count(String str, char key) {
716 char[] array = str.toCharArray();
718 for(int i=0; i<array.length; i++) {
726 private void createDirectory(String dirName) {
728 File file = new File(dirName);
729 if (!file.exists()) {
731 System.out.println("IoTCompiler: Directory " + dirName + " has been created!");
733 System.out.println("IoTCompiler: Failed to create directory " + dirName + "!");
736 System.out.println("IoTCompiler: Directory " + dirName + " exists...");
741 // Create a directory and possibly a sub directory
742 private String createDirectories(String dir, String subdir) {
745 createDirectory(path);
746 if (subdir != null) {
747 path = path + "/" + subdir;
748 createDirectory(path);
754 // Inserting array members into a Map object
755 // that maps arrKey to arrVal objects
756 private void arraysToMap(Map map, Object[] arrKey, Object[] arrVal) {
758 for(int i = 0; i < arrKey.length; i++) {
760 map.put(arrKey[i], arrVal[i]);
765 // Return parameter category, i.e. PRIMITIVES, NONPRIMITIVES, or USERDEFINED
766 private ParamCategory getParamCategory(String paramType) {
768 if (mapPrimitives.containsKey(paramType)) {
769 return ParamCategory.PRIMITIVES;
770 // We can either use mapNonPrimitivesJava or mapNonPrimitivesCplus here
771 } else if (mapNonPrimitivesJava.containsKey(getSimpleType(paramType))) {
772 return ParamCategory.NONPRIMITIVES;
774 return ParamCategory.USERDEFINED;
778 // Return full class name for non-primitives to generate Java import statements
779 // e.g. java.util.Set for Set, java.util.Map for Map
780 private String getNonPrimitiveJavaClass(String paramNonPrimitives) {
782 return mapNonPrimitivesJava.get(paramNonPrimitives);
786 // Return full class name for non-primitives to generate Cplus include statements
787 // e.g. #include <set> for Set, #include <map> for Map
788 private String getNonPrimitiveCplusClass(String paramNonPrimitives) {
790 return mapNonPrimitivesCplus.get(paramNonPrimitives);
794 // Get simple types, e.g. HashSet for HashSet<...>
795 // Basically strip off the "<...>"
796 private String getSimpleType(String paramType) {
798 // Check if this is generics
799 if(paramType.contains("<")) {
800 String[] type = paramType.split("<");
807 // Generate a set of classes for import statements
808 private Set<String> getImportClasses(Collection<String> methods, InterfaceDecl intDecl) {
810 Set<String> importClasses = new HashSet<String>();
811 for (String method : methods) {
812 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
813 for (String paramType : methPrmTypes) {
815 String simpleType = getSimpleType(paramType);
816 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
817 importClasses.add(getNonPrimitiveJavaClass(simpleType));
821 return importClasses;
825 // Generate a set of classes for include statements
826 private Set<String> getIncludeClasses(Collection<String> methods, InterfaceDecl intDecl) {
828 Set<String> includeClasses = new HashSet<String>();
829 for (String method : methods) {
831 List<String> methPrmTypes = intDecl.getMethodParamTypes(method);
832 for (String paramType : methPrmTypes) {
834 String simpleType = getSimpleType(paramType);
835 if (getParamCategory(simpleType) == ParamCategory.NONPRIMITIVES) {
836 includeClasses.add(getNonPrimitiveCplusClass(simpleType));
840 return includeClasses;
844 private void printImportStatements(Set<String> importClasses) {
846 for(String cls : importClasses) {
847 println("import " + cls + ";");
852 private void printIncludeStatements(Set<String> includeClasses) {
854 for(String cls : includeClasses) {
855 println("#include <" + cls + ">");
860 // Get the C++ version of a non-primitive type
861 // e.g. set for Set and map for Map
862 // Input nonPrimitiveType has to be generics in format
863 private String[] getTypeOfGeneric(String nonPrimitiveType) {
865 // Handle <, >, and , for 2-type generic/template
866 String[] substr = nonPrimitiveType.split("<")[1].split(">")[0].split(",");
871 private String checkAndGetCplusType(String paramType) {
873 if (getParamCategory(paramType) == ParamCategory.PRIMITIVES) {
874 return convertType(paramType);
875 } else if (getParamCategory(paramType) == ParamCategory.NONPRIMITIVES) {
877 // Check for generic/template format
878 if (paramType.contains("<") && paramType.contains(">")) {
880 String genericClass = getSimpleType(paramType);
881 String[] genericType = getTypeOfGeneric(paramType);
882 String cplusTemplate = null;
883 if (genericType.length == 1) // Generic/template with one type
884 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
885 "<" + convertType(genericType[0]) + ">";
886 else // Generic/template with two types
887 cplusTemplate = getNonPrimitiveCplusClass(genericClass) +
888 "<" + convertType(genericType[0]) + "," + convertType(genericType[1]) + ">";
889 return cplusTemplate;
891 return getNonPrimitiveCplusClass(paramType);
893 // Just return it as is if it's not non-primitives
898 // Get simple types, e.g. HashSet for HashSet<...>
899 // Basically strip off the "<...>"
900 private String checkAndGetParamClass(String paramType) {
902 // Check if this is generics
903 if(getParamCategory(paramType) == ParamCategory.USERDEFINED) {
904 return exchangeParamType(paramType);
910 // Returns the other interface for type-checking purposes for USERDEFINED
911 // classes based on the information provided in multiple policy files
912 // e.g. return CameraWithXXX instead of Camera
913 private String exchangeParamType(String intface) {
915 // Param type that's passed is the interface name we need to look for
916 // in the map of interfaces, based on available policy files.
917 DeclarationHandler decHandler = mapIntDeclHand.get(intface);
918 if (decHandler != null) {
919 // We've found the required interface policy files
920 RequiresDecl reqDecl = (RequiresDecl) decHandler.getRequiresDecl(intface);
921 Set<String> setExchInt = reqDecl.getInterfaces();
922 if (setExchInt.size() == 1) {
923 Iterator iter = setExchInt.iterator();
924 return (String) iter.next();
926 throw new Error("IoTCompiler: Ambiguous stub interfaces: " + setExchInt.toString() +
927 ". Only one new interface can be declared if the object " + intface +
928 " needs to be passed in as an input parameter!");
931 // NULL value - this means policy files missing
932 throw new Error("IoTCompiler: Parameter type lookup failed for " + intface +
933 "... Please provide the necessary policy files for user-defined types.");
938 public static void main(String[] args) throws Exception {
940 // If there is no argument or just "--help" or "-h", then invoke printUsage()
941 if ((args[0].equals("-help") ||
942 args[0].equals("--help")||
943 args[0].equals("-h")) ||
944 (args.length == 0)) {
946 IoTCompiler.printUsage();
948 } else if (args.length > 1) {
950 IoTCompiler comp = new IoTCompiler();
953 // Parse main policy file
954 ParseNode pnPol = IoTCompiler.parseFile(args[i]);
955 // Parse "requires" policy file
956 ParseNode pnReq = IoTCompiler.parseFile(args[i+1]);
957 // Get interface name
958 String intface = ParseTreeHandler.getOrigIntface(pnPol);
959 comp.setParseTree(intface, pnPol, pnReq);
960 comp.getMethodsForIntface(intface);
962 // 1) Check if this is the last option before "-java" or "-cplus"
963 // 2) Check if this is really the last option (no "-java" or "-cplus")
964 } while(!args[i].equals("-java") &&
965 !args[i].equals("-cplus") &&
968 // Generate everything if we don't see "-java" or "-cplus"
969 if (i == args.length) {
970 comp.generateJavaLocalInterfaces();
971 comp.generateJavaInterfaces();
972 comp.generateJavaStubClasses();
973 comp.generateCplusLocalInterfaces();
974 comp.generateCPlusInterfaces();
975 comp.generateCPlusStubClasses();
977 // Check other options
978 while(i < args.length) {
980 if (!args[i].equals("-java") &&
981 !args[i].equals("-cplus")) {
982 throw new Error("IoTCompiler: ERROR - unrecognized command line option: " + args[i]);
984 if (i + 1 < args.length) {
985 comp.setDirectory(args[i+1]);
987 throw new Error("IoTCompiler: ERROR - please provide <directory> after option: " + args[i]);
989 if (args[i].equals("-java")) {
990 comp.generateJavaLocalInterfaces();
991 comp.generateJavaInterfaces();
992 comp.generateJavaStubClasses();
994 comp.generateCplusLocalInterfaces();
995 comp.generateCPlusInterfaces();
996 comp.generateCPlusStubClasses();
1003 // Need to at least have exactly 2 parameters, i.e. main policy file and requires file
1004 IoTCompiler.printUsage();
1005 throw new Error("IoTCompiler: At least two arguments (main and requires policy files) have to be provided!");