Source: filter.js

/*
 * @file Simple info access (SINA) API: Filter Interface
 * @namespace sap.bc.ina.api.sina.filter
 * @copyright Copyright (c) 2014 SAP AG. All rights reserved.
 * @ignore
 */

(function(global) {
    "use strict";

    if (global !== null) {
        global.sap = global.sap || {};
        global.sap.bc = global.sap.bc || {};
        global.sap.bc.ina = global.sap.bc.ina || {};
        global.sap.bc.ina.api = global.sap.bc.ina.api || {};
        global.sap.bc.ina.api.sina = global.sap.bc.ina.api.sina || {};

        global.sap.bc.ina.api.sina.expandPackage = function(global, packageName) {
            var structure = packageName.split('.');
            var walker = global;
            for (var ii = 0; ii < structure.length; ii++) {
                if (typeof walker[structure[ii]] === 'undefined') {
                    walker[structure[ii]] = {};
                }
                walker = walker[structure[ii]];
            }
        };
    }
}(typeof window === 'undefined' ? null : window));

(function(global, isXS) {

    "use strict";

    var executeFilter = function($) {
        if (!$)
        {
            $ = global.$;
        }

        // =========================================================================
        // create packages
        // =========================================================================

        if (!isXS) {
            global.sap.bc.ina.api.sina.expandPackage(global, 'sap.bc.ina.api.sina.filter');
        }

        var filter = global.sap.bc.ina.api.sina.filter;
        var module = filter;
        module.DataSource = function(){this.init.apply(this,arguments);};
        module.DataSourceMetaData = function(){this.init.apply(this,arguments);};
        module.Filter = function(){this.init.apply(this,arguments);};
        module.Condition = function(){this.init.apply(this,arguments);};
        module.ConditionGroup = function(){this.init.apply(this,arguments);};

        // =========================================================================
        // class datasource metadata
        // =========================================================================
        module.DataSourceMetaData.prototype = {
            init : function(){}
        };

        // =========================================================================
        // class datasource
        // =========================================================================
        module.DataSource.prototype = {

            /**
             * A generic data source for a query.
             * @constructs sap.bc.ina.api.sina.filter.DataSource
             * Use {sap.bc.ina.api.sina.sinabase.createDataSource} factory instead of this constructor.
             * @private
             */
            init : function(){},

              /**
             * Compares this datasource with another datasource.
             * @memberOf sap.bc.ina.api.sina.filter.DataSource
             * @instance
             * @param  {sap.bc.ina.api.sina.impl.inav2.filter.DataSource} the other datasource to be
             * compared against this datasource.
             * @return {boolean} true if they are equal, false otherwise
             */
            equals : function(otherDS){
            },

            /**
             * Returns the metadata for this data source asynchronously from the server.
             * @ignore
             * @memberOf sap.bc.ina.api.sina.filter.DataSource
             * @instance
             * @param  {Function} callback Function will be called after the meta data arrives
             * from the server. This function must have one argument through which it will
             * receive the metadata object.
             */
            getMetaData : function(callback){
            },

            /**
             * Returns the metadata for this data source synchronously from the server.
             * @ignore
             * @memberOf sap.bc.ina.api.sina.filter.DataSource
             * @instance
             * Warning: Calling the function will block the javascript thread until
             * a result has been received.
             * @return {sap.bc.ina.api.sina.impl.inav2.filter.DataSourceMetaData} The metadata for this datasource.
             */
            getMetaDataSync : function(){
            },

            getLabel : function(){
            },

            setLabel : function(label){
            }

        };

        // =========================================================================
        // class filter
        // =========================================================================
        module.Filter.prototype = {

            /**
             * A simple filter for SINA queries.
             * Use sina.createFilter() method instead of this private constructor.
             * @constructs sap.bc.ina.api.sina.filter.Filter
             * @param  {Object} properties Configuration object.
             * @private
             * @since SAP HANA SPS 06
             * @ignore
             */
            init : function(properties){
                properties = properties||{};
                this.setDataSource(properties.dataSource,false);
                this.root = null;
                this.conditionGroupsByAttribute = {};
                this.defaultConditionGroup = new module.ConditionGroup({ operator : 'And' });
                this.searchTerms = "";
            },

            addFilterConditionGroup : function(conditionGroup){
                this.defaultConditionGroup.addCondition(conditionGroup);
            },

            /**
             * Adds a filter condition to the current set of filter conditions. By default
             * conditions of the same attribute will be 'OR'ed. Conditions between different
             * attributes will have an 'AND' operator.
             * @ignore
             * @memberOf sap.bc.ina.api.sina.filter.Filter
             * @instance
             * @since SAP HANA SPS 06
             * @param {String} attribute            Technical identifier of the attribute, as defined in the database.
             * @param {String} operator             Operator of the filter condition. The default value is "=".
             * @param {String} value                Value that should be filtered within the attribute.
             */
            addFilterCondition : function(attribute, operator, value) {
                // To be implemented by data provider
                return this;
            },

            getFilterConditions : function(){
                return this.defaultConditionGroup;
            },

            getSearchTerms : function(){
                return this.searchTerms;
            },

            hasFilterCondition : function(attribute, operator, value){
                return this.defaultConditionGroup.hasCondition(new module.Condition(attribute, operator, value));
            },

            empty : function() {
                // To be implemented by data provider
                return this;
            },

            /**
             * Gets the data source that is currently in use by the filter instance.
             * @return {sap.bc.ina.api.sina.filter.DataSource} The data source instance.
             */
            getDataSource : function(){
                return this.dataSource;
            },

            removeFilterCondition : function(attribute, operator, value){
                // To be implemented by data provider
                return this;
            },

            setSearchTerms : function(searchTerms){
                this.searchTerms = searchTerms;
            },

            /**
             * Sets the data source for the filter.
             * @param dataSource A SINA data source.
             */
            setDataSource : function(dataSource){
                this.dataSource = dataSource;
            },

            getJson : function() {
                // To be implemented by data provider
            }

        };

        // =========================================================================
        // class condition
        // =========================================================================
        module.Condition.prototype = {

            /**
             * Creates a new filter condition.
             * @ignore
             * @constructs sap.bc.ina.api.sina.impl.inav2.filter.Condition
             * @param {String|Object} attribute     Technical identifier of the attribute, as defined in the database.
             * If the type is Object, this object can have properties with the name and value of the arguments.
             * @param {String} operator             Operator of the filter condition. The default value is "=".
             * @param {String} value                Value that should be filtered in the attribute.
            */
            init : function(attribute,operator,value) {
                if ($.type(attribute)==='object') {
                    var props = attribute;
                    attribute = props.attribute;
                    operator = props.operator;
                    value = props.value;
                }
                this.attribute = attribute || "";
                this.operator = operator || "=";
                this.value = value;
            },

            equals : function(otherCondition){
                return  this.attribute.toLowerCase()===otherCondition.attribute.toLowerCase()&&
                        this.operator===otherCondition.operator&&
                        this.value.toLowerCase()===otherCondition.value.toLowerCase();
            },

            getJson : function(parent) {
                // implement in provider
            },

            setJson : function(json){
                // implement in provider
            },

            toString : function(){
                return this.attribute+this.operator+this.value+'';
            }

        };


        // =========================================================================
        // class condition group
        // =========================================================================
        module.ConditionGroup.prototype = {

            init : function(properties) {
                properties = properties || {};
                this.label = properties.label || '';
                this.conditions = properties.conditions || [];
                this.setOperator(properties.operator || 'And');
            },

            addCondition : function(condition) {
                this.conditions.push(condition);
                return this;
            },

            getConditions : function(){
                return this.conditions;
            },

            getConditionsAsArray : function(group,conditions){
                conditions = conditions || [];
                group = group || this;
                for (var i = 0; i < group.conditions.length; i++) {
                    if(group.conditions[i] instanceof module.ConditionGroup){
                        this.getConditionsAsArray(group.conditions[i],conditions);
                    }
                    else {
                        conditions.push(group.conditions[i]);
                    }
                }
                return conditions;
            },

            hasCondition : function(condition){
                var found = false;
                for (var i = 0, len = this.conditions.length; i < len; i++) {
                    var item = this.conditions[i];
                    if(item instanceof module.ConditionGroup){
                        found = item.hasCondition(condition);
                    }
                    else {
                        if(item.equals && item.equals(condition)){
                            found = true;
                        }
                    }
                    if(found===true){
                        break;
                    }
                }
                return found;
            },

            removeCondition : function(condition){
                this.conditions.splice(this.conditions.indexOf(condition),1);
                return this;
            },

            setLabel : function(label){
                this.label = label;
                return this;
            },

            setOperator : function(operator){
                switch (operator.toLowerCase()){
                    case 'or':
                        operator = 'Or';
                        break;
                    case 'and':
                        operator = 'And';
                        break;
                    default:
                        throw { message: 'unknown operator for condition group: '+operator };
                }
                this.operator = operator;
                return this;
            },

            toString : function(){
                return this.label;
            },

            getJson : function(parent) {
                // implement in provider
            },

            setJson : function(json) {
                // implement in provider
            }

        };
    };

    if (isXS) {
        executeFilter($.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"], function($){
            executeFilter($);
        });
    }
    else {
        executeFilter();
    }

}(typeof window === 'undefined' ? $ : window, typeof window === 'undefined'));