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