Attribute changed old-javascript
[app.Builder.js] / old-javascript / Project / Project.vala
1 //<Script type="text/javascript">
2
3 /**
4  * Project Object
5  * 
6  * Projects can only contain one directory... - it can import other projects..(later)
7  * 
8  * we need to sort out that - paths is currently a key/value array..
9  * 
10  * 
11  * 
12  */
13 namespace Project {
14          public errordomain Error {
15                 INVALID_TYPE,
16                 NEED_IMPLEMENTING,
17                 MISSING_FILE,
18                 INVALID_VALUE,
19                 INVALID_FORMAT
20         }
21
22         // static array of all projects.
23         public Gee.HashMap<string,Project>  projects;
24
25         
26         public bool  projects_loaded = false;
27
28         
29         public class Project : Object {
30                 
31                 public signal void on_changed (); 
32         
33                 public string id;
34                 public string fn = ""; // just a md5...
35                 public string name = "";
36                 public string runhtml = "";
37                 public string base_template = "";
38                 public string rootURL = "";
39                 public Gee.HashMap<string,string> paths;
40                 public Gee.HashMap<string,JsRender.JsRender> files ;
41                 //tree : false,
42                 public  string xtype;
43                  
44                 bool is_scanned; 
45            
46                 
47                 public Project (string path) {
48                     
49                         this.name = GLib.Path.get_basename(path); // default..
50
51                         this.is_scanned = false;
52                         this.paths = new Gee.HashMap<string,string>();
53                         this.files = new Gee.HashMap<string,JsRender.JsRender>();
54                         //XObject.extend(this, cfg);
55                         //this.files = { }; 
56                         if (path.length > 0) {
57                                 this.paths.set(path, "dir");
58                         }
59                         
60                     
61                     
62                 }
63
64         
65         
66         
67                 
68                 public static void loadAll(bool force = false)
69                 {
70                         if (projects_loaded && !force) {
71                                 return;
72                         }
73
74                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
75                         var dir = File.new_for_path(dirname);
76                         if (!dir.query_exists()) {
77                                 dir.make_directory();
78                                 return;
79                         }
80                         projects = new  Gee.HashMap<string,Project>();
81                           
82                    
83                         try {
84                                 var file_enum = dir.enumerate_children(
85                                         GLib.FileAttribute.STANDARD_DISPLAY_NAME, 
86                                         GLib.FileQueryInfoFlags.NONE, 
87                                         null
88                                 );
89                         
90                          
91                                 FileInfo next_file; 
92                                 while ((next_file = file_enum.next_file(null)) != null) {
93                                         var fn = next_file.get_display_name();
94                                         if (!Regex.match_simple("\\.json$", fn)) {
95                                                 continue;
96                                         }
97                                         factoryFromFile(dirname + "/" + fn);
98                                 }       
99                         } catch(Error e) {
100                                 print("oops - something went wrong scanning the projects\n");
101                         }
102                     
103
104                 }
105
106                 public static Gee.ArrayList<Project> allProjectsByName()
107                 {
108                     var ret = new Gee.ArrayList<Project>();
109                     var iter = projects.map_iterator();
110                             while (iter.next()) {
111                                 ret.add(iter.get_value());
112                             }
113                     // fixme -- sort...
114                     return ret;
115                 
116                 }
117                  
118                 // load project data from project file.
119                 public static void   factoryFromFile(string jsonfile)
120                 {
121                          
122                         print("parse %s\n", jsonfile);
123
124                         var pa = new Json.Parser();
125                         pa.load_from_file(jsonfile);
126                         var node = pa.get_root();
127
128                         
129                         if (node == null || node.get_node_type () != Json.NodeType.OBJECT) {
130                                 print("SKIP " + jsonfile + " - invalid format?\n");
131                                 return;
132                         }
133                         
134                         var obj = node.get_object ();
135                         var xtype =  obj.get_string_member("xtype");
136
137
138                         var paths = obj.get_object_member("paths");
139                         var i = 0;
140                         var fpath = "";
141                         paths.foreach_member((sobj, key, val) => {
142                                 if (i ==0 ) {
143                                         fpath = key;
144                                 }
145                                         
146                         });
147
148                         
149                         var proj = factory(xtype, fpath);
150
151                         proj.fn =  Path.get_basename(jsonfile).split(".")[0];
152
153                         // might not exist?
154
155                         if (obj.has_member("runhtml")) {
156                                 proj.runhtml  = obj.get_string_member("runhtml"); 
157                         }
158                         // might not exist?
159                         if (obj.has_member("base_template")) {
160                                 proj.base_template  = obj.get_string_member("base_template"); 
161                         }
162                         // might not exist?
163                         if (obj.has_member("rootURL")) {
164                                 proj.rootURL  = obj.get_string_member("rootURL"); 
165                         }
166                         
167                         proj.name = obj.get_string_member("name");
168
169                          
170                         paths.foreach_member((sobj, key, val) => {
171                                 proj.paths.set(key, "dir");
172                         });
173                         projects.set(proj.id,proj);
174                 }
175                 
176                 
177                 public static Project factory(string xtype, string path)
178                 {
179
180                         // check to see if it's already loaded..
181
182                          
183                         var iter = projects.map_iterator();
184                         while (iter.next()) {
185                                 if (iter.get_value().hasPath( path)) {
186                                         return iter.get_value();
187                                  }
188                         }
189
190
191                         switch(xtype) {
192                                 case "Gtk":
193                                         return new Gtk(path);
194                                 case "Roo":
195                                         return new Roo(path);
196                         }
197                         throw new Error.INVALID_TYPE("invalid project type");
198                                 
199                 }
200                  public static void  remove(Project project)
201                 {
202                         // delete the file..
203                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
204                          
205                         FileUtils.unlink(dirname + "/" + project.fn + ".json");
206                         projects.unset(project.id,null);
207                         
208
209                 }
210                  
211
212                 public void save()
213                 {
214                                 // fixme..
215             
216                         if (this.fn.length < 1) {
217                                 // make the filename..
218                                 //var t = new DateTime.now_local ();
219                                 //TimeVal tv;
220                                 //t.to_timeval(out tv);
221                                 //var str = "%l:%l".printf(tv.tv_sec,tv.tv_usec);
222                                 var str = this.firstPath();
223                                 
224                                 this.fn = GLib.Checksum.compute_for_string(GLib.ChecksumType.MD5, str, str.length);
225                         }
226
227                         var dirname = GLib.Environment.get_home_dir() + "/.Builder";
228                         var  s =  this.toJSON(false);
229                         FileUtils.set_contents(dirname + "/" + this.fn + ".json", s, s.length);  
230                         
231                         
232                 }
233
234                 
235                 
236                 public string toJSON(bool show_all)
237                 {
238                     
239                         var builder = new Json.Builder ();
240
241                         builder.begin_object ();
242
243                         builder.set_member_name ("name");
244                         builder.add_string_value (this.name);
245
246
247                         builder.set_member_name ("fn");
248                         builder.add_string_value (this.fn);
249
250                         builder.set_member_name ("xtype");
251                         builder.add_string_value (this.xtype);
252
253                         builder.set_member_name ("runhtml");
254                         builder.add_string_value (this.runhtml);
255
256
257                         builder.set_member_name ("rootURL");
258                         builder.add_string_value (this.rootURL);
259                         
260                         builder.set_member_name ("base_template");
261                         builder.add_string_value (this.base_template);                  
262                         // file ??? try/false?
263                         builder.set_member_name ("paths");
264
265
266                         builder.begin_object ();
267
268
269                         var iter = this.paths.map_iterator();
270                         while (iter.next()) {
271                                 builder.set_member_name (iter.get_key());
272                                 builder.add_string_value("path");
273                         }
274                         builder.end_object ();
275                         
276                         if (show_all) {
277                                 builder.set_member_name ("files");
278                                 builder.begin_array ();
279                                 var fiter = this.files.map_iterator();
280                                 while (fiter.next()) {
281                                     builder.add_string_value (fiter.get_key());
282                                 }
283                                 
284                                 
285                                 builder.end_array ();
286                         }
287
288                 
289                         builder.end_object ();
290
291                         var  generator = new Json.Generator ();
292                         var  root = builder.get_root ();
293                         generator.set_root (root);
294                         if (show_all) {
295                                 generator.pretty = true;
296                                 generator.indent = 4;
297                         }
298
299                         return  generator.to_data (null);
300                           
301                       
302                 }
303                 public string firstPath()
304                 {
305                     var iter = this.paths.map_iterator();
306                     while (iter.next()) {
307                         return iter.get_key();
308                     }
309                   
310                     return "";
311                 }
312
313                 public bool hasPath(string path)
314                 {
315                     var iter = this.paths.map_iterator();
316                     while (iter.next()) {
317                         if (iter.get_key() == path) {
318                                 return true;
319                         }
320                     }
321                   
322                     return false;
323                 }
324
325                 
326                 // returns the first path
327                 public string getName()
328                 {
329                     var iter = this.paths.map_iterator();
330                     while (iter.next()) {
331                         return GLib.Path.get_basename(iter.get_key());
332                     }
333                   
334                     return "";
335                 }
336
337                 public Gee.ArrayList<JsRender.JsRender> sortedFiles()
338                 {
339                         var files = new Gee.ArrayList<JsRender.JsRender>();
340
341                         var fiter = this.files.map_iterator();
342                         while(fiter.next()) {
343                                 files.add(fiter.get_value());
344                         }
345                         files.sort((fa,fb) => {
346                                 return ((JsRender.JsRender)fa).name.collate(((JsRender.JsRender)fb).name);
347
348                         });
349                         return files;
350
351                 }
352                 
353          
354                 public JsRender.JsRender? getByName(string name)
355                 {
356                     
357                         var fiter = files.map_iterator();
358                     while(fiter.next()) {
359                      
360                         var f = fiter.get_value();
361                         
362                         
363                         print ("Project.getByName: %s ?= %s\n" ,f.name , name);
364                         if (f.name == name) {
365                             return f;
366                         }
367                     };
368                     return null;
369                 }
370                 
371                 public JsRender.JsRender? getById(string id)
372                 {
373                     
374                         var fiter = files.map_iterator();
375                         while(fiter.next()) {
376                      
377                                 var f = fiter.get_value();
378                                 
379                                 
380                                 //console.log(f.id + '?=' + id);
381                                 if (f.id == id) {
382                                     return f;
383                                 }
384                             };
385                         return null;
386                 }
387
388                 public JsRender.JsRender newFile (string name)
389                 {
390                         var ret =  JsRender.JsRender.factory(this.xtype, 
391                                                          this, 
392                                                          this.firstPath() + "/" + name + ".bjs");
393                         this.addFile(ret);
394                         return ret;
395                 }
396                 
397                 public JsRender.JsRender loadFileOnly (string path)
398                 {
399                     var xt = this.xtype;
400                     return JsRender.JsRender.factory(xt, this, path);
401                     
402                 }
403                 
404                 public JsRender.JsRender create(string filename)
405                 {
406                     var ret = this.loadFileOnly(filename);
407                     ret.save();
408                     this.addFile(ret);
409                     return ret;
410                     
411                 }
412                     
413                      
414                 public void addFile(JsRender.JsRender pfile) { // add a single file, and trigger changed.
415                 
416                 
417                     this.files.set(pfile.path, pfile); // duplicate check?
418                     this.on_changed();
419                 }
420                 
421                 public void add(string path, string type)
422                 {
423                     this.paths.set(path,type);
424                     //Seed.print(" type is '" + type + "'");
425                     if (type == "dir") {
426                         this.scanDir(path);
427                     //    console.dump(this.files);
428                     }
429                     if (type == "file" ) {
430                         
431                         this.files.set(path,this.loadFileOnly( path ));
432                     }
433                     this.on_changed();
434                     
435                 }
436                 public void  scanDirs() // cached version
437                 {
438                     if (this.is_scanned) {
439                                 return;
440                         }
441                         this.scanDirsForce();
442                     //console.dump(this.files);
443                     
444                 }
445                 
446                 public void  scanDirsForce()
447                 {
448                         this.is_scanned = true;  
449                         var iter = this.paths.map_iterator();
450                     while (iter.next()) {
451                                 //print("path: " + iter.get_key() + " : " + iter.get_value() +"\n");
452                         if (iter.get_value() != "dir") {
453                             continue;
454                         }
455                         this.scanDir(iter.get_key());
456                     }
457                     //console.dump(this.files);
458                     
459                 }
460                     // list files.
461                 public void scanDir(string dir, int dp =0 ) 
462                 {
463                     //dp = dp || 0;
464                     //print("Project.Base: Running scandir on " + dir +"\n");
465                     if (dp > 5) { // no more than 5 deep?
466                         return;
467                     }
468                     // this should be done async -- but since we are getting the proto up ...
469                     
470                     var subs = new GLib.List<string>();;            
471                     var f = File.new_for_path(dir);
472                     try {
473                         var file_enum = f.enumerate_children(GLib.FileAttribute.STANDARD_DISPLAY_NAME, GLib.FileQueryInfoFlags.NONE, null);
474                         
475                          
476                         FileInfo next_file; 
477                         while ((next_file = file_enum.next_file(null)) != null) {
478                             var fn = next_file.get_display_name();
479                     
480                              
481                             //print("trying"  + dir + "/" + fn +"\n");
482                             
483                             if (fn[0] == '.') { // skip hidden
484                                 continue;
485                             }
486                             
487                             if (FileUtils.test(dir  + "/" + fn, GLib.FileTest.IS_DIR)) {
488                                 subs.append(dir  + "/" + fn);
489                                 continue;
490                             }
491                             
492                             if (!Regex.match_simple("\\.bjs$", fn)) {
493                                                 //print("no a bjs\n");
494                                 continue;
495                             }
496                             /*
497                             var parent = "";
498                             //if (dp > 0 ) {
499                             
500                             var sp = dir.split("/");
501                             var parent = "";
502                             for (var i = 0; i < sp.length; i++) {
503                                 
504                             }
505                             
506                             /*
507                             sp = sp.splice(sp.length - (dp +1), (dp +1));
508                             parent = sp.join('.');
509                             
510                             
511                             if (typeof(_this.files[dir  + '/' + fn]) != 'undefined') {
512                                 // we already have it..
513                                 _this.files[dir  + '/' + fn].parent = parent;
514                                 return;
515                             }
516                             */
517                             var xt = this.xtype;
518                                         var el = JsRender.JsRender.factory(xt,this, dir + "/" + fn);
519                             this.files.set( dir + "/" + fn, el);
520                             // parent ?? 
521                             
522                              
523                         }
524                     } catch (Error e) {
525                         print("Project::scanDirs failed : " + e.message + "\n");
526                     } catch (GLib.Error e) {
527                                 print("Project::scanDirs failed : " + e.message + "\n");
528                         }
529                         for (var i = 0; i < subs.length(); i++) {
530                         
531                          this.scanDir(subs.nth_data(i), dp+1);
532                     }
533                     
534                 }
535                   
536         }
537 }
538