/*
* @file Simple info access (SINA) API: Implementation of the SINA interface
* for the INA V2 service.
* @namespace sap.bc.ina.api.sina.impl.inav2.sina_impl
* @requires sap.bc.ina.api.sina
* @requires sap.bc.ina.api.sina.impl.inav2.filter
* @requires sap.bc.ina.api.sina.impl.inav2.system
* @requires sap.bc.ina.api.sina.impl.inav2.proxy
* @requires jQuery
* @copyright Copyright (c) 2013 SAP AG. All rights reserved.
*/
(function(global, isXS) {
"use strict";
var executeSinaImpl = function($) {
// =========================================================================
// create packages
// =========================================================================
if (!$) {
$ = global.$;
}
if (!isXS) {
global.sap.bc.ina.api.sina.expandPackage(global, 'sap.bc.ina.api.sina.impl.inav2.sina_impl');
global.sap.bc.ina.api.sina.expandPackage(global, 'sap.bc.ina.api.sina.impl.inav2.proxy');
}
var module = global.sap.bc.ina.api.sina.impl.inav2.sina_impl;
module.Sina = function(){this.init.apply(this,arguments);};
module.Facet = function(){this.init.apply(this,arguments);};
module.Perspective = function(){this.init.apply(this,arguments);};
module.Perspective2 = function(){this.init.apply(this,arguments);};
module.Query = function(){this.init.apply(this,arguments);};
module.CatalogQuery = function(){this.init.apply(this,arguments);};
module.CatalogResultSet = function(){this.init.apply(this,arguments);};
module.PerspectiveQuery = function(){this.init.apply(this,arguments);};
module.PerspectiveGetQuery = function(){this.init.apply(this,arguments);};
module.PerspectiveSearchQuery = function(){this.init.apply(this,arguments);};
module.PerspectiveSearchResultSet = function(){this.init.apply(this,arguments);};
module.Suggestion = function(){this.init.apply(this,arguments);};
module.SuggestionQuery = function(){this.init.apply(this,arguments);};
module.SuggestionResultSet = function(){this.init.apply(this,arguments);};
module.Suggestion2Query = function(){this.init.apply(this,arguments);};
module.Suggestion2ResultSet = function(){this.init.apply(this,arguments);};
module.ChartQuery = function(){this.init.apply(this,arguments);};
module.ChartResultSet = function(){this.init.apply(this,arguments);};
module.GroupBarChartQuery = function(){this.init.apply(this,arguments);};
module.GroupBarChartResultSet = function(){this.init.apply(this,arguments);};
module.LineChartQuery = function(){this.init.apply(this,arguments);};
module.LineChartResultSet = function(){this.init.apply(this,arguments);};
module.SearchQuery = function(){this.init.apply(this,arguments);};
module.SearchResultSet = function() { this.init.apply(this, arguments); };
module.SuggestionAutoQuery = function(properties) {
if (properties.system instanceof global.sap.bc.ina.api.sina.impl.inav2.system.ABAPSystem) {
$.extend(this, module.Suggestion2Query.prototype);
}
if (properties.system instanceof global.sap.bc.ina.api.sina.impl.inav2.system.HANASystem) {
$.extend(this, module.SuggestionQuery.prototype);
}
this.init.apply(this,arguments);
};
// =========================================================================
// import packages
// =========================================================================
var jsontemplates = global.sap.bc.ina.api.sina.impl.inav2.jsontemplates;
var filter = global.sap.bc.ina.api.sina.impl.inav2.filter;
// var system = global.sap.bc.ina.api.sina.impl.inav2.system;
var config = global.sap.bc.ina.api.sina.impl.inav2.proxy.config;
var sinabase = global.sap.bc.ina.api.sina.sinabase;
module.Condition = filter.Condition;
// =========================================================================
// register provider
// =========================================================================
module.IMPL_TYPE = "inav2";
sinabase.registerProvider({
impl_type: module.IMPL_TYPE,
sina: module.Sina,
chartQuery: module.ChartQuery,
searchQuery: module.SearchQuery,
groupBarChartQuery: module.GroupBarChartQuery,
lineChartQuery: module.LineChartQuery,
suggestionQuery: module.SuggestionAutoQuery,
perspectiveQuery: module.PerspectiveQuery,
perspectiveSearchQuery: module.PerspectiveSearchQuery,
perspectiveGetQuery: module.PerspectiveGetQuery,
Facet: module.Facet,
DataSource: filter.DataSource,
Filter: filter.Filter,
FilterCondition: filter.Condition,
FilterConditionGroup: filter.ConditionGroup
});
// =========================================================================
// sina
// =========================================================================
module.Sina.prototype = $.extend({}, sinabase.Sina.prototype, {
/**
* Creates a new instance of SINA that uses the INA V2 service. Use
* the SINA factory {@link sap.bc.ina.api.sina.getSina} instead of this
* private constructor.
* @private
* @augments {sap.bc.ina.api.sina.sinabase.Sina}
* @this {sap.bc.ina.api.sina.impl.inav2.sina_impl.Sina}
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.Sina
* @param {Object} properties Configuration properties for the instance.
* @since SAP HANA SPS 06
* @ignore
*/
init: function(properties) {
properties = properties || {};
this.sinaSystem(properties.system || new global.sap.bc.ina.api.sina.impl.inav2.system.HANASystem());
sinabase.Sina.prototype.init.apply(this, arguments);
},
/**
* Gets or sets an SAP client. Only used with system type ABAP.
* @ignore
* @since SAP HANA SPS 06
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.Sina
* @instance
* @param {Integer} sapclient Number of the SAP client to be used with the service.
* @return {Integer} The SAP client number that is currently set, but only if called
* without a parameter.
*/
sapclient: function(sapclient) {
var sys;
if (sapclient) {
if (sapclient < 0) {
sys = new global.sap.bc.ina.api.sina.impl.inav2.system.HANASystem();
} else {
sys = new global.sap.bc.ina.api.sina.impl.inav2.system.ABAPSystem({
"sapclient": sapclient
});
}
this.sinaSystem(sys);
} else {
return this.sinaSystem().properties.sapclient();
}
return {};
},
_registerPostProcessor: function(postProcessor) {
if (!this.postProcessor) {
this.postProcessor = [];
}
this.postProcessor.push(postProcessor);
},
_postprocess: function(sinAction, sourceTitle) {
if (this.postProcessor) {
for (var i = 0; i < this.postProcessor.length; i++) {
this.postProcessor[i](sinAction, sourceTitle);
}
}
},
});
// =========================================================================
// class query. Base for chart, search and perspective queries
// =========================================================================
module.Query.prototype = $.extend({}, {
/**
* The base query for chart, search, and suggestions queries.
* Use the sap.bc.ina.api.sina.create*Query factory methods instead of this class.
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.Query
* @private
* @ignore
*/
init: function(properties) {
this.filter = properties.filter || new filter.Filter({
dataSource: properties.dataSource
});
},
_resetResultSet: function() {
this.deferredResultSet = null;
this.resultSet = null;
this.jqXHR = null;
},
_getSinaError: function(data) {
var error = {};
if (data.error) {
var e = JSON.parse(error.responseText);
// error.message = e.error.message;
// error.code = e.error.code;
// return error;
return new sinabase.SinaError({
message: e.error.message,
errorCode: e.error.code
});
}
// if (data.Messages) {
// for (var i = 0; i < data.Messages.length; i++) {
// if (data.Messages[i].Type >= 2) {
// return new sinabase.SinaError({
// message: data.Messages[i].Text,
// errorCode: 0
// });
// }
// }
// }
return null;
},
setDataSource: function(dataSource) {
if (dataSource === undefined) {
return this;
}
dataSource = new filter.DataSource(dataSource);
if (this.filter.getDataSource() === undefined) {
this.filter.setDataSource(dataSource);
this._resetResultSet();
return this;
}
if (!this.filter.getDataSource().equals(dataSource)) {
this.filter.setDataSource(dataSource);
this._resetResultSet();
}
return this;
},
execute: function() {
var self = this;
var jsonRequest = self.createJsonRequest();
self.system.getServerInfo();
var jqXHR = self._fireRequest(jsonRequest, true);
var deferredResultSet = $.Deferred();
jqXHR.done(function(data) {
var error = self._getSinaError(data);
if (data && error) {
deferredResultSet.reject(error);
return;
}
var resultSet = new self.resultSetClass(self.resultSetProperties);
resultSet.setJsonData(data);
deferredResultSet.resolve(resultSet);
})
.fail(function(error) {
deferredResultSet.reject(error);
})
.always(function(data) {
self._responseJson = data;
});
return deferredResultSet.promise();
},
executeSync: function() {
var self = this;
if (!isXS && self.resultSet !== null) {
return self.resultSet;
}
var jsonRequest = self.createJsonRequest();
self.system.getServerInfo();
var data = self._fireRequest(jsonRequest, false);
self._responseJson = data;
self.resultSet = new self.resultSetClass(self.resultSetProperties);
if (!isXS && data && data.responseText) {
var response = JSON.parse(data.responseText);
self.resultSet.setJsonData(response);
} else if (data && data.arguments) {
self.resultSet.setJsonData(data.arguments[0]);
}
return self.resultSet;
},
/**
* Calls the server for the query instances.
* @private
* @ignore
* @memberOf sap.bc.ina.api.sina.impl.inav2.Query
* @instance
* @param {Object} jsonRequest Request data that is sent to the server.
* @param {boolean} async Should the request be asynchronous?
*/
_fireRequest: function(jsonRequest, async) {
var request = {
async: async,
url: this.system.inaUrl,
contentType: 'application/json',
dataType: 'json',
data: jsonRequest
};
var jqXHR = this.system.proxy.ajax(request);
return jqXHR;
},
/**
* Assembles the order-by expression needed for calling ina.v2 service.
* @private
* @ignore
* @memberOf sap.bc.ina.api.sina.impl.inav2.Query
* @instance
* @return {Object} Order-by expression.
*/
_assembleOrderBy: function() {
var orderByList = [];
function orderByToInaSyntax(orderBy, sortOrder) {
var inaOrderObj = {};
if (orderBy.toLowerCase() === '$$score$$') {
inaOrderObj.Function = 'Score';
} else {
inaOrderObj.AttributeName = orderBy;
}
inaOrderObj.SortOrder = sortOrder.toUpperCase();
return inaOrderObj;
}
var orderObj;
if ($.type(this.orderBy) === 'array') {
for (var j = 0; j < this.orderBy.length; j++) {
orderObj = orderByToInaSyntax(this.orderBy[j].orderBy, this.orderBy[j].sortOrder);
orderByList.push(orderObj);
}
} else if ($.type(this.orderBy) === 'object' && this.orderBy.orderBy) {
orderObj = orderByToInaSyntax(this.orderBy.orderBy, this.orderBy.sortOrder);
orderByList.push(orderObj);
}
return orderByList;
}
});
// =========================================================================
// class catalog query
// =========================================================================
module.CatalogQuery.prototype = $.extend({}, module.Query.prototype, {
/**
* A catalog query.
* @constructs sap.bc.ina.api.sina.impl.inav2.CatalogQuery
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.Query}
* @param {Object} properties Configuration object.
* @since SAP HANA SPS 06
* @private
* @ignore
*/
init: function(properties) {
properties = properties || {};
this.resultSetClass = module.SearchResultSet;
},
createJsonRequest: function() {
return jsontemplates.catalogRequest;
}
});
// =========================================================================
// class Facet
// =========================================================================
module.Facet.prototype = $.extend({}, sinabase.Facet.prototype, {
/**
* A facet that is contained in a perspective.
* @ignore
* @constructs sap.bc.ina.api.sina.impl.inav2.Facet
*/
init: function(properties) {
// TODO: make facet general available only in sinabase
properties = properties || {};
sinabase.Facet.prototype.init.apply(this, arguments);
if (this.facetType === '$$datasources$$') {
this.facetType = sinabase.FacetType.DATASOURCE;
this.query = new module.ChartQuery();
this.query.resultSet = new module.ChartResultSet({
"type": "datasource"
});
} else if (this.facetType === sinabase.FacetType.ATTRIBUTE) {
this.query = new module.ChartQuery();
this.query.resultSet = new module.ChartResultSet();
} else if (this.facetType === sinabase.FacetType.SEARCH) {
this.query = new module.SearchQuery();
this.query.resultSet = new module.SearchResultSet();
}
},
// TODO: move out of facet into Perspective
setJsonData: function(data) {
this.query.resultSet.setJsonData(data);
this._parseServerSideFacetMetaData(data.Metadata);
},
// TODO: move out of facet into Perspective
_parseServerSideFacetMetaData: function(data) {
if (data && data.Cube) {
this.title = data.Cube.Description;
this.dimension = data.Cube.ObjectName;
}
}
});
// =========================================================================
// class perspective query
// =========================================================================
module.PerspectiveQuery.prototype = $.extend({}, sinabase.PerspectiveQuery.prototype, module.Query.prototype, {
/**
* Creates a perspective query.
* @ignore
* @constructs sap.bc.ina.api.sina.impl.inav2.PerspectiveQuery
* @param {Object} properties Configuration object.
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.Query}
*/
init: function(properties) {
var self = this;
self.chartFacets = [];
self.searchFacet = null;
self.searchresultset = null;
self.layout = null;
self.templateFactsheet = properties.templateFactsheet || false;
properties = properties || {};
module.Query.prototype.init.apply(this, arguments);
sinabase.PerspectiveQuery.prototype.init.apply(this, arguments);
properties.orderBy = properties.orderBy || {};
this.setOrderBy(properties.orderBy);
this.resultSetClass = module.Perspective;
},
createJsonRequest: function() {
if (this.templateFactsheet) {
jsontemplates.perspectiveRequest = jsontemplates.perspectiveRequestFactsheet;
}
jsontemplates.perspectiveRequest.DataSource = this.filter.dataSource.toInAJson();
var searchterms = this.filter.getSearchTerms();
jsontemplates.perspectiveRequest.Search.SearchTerms = searchterms;
if (true || config || config.startWithSearch !== undefined || config.startWithSearch === 'false') {
if (searchterms==="*" && this.filter.dataSource.getObjectName().value.toLowerCase() === '$$all$$') {
//TODO: remove workaround: return a catalog request and only show datasource facet,
//due to high response time while searching for '*' in $$ALL$$
var cq = new module.CatalogQuery();
return cq.createJsonRequest();
}
}
jsontemplates.perspectiveRequest.Search.Top = this._top;
jsontemplates.perspectiveRequest.Search.Skip = this._skip;
jsontemplates.perspectiveRequest.Search.Filter = this.filter.getJson();
jsontemplates.perspectiveRequest.Search.OrderBy = this._assembleOrderBy();
return jsontemplates.perspectiveRequest;
},
getPerspective: function(onSuccess, onError) {
this.getResultSet(onSuccess, onError);
},
generatePerspectiveSync: function() {
return this.getResultSetSync();
}
});
// =========================================================================
// class Perspective (ResultSet)
// =========================================================================
module.Perspective.prototype = {
/**
* A perspective.
* @constructs sap.bc.ina.api.sina.impl.inav2.Perspective
* @ignore
*/
init: function(properties) {
var self = this;
self.chartFacets = [];
self.searchFacet = null;
self.searchresultset = null;
self.layout = null;
properties = properties || {};
},
getSearchResultSet: function() {
return this.searchresultset;
},
getChartFacets: function() {
return this.chartFacets;
},
getSearchFacet: function() {
return this.searchFacet;
},
getLayout: function() {
return this.layout;
},
determineFacetType : function(resultSetFacet){
try{
if(resultSetFacet.ResultSet.ItemLists[0].Items[0].NamedValues[0].Name==='$$DataSource$$')
return '$$datasources$$';
else
return sinabase.FacetType.ATTRIBUTE;
} catch(e){
return sinabase.FacetType.ATTRIBUTE;
}
},
setJsonData: function(data) {
var self = this;
//there is always a searchresult
self.searchFacet = new module.Facet({
"facetType": "searchresult"
});
self.searchFacet.setJsonData(data);
self.searchresultset = self.searchFacet.getQuery().getResultSetSync();
if (data.ResultsetFacets && data.ResultsetFacets.Elements) {
for (var j = 0; j < data.ResultsetFacets.Elements.length; j++) {
var facetType = self.determineFacetType(data.ResultsetFacets.Elements[j]);
var facet = new module.Facet({
"facetType": facetType
});
facet.setJsonData(data.ResultsetFacets.Elements[j]);
self.chartFacets.push(facet);
}
} else {
//TODO: remove workaround
//convert catalogquery searchresult to a datasource facet
var dsFacet = new module.Facet({
facetType: '$$datasources$$'
});
for (var i = 0; i < self.searchFacet.getQuery().getResultSetSync().getElements().length; i++) {
var dataSource = new filter.DataSource();
var resultElement = self.searchFacet.getQuery().getResultSetSync().getElements()[i];
dataSource.setObjectName(resultElement.ObjectName.valueRaw);
dataSource.setPackageName(resultElement.PackageName.valueRaw);
dataSource.setSchemaName(resultElement.SchemaName.valueRaw);
dataSource.setType(resultElement.Type.valueRaw);
dataSource.setLabel(resultElement.Description.value);
dsFacet.getQuery().getResultSetSync().getElements()[i] = {
dataSource: dataSource
};
}
self.searchFacet.getQuery().getResultSetSync().elements = [];
self.searchFacet.getQuery().getResultSetSync().totalcount = -1;
self.chartFacets.push(dsFacet);
}
}
};
// =========================================================================
// class perspective query
// =========================================================================
module.PerspectiveGetQuery.prototype = $.extend({}, module.Query.prototype, {
/**
* Creates a perspective search query.
* @ignore
* @constructs sap.bc.ina.api.sina.impl.inav2.PerspectiveGetQuery
* @param {Object} properties Configuration object.
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.Query}
*/
init: function(properties) {
var self = this;
properties = properties || {};
this.perspectiveId = properties.perspectiveId;
module.Query.prototype.init.apply(this, [properties]);
this.resultSetClass = module.Perspective2;
},
setPerspectiveId: function(perspectiveId) {
this.perspectiveId = perspectiveId;
},
getPerspective: function(onSuccess, onError) {
var self = this;
var request = {
async: true,
url: "/sap/bc/ina/service/v2/Perspectives('" + this.perspectiveId + "')",
type: "GET"
};
var jqXHR = this.system.proxy.ajax(request);
jqXHR.done(function(data) {
if (data && data.error) {
onError(data.error);
}
self.resultSet = new self.resultSetClass(self.resultSetProperties);
self.resultSet.setJsonData(data);
if (onSuccess) {
onSuccess(self.resultSet);
}
})
.fail(function(error) {
if (onError)
onError(error);
});
}
});
// =========================================================================
// class Perspective 2 - static JSON form server
// =========================================================================
module.Perspective2.prototype = {
/**
* A perspective.
* @constructs sap.bc.ina.api.sina.impl.inav2.Perspective2
* @ignore
*/
init: function(properties) {
var self = this;
properties = properties || {};
},
getFacetForID: function(facetId) {
var self = this;
for (var j = 0; j < self.facets.length; j++) {
if (self.facets[j].facetId === facetId) {
return self.facets[j];
}
}
return undefined;
},
getDimensionForID: function(dimensionId) {
var self = this;
for (var j = 0; j < self.dimensions.length; j++) {
if (self.dimensions[j].Name === dimensionId) {
return self.dimensions[j];
}
}
return undefined;
},
getPreviewDimension: function() {
var self = this;
if (this.bindings["WIDGET-4"] && this.bindings["WIDGET-4"].dimension) {
return this.bindings["WIDGET-4"].dimension;
}
if (this.bindings["WIDGET-1"] && this.bindings["WIDGET-1"].dimension) {
return this.bindings["WIDGET-1"].dimension;
}
if (this.bindings["WIDGET-2"] && this.bindings["WIDGET-2"].dimension) {
return this.bindings["WIDGET-2"].dimension;
}
if (this.bindings["WIDGET-3"] && this.bindings["WIDGET-3"].dimension) {
return this.bindings["WIDGET-3"].dimension;
}
return undefined;
},
setJsonData: function(data) {
var self = this;
self.rawdata = data;
self.ChangedAt = data.ChangedAt;
self.ChangedBy = data.ChangedBy;
self.content = JSON.parse(data.Content);
self.perspectiveId = data.Id;
self.name = data.Name;
self.packageName = data.Package;
self.isActive = data.isActive;
self.isGenerated = data.isGenerated;
self.datasource = self.content.Model.Queries[0].Datasource;
self.measures = [];
var measuresJSON = self.content.Model.Queries[0].CustomDimension1.Members;
for (var k = 0; k < measuresJSON.length; k++) {
self.measures.push(measuresJSON[k]);
}
self.dimensions = [];
var dimensionJSON = self.content.Model.Queries[0].Dimensions;
for (var j = 0; j < dimensionJSON.length; j++) {
self.dimensions.push(dimensionJSON[j]);
}
self.facets = [];
var facetJSON = self.content.Model.Facets;
for (var i = 0; i < facetJSON.length; i++) {
self.facets.push({
isActive: facetJSON[i].Active,
facetId: facetJSON[i].FacetId,
dimension: self.getDimensionForID(facetJSON[i].SeriesChart.ScaleDimensions[0].DimensionName)
});
}
self.bindings = {};
var bindingsJSON = self.content.Bindings;
for (var l = 0; l < bindingsJSON.length; l++) {
var bindingJSON = bindingsJSON[l];
self.bindings[bindingJSON.WidgetId] = self.getFacetForID(bindingJSON.FacetId);
}
}
};
// =========================================================================
// class perspective query
// =========================================================================
module.PerspectiveSearchQuery.prototype = $.extend({}, module.Query.prototype, {
/**
* Creates a perspective search query.
* @ignore
* @constructs sap.bc.ina.api.sina.impl.inav2.PerspectiveSearchQuery
* @param {Object} properties Configuration object.
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.Query}
*/
init: function(properties) {
var self = this;
properties = properties || {};
module.Query.prototype.init.apply(this, [properties]);
this.filter.searchTerms = properties.searchTerms || "*";
this.resultSetClass = module.PerspectiveSearchResultSet;
},
createJsonRequest: function() {
jsontemplates.perspectiveSearchRequest.Search.SearchTerms = this.filter.searchTerms;
jsontemplates.perspectiveSearchRequest.Search.Top = this._top;
jsontemplates.perspectiveSearchRequest.Search.Skip = this._skip;
return jsontemplates.perspectiveSearchRequest;
},
getPerspectiveResults: function(onSuccess, onError) {
this.getResultSet(onSuccess, onError);
}
});
// =========================================================================
// class PerspectiveSearch (ResultSet)
// =========================================================================
module.PerspectiveSearchResultSet.prototype = {
/**
* A perspective.
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.PerspectiveSearchResultSet
* @ignore
*/
init: function(properties) {
var self = this;
self.perspectives = [];
properties = properties || {};
},
getPerspectiveSearchResultSet: function() {
return this.perspectives;
},
setJsonData: function(data) {
var self = this;
var perspectivesJSON = data["ItemLists"][0]["Items"];
for (var i = 0; i < perspectivesJSON.length; i++) {
var namedValues = perspectivesJSON[i]["NamedValues"];
var perspective = {
packageId: namedValues[0].Value,
perspectiveId: namedValues[0].Value + "/" + namedValues[1].Value,
perspectiveDescription: namedValues[3].Value,
title: namedValues[2].Value
};
self.perspectives.push(perspective);
}
}
};
// =========================================================================
// class suggestion query
// =========================================================================
module.SuggestionQuery.prototype = $.extend({}, sinabase.SuggestionQuery.prototype, module.Query.prototype, {
/**
* A suggestion query for a SAP HANA system.
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.SuggestionQuery
* @augments {sap.bc.ina.api.sina.sinabase.SuggestionQuery}
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.Query}
* @param {Object} properties Configuration object.
* @since SAP HANA SPS 06
* @private
*/
init: function(properties) {
properties = properties || {};
this.attributes = properties.attributes || [];
module.Query.prototype.init.apply(this, arguments);
sinabase.SuggestionQuery.prototype.init.apply(this, arguments);
this.resultSetClass = module.SuggestionResultSet;
},
/**
* Adds a response attribute to this suggestion query. This attributes is used
* to look for suitable suggestions for the search term of this query. At least one term is required.
* @instance
* @since SAP HANA SPS 06
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.SuggestionQuery
* @param {String} attribute The name of the attribute as given in the SAP HANA database.
*/
addResponseAttribute: function(attribute) {
this.attributes.push(attribute);
this._resetResultSet();
return this;
},
/**
* Sets a list of response attributes for this suggestion query. These attributes are used
* to look for suitable suggestions for the search term of this query. At least one term is required.
* @instance
* @since SAP HANA SPS 06
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.SuggestionQuery
* @param {Array} attributes A list of names of the attributes as given in the SAP HANA database.
*/
setResponseAttributes: function(attributes) {
this.attributes = attributes;
this._resetResultSet();
return this;
},
createJsonRequest: function() {
jsontemplates.suggestionRequest.Suggestions.Precalculated = false;
var searchterms = this.filter.getSearchTerms();
if (this.attributes.length === 0) {
throw "add at least one response attribute to your query";
}
jsontemplates.suggestionRequest.Suggestions.SearchTerms = searchterms;
jsontemplates.suggestionRequest.Suggestions.AttributeNames = this.attributes;
jsontemplates.suggestionRequest.DataSource = this.filter.dataSource.toInAJson();
jsontemplates.suggestionRequest.Suggestions.Top = this._top;
var filter = this.filter.getJson();
if (filter && filter.Selection) {
jsontemplates.suggestionRequest.Suggestions.Filter = this.filter.getJson();
}
return jsontemplates.suggestionRequest;
}
});
// =========================================================================
// class suggestion result set
// =========================================================================
module.SuggestionResultSet.prototype = {
/**
* A suggestion result set for a SAP HANA system.
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.SuggestionResultSet
* @since SAP HANA SPS 06
* @private
*/
init: function() {
this.suggestions = [];
},
setJsonData: function(data) {
this.suggestions = [];
var itemLists = {};
for (var i = 0; i < data.ItemLists.length; i++) {
itemLists[data.ItemLists[i].Name] = data.ItemLists[i];
}
// only Suggestions ItemList is relevant here
for (var a = 0; a < itemLists.Suggestions.Items.length; a++) {
var item = itemLists.Suggestions.Items[a],
term = "",
attribute = "",
attributeDescription = "";
// dataSource = new filter.DataSource(),
// dataSourceDescription = "";
var suggestion = {};
for (var d = 0; d < item.NamedValues.length; ++d) {
var namedValue = item.NamedValues[d];
switch (namedValue.Name) {
case "Term":
term = namedValue.Value;
suggestion.label = term;
break;
// case "$$DataSource$$":
// dataSource = namedValue.Value;
// dataSource.setObjectName(dataSource);
// break;
// case "$$DataSourceDescription$$":
// dataSourceDescription = namedValue.Value;
// dataSource.setLabel(dataSourceDescription);
// break;
case "AttributeName":
attribute = namedValue.Value;
suggestion.attribute = attribute;
break;
case "$$AttributeDescription$$":
attributeDescription = namedValue.Value;
suggestion.attributeDescription = attributeDescription;
break;
case "Score":
var score = namedValue.Value;
suggestion.score = parseInt(score, 10);
break;
}
}
// suggestion.dataSource = dataSource;
this.suggestions.push(suggestion);
}
this.suggestions.sort(function(a, b) {
return b.score - a.score;
});
for (var o = this.suggestions.length - 1; o >= 0; o--) {
delete this.suggestions[o].score;
}
},
/**
* Returns the elements of the result set, ordered by relevancy score.
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.SuggestionResultSet
* @instance
* @since SAP HANA SPS 06
* @return {Array} A list of result set elements.
* @example
* var queryProperties = {
* dataSource : { schemaName : "SYSTEM",
* objectName : "J_EPM_PRODUCT"
* },
* searchTerms : "s*",
* attributes : ['CATEGORY','PRODUCT_ID','TEXT','PRICE','CURRENCY_CODE']
* };
* var query = sap.bc.ina.api.sina.createSuggestionQuery(queryProperties);
* var resultSet = query.getResultSetSync();
* var elements = resultSet.getElements();
* // contents of elements (shortened):
* [{"label":"USD","attribute":"CURRENCY_CODE"},
* {"label":"Software","attribute":"CATEGORY"},
* {"label":"Scanner","attribute":"CATEGORY"},
* {"label":"Speakers","attribute":"CATEGORY"},
* {"label":"1200 dpi x 1200 dpi - up to 25 ppm (mono) / up to 24 ppm (colour) - capacity: 100 sheets - Hi-Speed USB2.0, Ethernet","attribute":"TEXT"},
* {"label":"1000 dpi x 1000 dpi - up to 16 ppm (mono) / up to 15 ppm (colour)- capacity 80 sheets - scanner (216 x 297 mm, 1200dpi x 2400dpi)","attribute":"TEXT"},
* {"label":"Print 2400 dpi image quality color documents at speeds of up to 32 ppmĀ¹ (color) or 36 ppmĀ¹ (monochrome), letter/A4. Powerful 500 MHz processor, 512MB of memory","attribute":"TEXT"},
* {"label":"Scanner and Printer","attribute":"CATEGORY"},
* {"label":"1000 dpi x 1000 dpi - up to 15 ppm (mono) / up to 13 ppm (colour) - capacity: 40 sheets - Hi-Speed USB - excellent dimesions for the small office","attribute":"TEXT"},
* {"label":"Print up to 25 ppm letter and 24 ppm A4 color or monochrome, with a first-page-out-time of less than 13 seconds for monochrome and less than 15 seconds for color","attribute":"TEXT"}
* ]
*/
getElements: function() {
return this.suggestions;
}
};
// =========================================================================
// class suggestion 2 query
// =========================================================================
module.Suggestion2Query.prototype = $.extend({}, sinabase.SuggestionQuery.prototype, module.Query.prototype, {
init: function(properties) {
properties = properties || {};
this.attributes = properties.attributes || [];
module.Query.prototype.init.apply(this, [properties]);
sinabase.SuggestionQuery.prototype.init.apply(this, [properties]);
this.resultSetClass = module.Suggestion2ResultSet;
this.searchTerms = properties.searchTerms || {};
this.suggestionTerm = properties.suggestionTerm || '';
},
/**
* Adds a response attribute to this suggestion query. Instead of the SuggestionQuery
* which searches within these attributes. This Suggestion2Query will search everywhere
* but only returns these response attributes.
* @ignore
* @instance
* @since SAP HANA SPS 06
* @memberOf sap.bc.ina.api.sina.impl.inav2.Suggestion2Query
* @param {String} attribute the name of the attribute as given in the HANA database
*/
addResponseAttribute: function(attribute) {
this.attributes.push(attribute);
this._resetResultSet();
return this;
},
addSearchTerm: function(term) {
if (term) {
this.searchTerms[term] = term;
}
this._resetResultSet();
return this;
},
setSuggestionTerm: function(term) {
if (term.charAt(term.length - 1) !== '*') {
term += '*';
}
if (this.suggestionTerm !== term) {
this.suggestionTerm = term;
this._resetResultSet();
}
return this;
},
/**
* Adds a response attribute to this suggestion query. Instead of the SuggestionQuery
* which searches within these attributes. This Suggestion2Query will search everywhere
* but only returns these response attributes.
* @ignore
* @instance
* @memberOf sap.bc.ina.api.sina.impl.inav2.Suggestion2Query
* @param {Array} attributes list with the names of the attribute as given in the SAP HANA database.
*/
setResponseAttributes: function(attributes) {
this.attributes = attributes;
this._resetResultSet();
return this;
},
createJsonRequest: function() {
jsontemplates.suggestion2Request.Suggestions2.Precalculated = false;
jsontemplates.suggestion2Request.Suggestions2.NamedValues = [];
for (var i = 0; i < this.attributes.length; i++) {
jsontemplates.suggestion2Request.Suggestions2.NamedValues.push({
AttributeName: this.attributes[i],
Name: this.attributes[i]
});
}
jsontemplates.suggestion2Request.DataSource = this.filter.dataSource.toInAJson();
jsontemplates.suggestion2Request.Suggestions2.Top = this.getTop();
jsontemplates.suggestion2Request.Suggestions2.Skip = this.getSkip();
var rootConditionGroup = new filter.ConditionGroup();
var searchTermConditions = new filter.ConditionGroup();
for (var searchTerm in this.searchTerms) {
var stCondition = new filter.Condition('$$SearchTerms$$', 'contains', searchTerm);
rootConditionGroup.addCondition(stCondition);
}
var suggestionCondition = new filter.Condition('$$SuggestionTerms$$', 'contains', this.suggestionTerm);
rootConditionGroup.addCondition(suggestionCondition);
rootConditionGroup.addCondition(this.getFilter().getFilterConditions());
jsontemplates.suggestion2Request.Suggestions2.Filter = rootConditionGroup.getJson();
return jsontemplates.suggestion2Request;
}
});
// =========================================================================
// class suggestion 2 result set
// =========================================================================
module.Suggestion2ResultSet.prototype = {
init: function() {
this.datasources = {};
this.suggestions = [];
},
setJsonData: function(data) {
this.datasources = {};
this.suggestions = [];
function isNamedValueSuitable(name) {
switch (name) {
//upper and lower bounds are not needed now
case "Value1":
case "Value2":
case "Order":
return false;
default:
return true;
}
}
var itemLists = {};
if (!data.ItemLists) {
return;
}
for (var i = 0; i < data.ItemLists.length; i++) {
itemLists[data.ItemLists[i].Name] = data.ItemLists[i];
}
for (var a = 0; a < data.Grids.length; a++) {
var axes = data.Grids[a].Axes;
var cells = data.Grids[a].Cells;
if (axes === undefined || cells === undefined) {
return;
}
var suggestionDict = {};
for (var cellIndex = 0; cellIndex < cells.length; ++cellIndex) {
var cell = cells[cellIndex],
attributeName = "",
attributeLabel = "",
dataSourceLabel = "",
suggestion = {};
suggestion.dataSource = new filter.DataSource();
suggestion.attribute = {};
for (var j = 0; j < cell.Index.length; j++) {
var cellIndexValue = cell.Index[j];
var tuple = axes[j].Tuples[cellIndexValue];
if (tuple === undefined) {
continue;
}
for (var c = 0; c < tuple.length; c++) {
var dimension = axes[j].Dimensions[c];
var tupleValueForDimension = tuple[c];
var itemlist = itemLists[dimension.ItemListName];
var namedValues = itemlist.Items[tupleValueForDimension].NamedValues;
for (var d = 0; d < namedValues.length; ++d) {
var namedValue = namedValues[d];
switch (namedValue.Name) {
case "$$Term$$":
suggestion.valueRaw = cell.Value || cell.ValueFormatted || null;
suggestion.value = cell.ValueFormatted || cell.Value || null;
suggestion.labelRaw = namedValue.Value;
suggestion.label = namedValue.ValueFormatted;
if (!suggestion.filter) {
suggestion.filter = {};
}
suggestion.filter.value = suggestion.labelRaw;
suggestion.filter.valueLabel = suggestion.labelRaw;
break;
case "$$DataSource$$":
var objectName = namedValue.Value;
suggestion.dataSource.setObjectNameValue(objectName);
break;
case "$$DataSourceDescription$$":
var objectNameLabel = namedValue.Value;
suggestion.dataSource.setObjectNameLabel(objectNameLabel);
break;
case "$$Attribute$$":
var attribute = namedValue.Value;
if (!suggestion.filter) {
suggestion.filter = {};
}
suggestion.filter.attribute = attribute;
suggestion.attribute.value = attribute;
break;
case "$$AttributeDescription$$":
attributeLabel = namedValue.Value;
if (!suggestion.filter) {
suggestion.filter = {};
}
suggestion.filter.attributeLabel = attributeLabel;
suggestion.attribute.label = attributeLabel;
break;
}
}
}
}
this.suggestions.push(suggestion);
}
}
},
getElements: function() {
return this.suggestions;
}
};
// =========================================================================
// class chart query
// =========================================================================
module.ChartQuery.prototype = $.extend({}, sinabase.ChartQuery.prototype, module.Query.prototype, {
/**
* A query that yields results suitable for simple chart controls, like
* pie or bar charts.
* @since SAP HANA SPS 06
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.ChartQuery
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.Query}
* @augments {sap.bc.ina.api.sina.sinabase.ChartQuery}
* @private
*/
init: function(properties) {
properties = properties || {};
module.Query.prototype.init.apply(this, [properties]);
sinabase.ChartQuery.prototype.init.apply(this, [properties]);
this.dimensions = {};
this.dimensions.CustomDimension1 = {
Axis: "Columns",
Name: "CustomDimension1",
Members: []
};
properties.dimensions = properties.dimensions || {};
if ($.type(properties.dimensions) === 'array') {
for (var i = 0; i < properties.dimensions.length; i++) {
this.addDimension(properties.dimensions[i]);
}
} else if ($.type(properties.dimensions) === 'string' || $.type(properties.dimensions) === 'object') {
this.addDimension(properties.dimensions);
}
properties.measures = properties.measures || {};
if ($.type(properties.measures) === 'array') {
for (var j = 0; j < properties.measures.length; j++) {
this.addMeasure(properties.measures[j]);
}
} else if ($.type(properties.measures) === 'object') {
this.addMeasure(properties.measures);
}
this.resultSetClass = module.ChartResultSet;
},
createJsonRequest: function() {
jsontemplates.chartRequest.DataSource = this.filter.dataSource.toInAJson();
jsontemplates.chartRequest.SearchTerms = this.filter.getSearchTerms();
jsontemplates.chartRequest.Analytics.Definition.Filter = this.filter.getJson();
jsontemplates.chartRequest.Analytics.Definition.Dimensions = [];
for (var dimension in this.dimensions) {
jsontemplates.chartRequest.Analytics.Definition.Dimensions.push(this.dimensions[dimension]);
}
return jsontemplates.chartRequest;
},
/**
* Adds a count measure for the given dimension to the chart query.
* @memberOf sap.bc.ina.api.sina.impl.inav2.ChartQuery
* @instance
* @param {string} dimension The dimension that the count is computed for.
* @return {sap.bc.ina.api.sina.impl.inav2.ChartQuery} The chart query to allow chained method calls.
*/
count: function(dimension) {
this.addMeasure({
name: dimension,
aggregationFunction: 'COUNT'
});
return this;
},
/**
* Adds one of the following aggregations to a dimension: 'COUNT', 'AVG', 'SUM', 'MIN', 'MAX'
* @memberOf sap.bc.ina.api.sina.impl.inav2.ChartQuery
* @instance
* @since SAP HANA SPS 06
* @param {Object} properties The configuration object can have the following properties:p
* name, aggregationFunction, sortOrder, top.
* @example
* var query = sina.createChartQuery()
* .dataSource({ "schemaName" : {"value":"SYSTEM"},
* "objectName" : {"value":"J_EPM_PRODUCT"})
* .addDimension("CATEGORY")
* .addMeasure({name:"CATEGORY",aggregationFunction:"COUNT"});
* var resultSet = query.getResultSetSync();
*/
addMeasure: function(properties) {
if ($.isEmptyObject(properties)) {
return {};
}
var axis = "Columns";
var name = "CustomDimension1"; //COUNT_"+dimension;
var member;
if (properties.aggregationFunction.toUpperCase() === 'COUNT' || properties.aggregationFunction.toUpperCase() === 'AVG') {
member = this._createAggregationDimension(properties.aggregationFunction, properties.name, properties.aggregationFunction, properties.sortOrder || undefined, properties.top || undefined);
} else {
member = this._createAggregationDimension(properties.aggregationFunction, "", properties.name, properties.sortOrder, properties.top);
delete member.AggregationDimension;
delete member.Name;
delete member.SortOrder;
}
this.dimensions.CustomDimension1.Members.push(member);
return this;
},
/**
* Adds a dimension to the query.
* @memberOf sap.bc.ina.api.sina.impl.inav2.ChartQuery
* @instance
* @since SAP HANA SPS 06
* @param {String|Object} dimension The name of the dimension. This is the same as the name of the corresponding database attribute.
* If it is an object, the name and values of this object must be the same as the functions parameters.
* @param {int} sortOrder Sort order of this dimension. 1 for ascending, 2 for descending.
* Default is 1.
* @param {int} top How many members does the dimension have? The default value is 5.
* @example <caption>Plain function call</caption>
* var query = sina.createChartQuery()
* .addDimension("CATEGORY",1,5)
* @example <caption>Call with properties object</caption>
* var query = sina.createChartQuery({
* dimensions: [{name: "YEAR", sortOrder: 1, top:5}]
* });
*/
addDimension: function(dimension, sortOrder, top) {
if ($.type(dimension) === 'object') {
if ($.isEmptyObject(dimension)) {
return {};
}
this.dimensions[dimension.name] = this._createDimension(dimension.name, null, dimension.sortOrder, dimension.top);
} else if ($.type(dimension) === 'string') {
if (!dimension) {
return {};
}
this.dimensions[dimension] = this._createDimension(dimension, null, sortOrder, top);
}
return this;
},
_createDimension: function(dimension, axis, sortOrder, top) {
return {
"Axis": axis || "Rows",
"Name": dimension,
"SortOrder": sortOrder || 1,
"Top": top || 5
};
},
/**
* Creates an aggregation for a dimension.
* @private
* @ignore
* @param {String} aggregation Type of aggregation to be created. The default value is SUM.
* @param {String} dimension Dimension that the aggregation is created for.
* @param {int} sortOrder Sort order of the aggregation dimension. 1 for ascending, 2 for descending.
* @param {String} name Name of the aggregation to be created.
* @return {Object} An object suitable for an INA request.
*/
_createAggregationDimension: function(aggregationFunction, aggregationDimension, name, sortOrder) {
return {
"Aggregation": aggregationFunction,
"AggregationDimension": aggregationDimension,
"MemberOperand": {
"AttributeName": "Measures",
"Comparison": "=",
"Value": name
},
"Name": name,
"SortOrder": sortOrder || 2
};
}
});
// =========================================================================
// class chart result set
// =========================================================================
module.ChartResultSet.prototype = {
/**
* A result set that yields elements suitable for simple chart controls, like
* pie or bar charts.
* @since SAP HANA SPS 06
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.ChartResultSet
* @private
*/
init: function(properties) {
properties = properties || {};
this.type = properties.type;
this.elements = [];
},
/**
* Creates filter conditions for simple charts based on named values.
* It also decides whether the element sets a filter range or an 'equals' filter.
* There are the following cases:
* 1) Value1 and Value2 both have values that are not the empty string:
* It is a range with upper and lower boundary.
* 2) Value2 has no value:
* It is not a range but an equals ("=") filter condition.
* 3) Either Value1 or Value2 have an empty string ("") as value:
* It is a range with only one boundary, upper or lower.
* @private
* @ignore
* @param {object} element The chart element that the filter condition is added to.
* @param {object} namedValues Server side data.
* @param {object} metadata Server side meta data.
*/
_parseNamedValues: function(element, namedValues, metadata) {
var self = this;
for (var i = 0; i < namedValues.length; i++) {
var name = namedValues[i].Name;
var value = namedValues[i].Value;
element.label = namedValues[i].ValueFormatted;
element.labelRaw = namedValues[i].Value;
switch (name) {
case '$$DataSource$$':
self._parseNamedValuesForDataSource(element, value);
break;
case '$$AttributeValue$$':
self._parseNamedValuesForRange(element, value, metadata);
break;
}
}
},
_parseNamedValuesForRange: function(element, values, metadata) {
var valueIDRaw,
value1,
value2;
for (var d = 0; d < values.length; ++d) {
var namedValue = values[d];
switch (namedValue.Name) {
case "ValueID":
element.label = namedValue.ValueFormatted;
valueIDRaw = namedValue.Value;
break;
case "Value1":
if (metadata.Cube.ObjectName && (namedValue.Value !== undefined)) {
value1 = new filter.Condition(metadata.Cube.ObjectName, ">=", namedValue.Value);
}
break;
case "Value2":
if (metadata.Cube.ObjectName && (namedValue.Value !== undefined)) {
value2 = new filter.Condition(metadata.Cube.ObjectName, "<=", namedValue.Value);
}
break;
case "Order":
break;
}
}
if (valueIDRaw) {
if (value1 && value2) {
// 1) range
var group = new filter.ConditionGroup();
group.setOperator("AND");
group.setLabel(element.label);
if (value1.value) {
// 3) upper boundary of the range
group.addCondition(value1);
}
if (value2.value) {
// 3) lower boundary of the range
group.addCondition(value2);
}
element.labelRaw = group;
} else if (value1 && value1.value && (!value2)) {
// 2) not a range
value1.operator = '=';
element.labelRaw = value1;
} else if (value2 && value2.value && (!value1)) {
// 2) not a range
value2.operator = '=';
element.labelRaw = value2;
}
}
},
// DataSource chart (category tree)
_parseNamedValuesForDataSource: function(element, values) {
element.dataSource = new filter.DataSource();
for (var d = 0; d < values.length; ++d) {
var namedValue = values[d];
switch (namedValue.Name) {
case "ObjectName":
var label = namedValue.ValueFormatted;
element.dataSource.setLabel(label);
element.dataSource.setObjectName(namedValue.Value, namedValue.ValueFormatted);
break;
case "PackageName":
element.dataSource.setPackageName(namedValue.Value, namedValue.ValueFormatted);
break;
case "SchemaName":
element.dataSource.setSchemaName(namedValue.Value, namedValue.ValueFormatted);
break;
case "Type":
element.dataSource.setType(namedValue.Value, namedValue.ValueFormatted);
break;
default:
element[namedValue.Name] = namedValue.Value;
break;
}
}
},
setJsonData: function(data) {
this.elements = [];
var metadata;
if (data.Metadata) {
metadata = data.Metadata;
}
if (data.ResultSet) {
data = data.ResultSet;
}
var itemLists = {};
for (var i = 0; i < data.ItemLists.length; i++) {
itemLists[data.ItemLists[i].Name] = data.ItemLists[i];
}
for (var a = 0; a < data.Grids.length; a++) {
var axes = data.Grids[a].Axes;
var cells = data.Grids[a].Cells;
for (var cellIndex = 0; cellIndex < cells.length; ++cellIndex) {
//one dimension chart
if (axes[0].Dimensions.length === 1) {
var cell = cells[cellIndex];
var element = {
valueRaw: cell.Value || cell.ValueFormatted || null,
value: cell.ValueFormatted || cell.Value || null
};
// only axes 0 is relevant for chart results
for (var j = 0; j < 1; j++) {
var cellIndexValue = cell.Index[j];
var tuple = axes[j].Tuples[cellIndexValue];
if (tuple === undefined) {
continue;
}
for (var c = 0; c < tuple.length; c++) {
var dimension = axes[j].Dimensions[c];
var tupleValueForDimension = tuple[c];
var itemlist = itemLists[dimension.ItemListName];
var namedValues = itemlist.Items[tupleValueForDimension].NamedValues;
this._parseNamedValues(element, namedValues, metadata);
}
}
this.elements.push(element);
}
}
}
},
/**
* Returns the elements of the result set.
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.ChartResultSet
* @instance
* @since SAP HANA SPS 06
* @return {Array} A list of result set elements.
* @example
* var query = sap.bc.ina.api.sina.createChartQuery()
* .dataSource({ schemaName : "SYSTEM",
* objectName : "J_EPM_PRODUCT"
* })
* .addDimension("CATEGORY")
* .addMeasure({ name : "CATEGORY",
* aggregationFunction : "COUNT"
* }); //end of query
* var resultSet = query.getResultSetSync();
* var elements = resultSet.getElements();
* // contents of elements:
* [
{
"label": "Others",
"labelRaw": "Others",
"value": "13",
"valueRaw": 13
},
{
"label": "Notebooks",
"labelRaw": "Notebooks",
"value": "10",
"valueRaw": 10
},
{
"label": "Flat screens",
"labelRaw": "Flat screens",
"value": "9",
"valueRaw": 9
},
{
"label": "Software",
"labelRaw": "Software",
"value": "8",
"valueRaw": 8
},
{
"label": "Electronics",
"labelRaw": "Electronics",
"value": "5",
"valueRaw": 5
}
]
*/
getElements: function() {
return this.elements;
}
};
// =======================================================================
// result set parser
// =======================================================================
var ResultSetParser = function() {
this.init.apply(this, arguments);
};
ResultSetParser.prototype = {
init: function(options) {
this.resultSet = options.resultSet;
this.parse();
},
parse: function() {
// enhance result set:
// -> create link to item lists in dimensions of axes
this.enhance(this.resultSet);
// get reference to grid,row axis,col axis
var grid = this.resultSet.Grids[0];
var rowAxis = grid.Axes[0];
var colAxis = grid.Axes[1];
// key function for getting key of an item
// (key needed for insertion into tree)
var keyFunction = function(item) {
return item.NamedValues[0].Value;
};
// create new tree
var tree = new Tree({
keyFunction: keyFunction
});
// loop at all cells and add cell to result tree
for (var i = 0; i < grid.Cells.length; ++i) {
var cell = grid.Cells[i];
var rowIndex = cell.Index[0];
var rowItems = this.resolve(rowAxis, rowIndex);
var rowItemsDebug = rowItems.map(keyFunction);
var colIndex = cell.Index[1];
var colItems = this.resolve(colAxis, colIndex);
var colItemsDebug = colItems.map(keyFunction);
colItems = [$.extend({}, colItems[0])];
// add cell info to col item
colItems[0].cell = cell;
// assemble tree path = rowItems + colItems
var treePath = rowItems;
treePath.push.apply(treePath, colItems);
// insert
tree.insert(treePath);
}
return tree;
},
resolve: function(axis, index) {
var items = [];
var tuples = axis.Tuples[index];
for (var i = 0; i < tuples.length; ++i) {
var itemIndex = tuples[i];
var item = axis.Dimensions[i].ItemList.Items[itemIndex];
items.push(item);
}
return items;
},
enhance: function(resultSet) {
// create dictionary with item lists
var itemListByName = {};
for (var i = 0; i < resultSet.ItemLists.length; ++i) {
var itemList = resultSet.ItemLists[i];
itemListByName[itemList.Name] = itemList;
}
// loop at all dimensions and set link to item list
for (i = 0; i < resultSet.Grids.length; ++i) {
var grid = resultSet.Grids[i];
for (var j = 0; j < grid.Axes.length; ++j) {
var axis = grid.Axes[j];
for (var k = 0; k < axis.Dimensions.length; ++k) {
var dimension = axis.Dimensions[k];
dimension.ItemList = itemListByName[dimension.ItemListName];
}
}
}
}
};
// =======================================================================
// tree
// =======================================================================
var Tree = function() {
this.init.apply(this, arguments);
};
Tree.prototype = {
init: function(options) {
// create root tree element
this.root = {
data: "root",
subTree: {}
};
// set key function
if (options && options.keyFunction) {
this.keyFunction = options.keyFunction;
} else {
this.keyFunction = function(obj) {
return obj;
};
}
},
insert: function(path) {
var parent = this.root;
for (var i = 0; i < path.length; ++i) {
var pathElement = path[i];
var key = this.keyFunction(pathElement);
if (!parent.subTree.hasOwnProperty(key)) {
parent.subTree[key] = {
subTree: {},
data: pathElement
};
}
parent = parent.subTree[key];
}
},
toString: function() {
var stringStream = [];
this.toStringHelper(this.root, [], stringStream);
return stringStream.join("");
},
toStringHelper: function(tree, path, stringStream) {
var pathElement = null;
if (tree === this.root) {
pathElement = tree.data;
} else {
pathElement = this.keyFunction(tree.data);
}
path.push(pathElement);
var hasChildren = false;
for (var child in tree.subTree) {
if (tree.subTree.hasOwnProperty(child)) {
hasChildren = true;
var subTree = tree.subTree[child];
var pathCopy = path.slice(0);
this.toStringHelper(subTree, pathCopy, stringStream);
}
}
if (!hasChildren) {
stringStream.push(path.toString() + "\n");
}
}
};
// =========================================================================
// class group bar chart query
// =========================================================================
module.GroupBarChartQuery.prototype = $.extend({}, module.ChartQuery.prototype, {
/**
* A query that yields results suitable for a grouped bar chart control.
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.GroupBarChartQuery
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.ChartQuery}
* @private
*/
init: function(properties) {
properties = properties || {};
module.ChartQuery.prototype.init.apply(this, [properties]);
this.resultSetClass = module.GroupBarChartResultSet;
}
});
// =========================================================================
// class goruped bar chart result set
// =========================================================================
module.GroupBarChartResultSet.prototype = {
/**
* A result set that yields elements suitable for a grouped bar chart.
* @since SAP HANA SPS 06
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.GroupBarChartResultSet
* @private
*/
init: function(properties) {
properties = properties || {};
this.elements = [];
},
setJsonData: function(data) {
var self = this;
this.elements = [];
var resultSetParser = new ResultSetParser({
resultSet: data
});
var tree = resultSetParser.parse();
function parseSubTree(subTree, parentElem) {
for (var itemName in subTree) {
var item = subTree[itemName];
var elem = {
label: item.data.NamedValues[0].ValueFormatted,
value: []
};
if (item.data.cell) {
elem.value = {
value: item.data.cell.ValueFormatted,
valueRaw: item.data.cell.Value
};
}
if (parentElem) {
parentElem.value.push(elem);
} else {
self.elements.push(elem);
}
if (item.subTree) {
parseSubTree(item.subTree, elem);
}
}
}
parseSubTree(tree.root.subTree);
},
/**
* Returns the elements of the result set.
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.GroupBarChartResultSet
* @instance
* @since SAP HANA SPS 06
* @return {Array} A list of result set elements.
* @example
* var query = sap.bc.ina.api.sina.createGroupBarChartQuery();
* query.dataSource({ schemaName : "SYSTEM",
* objectName : "J_EPM_PRODUCT"
* });
* query.addDimension('CURRENCY_CODE');
* query.addDimension('CATEGORY');
* query.count('PRODUCT_ID');
* var resultSet = query.getResultSetSync();
* var elements = resultSet.getELements();
* // contents of elements:
* [
{
"label": "EUR",
"value": [
{
"label": "Notebooks",
"value": [
{
"label": "COUNT",
"value": {
"value": "6",
"valueRaw": 6
}
}
]
},
{
"label": "Others",
"value": [
{
"label": "COUNT",
"value": {
"value": "5",
"valueRaw": 5
}
}
]
},
{
"label": "Software",
"value": [
{
"label": "COUNT",
"value": {
"value": "3",
"valueRaw": 3
}
}
]
}
]
}
]
*/
getElements: function() {
return this.elements;
}
};
// =========================================================================
// class line chart query
// =========================================================================
module.LineChartQuery.prototype = $.extend({}, module.ChartQuery.prototype, {
/**
* A query that yields results suitable for a line chart control.
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.LineChartQuery
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.ChartQuery}
* @private
*/
init: function(properties) {
properties = properties || {};
module.ChartQuery.prototype.init.apply(this, [properties]);
this.resultSetClass = module.LineChartResultSet;
}
});
// =========================================================================
// class line chart result set
// =========================================================================
module.LineChartResultSet.prototype = $.extend({}, module.GroupBarChartResultSet.prototype, {
/**
* A result set that yields elements suitable for a line chart.
* @since SAP HANA SPS 06
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.LineChartResultSet
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.GroupBarChartResultSet}
* @private
*/
init: function(properties) {
properties = properties || {};
this.elements = [];
},
setJsonData: function(data) {
var self = this;
this.elements = [];
var resultSetParser = new ResultSetParser({
resultSet: data
});
var tree = resultSetParser.parse();
//create line chart result format
function parseSubTree(subTree, parentElem) {
for (var dimensionLineItemName in subTree) {
var dimensionLineItem = subTree[dimensionLineItemName];
var elem = {
label: dimensionLineItem.data.NamedValues[0].ValueFormatted,
value: []
};
for (var dimensionXItemName in dimensionLineItem.subTree) {
var dimensionXItem = dimensionLineItem.subTree[dimensionXItemName];
var point = {
x: dimensionXItem.data.NamedValues[0].ValueFormatted
};
for (var measureYItemName in dimensionXItem.subTree) {
var measureYItem = dimensionXItem.subTree[measureYItemName];
point.y = measureYItem.data.cell.Value;
}
elem.value.push(point);
}
self.elements.push(elem);
}
}
parseSubTree(tree.root.subTree);
},
/**
* Returns the elements of the result set.
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.LineChartResultSet
* @instance
* @since SAP HANA SPS 06
* @return {Array} A list of result set elements.
* @example
* var queryProperties = {
* dataSource : { schemaName : "SYSTEM",
objectName : "J_EPM_PRODUCT"
},
dimensionX : {name: 'CATEGORY'},
dimensionLine : {name: 'CURRENCY_CODE'},
measureY : {name: 'PRODUCT_ID', aggregationFunction: 'COUNT'}
};
query = sap.bc.ina.api.sina.createLineChartQuery(queryProperties);
* var resultSet = query.getResultSetSync();
* var elements = resultSet.getEements();
* // contents of elements (shortened):
* [
{
"label": "EUR",
"value": [
{
"x": "Notebooks",
"y": 6
},
{
"x": "Others",
"y": 5
},
{
"x": "Software",
"y": 3
},
{
"x": "Speakers",
"y": 3
},
{
"x": "Electronics",
"y": 2
},
{
"x": "Flat screens",
"y": 2
},
{
"x": "Laser printers",
"y": 2
},
{
"x": "Mice",
"y": 2
},
{
"x": "PC",
"y": 2
},
{
"x": "Workstation ensemble",
"y": 2
}
]
},
{
"label": "USD",
"value": [
{
"x": "Others",
"y": 4
},
{
"x": "Flat screens",
"y": 2
},
{
"x": "Handhelds",
"y": 2
},
{
"x": "High Tech",
"y": 2
},
{
"x": "Notebooks",
"y": 2
},
{
"x": "Software",
"y": 2
},
{
"x": "Electronics",
"y": 1
},
{
"x": "Graphic cards",
"y": 1
},
{
"x": "Handheld",
"y": 1
},
{
"x": "Headset",
"y": 1
}
]
}
]
*/
getElements: function() {
return this.elements;
}
});
// =========================================================================
// class search query
// =========================================================================
module.SearchQuery.prototype = $.extend({}, sinabase.SearchQuery.prototype, module.Query.prototype, {
/**
* A query that yields results suitable for a simple result list.
* @constructs sap.bc.ina.api.sina.impl.inav2.sina_impl.SearchQuery
* @augments {sap.bc.ina.api.sina.sinabase.SearchQuery}
* @augments {sap.bc.ina.api.sina.impl.inav2.sina_impl.Query}
* @private
*/
init: function(properties) {
properties = properties || {};
module.Query.prototype.init.apply(this, [properties]);
sinabase.SearchQuery.prototype.init.apply(this, [properties]);
this.sqlSearch = (properties.sqlSearch === undefined || properties.sqlSearch === true) ? true : false;
this.attributes = properties.attributes || [];
properties.orderBy = properties.orderBy || {};
this.setOrderBy(properties.orderBy);
this.resultSetClass = module.SearchResultSet;
},
/**
* Adds a response attribute to the search query. The content of this
* attribute is returned if the search term was found in one of the
* response attributes.
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.SearchQuery
* @instance
* @param {String|Object} attribute If the argument is a string, it is
* the name of an attribute of the database view. If it is an object, it can contain
* the name of the attribute and additional server-side
* functions, like snippet or highlighting.
* See {@link sap.bc.ina.api.sina.sinabase.Sina#createSearchQuery} for examples.
*/
addResponseAttribute: function(attribute) {
this.attributes.push(attribute);
this._resetResultSet();
return this;
},
createJsonRequest: function() {
var self = this;
jsontemplates.searchRequest.DataSource = this.filter.dataSource.toInAJson();
if (this.system instanceof global.sap.bc.ina.api.sina.impl.inav2.system.HANASystem) {
if (this.attributes.length === 0) {
throw {
message: "Add at least one response attribute to your query"
};
}
if (this.sqlSearch === true) {
// TODO: remove workaround for SPS6. See CSS 0001971234 2013
jsontemplates.searchRequest.Options = ["SqlSearch"];
}
}
var selectedValues = [];
for (var i = 0; i < this.attributes.length; ++i) {
var attribute = this.attributes[i];
if ($.type(attribute) === 'string') {
selectedValues.push({
Name: attribute,
AttributeName: attribute
});
} else if ($.type(attribute) === 'object') {
var selectedValue = {
Name: attribute.name || attribute.attributeName,
AttributeName: attribute.attributeName || attribute.name
};
if (attribute.highlighted === true) {
selectedValue.Function = 'Highlighted';
}
if (attribute.snippet === true) {
selectedValue.Function = 'Snippet';
}
if (attribute.startPosition !== undefined) {
selectedValue.StartPosition = attribute.startPosition;
}
if (attribute.maxLength !== undefined) {
selectedValue.MaxLength = attribute.maxLength;
}
selectedValues.push(selectedValue);
}
}
jsontemplates.searchRequest.Search.SelectedValues = selectedValues;
var searchterms = this.filter.getSearchTerms();
if (!searchterms) {
searchterms = '*';
}
jsontemplates.searchRequest.SearchTerms = searchterms;
jsontemplates.searchRequest.Search.Top = this._top;
jsontemplates.searchRequest.Search.Skip = this._skip;
jsontemplates.searchRequest.Search.Filter = this.filter.getJson();
jsontemplates.searchRequest.Search.OrderBy = this._assembleOrderBy();
return jsontemplates.searchRequest;
},
/**
* Sets how the result will be ordered.
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.SearchQuery
* @instance
* @param {Object|Array} orderBy If orderBy is an object, it must have the
* properties 'orderBy' (string) and 'sortOrder' (string).
* The orderBy property can either be the name of a database attribute that
* the result will be sorted alphabetically for, or it can be the special
* '$$score$$' string. The result will then be ordered according to the SAP HANA
* Score function.
* This function can also receive an array of these objects for multiple
* order-by values, for example to order by $$score$$ and then alphabetically
* for an attribute. The result will then be ordered after the first entry.
* If two results have the same rank however, they will be ordered after the
* second order-by value, and so on.
* @default {orderBy:'$$score$$', sortOrder:'DESC'}
* See {@link sap.bc.ina.api.sina.sinabase.Sina#createSearchQuery} for examples.
*/
setOrderBy: function(orderBy) {
this._resetResultSet();
this.orderBy = orderBy || {
orderBy: '$$score$$',
sortOrder: 'DESC'
};
}
});
// =========================================================================
// class result set
// =========================================================================
module.SearchResultSet.prototype = {
/**
* A result set suitable for a simple result list. An instance of this
* class will be returned by {@link sap.bc.ina.api.sina.impl.inav2.sina_impl.SearchQuery#getResultSet}
* @constructs sap.bc.ina.api.sina.impl.inav2.SearchResultSet
* @private
*/
init: function(properties) {
properties = properties || {};
this.elements = [];
this.totalcount = 0;
},
toString: function(rs) {
var elements = this.elements;
var elements2 = [];
var i;
for (i = 0; i < elements.length; ++i) {
var element = elements[i];
var element2 = {};
for (var attrName in element) {
if (attrName.slice(0, 2) === '$$' || attrName.slice(0, 1) === '_') {
continue;
}
var attrValue = element[attrName];
if (!attrValue.label || !attrValue.value) {
continue;
}
var attribute = {
label: attrValue.label,
value: attrValue.value
};
element2[attrName] = attribute;
}
elements2.push(element2);
}
return JSON.stringify(elements2);
},
setJsonData: function(data) {
this.elements = [];
function ResultElementRenderingTemplateSpecification() {
this.type = "";
this.platform = "";
this.technology = "";
this.width = "";
this.height = "";
this.variant = "";
// this.description = "";
this.uri = "";
// this.request = null;
// this.encodedJSON = "";
}
ResultElementRenderingTemplateSpecification.prototype = {
_fromInaJson: function(inaJson) {
this.type = inaJson.Type || "";
this.platform = inaJson.Platform || "";
this.technology = inaJson.Technology || "";
this.width = inaJson.Width || "";
this.height = inaJson.Height || "";
this.variant = inaJson.Variant || "";
// this.description = inaJson.Description || "";
this.uri = inaJson.Uri || "";
}
};
function ResultElementRelatedAction() {
this.type = "";
this.description = "";
this.uri = "";
this.request = null;
this.encodedJSON = "";
}
ResultElementRelatedAction.prototype = {
_fromInaJson: function(inaJson) {
var self = this;
self.description = inaJson.Description;
self.uri = inaJson.Uri;
switch (inaJson.Type) {
case "RelatedRequest":
self.type = 'Search';
var queryProps = {};
queryProps.dataSource = new filter.DataSource();
queryProps.dataSource.fromInAJson(inaJson.Request.DataSource);
queryProps.system = global.sap.bc.ina.api.sina.sinaSystem();
queryProps.top = 1;
self.request = new module.SearchQuery(queryProps);
self.request.filter.setJson(inaJson.Request.Filter);
// mark request without filter condition as invalid
if (inaJson.Request.Filter.Selection === undefined) {
self.request.invalid = true;
self.request.invalidMessage = "Related request '" + self.description + "' is invalid because of missing filter conditions.";
}
break;
case "GeneralUri":
self.type = 'Link';
self.url = self.uri;
break;
case "SAPNavigation":
self.type = 'Navigation';
self.url = self.uri;
break;
}
self.encodedJSON = encodeURIComponent(self);
}
};
function ResultElementAttributeMetaData(resultElementAttribute) {
this.resultElementAttribute = resultElementAttribute;
this.correspondingSearchAttributeName = "";
this.description = "";
this.isTitle = false;
this.presentationUsage = [];
this.displayOrder = null;
}
ResultElementAttributeMetaData.prototype = {
_fromInaJson: function(inaAttributeMetaData) {
var self = this;
self.correspondingSearchAttributeName = inaAttributeMetaData.correspondingSearchAttributeName || "";
self.description = inaAttributeMetaData.Description || "";
self.presentationUsage = inaAttributeMetaData.presentationUsage || [];
if (inaAttributeMetaData.IsTitle !== undefined) {
self.isTitle = inaAttributeMetaData.IsTitle;
}
if (self.isTitle) {
if (!self.resultElementAttribute.resultElement.title) {
self.resultElementAttribute.resultElement.title = self.resultElementAttribute.resultElement.$$DataSourceMetaData$$.getLabel() + ":";
}
self.resultElementAttribute.resultElement._registerPostProcessor(function() {
self.resultElementAttribute.resultElement.title = self.resultElementAttribute.resultElement.title + " " + self.resultElementAttribute.value;
});
}
}
};
function ResultElementAttribute(resultElement) {
this.resultElement = resultElement;
this.$$MetaData$$ = new ResultElementAttributeMetaData(this);
this.label = "";
this.labelRaw = "";
this.value = "";
this.valueRaw = "";
}
ResultElementAttribute.prototype = {
_fromInaJson: function(inaAttribute) {
var self = this;
self.labelRaw = this.$$MetaData$$.correspondingSearchAttributeName || inaAttribute.Name || "";
self.label = this.$$MetaData$$.description || inaAttribute.Name || "";
self.valueRaw = inaAttribute.Value || null;
self.value = inaAttribute.ValueFormatted || null;
},
toString: function() {
//stay compatible with result templates <= SAP HANA SPS 05
return this.value;
}
};
function ResultElement() {
//these members are always provided:
this.title = "";
this.$$DataSourceMetaData$$ = {};
this.$$RelatedActions$$ = {};
this.$$RenderingTemplateSpecification$$ = {};
this.$$WhyFound$$ = [];
this.$$PostProcessors$$ = [];
//the real result item attributes will be added to
//this object dynamically
}
ResultElement.prototype = {
_fromInaJson: function(namedValues) {
var self = this;
for (var k = 0; k < namedValues.length; ++k) {
var namedValue = namedValues[k];
switch (namedValue.Name) {
case "$$DataSourceMetaData$$":
var dataSourceMetaData = namedValue.Value[0];
var dataSource = new filter.DataSource(dataSourceMetaData);
self.$$DataSourceMetaData$$ = dataSource;
break;
case "$$AttributeMetadata$$":
for (var m = 0; m < namedValue.Value.length; ++m) {
var inaAttributeMetaData = namedValue.Value[m];
if (!self[inaAttributeMetaData.Name]) {
self[inaAttributeMetaData.Name] = new ResultElementAttribute(self);
}
self[inaAttributeMetaData.Name].$$MetaData$$._fromInaJson(inaAttributeMetaData);
self[inaAttributeMetaData.Name].$$MetaData$$.displayOrder = m;
}
break;
case "$$ResultItemAttributes$$":
for (var l = 0; l < namedValue.Value.length; ++l) {
var inaAttribute = namedValue.Value[l];
if (!self[inaAttribute.Name]) {
self[inaAttribute.Name] = new ResultElementAttribute(self);
}
self[inaAttribute.Name]._fromInaJson(inaAttribute);
}
break;
case "$$RelatedActions$$":
var actions = {};
for (var n = 0; n < namedValue.Value.length; ++n) {
var action = namedValue.Value[n];
var sinaAction = new ResultElementRelatedAction();
sinaAction._fromInaJson(action);
actions[action.ID] = sinaAction;
}
self.$$RelatedActions$$ = actions;
break;
case "$$RenderingTemplateSpecification$$":
for (var o = 0; o < namedValue.Value.length; ++o) {
var template = new ResultElementRenderingTemplateSpecification();
template._fromInaJson(namedValue.Value[o]);
// template = propertiesToLowerCase(template);
if (template.type === "ItemDetails") {
self._detailTemplate = template; //save for later, so no 2nd request is needed
} else {
self.$$RenderingTemplateSpecification$$ = template;
}
}
break;
case "$$WhyFound$$":
for (var z = 0; z < namedValue.Value.length; ++z) {
var whyfoundElem = {};
whyfoundElem.label = namedValue.Value[z].Description;
whyfoundElem.labelRaw = namedValue.Value[z].Name;
whyfoundElem.value = namedValue.Value[z].Value;
whyfoundElem.valueHighlighted = whyfoundElem.value;
whyfoundElem.valueRaw = namedValue.Value[z].Value;
self.$$WhyFound$$.push(whyfoundElem);
}
break;
default:
// we assume thats a (HANA InA) result element:
self[namedValue.Name] = new ResultElementAttribute();
self[namedValue.Name].label = namedValue.Name || "";
self[namedValue.Name].valueRaw = namedValue.Value || namedValue.ValueFormatted || null;
self[namedValue.Name].value = namedValue.ValueFormatted || namedValue.Value || null;
}
}
for (var i = 0; i < this.$$PostProcessors$$.length; i++) {
this.$$PostProcessors$$[i]();
}
},
_registerPostProcessor: function(fn) {
this.$$PostProcessors$$.push(fn);
}
};
function _prepareDetails(element) {
// TODO: remove service workaround: if there is no detail query -> try to create
if (element._detailTemplate && !element.$$RelatedActions$$.$$DETAILS$$) {
element.$$RelatedActions$$.$$DETAILS$$ = {
request: new module.SearchQuery(),
description: '',
encodedJSON: '',
type: 'Search',
uri: ''
};
}
// End of workaround
// prefill result set of detail query
if (element._detailTemplate && element.$$RelatedActions$$.$$DETAILS$$) {
var detailResultSet = new module.SearchResultSet();
detailResultSet.elements[0] = $.extend(true, {}, element);
detailResultSet.elements[0].$$RenderingTemplateSpecification$$ = element._detailTemplate;
detailResultSet.totalcount = 1;
delete detailResultSet.elements[0].$$RelatedActions$$.$$DETAILS$$;
element.$$RelatedActions$$.$$DETAILS$$.request.resultSet = detailResultSet;
return detailResultSet.elements[0];
}
// return function(onSuccess,onError){
// if(this._detailResultSet){
// if(onSuccess){
// onSuccess(this._detailResultSet);
// }
// }
// else{
// this.$$RelatedActions$$.$$DETAILS$$.request.getResultSet(onSuccess,onError);
// }
// };
return {};
}
var itemLists = {};
if (!data.ItemLists) {
return {};
}
for (var i = 0; i < data.ItemLists.length; i++) {
itemLists[data.ItemLists[i].Name] = data.ItemLists[i];
if (data.ItemLists[i].Name.toLowerCase() === "searchresult") {
this.totalcount = data.ItemLists[i].TotalCount.Value;
}
}
var axis0;
if (data && data.Grids && data.Grids[0] && data.Grids[0].Axes && data.Grids[0].Axes[0]) {
axis0 = data.Grids[0].Axes[0];
} else {
return {};
}
// only axes 0 is relevant for abap search results
for (var j = 0; j < axis0.Tuples.length; j++) {
var tuple = axis0.Tuples[j];
if (tuple === undefined) {
continue;
}
var element = new ResultElement();
for (var c = tuple.length - 1; c >= 0; c--) {
// for (var c = 0; c < tuple.length; c++) {
var dimension = axis0.Dimensions[c];
var tupleValueForDimension = tuple[c];
var itemlist = itemLists[dimension.ItemListName];
var namedValues = itemlist.Items[tupleValueForDimension].NamedValues;
element._fromInaJson(namedValues);
}
if (axis0 && axis0.Dimensions[1]) {
var dimensionMetaData = axis0.Dimensions[1];
var itemlistMetaData = itemLists[dimensionMetaData.ItemListName];
var pointer2MyMetaData = tuple[1];
if (itemlistMetaData && itemlistMetaData.Items && itemlistMetaData.Items[pointer2MyMetaData]) {
var namedValuesAttributeMetadata = itemlistMetaData.Items[pointer2MyMetaData].NamedValues[2];
if (namedValuesAttributeMetadata) {
element = this._postProcess4WhyFound(element, namedValuesAttributeMetadata.Value);
}
}
}
var detail = _prepareDetails(element);
this._postProcessRelatedAction(element);
if (detail) {
this._postProcessRelatedAction(detail);
}
this.elements.push(element);
}
return {};
},
/**
* Returns the elements of the result set.
* @memberOf sap.bc.ina.api.sina.impl.inav2.sina_impl.SearchResultSet
* @instance
* @since SAP HANA SPS 06
* @return {Array} A list of result set elements.
* @example
* var query = sap.bc.ina.api.sina.createSearchQuery({
dataSource : { schemaName : "SYSTEM",
objectName : "J_EPM_PRODUCT" },
attributes : [ "PRODUCT_ID",
"TEXT",
"CATEGORY",
"PRICE",
"CURRENCY_CODE"],
searchTerms : "basic",
top : 5
});
* var resultSet = query.getResultSetSync();
* var elements = resultSet.getElements();
* // contents of elements (shortened):
* [{ "PRODUCT_ID":{"label":"PRODUCT_ID","valueRaw":"HT-1000","value":"HT-1000"},
* "TEXT":{"label":"TEXT","valueRaw":"Notebook Basic 15 with 1,7GHz - 15","value":"Notebook Basic 15 with 1,7GHz - 15"},
* "CATEGORY":{"label":"CATEGORY","valueRaw":"Notebooks","value":"Notebooks"},
* "PRICE":{"label":"PRICE","valueRaw":"956.00","value":"956.00"},
* "CURRENCY_CODE":{"label":"CURRENCY_CODE","valueRaw":"EUR","value":"EUR"}},
* // second result item:
* {"PRODUCT_ID":{"label":"PRODUCT_ID","valueRaw":"HT-1001","value":"HT-1001"},
* "TEXT":{"label":"TEXT","valueRaw":"Notebook Basic 17 with 1,7GHz - 17","value":"Notebook Basic 17 with 1,7GHz - 17"},
* "CATEGORY":{"label":"CATEGORY","valueRaw":"Notebooks","value":"Notebooks"},
* "PRICE":{"label":"PRICE","valueRaw":"1249.00","value":"1249.00"},
* "CURRENCY_CODE":{"label":"CURRENCY_CODE","valueRaw":"EUR","value":"EUR"}},
* // third result item:
* {"PRODUCT_ID":{"label":"PRODUCT_ID","valueRaw":"HT-1002","value":"HT-1002"},
* "TEXT":{"label":"TEXT","valueRaw":"Notebook Basic 18 with 1,7GHz - 18","value":"Notebook Basic 18 with 1,7GHz - 18"},
* "CATEGORY":{"label":"CATEGORY","valueRaw":"Notebooks","value":"Notebooks"},
* "PRICE":{"label":"PRICE","valueRaw":"1570.00","value":"1570.00"},
* "CURRENCY_CODE":{"label":"CURRENCY_CODE","valueRaw":"USD","value":"USD"}},
* // fourth result item:
* {"PRODUCT_ID":{"label":"PRODUCT_ID","valueRaw":"HT-1003","value":"HT-1003"},
* "TEXT":{"label":"TEXT","valueRaw":"Notebook Basic 19 with 1,7GHz - 19","value":"Notebook Basic 19 with 1,7GHz - 19"},
* "CATEGORY":{"label":"CATEGORY","valueRaw":"Notebooks","value":"Notebooks"},
* "PRICE":{"label":"PRICE","valueRaw":"1650.00","value":"1650.00"},
* "CURRENCY_CODE":{"label":"CURRENCY_CODE","valueRaw":"EUR","value":"EUR"}},
* // fifth result item:
* {"PRODUCT_ID":{"label":"PRODUCT_ID","valueRaw":"HT-8000","value":"HT-8000"},
* "TEXT":{"label":"TEXT","valueRaw":"1,5 Ghz, single core, 40 GB HDD, Windows Vista Home Basic, 512 MB RAM","value":"1,5 Ghz, single core, 40 GB HDD, Windows Vista Home Basic, 512 MB RAM"},
* "CATEGORY":{"label":"CATEGORY","valueRaw":"Notebooks","value":"Notebooks"},
* "PRICE":{"label":"PRICE","valueRaw":"799.00","value":"799.00"},
* "CURRENCY_CODE":{"label":"CURRENCY_CODE","valueRaw":"EUR","value":"EUR"}}
* ]
*/
getElements: function() {
return this.elements;
},
_postProcessRelatedAction: function(element) {
if (!element.$$RelatedActions$$) {
return;
}
for (var relatedActionID in element.$$RelatedActions$$) {
var relatedAction = element.$$RelatedActions$$[relatedActionID];
//Postprocessing
if (relatedAction.type === "Search") {
global.sap.bc.ina.api.sina._postprocess(relatedAction, element.title);
}
}
},
_postProcess4WhyFound: function(element, metaAttributes) {
if (element.$$WhyFound$$ && element.$$WhyFound$$.length > 0) {
var i = element.$$WhyFound$$.length;
var value;
var hasResponseAttribute;
while (i--) {
hasResponseAttribute = false;
if (element[element.$$WhyFound$$[i].labelRaw] !== undefined && metaAttributes !== undefined) {
//// value = element.$$WhyFound$$[i].value.replace(/<b>/g, '<div class="InA-highlighter" data-sap-widget="highlighter">').replace(/<\/b>/g, '</div">');
// value = element.$$WhyFound$$[i].value;
// element[element.$$WhyFound$$[i].labelRaw].value = value;
// element[element.$$WhyFound$$[i].labelRaw].valueRaw = value;
// element.$$WhyFound$$.splice(i,1);
var j = metaAttributes.length;
while (j--) {
// The WhyFound attributes are requst attributes. Try to get its corresponding response attribute
if (metaAttributes[j].Name === element.$$WhyFound$$[i].labelRaw && metaAttributes[j].correspondingSearchAttributeName) {
element.$$WhyFound$$[i].labelRaw = metaAttributes[j].correspondingSearchAttributeName;
hasResponseAttribute = true;
}
}
}
// if (!hasResponseAttribute){
// element.$$WhyFound$$[i].label = element.$$WhyFound$$[i].label + " (modeling error: add missing corresponding response attribute!)";
// }
}
}
return element;
}
};
};
if (isXS) {
executeSinaImpl($.sap.bc.ina.api.sina.sinaxsjq.jq);
} else if (typeof define === "function" && define.amd && !global.sap.ushell) { // only concatenated sina is in ushell repo!
define(["jquery", "./filter", "../../sinabase", "./system", "./proxy"], function($) {
executeSinaImpl($);
});
} else {
executeSinaImpl();
}
}(typeof window === 'undefined' ? $ : window, typeof window === 'undefined'));