329 lines
9 KiB
JavaScript
329 lines
9 KiB
JavaScript
|
dojo.provide("dojox.data.SnapLogicStore");
|
||
|
|
||
|
dojo.require("dojo.io.script");
|
||
|
dojo.require("dojo.data.util.sorter");
|
||
|
|
||
|
dojo.declare("dojox.data.SnapLogicStore", null, {
|
||
|
Parts: {
|
||
|
DATA: "data",
|
||
|
COUNT: "count"
|
||
|
},
|
||
|
|
||
|
url: "",
|
||
|
|
||
|
constructor: function(/* Object */args){
|
||
|
// summary:
|
||
|
// Initialize a SnapLogicStore object.
|
||
|
// args:
|
||
|
// An object that contains properties for initializing the new data store object. The
|
||
|
// following properties are understood:
|
||
|
// url:
|
||
|
// A URL to the SnapLogic pipeline's output routed through PipeToHttp. Typically, this
|
||
|
// will look like "http://<server-host>:<port>/pipe/<pipeline-url>/<pipeline-output-view>".
|
||
|
// parameters:
|
||
|
// An object whose properties define parameters to the pipeline. The values of these
|
||
|
// properties will be sent to the pipeline as parameters when it run.
|
||
|
//
|
||
|
if(args.url){
|
||
|
this.url = args.url;
|
||
|
}
|
||
|
this._parameters = args.parameters;
|
||
|
},
|
||
|
|
||
|
_assertIsItem: function(/* item */item){
|
||
|
// summary:
|
||
|
// This function tests whether the item passed in is indeed an item in the store.
|
||
|
// item:
|
||
|
// The item to test for being contained by the store.
|
||
|
if(!this.isItem(item)){
|
||
|
throw new Error("dojox.data.SnapLogicStore: a function was passed an item argument that was not an item");
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_assertIsAttribute: function(/* attribute-name-string */ attribute){
|
||
|
// summary:
|
||
|
// This function tests whether the item passed in is indeed a valid 'attribute' like type for the store.
|
||
|
// attribute:
|
||
|
// The attribute to test for being contained by the store.
|
||
|
if(typeof attribute !== "string"){
|
||
|
throw new Error("dojox.data.SnapLogicStore: a function was passed an attribute argument that was not an attribute name string");
|
||
|
}
|
||
|
},
|
||
|
|
||
|
getFeatures: function(){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.getFeatures()
|
||
|
return {
|
||
|
'dojo.data.api.Read': true
|
||
|
};
|
||
|
},
|
||
|
|
||
|
getValue: function(item, attribute, defaultValue){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.getValue()
|
||
|
this._assertIsItem(item);
|
||
|
this._assertIsAttribute(attribute);
|
||
|
var i = dojo.indexOf(item.attributes, attribute);
|
||
|
if(i !== -1){
|
||
|
return item.values[i];
|
||
|
}
|
||
|
return defaultValue;
|
||
|
},
|
||
|
|
||
|
getAttributes: function(item){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.getAttributes()
|
||
|
this._assertIsItem(item);
|
||
|
return item.attributes;
|
||
|
},
|
||
|
|
||
|
hasAttribute: function(item, attribute){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.hasAttributes()
|
||
|
this._assertIsItem(item);
|
||
|
this._assertIsAttribute(attribute);
|
||
|
for(var i = 0; i < item.attributes.length; ++i){
|
||
|
if(attribute == item.attributes[i]){
|
||
|
return true;
|
||
|
}
|
||
|
}
|
||
|
return false;
|
||
|
},
|
||
|
|
||
|
isItemLoaded: function(item){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.isItemLoaded()
|
||
|
return this.isItem(item); // Boolean
|
||
|
},
|
||
|
|
||
|
loadItem: function(keywordArgs){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.loadItem()
|
||
|
},
|
||
|
|
||
|
getLabel: function(item){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.getLabel()
|
||
|
return undefined;
|
||
|
},
|
||
|
|
||
|
getLabelAttributes: function(item){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.getLabelAttributes()
|
||
|
return null;
|
||
|
},
|
||
|
|
||
|
containsValue: function(item, attribute, value){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.containsValue()
|
||
|
return this.getValue(item, attribute) === value; // Boolean
|
||
|
},
|
||
|
|
||
|
getValues: function(item, attribute){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.getValue()
|
||
|
this._assertIsItem(item);
|
||
|
this._assertIsAttribute(attribute);
|
||
|
var i = dojo.indexOf(item.attributes, attribute);
|
||
|
if(i !== -1){
|
||
|
return [item.values[i]]; // Array
|
||
|
}
|
||
|
return [];
|
||
|
},
|
||
|
|
||
|
isItem: function(item){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.isItem()
|
||
|
if(item && item._store === this){
|
||
|
return true;
|
||
|
}
|
||
|
return false;
|
||
|
},
|
||
|
|
||
|
close: function(request){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.close()
|
||
|
},
|
||
|
|
||
|
_fetchHandler: function(/* Object */request){
|
||
|
// summary:
|
||
|
// Process data retrieved via fetch and send it back to requester.
|
||
|
// response:
|
||
|
// The data returend from the I/O transport. In the normal case, it will be an array of result rows
|
||
|
// from the pipeline. In the special case for record count optimization, response will be an array
|
||
|
// with a single element containing the total pipeline result row count. See fetch() for details
|
||
|
// on this optimization.
|
||
|
|
||
|
var scope = request.scope || dojo.global;
|
||
|
|
||
|
if(request.onBegin){
|
||
|
// Check for the record count optimization
|
||
|
request.onBegin.call(scope, request._countResponse[0], request);
|
||
|
}
|
||
|
|
||
|
if(request.onItem || request.onComplete){
|
||
|
var response = request._dataResponse;
|
||
|
|
||
|
if (!response.length){
|
||
|
request.onError.call(scope,
|
||
|
new Error("dojox.data.SnapLogicStore: invalid response of length 0"),
|
||
|
request);
|
||
|
return;
|
||
|
}else if(request.query != 'record count'){
|
||
|
//If this was not a record count request, the first element returned will contain
|
||
|
//the field names.
|
||
|
var field_names = response.shift();
|
||
|
|
||
|
var items = [];
|
||
|
for(var i = 0; i < response.length; ++i){
|
||
|
if(request._aborted){
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
items.push({attributes: field_names, values: response[i], _store: this});
|
||
|
}
|
||
|
|
||
|
if(request.sort && !request._aborted){
|
||
|
items.sort(dojo.data.util.sorter.createSortFunction(request.sort, self));
|
||
|
}
|
||
|
}else{
|
||
|
//This is a record count request, so manually set the field names.
|
||
|
items = [({attributes: ['count'], values: response, _store: this})];
|
||
|
}
|
||
|
|
||
|
if(request.onItem){
|
||
|
for(var i = 0; i < items.length; ++i){
|
||
|
if (request._aborted) {
|
||
|
break;
|
||
|
}
|
||
|
request.onItem.call(scope, items[i], request);
|
||
|
}
|
||
|
items = null;
|
||
|
}
|
||
|
|
||
|
if(request.onComplete && !request._aborted){
|
||
|
request.onComplete.call(scope, items, request);
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
_partHandler: function(/* Object */request, /* String */part, /* Object */response){
|
||
|
// summary:
|
||
|
// Handle the individual replies for both data and length requests.
|
||
|
// request:
|
||
|
// The request/handle object used with the original fetch() call.
|
||
|
// part:
|
||
|
// A value indicating which request this handler call is for (this.Parts).
|
||
|
// response:
|
||
|
// Response received from the underlying IO transport.
|
||
|
|
||
|
if(response instanceof Error){
|
||
|
if(part == this.Parts.DATA){
|
||
|
request._dataHandle = null;
|
||
|
}else{
|
||
|
request._countHandle = null;
|
||
|
}
|
||
|
request._aborted = true;
|
||
|
if(request.onError){
|
||
|
request.onError.call(request.scope, response, request);
|
||
|
}
|
||
|
}else{
|
||
|
if(request._aborted){
|
||
|
return;
|
||
|
}
|
||
|
if(part == this.Parts.DATA){
|
||
|
request._dataResponse = response;
|
||
|
}else{
|
||
|
request._countResponse = response;
|
||
|
}
|
||
|
if((!request._dataHandle || request._dataResponse !== null) &&
|
||
|
(!request._countHandle || request._countResponse !== null)){
|
||
|
this._fetchHandler(request);
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
|
||
|
fetch: function(/* Object */request){
|
||
|
// summary:
|
||
|
// See dojo.data.api.Read.close()
|
||
|
// request:
|
||
|
// See dojo.data.api.Read.close() for generic interface.
|
||
|
//
|
||
|
// In addition to the standard Read API fetch support, this store supports an optimization for
|
||
|
// for retrieving the total count of records in the Pipeline without retrieving the data. To
|
||
|
// use this optimization, simply provide an onBegin handler without an onItem or onComplete handler.
|
||
|
|
||
|
request._countResponse = null;
|
||
|
request._dataResponse = null;
|
||
|
request._aborted = false;
|
||
|
request.abort = function(){
|
||
|
if(!request._aborted){
|
||
|
request._aborted = true;
|
||
|
if(request._dataHandle && request._dataHandle.cancel){
|
||
|
request._dataHandle.cancel();
|
||
|
}
|
||
|
if(request._countHandle && request._countHandle.cancel){
|
||
|
request._countHandle.cancel();
|
||
|
}
|
||
|
}
|
||
|
};
|
||
|
|
||
|
// Only make the call for data if onItem or onComplete is used. Otherwise, onBegin will only
|
||
|
// require the total row count.
|
||
|
if(request.onItem || request.onComplete){
|
||
|
var content = this._parameters || {};
|
||
|
if(request.start){
|
||
|
if(request.start < 0){
|
||
|
throw new Error("dojox.data.SnapLogicStore: request start value must be 0 or greater");
|
||
|
}
|
||
|
content['sn.start'] = request.start + 1;
|
||
|
}
|
||
|
if(request.count){
|
||
|
if(request.count < 0){
|
||
|
throw new Error("dojox.data.SnapLogicStore: request count value 0 or greater");
|
||
|
}
|
||
|
content['sn.limit'] = request.count;
|
||
|
}
|
||
|
|
||
|
content['sn.content_type'] = 'application/javascript';
|
||
|
|
||
|
var store = this;
|
||
|
var handler = function(response, ioArgs){
|
||
|
if(response instanceof Error){
|
||
|
store._fetchHandler(response, request);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
var getArgs = {
|
||
|
url: this.url,
|
||
|
content: content,
|
||
|
// preventCache: true,
|
||
|
timeout: 60000, //Starting a pipeline can take a long time.
|
||
|
callbackParamName: "sn.stream_header",
|
||
|
handle: dojo.hitch(this, "_partHandler", request, this.Parts.DATA)
|
||
|
};
|
||
|
|
||
|
request._dataHandle = dojo.io.script.get(getArgs);
|
||
|
}
|
||
|
|
||
|
if(request.onBegin){
|
||
|
var content = {};
|
||
|
content['sn.count'] = 'records';
|
||
|
content['sn.content_type'] = 'application/javascript';
|
||
|
|
||
|
var getArgs = {
|
||
|
url: this.url,
|
||
|
content: content,
|
||
|
timeout: 60000,
|
||
|
callbackParamName: "sn.stream_header",
|
||
|
handle: dojo.hitch(this, "_partHandler", request, this.Parts.COUNT)
|
||
|
};
|
||
|
|
||
|
request._countHandle = dojo.io.script.get(getArgs);
|
||
|
}
|
||
|
|
||
|
return request; // Object
|
||
|
}
|
||
|
});
|
||
|
|