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