+
+ this.state_dict_create = function(default_set)
+ {
+ default_set = (default_set === undefined) ? STATE_SET_OUT : default_set;
+ var state_dict = {};
+ // We cannot use constants in literal definition, so...
+ state_dict[STATE_WARNINGS] = {};
+ state_dict[STATE_SET] = default_set;
+ state_dict[STATE_VISIBLE] = true;
+ return state_dict;
+ }
+
+ // RECORDS
+
+ this.set_records = function(query_uuid, records, default_set)
+ {
+ default_set = (default_set === undefined) ? STATE_SET_OUT : default_set;
+
+ var self = this;
+ var key, object, query_ext, record_key;
+
+ query_ext = this.find_analyzed_query_ext(query_uuid);
+ object = query_ext.query.object;
+ if (object.indexOf(':') != -1) {
+ object = object.split(':')[1];
+ }
+ record_key = manifold.metadata.get_key(object);
+
+ // ["start_time", "resource", "end_time"]
+ // ["urn"]
+
+ $.each(records, function(i, record) {
+ //var key = manifold.metadata.get_key(query_ext.query.object);
+
+ var record_key_value = manifold.record_get_value(record, record_key);
+ query_ext.records.put(record_key_value, record);
+
+ if (!(query_ext.state.get(record_key_value)))
+ query_ext.state.put(record_key_value, self.state_dict_create(default_set));
+ });
+ }
+
+ this.get_records = function(query_uuid)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ return query_ext.records.values();
+ }
+
+ this.get_record = function(query_uuid, record_key)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ return query_ext.records.get(record_key);
+ }
+
+ this.del_record = function(query_uuid, record_key)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ return query_ext.records.remove(record_key);
+ }
+
+ this.del_state = function(query_uuid, record_key)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ return query_ext.state.remove(record_key);
+ }
+
+ this.add_record = function(query_uuid, record, new_state)
+ {
+ var query_ext, key, record_key;
+ query_ext = this.find_analyzed_query_ext(query_uuid);
+
+ if (typeof(record) == 'object') {
+ key = manifold.metadata.get_key(query_ext.query.object);
+ record_key = manifold.record_get_value(record, key);
+ } else {
+ record_key = record;
+ }
+
+ var record_entry = query_ext.records.get(record_key);
+ if (!record_entry)
+ query_ext.records.put(record_key, record);
+
+ manifold.query_store.set_record_state(query_uuid, record_key, STATE_SET, new_state);
+ }
+
+ this.remove_record = function(query_uuid, record, new_state)
+ {
+ var query_ext, key, record_key;
+ query_ext = this.find_analyzed_query_ext(query_uuid);
+
+ if (typeof(record) == 'object') {
+ key = manifold.metadata.get_key(query_ext.query.object);
+ record_key = manifold.record_get_value(record, key);
+ } else {
+ record_key = record;
+ }
+
+ if ((query_ext.query.object == 'lease') && (new_state == STATE_SET_OUT)) {
+ // Leases that are marked out are in fact leases from other slices
+ // We need to _remove_ leases that we mark as OUT
+ manifold.query_store.del_record(query_uuid, record_key);
+ manifold.query_store.del_state(query_uuid, record_key);
+ } else {
+ manifold.query_store.set_record_state(query_uuid, record_key, STATE_SET, new_state);
+ }
+ }
+
+ this.iter_records = function(query_uuid, callback)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ query_ext.records.each(callback);
+ //callback = function(record_key, record)
+ }
+
+ this.iter_visible_records = function(query_uuid, callback)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ query_ext.records.each(function(record_key, record) {
+ if (query_ext.state.get(record_key)[STATE_VISIBLE]) // .STATE_VISIBLE would be for the string key
+ callback(record_key, record);
+ });
+ //callback = function(record_key, record)
+
+ }
+
+ // STATE
+
+ this.set_record_state = function(query_uuid, result_key, state, value)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ var state_dict = query_ext.state.get(result_key);
+ if (!state_dict)
+ state_dict = this.state_dict_create();
+
+ state_dict[state] = value;
+
+ query_ext.state.put(result_key, state_dict);
+ }
+
+ this.get_record_state = function(query_uuid, result_key, state)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ var state_dict = query_ext.state.get(result_key);
+ if (!state_dict)
+ return null;
+ return state_dict[state];
+ }
+
+ // FILTERS
+
+ this.add_filter = function(query_uuid, filter)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ // XXX When we update a filter
+ query_ext.filters.push(filter);
+
+ this.apply_filters(query_uuid);
+
+ }
+
+ this.update_filter = function(query_uuid, filter)
+ {
+ // XXX
+
+ this.apply_filters(query_uuid);
+ }
+
+ this.remove_filter = function(query_uuid, filter)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ query_ext.filters = $.grep(query_ext.filters, function(x) {
+ return !(x.equals(filter));
+ });
+
+ this.apply_filters(query_uuid);
+ }
+
+ this.get_filters = function(query_uuid)
+ {
+ var query_ext = this.find_analyzed_query_ext(query_uuid);
+ return query_ext.filters;
+ }
+
+ this.recount = function(query_uuid)
+ {
+ var query_ext;
+ var is_reserved, is_pending, in_set, is_unconfigured;
+
+ query_ext = manifold.query_store.find_analyzed_query_ext(query_uuid);
+ query_ext.num_pending = 0;
+ query_ext.num_unconfigured = 0;
+
+ this.iter_records(query_uuid, function(record_key, record) {
+ var record_state = manifold.query_store.get_record_state(query_uuid, record_key, STATE_SET);
+ var record_warnings = manifold.query_store.get_record_state(query_uuid, record_key, STATE_WARNINGS);
+
+ is_reserved = (record_state == STATE_SET_IN)
+ || (record_state == STATE_SET_OUT_PENDING)
+ || (record_state == STATE_SET_IN_SUCCESS)
+ || (record_state == STATE_SET_OUT_FAILURE);
+
+ is_pending = (record_state == STATE_SET_IN_PENDING)
+ || (record_state == STATE_SET_OUT_PENDING);
+
+ in_set = (record_state == STATE_SET_IN) // should not have warnings
+ || (record_state == STATE_SET_IN_PENDING)
+ || (record_state == STATE_SET_IN_SUCCESS)
+ || (record_state == STATE_SET_OUT_FAILURE); // should not have warnings
+
+ is_unconfigured = (in_set && !$.isEmptyObject(record_warnings));
+
+ /* Let's update num_pending and num_unconfigured at this stage */
+ if (is_pending)
+ query_ext.num_pending++;
+ if (is_unconfigured)
+ query_ext.num_unconfigured++;
+ });
+
+ }
+
+ this.apply_filters = function(query_uuid)
+ {
+ var start = new Date().getTime();
+
+ // Toggle visibility of records according to the different filters.
+
+ var self = this;
+ var filters = this.get_filters(query_uuid);
+ var col_value;
+ /* Let's update num_pending and num_unconfigured at this stage */
+
+ // Adapted from querytable._querytable_filter()
+
+ this.iter_records(query_uuid, function(record_key, record) {
+ var is_reserved, is_pending, in_set, is_unconfigured;
+
+ /* By default, a record is visible unless a filter says the opposite */
+ var visible = true;
+
+ var record_state = manifold.query_store.get_record_state(query_uuid, record_key, STATE_SET);
+ var record_warnings = manifold.query_store.get_record_state(query_uuid, record_key, STATE_WARNINGS);
+
+ is_reserved = (record_state == STATE_SET_IN)
+ || (record_state == STATE_SET_OUT_PENDING)
+ || (record_state == STATE_SET_IN_SUCCESS)
+ || (record_state == STATE_SET_OUT_FAILURE);
+
+ is_pending = (record_state == STATE_SET_IN_PENDING)
+ || (record_state == STATE_SET_OUT_PENDING);
+
+ in_set = (record_state == STATE_SET_IN) // should not have warnings
+ || (record_state == STATE_SET_IN_PENDING)
+ || (record_state == STATE_SET_IN_SUCCESS)
+ || (record_state == STATE_SET_OUT_FAILURE); // should not have warnings
+
+ is_unconfigured = (in_set && !$.isEmptyObject(record_warnings));
+
+ // We go through each filter and decide whether it affects the visibility of the record
+ $.each(filters, function(index, filter) {
+ var key = filter[0];
+ var op = filter[1];
+ var value = filter[2];
+
+
+ /* We do some special handling for the manifold:status filter
+ * predicates. */
+
+ if (key == 'manifold:status') {
+ if (op != '=' && op != '==') {
+ // Unsupported filter, let's ignore it
+ console.log("Unsupported filter on manifold:status. Should be EQUAL only.");
+ return true; // ~ continue
+ }
+
+ switch (value) {
+ case 'reserved':
+ // true => ~ continue
+ // false => ~ break
+ visible = is_reserved;
+ return visible;
+ case 'unconfigured':
+ visible = is_unconfigured;
+ return visible;
+ case 'pending':
+ visible = is_pending;
+ return visible;
+ }
+ return false; // ~ break
+ }
+
+ /* Normal filtering behaviour (according to the record content) follows... */
+ col_value = manifold.record_get_value(record, key);
+
+ // When the filter does not match, we hide the column by default
+ if (col_value === 'undefined') {
+ visible = false;
+ return false; // ~ break
+ }
+
+ // XXX This should accept pluggable filtering functions.
+
+
+ /* Test whether current filter is compatible with the column */
+ if (op == '=' || op == '==') {
+ if ( col_value != value || col_value==null || col_value=="" || col_value=="n/a")
+ visible = false;
+
+ }else if (op == 'included') {
+ /* By default, the filter returns false unless the record
+ * field match at least one value of the included statement
+ */
+ visible = false;
+ $.each(value, function(i,x) {
+ if(x == col_value){
+ visible = true;
+ return false; // ~ break
+ }
+ });
+ }else if (op == '!=') {
+ if ( col_value == value || col_value==null || col_value=="" || col_value=="n/a")
+ visible = false;
+ } else if(op=='<') {
+ if ( parseFloat(col_value) >= value || col_value==null || col_value=="" || col_value=="n/a")
+ visible = false;
+ } else if(op=='>') {
+ if ( parseFloat(col_value) <= value || col_value==null || col_value=="" || col_value=="n/a")
+ visible = false;
+ } else if(op=='<=' || op=='≤') {
+ if ( parseFloat(col_value) > value || col_value==null || col_value=="" || col_value=="n/a")
+ visible = false;
+ } else if(op=='>=' || op=='≥') {
+ if ( parseFloat(col_value) < value || col_value==null || col_value=="" || col_value=="n/a")
+ visible = false;
+ }else{
+ // How to break out of a loop ?
+ alert("filter not supported");
+ return false; // break
+ }
+
+ });
+
+ // Set the visibility status in the query store
+ self.set_record_state(query_uuid, record_key, STATE_VISIBLE, visible);
+ });
+
+ var end = new Date().getTime();
+ console.log("APPLY FILTERS took", end - start, "ms");
+
+ }
+