JsRender/Node.vala
[app.Builder.js] / JsRender / Node.vala
1
2 // test..
3 // valac gitlive/app.Builder.js/JsRender/Lang.vala gitlive/app.Builder.js/JsRender/Node.vala --pkg gee-1.0 --pkg=json-glib-1.0 -o /tmp/Lang ;/tmp/Lang
4
5 public class JsRender.Node  {
6     
7     public GLib.List<Node> items; // child items..
8     
9     public Gee.HashMap<string,string> props; // the properties..
10     public Gee.HashMap<string,string> listeners; // the listeners..
11     public string  xvala_cls;
12         public string xvala_xcls; // 'Xcls_' + id;
13     public string xvala_id; // item id or ""
14             
15     public bool is_array;
16     
17     public Node()
18     {
19         this.items = new GLib.List<Node>();
20         this.props = new Gee.HashMap<string,string>();
21                 this.listeners = new Gee.HashMap<string,string>();
22         this.is_array = false;
23         this.xvala_xcls = "";
24     }
25     
26     
27     
28     
29     public bool isArray()
30     {
31         return this.is_array;
32     }
33     public bool hasChildren()
34     {
35         return this.items.length() > 0;
36     }
37     public bool hasXnsType()
38     {
39         if (this.props.get("|xns") != null && this.props.get("xtype") != null) {
40             return true;
41             
42         }
43         return false;
44     }
45         public string fqn()
46         {
47                 if (!this.hasXnsType ()) {
48                         return "";
49                 }
50                 return this.props.get("|xns") + "." + this.props.get("xtype"); 
51
52         }
53         
54     // wrapper around get props that returns empty string if not found.
55     public string get(string key)
56     {
57         var k = this.props.get(key);
58         if (k != null) {
59                         return k;
60                 }
61                 
62                 k = this.props.get("|" + key);
63                 if (k != null) {
64                         
65                 return k;
66                 }
67         
68         return "";
69         
70     }
71      
72     /* creates javascript based on the rules */
73     public Node? findProp(string n) {
74                 for(var i=0;i< this.items.length();i++) {
75                         var p = this.items.nth_data(i).get("*prop");
76                         if (this.items.nth_data(i).get("*prop").length < 1) {
77                                 continue;
78                         }
79                         if (p == n) {
80                                 return this.items.nth_data(i);
81                         }
82                 }
83                 return null;
84
85         }
86   
87     
88     public string mungeToString (bool isListener, string pad,  GLib.List<string> doubleStringProps)
89     {
90         
91          
92         pad = pad.length < 1 ? "    " : pad;
93         
94         
95          
96         
97         //isListener = isListener || false;
98
99        //var keys = this.keys();
100         var isArray = this.isArray();
101         
102         
103         var els = new GLib.List<string>(); 
104         var skip = new Gee.ArrayList<string>();
105         if (!isArray && this.hasXnsType() ) {
106                 // this.mungeXtype(obj['|xns'] + '.' + obj['xtype'], els); ??????
107                 
108                 
109                skip.add("|xns");
110                skip.add("xtype");
111                
112         }
113         //var newitems = new Gee.ArrayList<JsRender.Node>();
114         var oprops = new Gee.HashMap<string,Node>();
115         
116         if (!isArray && this.hasChildren()) {
117             // look for '*props'
118            
119             for (var ii =0; ii< this.items.length(); ii++) {
120                 var pl = this.items.nth_data(ii);
121                 if (!pl.props.has_key("*prop")) {
122                     //newitems.add(pl);
123                     continue;
124                 }
125                 
126                 //print(JSON.stringify(pl,null,4));
127                 // we have a prop...
128                 //var prop = pl['*prop'] + '';
129                 //delete pl['*prop'];
130                 var prop = pl.get("*prop");
131                 // name ends in [];
132                 if (! Regex.match_simple("\\[\\]$", prop)) {
133                     // it's a standard prop..
134                     
135                     // munge property..??
136                     oprops.set(prop, pl);
137                     
138                     
139                     //keys.push(prop);
140                     continue;
141                 }
142                 
143                 prop  = prop.substring(0,  -2); //strip []
144                 // it's an array type..
145                 if (!oprops.has_key(prop)) {
146                     var cn = new Node();
147                     oprops.set(prop, cn);
148                     
149                 }
150                 // ignores the fact it might be duplciated...
151                 oprops.get(prop).is_array = true;
152                 oprops.get(prop).items.append(pl);
153               
154                 
155                 
156                 
157             }
158             
159             //obj.items = newitems;
160             //if (!obj.items.length) {
161             //    delete obj.items;
162             //}
163             
164         }
165         if (this.isArray()) {
166             
167             
168             for (var i=0;i< this.items.length();i++) {
169                 var el = this.items.nth_data(i);
170                 
171                 els.append("%d".printf(i) + " : " + el.mungeToString(false, pad,doubleStringProps));
172                 
173             }
174             var spad = pad.substring(0, pad.length-4);
175             return   "{\n" +
176                 pad  + string.join(",\n" + pad , els) + 
177                 "\n" + spad +  "}";
178                
179             
180             
181             
182           
183         } 
184         string left;
185         Regex func_regex ;
186         try {
187             func_regex = new Regex("^\\s+|\\s+$");
188         } catch (Error e) {
189             print("failed to build regex");
190             return "";
191         }
192         var piter = this.props.map_iterator();
193         while (piter.next() ) {
194             var k = piter.get_key();
195             var v = piter.get_value();
196             
197             if (skip.contains(k) ) {
198                 continue;
199             }
200             
201             
202             string leftv = k[0] == '|' ? k.substring(1) : k;
203             // skip builder stuff. prefixed with  '.' .. just like unix fs..
204             if (leftv[0] == '.') { // |. or . -- do not output..
205                 continue;
206             }
207              if (k[0] == '*') {
208                 // ignore '*prop';
209                 continue;
210              }
211                 
212             
213             if (Lang.isKeyword(leftv) || Lang.isBuiltin(leftv)) {
214                 left = "'" + leftv + "'";
215             } else if (Regex.match_simple("[^A-Za-z_]+",leftv)) { // not plain a-z... - quoted.
216                 var val = this.quoteString(leftv);
217                 
218                 left = "'" + val.substring(1, val.length-1).replace("'", "\\'") + "'";
219             } else {
220                 left = leftv;
221             }
222             left += " : ";
223             
224             if (isListener) {
225             // change the lines...
226                             
227                 string str;
228                 try {
229                     str = func_regex.replace(v,v.length, 0, "");
230                 } catch(Error e) {
231                     print("regex failed");
232                     return "";
233                 }
234                 
235                 var lines = str.split("\n");
236                 if (lines.length > 1) {
237                     str = string.join("\n" + pad, lines);
238                 }
239                 
240                 els.append(left  + str);
241                 continue;
242             }
243              
244             // next.. is it a function..
245             if (k[0] == '|') {
246                 // does not hapepnd with arrays.. 
247                 if (v.length < 1) {  //if (typeof(el) == 'string' && !obj[i].length) { //skip empty.
248                     continue;
249                 }
250                 
251                 string str;
252                 try {
253                     str = func_regex.replace(v,v.length, 0, "");
254                 } catch(Error e) {
255                     print("regex failed");
256                     return "";
257                 }
258                 
259                 var lines = str.split("\n");
260                 if (lines.length > 1) {
261                     str =  string.join("\n" + pad, lines);
262                 }
263                 
264                 els.append(left + str);
265                 continue;
266             }
267             // standard..
268             
269             
270             if (Lang.isNumber(v) || Lang.isBoolean(v)) { // boolean or number...?
271                 els.append(left + v );
272                 continue;
273             }
274             
275             // strings..
276             if (doubleStringProps.length() < 1) {
277                 els.append(left + this.quoteString(v));
278                 continue;
279             }
280            
281             if (doubleStringProps.index(k) > -1) {
282                 els.append(left + this.quoteString(v));
283                 continue;
284             }
285              
286             // single quote.. v.substring(1, v.length-1).replace("'", "\\'") + "'";
287             els.append(left + "'" + v.substring(1, v.length-1).replace("'", "\\'") + "'");
288             
289
290            
291            
292            
293         }
294         var iter = oprops.map_iterator();
295         while (iter.next()) {
296             var k = iter.get_key();
297             var vo = iter.get_value();
298             string leftv = k[0] == '|' ? k.substring(1) : k;
299             if (Lang.isKeyword(leftv) || Lang.isBuiltin(leftv)) {
300                 left = "'" + leftv + "'";
301             } else if (Regex.match_simple("[^A-Za-z_]+",leftv)) { // not plain a-z... - quoted.
302                 var val = this.quoteString(leftv);
303                 
304                 left = "'" + val.substring(1, val.length-1).replace("'", "\\'") + "'";
305             } else {
306                 left = leftv;
307             }
308             left += " : ";
309             
310             var right = vo.mungeToString(k == "listeners", pad + "    ",doubleStringProps);
311             
312             //if (!left.length && isArray) print(right);
313             
314             if (right.length > 0){
315                 els.append(left + right);
316             }
317         
318             
319         }
320         if (els.length() < 1) {
321             return "";
322         }
323         // oprops...    
324             
325         var spad = pad.substring(0, pad.length-4);
326         return   "{\n" +
327             pad  + string.join(",\n" + pad , els) + 
328             "\n" + spad +  "}";
329            
330            
331                
332         
333         
334     }
335     static Json.Generator gen = null;
336     
337     public string quoteString(string str)
338     {
339         if (Node.gen == null) {
340             Node.gen = new Json.Generator();
341         }
342         var builder = new Json.Builder();
343         builder.add_string_value(str);
344         Node.gen.set_root (builder.get_root ());
345         return  Node.gen.to_data (null);   
346     }
347
348     public void loadFromJson(Json.Object obj) {
349         obj.foreach_member((o , key, value) => {
350             if (key == "items") {
351                 var ar = value.get_array();
352                 ar.foreach_element( (are, ix, el) => {
353                     var node = new Node();
354                     node.loadFromJson(el.get_object());
355                     this.items.append(node);
356                 });
357                 return;
358             }
359             if (key == "listeners") {
360                 var li = value.get_object();
361                 obj.foreach_member((lio , li_key, li_value) => {
362                     this.listeners.set(li_key, li_value.get_string());
363
364                 });
365                 return;
366             }
367             this.props.set(key, value.get_string());
368         });
369         
370
371
372
373     }
374     
375     
376 }