plugins: updated query_editor
[myslice.git] / plugins / updater / updater.js
1 /**
2  * Description: associate with a Get query, maintains the 'Update' query that records pending changes
3  * Copyright (c) 2012 UPMC Sorbonne Universite - INRIA
4  * License: GPLv3
5  */
6
7 // xxx this is ongoing work, very rough, and not working at all yet 
8
9 ( function ( $ ) {
10     
11     var debug=false;
12 //    debug=true
13
14     $.fn.Updater = function ( method ) {
15         /* Method calling logic */
16         if ( methods[method] ) {
17             return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
18         } else if ( typeof method === 'object' || ! method ) {
19             return methods.init.apply( this, arguments );
20         } else {
21             $.error( 'Method ' +  method + ' does not exist on $.Updater' );
22         }
23     };
24     
25     var methods = {
26         init : function( options ) {
27             return this.each(function(){
28                 var $this = $(this);
29                 var updater = new Updater (options);
30                 $this.data('Updater',updater);
31                 // xxx not tested yet
32                 var results_channel = '/results/' + options.query_uuid + '/changed';
33                 $.subscribe(results_channel, function (e,rows) { updater.query_completed (e,rows); } );
34                 // under test..
35                 var failed_channel = '/results/' + options.query_uuid + '/failed';
36                 $.subscribe(failed_channel, $this, function (e,code,output) { updater.query_failed (e, code, output); } );
37             });
38         },
39         destroy : function( ) {
40             return this.each(function(){
41                 var $this = $(this);
42                 $(window).unbind('Updater');
43                 data.Updater.remove();
44                 $this.removeData('Updater');
45             });
46         },
47
48         show : function( content ) { }
49     };
50     
51     function Updater (options) {
52         this.options=options;
53         // xxx should try to locate update_query first, in case we have several Updaters
54         // on the same query
55         // however the mental model behind the global manifold object for now is 
56         // to unambiguously find a query based on its query_uuid, which in the joomla
57         // implementation wouldn't fly
58         // we keep this for a later improvement
59         var query=manifold.find_query (options.query_uuid);
60         // very rough way of filling this for now
61         this.update_query = 
62             new ManifoldQuery ("update", query.object, null, query.filters, 
63                                {}, // params
64                                query.fields, 
65                                undefined, /* unique */ 
66                                Math.uuid(32,16), 
67                                undefined, undefined /* maybe some day I'll get that one */);
68         manifold.insert_query (this.update_query);
69         // arm button once document is loaded
70         (function(updater) {$(document).ready(function(){updater.arm_button()})})(this);
71
72         this.arm_button = function () {
73             $('#updater-' + this.options.plugin_uuid).click(this, this.submit_update_request);
74         },
75         this.submit_update_request = function (e) {
76             var query_uuid = e.data.options.query_uuid;
77             var update_query = e.data.update_query;
78             if (debug) messages.debug("Updater.submit_update_request " + update_query.__repr());
79             // actually send the Update query, but publish results as if coming from the original query
80             manifold.asynchroneous_exec ( [ {'query_uuid': update_query.query_uuid, 'publish_uuid' : query_uuid} ], false);
81             // disable button while the query is flying
82             $('#updater-' + e.data.options.plugin_uuid).attr('disabled', 'disabled');
83         },
84
85         this.query_failed = function (e, code, output) {
86             var plugindiv=e.data;
87             var updater=plugindiv.data('Updater');
88             $('#updater-' + updater.options.plugin_uuid).removeAttr('disabled');
89             // just as a means to deom how to retrieve the stuff passed on the channel
90             if (debug) messages.debug("retrieved error code " + code + " and output " + output);
91         }
92             
93         this.update_resources = function (e, resources, change) {
94             data = e.data.instance.data().Slices;
95
96             data.update_query.params['resource'] = resources
97             $.publish('/update/' + data.options.query_uuid, [data.update_query, true]);
98         },
99
100         this.update_leases = function (e, leases, change) {
101             data = e.data.instance.data().Slices;
102             
103             data.update_query.params['lease'] = leases
104             $.publish('/update/' + data.options.query_uuid, [data.update_query, true]);
105         },
106         
107         this.query_completed = function (e, rows, query) {
108
109             /* This function is called twice : get and update */
110             messages.info("updater.query_completed - not implemented yet");
111             return;
112       
113             var data = e.data.instance.data().Slices;
114       
115             /* Update placeholders and trigger subqueries updates */
116             if (rows.length == 0) {
117                 alert("no result");
118                 return;
119             }
120             var slice = rows[0];
121       
122             /* for get */
123             if (data.update_query == null) {
124                 data.update_query = new Query('update','slice', 'now', query.filter, {"resource": null, "lease": null}, query.fields, 0, data.options.query_uuid);
125             }
126             /* In case of update the list of resources and leases should be updated accordingly */
127       
128             /* only for get ? */
129             $.each(slice, function(key, value) {
130                 if (typeof value == 'string') {
131                     $('#myslice__' + key).html(value);
132                 }
133             });
134       
135             /* TODO avoid repetitions + made this code generic and plugin-independent */
136             
137             if (query.method == 'update') {
138                 // XXX NON, les uuid doivent etre les memes que dans la query Get, cet appel devrait etre fait avant.
139                 query.analyzed_subqueries();
140             }
141       
142             /* NOTE: Dans le cadre d'un update, on n'a pas besoin de refaire tout
143              * le query plan et obtenir toutes les infos, par contre on ne peut pas
144              * savoir d'avance quels parametres ont été accordés, changés, etc.
145              * Dans le cas général, ca pourrait affecter le query plan...
146              * Par contre on n'a pas d'information sur toutes les resources, mais
147              * uniquement celles dans la liste. Comment gérer ?
148              */
149             
150             /* Inform child plugins about their respective parts of the results */
151             /* Only for get */
152             var r_subq = query.analyzed_query.subqueries['resource'];
153             var l_subq = query.analyzed_query.subqueries['lease'];
154             $.publish('/results/' + r_subq.uuid + '/changed', [slice['resource'], r_subq]);
155             $.publish('/results/' + l_subq.uuid + '/changed', [slice['lease'],    l_subq]);
156             
157             /* Subscribe to get notifications from child plugins */
158             if (!data.child_subscribe) {
159                 $.subscribe('/update-set/' + r_subq.uuid, {instance: e.data.instance}, update_resources);
160                 $.subscribe('/update-set/' + l_subq.uuid, {instance: e.data.instance}, update_leases);
161                 data.child_subscribe = true
162             }
163             
164         }
165     }
166 })( jQuery );
167