# Source: core/Object.js

    /*
     * Helma License Notice
     *
     * The contents of this file are subject to the Helma License
     * Version 2.0 (the "License"). You may not use this file except in
     * compliance with the License. A copy of the License is available at
     * http://adele.helma.org/download/helma/license.txt
     *
     * Copyright 1998-2006 Helma Software. All Rights Reserved.
     *
     * $RCSfile: Object.js,v $
     * $Author$
     * $Revision$
     * $Date$
     */

    /**
     * @fileoverview Adds useful methods to the JavaScript Object type.
     * <br /><br />
     * To use this optional module, its repository needs to be added to the
     * application, for example by calling app.addRepository('modules/core/Object.js')
     */

    app.addRepository('modules/core/Global.js');

    /**
     * Copies the properties of this object into a clone.
     * @external
     * @memberof {Object}
     * @param {Object} clone The optional target object
     * @param {Boolean} recursive If true child objects are cloned as well, otherwise
     * the clone contains references to the child objects
     * @returns The resulting object
     */
    Object.prototype.clone = function(clone, recursive) {

        var getValue = function(value, recursive) {
            if (recursive !== true || value == null
                    || (typeof (value) !== "object" && typeof (value) !== "function")) {
                return value;
            }
            return value.clone(null, recursive);
        };

        if (typeof (this) === "object") {
            if (this === null) {
                return null;
            }
            switch (this.constructor) {
                case String:
                case Number:
                case Boolean:
                case Date:
                    return new this.constructor(this.valueOf());

                case Array:
                    return this.map(function(value) {
                        return getValue(value, recursive);
                    });

                default:
                    if (clone == null) {
                        clone = new this.constructor();
                    }
                    for ( var propName in this) {
                        clone[propName] = getValue(this[propName], recursive);
                    }
                    return clone;
            }
        } else if (typeof (this) === "function" && this.constructor === RegExp) {
            return new RegExp(this.valueOf());
        }
        return this;
    };

    /**
     * reduce an extended object (ie. a HopObject)
     * to a generic javascript object
     * @external
     * @memberof {Object}
     * @param HopObject the HopObject to be reduced
     * @return Object the resulting generic object
     */
    Object.prototype.reduce = function(recursive) {
        var result = {};
        for (var i in this) {
            if (this[i] instanceof HopObject == false)
                result[i] = this[i];
            else if (recursive)
                result[i] = this.reduce(true);
        }
        return result;
    };

    /**
     * print the contents of an object for debugging
     * @external
     * @memberof {Object}
     * @param Object the object to dump
     * @param Boolean recursive flag (if true, dump child objects, too)
     */
    Object.prototype.dump = function(recursive) {
        var beginList = "<ul>";
        var endList = "</ul>";
        var beginItem = "<li>";
        var endItem = "</li>";
        var beginKey = "<strong>";
        var endKey = ":</strong> ";
        res.write(beginList);
        for (var p in this) {
            res.write(beginItem);
            res.write(beginKey);
            res.write(p);
            res.write(endKey);
            if (recursive && typeof this[p] == "object") {
                var recurse = true;
                var types = [Function, Date, String, Number];
                for (var i in types) {
                    if (this[p] instanceof types[i]) {
                        recurse = false
                        break;
                    }
                }
                if (recurse == true)
                    this[p].dump(true);
                else {
                    res.write(this[p].toSource());
                }
            } else if (this[p]) {
                res.write(encode(this[p].toSource()));
            }
            res.write(endItem);
        }
        res.write(endList);
        return;
    };

    // prevent any newly added properties from being enumerated
    for (var i in Object)
       Object.dontEnum(i);
    for (var i in Object.prototype)
       Object.prototype.dontEnum(i);