Perfecting parser, lexer, and parse-tree handling for policy files; Generating skelet...
[iot2.git] / iotjava / iotpolicy / tree / ParseTreeHandler.java
diff --git a/iotjava/iotpolicy/tree/ParseTreeHandler.java b/iotjava/iotpolicy/tree/ParseTreeHandler.java
new file mode 100644 (file)
index 0000000..69a36c2
--- /dev/null
@@ -0,0 +1,257 @@
+package iotpolicy.tree;
+
+import java_cup.runtime.ComplexSymbolFactory;
+import java_cup.runtime.ScannerBuffer;
+import java.io.*;
+import iotpolicy.tree.ParseNodeVector;
+import iotpolicy.tree.ParseNode;
+
+/** Class ParseTreeHandler handles the parse tree generated by the 
+ *  parser (and lexer) from the policy file. 
+ *  This class accepts the AST in the form of XMLElement class object.
+ *  It gives interfaces to extract the 3 sections of a policy file:
+ *  1) Interface
+ *  2) Capability list
+ *  3) Generated interface list
+ *
+ * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
+ * @version     1.0
+ * @since       2016-09-20
+ */
+public final class ParseTreeHandler {
+
+       /**
+        * Class properties
+        */
+       private ParseNode pn;
+       private InterfaceDecl intDecl;
+       private CapabilityDecl capDecl;
+       private RequiresDecl reqDecl;
+
+
+       /**
+        * Class constructors
+        */
+       public ParseTreeHandler() {
+
+               pn = null;
+               intDecl = new InterfaceDecl();
+               capDecl = new CapabilityDecl();
+               reqDecl = new RequiresDecl();
+       }
+
+
+       public ParseTreeHandler(String _intFace, ParseNode _pn) {
+
+               pn = _pn;
+               intDecl = new InterfaceDecl(_intFace);
+               capDecl = new CapabilityDecl(_intFace);
+               reqDecl = new RequiresDecl(_intFace);
+       }
+
+
+       /**
+        * processInterfaceDecl() processes interface declaration part
+        */
+       public void processInterfaceDecl() {
+
+               // Get the root - interface list (element 0)
+               ParseNodeVector pnv = pn.getChildren();
+               ParseNode pnRoot = pnv.elementAt(0);
+               // Get the second child of root for "method_list"
+               ParseNodeVector pnvGen2 = pnRoot.getChildren();
+               if (pnvGen2.size() == 0) {
+                       throw new Error("ParseTreeHandler: Interface declaration is missing! Please check your policy file...");
+               }
+               ParseNode pnGen2 = pnvGen2.elementAt(1);
+               // Get the next level child for methods
+               ParseNodeVector pnvGen3 = pnGen2.getChildren();
+               // Loop and extract methods
+               for(int i = 0; i < pnvGen3.size(); i++) {
+
+                       // Get the level where label is "method"
+                       ParseNode pnGen3 = pnvGen3.elementAt(i);
+                       // Get the next level child - method info
+                       ParseNodeVector pnvGen4 = pnGen3.getChildren();
+                       // Method type
+                       ParseNode pnGen4_type = pnvGen4.elementAt(0);
+                       // Method identifier
+                       ParseNode pnGen4_ident  = pnvGen4.elementAt(1);
+                       // Add a new method (type and identifier)
+                       intDecl.addNewMethod(pnGen4_ident.getLiteral().toString(), 
+                               pnGen4_type.getLiteral().toString());
+                       // Get the next level child - method params
+                       ParseNode pnGen4_params  = pnvGen4.elementAt(2);
+                       ParseNodeVector pnvGen5 = pnGen4_params.getChildren();
+                       for(int j = 0; j < pnvGen5.size(); j++) {
+
+                               ParseNode pnGen5 = pnvGen5.elementAt(j);
+                               ParseNodeVector pnvGen6 = pnGen5.getChildren();
+                               // Param type
+                               ParseNode pnGen6_type = pnvGen6.elementAt(0);
+                               // Param identifier
+                               ParseNode pnGen6_ident = pnvGen6.elementAt(1);
+                               // Add a new method param (type and identifier)
+                               intDecl.addMethodParam(pnGen4_ident.getLiteral().toString(),
+                                       pnGen6_ident.getLiteral().toString(), pnGen6_type.getLiteral().toString());
+                       }
+                       //System.out.println();
+               }
+       }
+
+
+       /**
+        * processCapabilityDecl() processes capability declaration part
+        */
+       public void processCapabilityDecl() {
+
+               // Get the root - capability list (element 1)
+               ParseNodeVector pnv = pn.getChildren();
+               ParseNode pnRoot = pnv.elementAt(1);
+               // Get the second child of root for "capab_list"
+               ParseNodeVector pnvGen2 = pnRoot.getChildren();
+               if (pnvGen2.size() == 0) {
+                       throw new Error("ParseTreeHandler: Capability declaration is missing! Please check your policy file...");
+               }
+               // Iterate over the list of capabilities
+               for(int i = 0; i < pnvGen2.size(); i++) {
+
+                       ParseNode pnGen2 = pnvGen2.elementAt(i);
+                       // Get the next level child for capabilities
+                       ParseNodeVector pnvGen3 = pnGen2.getChildren();
+                       // Get the capability name, e.g. ImageCapture for Camera.ImageCapture
+                       ParseNode pnGen3_capab = pnvGen3.elementAt(1);
+                       // Add new capability
+                       capDecl.addNewCapability(pnGen3_capab.getLiteral().toString());
+                       // Get the capability contents, i.e. descriptions and methods
+                       ParseNode pnGen3_capab_cont = pnvGen3.elementAt(2);
+                       ParseNodeVector pnvGen4 = pnGen3_capab_cont.getChildren();
+                       // Iterate over the list of capability contents
+                       for(int j = 0; j < pnvGen4.size(); j++) {
+
+                               ParseNode pnGen4 = pnvGen4.elementAt(j);
+                               ParseNodeVector pnvGen5 = pnGen4.getChildren();
+                               ParseNode pnGen5 = pnvGen5.elementAt(0);
+                               // Check the label and separate between description (capab_desc)
+                               // and method name (capab_ident)
+                               String label = pnGen5.getLabel().toString();
+                               if (label.equals("capab_desc")) {
+                                       capDecl.addNewDescription(pnGen3_capab.getLiteral().toString(),
+                                               pnGen5.getLiteral().toString());
+                               } else if (label.equals("capab_ident")) {
+                                       capDecl.addNewMethod(pnGen3_capab.getLiteral().toString(),
+                                               pnGen5.getLiteral().toString());                                
+                               } else
+                                       throw new Error("ParseTreeHandler: Unknown label '" + label + "' while operating on parse tree!");
+
+                       }
+               }
+       }
+
+
+       /**
+        * processRequiresDecl() processes "requires" declaration part
+        */
+       public void processRequiresDecl() {
+
+               // Get the root - requires list (element 2)
+               ParseNodeVector pnv = pn.getChildren();
+               ParseNode pnRoot = pnv.elementAt(2);
+               // Get the second child of root for "capab_list"
+               ParseNodeVector pnvGen2 = pnRoot.getChildren();
+               if (pnvGen2.size() == 0) {
+                       throw new Error("ParseTreeHandler: 'Requires' declaration is missing! Please check your policy file...");
+               }
+               // Iterate over the list of requires statements
+               for(int i = 0; i < pnvGen2.size(); i++) {
+
+                       ParseNode pnGen2 = pnvGen2.elementAt(i);
+                       ParseNodeVector pnvGen3 = pnGen2.getChildren();
+                       // Get the new interface that we want to generate
+                       ParseNode pnGen3_intface = pnvGen3.elementAt(2);
+                       reqDecl.addNewIntface(pnGen3_intface.getLiteral().toString());
+                       // Get capability list at element 1
+                       ParseNode pnGen3_capab_list = pnvGen3.elementAt(1);
+                       ParseNodeVector pnvGen4 = pnGen3_capab_list.getChildren();
+                       // Browse through capabilities
+                       for (int j = 0; j < pnvGen4.size(); j++) {
+                               ParseNode pnGen4 = pnvGen4.elementAt(j);
+                               reqDecl.addNewCapability(pnGen3_intface.getLiteral().toString(),
+                                       pnGen4.getLiteral().toString());
+                       }
+               }
+       }
+
+
+       /**
+        * getInterfaceDecl() returns InterfaceDecl object
+        */
+       public InterfaceDecl getInterfaceDecl() {
+
+               return intDecl;
+       }
+
+
+       /**
+        * getCapabilityDecl() returns CapabilityDecl object
+        */
+       public CapabilityDecl getCapabilityDecl() {
+
+               return capDecl;
+       }
+
+
+       /**
+        * getRequiresDecl() returns RequiresDecl object
+        */
+       public RequiresDecl getRequiresDecl() {
+
+               return reqDecl;
+       }
+
+
+       /**
+        * getOrigIntface() returns the original interface in policy, e.g. Camera
+        * <p>
+        * The ParseNode object should be the one returned from <Parser>.parse().value
+        */
+       public static String getOrigIntface(ParseNode pn) {
+
+               // Get the root: just keyword "interface"
+               ParseNodeVector pnv = pn.getChildren();
+               ParseNode pnRoot = pnv.elementAt(0);
+               // Get the child: intface_ident = original interface identifier, e.g. Camera
+               ParseNodeVector pnvGen2 = pnRoot.getChildren();
+               if (pnvGen2.size() == 0) {
+                       throw new Error("ParseTreeHandler: Interface declaration is missing! Please check your policy file...");
+               }
+               ParseNode pnGen2 = pnvGen2.elementAt(0);
+               // Confirm that this is "intface_ident"
+               if (pnGen2.getLabel().equals("intface_ident")) {
+                       if (pnGen2.getLiteral() != null) {
+                               return pnGen2.getLiteral().toString();
+                       } else
+                               throw new Error("ParseTreeHandler: No interface name found! Please fix policy file!");
+               } else
+                       throw new Error("ParseTreeHandler: Label 'intface_ident' is not found! Instead, '" + pnGen2.getLabel() + "' was found...");
+       }
+
+
+/*     public static void main(String[] args) throws Exception {
+
+               // initialize the symbol factory
+               ComplexSymbolFactory csf = new ComplexSymbolFactory();
+               // create a buffering scanner wrapper
+               ScannerBuffer lexer = new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(args[0])),csf));
+               // start parsing
+               Parser p = new Parser(lexer,csf);
+               ParseNode pn = (ParseNode) p.parse().value;
+
+               String intFace = ParseTreeHandler.getOrigIntface(pn);
+               System.out.println("Original interface name: " + intFace);
+               ParseTreeHandler pth = new ParseTreeHandler(intFace, pn);
+               pth.processInterfaceDecl();
+               pth.processCapabilityDecl();
+               pth.processRequiresDecl();
+       }*/
+}