Moving struct and enum declaration into interface declaration
[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 import java.util.List;
10 import java.util.ArrayList;
11
12 /** Class ParseTreeHandler handles the parse tree generated by the 
13  *  parser (and lexer) from the policy file. 
14  *  This class accepts the AST in the form of ParseNode and
15  *  ParseNodeVector class objects.
16  *  It gives interfaces to extract the 4 types of policy file:
17  *  1) Interface and capabilities definition
18  *  2) Generated interface list ("requires" statements)
19  *  3) Enum declaration
20  *  4) Struct declaration
21  *
22  * @author      Rahmadi Trimananda <rahmadi.trimananda @ uci.edu>
23  * @version     1.0
24  * @since       2016-09-20
25  */
26 public final class ParseTreeHandler {
27
28         /**
29          * Class properties
30          */
31         private ParseNode pnPol;                // Policy: interface and capabilities
32         private ParseNode pnReq;                // Policy: "requires" statements
33         private InterfaceDecl intDecl;
34         private CapabilityDecl capDecl;
35         private RequiresDecl reqDecl;
36         private EnumDecl enumDecl;
37         private StructDecl structDecl;
38
39
40         /**
41          * Class constructors
42          */
43         public ParseTreeHandler() {
44
45                 pnPol = null;
46                 pnReq = null;
47                 intDecl = new InterfaceDecl();
48                 capDecl = new CapabilityDecl();
49                 reqDecl = new RequiresDecl();
50                 enumDecl = new EnumDecl();
51                 structDecl = new StructDecl();
52         }
53
54
55         public ParseTreeHandler(String _intFace, ParseNode _pnPol, ParseNode _pnReq) {
56
57                 pnPol = _pnPol;
58                 pnReq = _pnReq;
59                 intDecl = new InterfaceDecl(_intFace);
60                 capDecl = new CapabilityDecl(_intFace);
61                 reqDecl = new RequiresDecl(_intFace);
62                 enumDecl = new EnumDecl();
63                 structDecl = new StructDecl();
64         }
65
66
67         /**
68          * processInterfaceDecl() processes interface declaration part
69          */
70         public void processInterfaceDecl() {
71
72                 ParseNodeVector pnv = pnPol.getChildren();
73                 ParseNode pnRoot = pnv.elementAt(0);
74                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
75                 if (pnvGen2.size() == 0) {
76                         throw new Error("ParseTreeHandler: Interface declaration is missing! Please check your policy file...");
77                 }
78                 ParseNode pnGen2 = pnvGen2.elementAt(1);
79                 ParseNodeVector pnvGen3 = pnGen2.getChildren();
80                 for(int i = 0; i < pnvGen3.size(); i++) { // Loop on methods
81
82                         ParseNode pnGen3 = pnvGen3.elementAt(i);
83                         ParseNodeVector pnvGen4 = pnGen3.getChildren();
84                         // Method type, identifier, and param node
85                         ParseNode pnGen4_type = pnvGen4.elementAt(0);
86                         ParseNode pnGen4_ident  = pnvGen4.elementAt(1);
87                         ParseNode pnGen4_params  = pnvGen4.elementAt(2);
88                         ParseNodeVector pnvGen5 = pnGen4_params.getChildren();
89                         // First loop - create a key without spaces, e.g. MethodA(intA,SpeakerB)
90                         String methodKey = pnGen4_ident.getLiteral().toString() + "(";
91                         List<String> paramTypes = new ArrayList<String>();
92                         List<String> params = new ArrayList<String>();
93                         for(int j = 0; j < pnvGen5.size(); j++) { // Loop on params
94
95                                 ParseNode pnGen5 = pnvGen5.elementAt(j);
96                                 ParseNodeVector pnvGen6 = pnGen5.getChildren();
97                                 // Param type and identifier
98                                 ParseNode pnGen6_type = pnvGen6.elementAt(0);
99                                 ParseNode pnGen6_ident = pnvGen6.elementAt(1);
100                                 methodKey = methodKey + pnGen6_type.getLiteral().toString();
101                                 methodKey = methodKey + pnGen6_ident.getLiteral().toString();
102                                 // Keep the parameters temporarily
103                                 paramTypes.add(pnGen6_type.getLiteral().toString());
104                                 params.add(pnGen6_ident.getLiteral().toString());
105                                 // Don't add comma for the last parameter
106                                 if (j != pnvGen5.size() - 1) {
107                                         methodKey = methodKey + ",";
108                                 }
109                         }
110                         methodKey = methodKey + ")";
111                         // Add a new method (signature key, identifier, and type)
112                         intDecl.addNewMethod(methodKey, pnGen4_ident.getLiteral().toString(), 
113                                 pnGen4_type.getLiteral().toString());
114                         // Second loop - add the method parameters
115                         for(int j = 0; j < params.size(); j++) {
116                                 intDecl.addMethodParam(methodKey, params.get(j), paramTypes.get(j));
117                         }
118                 }
119         }
120
121
122         /**
123          * processCapabilityDecl() processes capability declaration part
124          */
125         public void processCapabilityDecl() {
126
127                 // Get the root - capability list (element 1)
128                 ParseNodeVector pnv = pnPol.getChildren();
129                 ParseNode pnRoot = pnv.elementAt(0);
130                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
131                 // Get the third child of root for "capab_list"
132                 ParseNode pnGen2 = pnvGen2.elementAt(2);
133                 ParseNodeVector pnvGen3 = pnGen2.getChildren();
134                 if (pnvGen3.size() == 0) {
135                         throw new Error("ParseTreeHandler: Capability declaration is missing! Please check your policy file...");
136                 }
137                 // Iterate over the list of capabilities
138                 for(int i = 0; i < pnvGen3.size(); i++) {
139
140                         ParseNode pnGen3 = pnvGen3.elementAt(i);
141                         // Get the next level child for capabilities
142                         ParseNodeVector pnvGen4 = pnGen3.getChildren();
143                         // Get the capability name, e.g. ImageCapture for Camera.ImageCapture
144                         ParseNode pnGen4_capab = pnvGen4.elementAt(0);
145                         // Add new capability
146                         capDecl.addNewCapability(pnGen4_capab.getLiteral().toString());
147                         // Get the capability contents, i.e. descriptions and methods
148                         ParseNode pnGen4_capab_cont = pnvGen4.elementAt(1);
149                         ParseNodeVector pnvGen5 = pnGen4_capab_cont.getChildren();
150                         // Iterate over the list of capability contents
151                         for(int j = 0; j < pnvGen5.size(); j++) {
152
153                                 ParseNode pnGen5 = pnvGen5.elementAt(j);
154                                 ParseNodeVector pnvGen6 = pnGen5.getChildren();
155                                 ParseNode pnGen6 = pnvGen6.elementAt(0);
156                                 // Check the label and separate between description (capab_desc)
157                                 // and method name (capab_ident)
158                                 String label = pnGen6.getLabel().toString();
159                                 if (label.equals("capab_desc")) {
160                                         capDecl.addNewDescription(pnGen4_capab.getLiteral().toString(),
161                                                 pnGen6.getLiteral().toString());
162                                 } else if (label.equals("capab_meth")) {
163                                         capDecl.addNewMethod(pnGen4_capab.getLiteral().toString(),
164                                                 pnGen6.getLiteral().toString().replaceAll("\\s+",""));
165                                 } else
166                                         throw new Error("ParseTreeHandler: Unknown label '" + label + "' while operating on parse tree!");
167
168                         }
169                 }
170         }
171
172
173         /**
174          * processRequiresDecl() processes "requires" declaration part
175          */
176         public void processRequiresDecl() {
177
178                 // Get the root - requires list (element 2)
179                 ParseNodeVector pnv = pnReq.getChildren();
180                 ParseNode pnRoot = pnv.elementAt(0);
181                 // Get the second child of root for "reqlist"
182                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
183                 if (pnvGen2.size() == 0) {
184                         throw new Error("ParseTreeHandler: 'Requires' declaration is missing! Please check your policy file...");
185                 }
186                 // Iterate over the list of requires statements
187                 for(int i = 0; i < pnvGen2.size(); i++) {
188
189                         ParseNode pnGen2 = pnvGen2.elementAt(i);
190                         ParseNodeVector pnvGen3 = pnGen2.getChildren();
191                         // Get the new interface that we want to generate
192                         ParseNode pnGen3_intface = pnvGen3.elementAt(2);
193                         reqDecl.addNewIntface(pnGen3_intface.getLiteral().toString());
194                         // Get capability list at element 1
195                         ParseNode pnGen3_capab_list = pnvGen3.elementAt(1);
196                         ParseNodeVector pnvGen4 = pnGen3_capab_list.getChildren();
197                         // Browse through capabilities
198                         for (int j = 0; j < pnvGen4.size(); j++) {
199                                 ParseNode pnGen4 = pnvGen4.elementAt(j);
200                                 reqDecl.addNewCapability(pnGen3_intface.getLiteral().toString(),
201                                         pnGen4.getLiteral().toString());
202                         }
203                 }
204         }
205
206
207         /**
208          * getInterfaceDecl() returns InterfaceDecl object
209          */
210         public InterfaceDecl getInterfaceDecl() {
211
212                 return intDecl;
213         }
214
215
216         /**
217          * getCapabilityDecl() returns CapabilityDecl object
218          */
219         public CapabilityDecl getCapabilityDecl() {
220
221                 return capDecl;
222         }
223
224
225         /**
226          * getRequiresDecl() returns RequiresDecl object
227          */
228         public RequiresDecl getRequiresDecl() {
229
230                 return reqDecl;
231         }
232
233
234         /**
235          * getEnumDecl() returns EnumDecl object
236          */
237         public EnumDecl getEnumDecl() {
238
239                 return enumDecl;
240         }
241
242
243         /**
244          * getStructDecl() returns StructDecl object
245          */
246         public StructDecl getStructDecl() {
247
248                 return structDecl;
249         }
250
251
252         /**
253          * getOrigIntface() returns the original interface in policy, e.g. Camera
254          * <p>
255          * The ParseNode object should be the one returned from <Parser>.parse().value
256          */
257         public static String getOrigIntface(ParseNode pn) {
258
259                 // Get the root: just keyword "interface"
260                 ParseNodeVector pnv = pn.getChildren();
261                 ParseNode pnRoot = pnv.elementAt(0);
262                 // Get the child: intface_ident = original interface identifier, e.g. Camera
263                 ParseNodeVector pnvGen2 = pnRoot.getChildren();
264                 if (pnvGen2.size() == 0) {
265                         throw new Error("ParseTreeHandler: Interface declaration is missing! Please check your policy file...");
266                 }
267                 // Get "intface_def"
268                 ParseNode pnGen2 = pnvGen2.elementAt(0);
269                 // Confirm that this is "intface_ident"
270                 if (pnGen2.getLabel().equals("intface_ident")) {
271                         if (pnGen2.getLiteral() != null) {
272                                 return pnGen2.getLiteral().toString();
273                         } else
274                                 throw new Error("ParseTreeHandler: No interface name found! Please fix policy file!");
275                 } else
276                         throw new Error("ParseTreeHandler: Label 'intface_ident' is not found! Instead, '" + pnGen2.getLabel() + "' was found...");
277         }
278 }