﻿/* ---------------------------------------------------------
 * ObjectOrientedLayer是基于Prototype工具包的JS面向对象实现
 * (c) 2007 verTEars
 * ---------------------------------------------------------
 *   _using(string _namespace)
 *
 *     用于include一个名为_namespace的js文件，
 *     如果_namespace使用点式，则最后一个节点为文件名，
 *     其它节点为目录名。
 *
 *   _namespace()
 *    
 *     用于创建命名空间。
 *
 *   _class(object classBody, _class baseArgs)
 *
 *     用于创建一个成员为classBody的类，
 *     如果带有参数baseArgs则创建一个继承自baseArgs的类，
 *     可以多重继承。
 *
 *   _class.eventBind(function funcBody)
 *      
 *      用于在类定义时绑定事件处理函数
 *
 *   _abstract(object classBody, _class baseArgs)
 *
 *     用于创建抽象类，抽象类也可以继承一个或多个baseArgs；
 *     如果试图实体化抽象类，运行时将抛出一个异常。
 *
 *   _abstract.method()
 *
 *     用于创建抽象方法，抽象方法必须被覆盖；
 *     如果不覆盖抽象方法，运行时将抛出一个异常。
 *
 *   _interface(object interfaceBody)
 *
 *     用于创建接口；如果试图实体化接口，
 *     运行时将抛出一个异常。
 *
 *   _interface.method()
 *
 *     用于创建接口方法，接口方法必须被实现；
 *     如果不实现接口方法，运行时将抛出一个异常。
 * 
 ---------------------------------------------------------*/
 
if((typeof Prototype=='undefined') || 
   (typeof Element == 'undefined') || 
   (typeof Element.Methods=='undefined') ||
   parseFloat(Prototype.Version.split(".")[0] + "." +
              Prototype.Version.split(".")[1]) < 1.5)
   throw("ObjectOrientedLayer需要Prototype工具包 1.5.0 以上版本"); 

var _namespaceList = []; //记录被定义的命名空间，防止重复定义。
var _usingList = []; //记录被引用的命名空间，防止重复引用。

var _using = function(/*string*/ _namespace){
    var have = false;
    for(var i = 0; i < _usingList.length; i++){
        if(_usingList[i] == _namespace){
            have = true;
            break;
        }
    }
    if(!have){
        var script = document.getElementsByTagName("script");
        for(var i = 0; i < script.length; i++){
            var s = script[i];
            if(s.src && s.src.match(/ObjectOrientedLayer\.js(\?.*)?$/)){
                var path = s.src.replace(/ObjectOrientedLayer\.js(\?.*)?$/,'');
                document.write('<script type="text/javascript" src="' + path + _namespace.replace('.', '/') + '.js"></script>');
                break;
            }
        }
        _usingList[_usingList.length] = _namespace;
    }
}

var _createNamespace = function(){
    return function() {
        throw("命名空间不能被运行！");
    }
}

var _namespace = function(/*string*/ _namespace){
    var n = _namespace.split('.');
    for(var i = 0; i < n.length; i++){
        var nameSpace = '';
        var firstchild = true;
        for(var j = 0; j <= i; j++){
            if(firstchild){
                nameSpace += n[j];
                firstchild = false;
            }else
                nameSpace += '.' + n[j];
        }
        var have = false;
        for(var j = 0; j < _namespaceList.length; j++){
            if(_namespaceList[j] == nameSpace){
                have = true;
                break;
            }
        }
        if(!have){
            eval(nameSpace + ' = _createNamespace();');
            _namespaceList[_namespaceList.length] = nameSpace;
        }
    }
}

var _base = function(destination, source) {
    for (var property in source) {
        if(typeof(source[property]) == 'function')
            destination["base_" + property] = source[property];
    }
    return destination;
}
    
var _class = function(/*object*/ classBody, /*_class || _interface*/ baseArgs){
    var c = Class.create();
    for(var i = arguments.length - 1; i > 0; i--){
        Object.extend(c.prototype, arguments[i].prototype);
        _base(c.prototype, arguments[i].prototype);
    }
    c.prototype.initialize = function(){};
    Object.extend(c.prototype, classBody);
    return c;
}
_class.eventBind = function(funcBody){
    return function(event){
        event = event || window.event;
        funcBody(event);
    }
}

var _abstract = function(/*object*/ classBody, /*_class*/ baseArgs){
    function _create(){
        return function() {
            throw("抽象类不能被实体化！");
        }
    }
    var c = _create();
    for(var i = arguments.length - 1; i > 0; i--){
        Object.extend(c.prototype, arguments[i].prototype);
        _base(c.prototype, arguments[i].prototype);
    }
    c.prototype.initialize = function(){};
    Object.extend(c.prototype, classBody);
    return c;
}
_abstract.method = function(){
    return function() {
        throw("抽象方法必须被覆盖！");
    }
}



var _interface = function(/*object*/ interfaceBody){
    function _create(){
        return function() {
            throw("接口不能被实体化！");
        }
    }
    var i = _create();
    Object.extend(i.prototype, interfaceBody);
    return i;
}
_interface.method = function(){
    return function() {
        throw("接口方法必须被实现！");
    }
}