src/Palete/GirObject.vala
[app.Builder.js] / src / Palete / GirObject.vala
1 /**
2  * This is the base class for representing the vala API
3  *  
4  * it was originally based on parsing Gir files - but since then
5  * has evolved into using libvala  
6  * 
7  * 
8  */
9
10
11
12 namespace Palete {
13         public errordomain GirError {
14                 INVALID_TYPE,
15                 NEED_IMPLEMENTING,
16                 MISSING_FILE,
17                 INVALID_VALUE,
18                 INVALID_FORMAT
19         }
20         public class GirObject: Object {
21                 public string name;
22                 public string ns;
23                 public string propertyof;
24                 public string type;
25                 public string nodetype;
26                 public string  package;
27                 
28                 public GirObject paramset = null;
29                 public GirObject return_value = null;
30                     
31                 public bool is_instance;
32                 public bool is_array;
33                 public bool  is_varargs;
34                 public bool  ctor_only; // specially added ctor properties..
35                 public  string parent;
36                 public  string value;
37                 // to be filled in...
38          
39                 public  string sig;
40
41                 bool is_overlaid;
42
43                 public  GirObject gparent;
44                 public Gee.ArrayList<GirObject> params;
45                 public Gee.ArrayList<string> implements;
46                 public Gee.ArrayList<string> inherits; // full list of all classes and interfaces...
47                 public Gee.HashMap<string,GirObject> ctors;
48                 public Gee.HashMap<string,GirObject> methods;
49                 public Gee.HashMap<string,string>    includes;
50                 public Gee.HashMap<string,GirObject> classes;
51                 public Gee.HashMap<string,GirObject> props;
52                 public Gee.HashMap<string,GirObject> consts;
53                 public Gee.HashMap<string,GirObject> signals;
54                 public string doctxt;
55
56
57                 
58                 public GirObject(string nodetype, string n)
59                 {
60                         this.nodetype = nodetype;
61                         this.name = n;
62                         this.ns = "";
63                         this.parent = "";
64                         this.type = "";
65                         this.propertyof = "";
66                         this.is_array = false;
67                         this.is_instance = false;
68                         this.is_varargs = false;
69                         this.ctor_only  =false;
70                         this.doctxt = "";
71                 
72                         this.sig = "";
73
74                         this.gparent = null;
75                         
76                         this.implements = new Gee.ArrayList<string>();
77                         this.inherits  = new Gee.ArrayList<string>(); // list of all ancestors. (interfaces and parents)
78                         this.includes   = new Gee.HashMap<string,string>();
79
80                         this.params = new Gee.ArrayList<GirObject>();
81                         this.ctors      = new Gee.HashMap<string,GirObject>();
82                         this.methods    =new Gee.HashMap<string,GirObject>();
83
84                         this.classes    = new Gee.HashMap<string,GirObject>();
85                         this.props      = new Gee.HashMap<string,GirObject>();
86                         this.consts     = new Gee.HashMap<string,GirObject>();
87                         this.signals    = new Gee.HashMap<string,GirObject>();
88                         this.is_overlaid = false;
89                         this.paramset = null;
90                 }
91
92                 public string[] inheritsToStringArray()
93                 {
94                         string[] ret = {};
95                         for(var i =0;i< this.inherits.size; i++) {
96                                 ret += this.inherits.get(i);
97                         }
98                         return ret;
99
100                 }
101
102                 
103                 public void  overlayParent()
104                 {
105                         
106                         if (this.parent.length < 1 || this.is_overlaid) {
107                                 this.is_overlaid = true;
108                                 return;
109                         }
110                         // print("Overlaying " +this.name + " with " + this.parent + "\n");
111
112                         var pcls = this.clsToObject( this.parent);
113                         if (pcls == null) {
114                                 throw new GirError.INVALID_VALUE("Could not find class : " + 
115                                         this.parent + " of " + this.name  + " in " + this.ns);
116                         }
117                         
118                         pcls.overlayParent( );
119                         this.copyFrom(pcls,false);
120                         for(var i=0; i < this.implements.size; i++) {
121                                 var clsname = this.implements.get(i);
122                                 var picls = this.clsToObject(clsname);
123                                 this.copyFrom(picls,true);
124                         }
125                         this.is_overlaid = true;
126                         
127                 }
128
129                 public void overlayCtorProperties() 
130                 {
131                         //print("Check overlay Ctor %s\n", this.name);
132                         if (!this.ctors.has_key("new")) {
133                                 return;
134                         }
135                         var ctor = this.ctors.get("new");
136                         if (ctor.paramset == null || ctor.paramset.params.size < 1) {
137                                 return;
138                         }
139                         //print("Found Ctor\n");
140                         var iter = ctor.paramset.params.list_iterator();
141                         while (iter.next()) {
142                                 var n = iter.get().name;
143                                 
144                                 if (this.props.has_key(n)) {
145                                         continue;
146                                 }
147                                 if (n == "...") {
148                                         continue;
149                                 }
150                                 //print("Adding prop %s\n", n);
151                                 
152                                 // it's a new prop..
153                                 var c = new GirObject("Prop",n);
154                                 c.gparent = this;
155                                 c.ns = this.ns;
156                                 c.propertyof = this.name;
157                                 c.type = iter.get().type;
158                                 c.ctor_only = true;
159                                 this.props.set(n, c);
160                         }
161                         
162
163                 }
164
165
166                 
167                 public string fqn() {
168                         // not sure if fqn really is correct here...
169                         // 
170                         return this.nodetype == "Class" || this.nodetype=="Interface"
171                                         ? this.name : (this.ns + this.name);
172                 }
173                 
174                 public void copyFrom(GirObject pcls, bool is_interface) 
175                 {
176
177                         this.inherits.add(pcls.fqn());
178
179                         var liter = pcls.inherits.list_iterator();
180                         while(liter.next()) {
181                         if (this.inherits.contains(liter.get())) {
182                                         continue;
183                                 }
184                                 this.inherits.add(liter.get()); 
185                         }          
186                         
187                         
188                         var iter = pcls.methods.map_iterator();
189                         while(iter.next()) {
190                         if (null != this.methods.get(iter.get_key())) {
191                                         continue;
192                                 }
193                                 
194                                 this.methods.set(iter.get_key(), iter.get_value());
195                         }
196                         
197                         iter = pcls.props.map_iterator();
198                         while(iter.next()) {
199                                  if (null != this.props.get(iter.get_key())) {
200                                         continue;
201                                 }
202                                 
203                                 this.props.set(iter.get_key(), iter.get_value());
204                         }               
205                         
206                         iter = pcls.signals.map_iterator();
207                         while(iter.next()) {
208                                 if (null != this.signals.get(iter.get_key())) {
209                                                 continue;
210                                 }
211         
212                                 this.signals.set(iter.get_key(), iter.get_value());
213                         }       
214                 }
215                 
216                 public Json.Object toJSON()
217                 {
218                     var r = new Json.Object();
219                     r.set_string_member("nodetype", this.nodetype);
220                     r.set_string_member("name", this.name);
221                                 if (this.propertyof.length > 0) {
222                         r.set_string_member("of", this.propertyof);
223                     }
224                     if (this.type.length > 0) {
225                         r.set_string_member("type", this.type);
226                     }
227                     if (this.parent != null && this.parent.length > 0) {
228                         r.set_string_member("parent", this.parent);
229                     }
230                     if (this.sig.length > 0) {
231                         r.set_string_member("sig", this.sig);
232                     }
233                 
234                     // is_arary / is_instance / is_varargs..
235
236                 
237                         if (this.inherits.size > 0) {
238                         r.set_array_member("inherits", this.toJSONArrayString(this.inherits));
239                     }
240                     
241                     if (this.implements.size > 0) {
242                         r.set_array_member("implements", this.toJSONArrayString(this.implements));
243                     }
244                     
245                     if (this.params.size > 0) {
246                         r.set_array_member("params", this.toJSONArrayObject(this.params));
247                     }
248                     if (this.ctors.size > 0) {
249                         r.set_object_member("ctors", this.toJSONObject(this.ctors));
250                     }
251                     if (this.methods.size > 0) {
252                         r.set_object_member("methods", this.toJSONObject(this.methods));
253                     }
254                     if (this.includes.size > 0) {
255                         r.set_object_member("includes", this.toJSONObjectString(this.includes));
256                     }
257                     if (this.classes.size > 0) {
258                         r.set_object_member("classes", this.toJSONObject(this.classes));
259                     }
260                     if (this.props.size > 0) {
261                         r.set_object_member("props", this.toJSONObject(this.props));
262                     }
263                     if (this.consts.size > 0) {
264                         r.set_object_member("consts", this.toJSONObject(this.consts));
265                     }
266                     if (this.signals.size > 0) {
267                         r.set_object_member("signals", this.toJSONObject(this.signals));
268                     }
269                     if (this.paramset != null) {
270                         r.set_object_member("paramset", this.paramset.toJSON());
271                     }
272                     if (this.return_value != null) {
273                         r.set_object_member("return_value", this.return_value.toJSON());
274                     }
275                     return r;
276                 }
277                 public Json.Object toJSONObject(Gee.HashMap<string,GirObject> map)
278                 {
279                     var r = new Json.Object();
280                     var iter = map.map_iterator();
281                     while(iter.next()) {
282                         r.set_object_member(iter.get_key(), iter.get_value().toJSON());
283                     }
284                     return r;
285                 }
286                 public Json.Object  toJSONObjectString(Gee.HashMap<string,string> map)
287                 {
288                     var r = new Json.Object();
289                     var iter = map.map_iterator();
290                     while(iter.next()) {
291                         r.set_string_member(iter.get_key(), iter.get_value());
292                     }
293                     return r;
294                 }
295                 public Json.Array toJSONArrayString(Gee.ArrayList<string> map)
296                 {
297                     var r = new Json.Array();
298                     for(var i =0;i< map.size;i++) {
299                     
300                         r.add_string_element(map.get(i));
301                     }
302                     return r;
303                 }
304                 public Json.Array toJSONArrayObject(Gee.ArrayList<GirObject> map)
305                 {
306                     var r = new Json.Array();
307                     for(var i =0;i< map.size;i++) {
308                     
309                         r.add_object_element(map.get(i).toJSON());
310                     }
311                     return r;
312                 }
313                 public string asJSONString()
314                 {
315                         var generator = new Json.Generator ();
316                         generator.indent = 4;
317                         generator.pretty = true;
318                         var n = new Json.Node(Json.NodeType.OBJECT);
319                         n.set_object(this.toJSON());
320                         generator.set_root(n);
321         
322                         return generator.to_data(null);
323                 }
324
325  
326                 public GirObject fetchByFqn(string fqn) {
327                         //print("Searching (%s)%s for %s\n", this.nodetype, this.name, fqn);
328                         var bits = fqn.split(".");
329                         
330                         var ret = this.classes.get(bits[0]);
331                         if (ret != null) {
332                                 if (bits.length < 2) {
333                                         return ret;
334                                 }
335                                 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
336                         }
337
338                         ret = this.ctors.get(bits[0]);                  
339                         if (ret != null) {
340                                 if (bits.length < 2) {
341                                         return ret;
342                                 }
343                                 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
344                         }
345
346                         ret = this.methods.get(bits[0]);                        
347                         if (ret != null) {
348                                 if (bits.length < 2) {
349                                         return ret;
350                                 }
351                                 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
352                         }
353                         ret = this.props.get(bits[0]);                  
354                         if (ret != null) {
355                                 if (bits.length < 2) {
356                                         return ret;
357                                 }
358                                 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
359                         }
360                         ret = this.consts.get(bits[0]);                 
361                         if (ret != null) {
362                                 if (bits.length < 2) {
363                                         return ret;
364                                 }
365                                 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
366                         }
367
368                         ret = this.signals.get(bits[0]);                        
369                         if (ret != null) {
370                                 if (bits.length < 2) {
371                                         return ret;
372                                 }
373                                 return ret.fetchByFqn(fqn.substring(bits[0].length+1));
374                         }
375                         if (this.paramset == null) {
376                                 return null;
377                         }
378                         var iter = this.paramset.params.list_iterator();
379                         while (iter.next()) {
380                                 var p = iter.get();
381                                 if (p.name != bits[0]) {
382                                         continue;
383                                 }
384                                 return p;
385                         }
386                                  
387                         // fixme - other queires? - enums?
388                         return null;
389                 }
390                 /**
391                  *  -----------------------------------------------
392                  *  code relating to the structure loader ....
393                  * 
394                  */
395                  
396                 public GirObject clsToObject(string in_pn)
397                 {
398                         var pn = in_pn;
399                         /*
400                         
401                         
402                         var gir = Gir.factory (this.ns);
403                         if (in_pn.contains(".")) {
404                                 gir =  Gir.factory(in_pn.split(".")[0]);
405                                 pn = in_pn.split(".")[1];
406                         }
407                         */
408                         
409                         var gir = VapiParser.factory (this.ns);
410                         if (in_pn.contains(".")) {
411                                 gir =  VapiParser.factory(in_pn.split(".")[0]);
412                                 pn = in_pn.split(".")[1];
413                         }
414                         
415                         
416                         return gir.classes.get(pn);
417
418                         
419                 }
420                 public string fqtype() {
421                         return Gir.fqtypeLookup(this.type, this.ns);
422                         
423                         /* return Gir.fqtypeLookup(this.type, this.ns); */
424                 }
425         }
426             
427 }