代码改变世界

JSON 模式匹配 Dispatcher

2010-07-15 14:54 by Cat Chen, ... 阅读, ... 评论, 收藏,  编辑
(function() {
    
var Dispatcher = window.Dispatcher = {};
    
    
var operators = Dispatcher.Operators = {};
    
    operators[
""= function(testValue, value) {
        
if (testValue instanceof Array) {
            
return operators["in"].apply(this, arguments);
        } 
else if (testValue instanceof RegExp) {
            
return operators["re"].apply(this, arguments);
        } 
else if (testValue instanceof Function) {
            
return operators["ld"].apply(this, arguments);
        } 
else {
            
return operators["eq"].apply(this, arguments);
        }
    };
    
    operators[
"eq"= function(testValue, value) {
        
if (arguments.length < 2) {
            
return false;
        }
        
if (testValue === null || testValue === undefined || value === null || value === undefined) {
            
return (value === testValue);
        }
        
switch (testValue.constructor) {
            
case String:
            
case Number:
            
case Boolean:
                
if (testValue.constructor != value.constructor) {
                    
return false;
                }
                
return value == testValue && value.constructor == testValue.constructor;
            
default:
                
if (testValue instanceof Array) {
                    
if (!(value instanceof Array)) {
                        
return false;
                    }
                    
if (value.length != testValue.length) {
                        
return false;
                    }
                    
for (var i = 0; i < testValue.length; i++) {
                        
if (!operators["eq"](testValue[i], value[i])) {
                            
return false;
                        }
                    }
                    
return true;
                } 
else {
                    
if (!(value instanceof Object)) {
                        
return false;
                    }
                    
/* assuming that something is neither String, Number, Boolean, nor Array is Object */
                    
for (var key in testValue) {
                        
var index = key.lastIndexOf("$");
                        
var valueKey;
                        
var childValue;
                        
var childTestValue = testValue[key];
                        
var operator;
                        
if (index < 0) {
                            valueKey 
= key;
                            operator 
= "";
                        } 
else {
                            valueKey 
= key.substr(0, index);
                            operator 
= key.substr(index + 1);
                        }
                        
if (operators[operator]) {
                            
if (valueKey in value) {
                                childValue 
= value[valueKey];
                                
if (!operators[operator](childTestValue, childValue)) {
                                    
return false;
                                }
                            } 
else {
                                
if (!operators[operator](childTestValue)) {
                                    
return false;
                                }
                            }
                        } 
else {
                            
throw "operator doesn't exist: " + operator;
                        }
                    }
                    
return true;
                }
        }
    };
    
    operators[
"ne"= function(testValue, value) { return arguments.length == 2 && !operators["eq"](testValue, value); };
    operators[
"lt"= function(testValue, value) { return arguments.length == 2 && value < testValue; };
    operators[
"lte"= function(testValue, value) { return arguments.length == 2 && value <= testValue; };
    operators[
"gt"= function(testValue, value) { return arguments.length == 2 && value > testValue; };
    operators[
"gte"= function(testValue, value) { return arguments.length == 2 && value >= testValue; };
    
    
var createFilter = function(condition) {
        
return function(json) {
            
if (arguments.length > 0) {
                
return operators[""](condition, json);
            } 
else {
                
return operators[""](condition);
            }
        };
    };

    
var filterHandlerBundles = [];

    Dispatcher.capture 
= function(filter, handler) {
        
if (!(filter instanceof Function)) {
            filter 
= createFilter(filter);
        }
        filterHandlerBundles.push({
            filter: filter,
            handler: handler
        });
    };

    Dispatcher.notify 
= function(json) {
        
for (var i = 0; i < filterHandlerBundles.length; i++) {
            
if (filterHandlerBundles[i].filter.apply(this, arguments)) {
                filterHandlerBundles[i].handler(json);
            }
        }
    };
    
    Dispatcher.extend(Dispatcher);
})();