Perfecting parser, lexer, and parse-tree handling for policy files; Generating skelet...
[iot2.git] / iotjava / iotpolicy / tree / ParseTreeHandler.java
1 package iotpolicy.tree;
2
3 import java_cup.runtime.ComplexSymbolFactory;
4 import java_cup.runtime.ScannerBuffer;
5 import java.io.*;
6 import iotpolicy.tree.ParseNodeVector;
7 import iotpolicy.tree.ParseNode;
8
9 /** Class ParseTreeHandler handles the parse tree generated by the 
10  *  parser (and lexer) from the policy file. 
11  *  This class accepts the AST in the form of XMLElement class object.
12  *  It gives interfaces to extract the 3 sections of a policy file:
13  *  1) Interface
14  *  2) Capability list
15  *  3) Generated interface list
16  *
17  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
18  * @version     1.0
19  * @since       2016-09-20
20  */
21 public final class ParseTreeHandler {
22
23         /**
24          * Class properties
25          */
26         private ParseNode pn;
27         private InterfaceDecl intDecl;
28         private CapabilityDecl capDecl;
29         private RequiresDecl reqDecl;
30
31
32         /**
33          * Class constructors
34          */
35         public ParseTreeHandler() {
36
37                 pn = null;
38                 intDecl = new InterfaceDecl();
39                 capDecl = new CapabilityDecl();
40                 reqDecl = new RequiresDecl();
41         }
42
43
44         public ParseTreeHandler(String _intFace, ParseNode _pn) {
45
46                 pn = _pn;
47                 intDecl = new InterfaceDecl(_intFace);
48                 capDecl = new CapabilityDecl(_intFace);
49                 reqDecl = new RequiresDecl(_intFace);
50         }
51
52
53         /**
54          * processInterfaceDecl() processes interface declaration part
55          */
56         public void processInterfaceDecl() {
57
58                 // Get the root - interface list (element 0)
59                 ParseNodeVector pnv = pn.getChildren();
60                 ParseNode pnRoot = pnv.elementAt(0);
61                 // Get the second child of root for "method_list"
62                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
63                 if (pnvGen2.size() == 0) {
64                         throw new Error("ParseTreeHandler: Interface declaration is missing! Please check your policy file...");
65                 }
66                 ParseNode pnGen2 = pnvGen2.elementAt(1);
67                 // Get the next level child for methods
68                 ParseNodeVector pnvGen3 = pnGen2.getChildren();
69                 // Loop and extract methods
70                 for(int i = 0; i < pnvGen3.size(); i++) {
71
72                         // Get the level where label is "method"
73                         ParseNode pnGen3 = pnvGen3.elementAt(i);
74                         // Get the next level child - method info
75                         ParseNodeVector pnvGen4 = pnGen3.getChildren();
76                         // Method type
77                         ParseNode pnGen4_type = pnvGen4.elementAt(0);
78                         // Method identifier
79                         ParseNode pnGen4_ident  = pnvGen4.elementAt(1);
80                         // Add a new method (type and identifier)
81                         intDecl.addNewMethod(pnGen4_ident.getLiteral().toString(), 
82                                 pnGen4_type.getLiteral().toString());
83                         // Get the next level child - method params
84                         ParseNode pnGen4_params  = pnvGen4.elementAt(2);
85                         ParseNodeVector pnvGen5 = pnGen4_params.getChildren();
86                         for(int j = 0; j < pnvGen5.size(); j++) {
87
88                                 ParseNode pnGen5 = pnvGen5.elementAt(j);
89                                 ParseNodeVector pnvGen6 = pnGen5.getChildren();
90                                 // Param type
91                                 ParseNode pnGen6_type = pnvGen6.elementAt(0);
92                                 // Param identifier
93                                 ParseNode pnGen6_ident = pnvGen6.elementAt(1);
94                                 // Add a new method param (type and identifier)
95                                 intDecl.addMethodParam(pnGen4_ident.getLiteral().toString(),
96                                         pnGen6_ident.getLiteral().toString(), pnGen6_type.getLiteral().toString());
97                         }
98                         //System.out.println();
99                 }
100         }
101
102
103         /**
104          * processCapabilityDecl() processes capability declaration part
105          */
106         public void processCapabilityDecl() {
107
108                 // Get the root - capability list (element 1)
109                 ParseNodeVector pnv = pn.getChildren();
110                 ParseNode pnRoot = pnv.elementAt(1);
111                 // Get the second child of root for "capab_list"
112                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
113                 if (pnvGen2.size() == 0) {
114                         throw new Error("ParseTreeHandler: Capability declaration is missing! Please check your policy file...");
115                 }
116                 // Iterate over the list of capabilities
117                 for(int i = 0; i < pnvGen2.size(); i++) {
118
119                         ParseNode pnGen2 = pnvGen2.elementAt(i);
120                         // Get the next level child for capabilities
121                         ParseNodeVector pnvGen3 = pnGen2.getChildren();
122                         // Get the capability name, e.g. ImageCapture for Camera.ImageCapture
123                         ParseNode pnGen3_capab = pnvGen3.elementAt(1);
124                         // Add new capability
125                         capDecl.addNewCapability(pnGen3_capab.getLiteral().toString());
126                         // Get the capability contents, i.e. descriptions and methods
127                         ParseNode pnGen3_capab_cont = pnvGen3.elementAt(2);
128                         ParseNodeVector pnvGen4 = pnGen3_capab_cont.getChildren();
129                         // Iterate over the list of capability contents
130                         for(int j = 0; j < pnvGen4.size(); j++) {
131
132                                 ParseNode pnGen4 = pnvGen4.elementAt(j);
133                                 ParseNodeVector pnvGen5 = pnGen4.getChildren();
134                                 ParseNode pnGen5 = pnvGen5.elementAt(0);
135                                 // Check the label and separate between description (capab_desc)
136                                 // and method name (capab_ident)
137                                 String label = pnGen5.getLabel().toString();
138                                 if (label.equals("capab_desc")) {
139                                         capDecl.addNewDescription(pnGen3_capab.getLiteral().toString(),
140                                                 pnGen5.getLiteral().toString());
141                                 } else if (label.equals("capab_ident")) {
142                                         capDecl.addNewMethod(pnGen3_capab.getLiteral().toString(),
143                                                 pnGen5.getLiteral().toString());                                
144                                 } else
145                                         throw new Error("ParseTreeHandler: Unknown label '" + label + "' while operating on parse tree!");
146
147                         }
148                 }
149         }
150
151
152         /**
153          * processRequiresDecl() processes "requires" declaration part
154          */
155         public void processRequiresDecl() {
156
157                 // Get the root - requires list (element 2)
158                 ParseNodeVector pnv = pn.getChildren();
159                 ParseNode pnRoot = pnv.elementAt(2);
160                 // Get the second child of root for "capab_list"
161                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
162                 if (pnvGen2.size() == 0) {
163                         throw new Error("ParseTreeHandler: 'Requires' declaration is missing! Please check your policy file...");
164                 }
165                 // Iterate over the list of requires statements
166                 for(int i = 0; i < pnvGen2.size(); i++) {
167
168                         ParseNode pnGen2 = pnvGen2.elementAt(i);
169                         ParseNodeVector pnvGen3 = pnGen2.getChildren();
170                         // Get the new interface that we want to generate
171                         ParseNode pnGen3_intface = pnvGen3.elementAt(2);
172                         reqDecl.addNewIntface(pnGen3_intface.getLiteral().toString());
173                         // Get capability list at element 1
174                         ParseNode pnGen3_capab_list = pnvGen3.elementAt(1);
175                         ParseNodeVector pnvGen4 = pnGen3_capab_list.getChildren();
176                         // Browse through capabilities
177                         for (int j = 0; j < pnvGen4.size(); j++) {
178                                 ParseNode pnGen4 = pnvGen4.elementAt(j);
179                                 reqDecl.addNewCapability(pnGen3_intface.getLiteral().toString(),
180                                         pnGen4.getLiteral().toString());
181                         }
182                 }
183         }
184
185
186         /**
187          * getInterfaceDecl() returns InterfaceDecl object
188          */
189         public InterfaceDecl getInterfaceDecl() {
190
191                 return intDecl;
192         }
193
194
195         /**
196          * getCapabilityDecl() returns CapabilityDecl object
197          */
198         public CapabilityDecl getCapabilityDecl() {
199
200                 return capDecl;
201         }
202
203
204         /**
205          * getRequiresDecl() returns RequiresDecl object
206          */
207         public RequiresDecl getRequiresDecl() {
208
209                 return reqDecl;
210         }
211
212
213         /**
214          * getOrigIntface() returns the original interface in policy, e.g. Camera
215          * <p>
216          * The ParseNode object should be the one returned from <Parser>.parse().value
217          */
218         public static String getOrigIntface(ParseNode pn) {
219
220                 // Get the root: just keyword "interface"
221                 ParseNodeVector pnv = pn.getChildren();
222                 ParseNode pnRoot = pnv.elementAt(0);
223                 // Get the child: intface_ident = original interface identifier, e.g. Camera
224                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
225                 if (pnvGen2.size() == 0) {
226                         throw new Error("ParseTreeHandler: Interface declaration is missing! Please check your policy file...");
227                 }
228                 ParseNode pnGen2 = pnvGen2.elementAt(0);
229                 // Confirm that this is "intface_ident"
230                 if (pnGen2.getLabel().equals("intface_ident")) {
231                         if (pnGen2.getLiteral() != null) {
232                                 return pnGen2.getLiteral().toString();
233                         } else
234                                 throw new Error("ParseTreeHandler: No interface name found! Please fix policy file!");
235                 } else
236                         throw new Error("ParseTreeHandler: Label 'intface_ident' is not found! Instead, '" + pnGen2.getLabel() + "' was found...");
237         }
238
239
240 /*      public static void main(String[] args) throws Exception {
241
242                 // initialize the symbol factory
243                 ComplexSymbolFactory csf = new ComplexSymbolFactory();
244                 // create a buffering scanner wrapper
245                 ScannerBuffer lexer = new ScannerBuffer(new Lexer(new BufferedReader(new FileReader(args[0])),csf));
246                 // start parsing
247                 Parser p = new Parser(lexer,csf);
248                 ParseNode pn = (ParseNode) p.parse().value;
249
250                 String intFace = ParseTreeHandler.getOrigIntface(pn);
251                 System.out.println("Original interface name: " + intFace);
252                 ParseTreeHandler pth = new ParseTreeHandler(intFace, pn);
253                 pth.processInterfaceDecl();
254                 pth.processCapabilityDecl();
255                 pth.processRequiresDecl();
256         }*/
257 }