Util.insertProto =
function /* insertProto */( obj, newProto )
{
  if ( obj.__proto__ == newProto ) return;
  var oldProto = obj.__proto__;
  obj.__proto__ = newProto;
  while( newProto.__proto__.constructor != Object )
    newProto = newProto.__proto__;
  newProto.__proto__ = oldProto;
}

Util.concatProto =
function /* concatProto */( obj, newProto )
{
  if ( obj.__proto__ == newProto ) return;
  var pObj = obj;
  while( pObj.__proto__ != null )
    {
      obj = pObj;
      pObj = obj.__proto__;
      if ( pObj == Function.prototype ) {
  obj.__proto__ = newProto;
  //Util.concatProto( newProto, Function );
  return;
      }
      if ( pObj == newProto ) return;
    }
  obj.__proto__ = newProto;
}

Util.concatParent =
function /* concatParent */( obj, newParent )
{
  if ( obj.__parent__ == newParent ) return;
  var pObj = obj;
  while( pObj.__parent__ != null )
    {
      obj = pObj;
      pObj = obj.__parent__;
      if ( pObj == newParent ) return;
    }
  obj.__parent__ = newParent;
}

Util.isInInstance =
function /* isInInstance */( o, prop )
{
  // Otra implementacion -- tiene problemas con los arrays
  //dirty hack para arrays vacias
  var isEmptyArray = ( ( o.constructor == Array ) && ( o.length == 0 ) );

  if ( (o == null) || (typeof o == "undefined") )
    return false;
  var oProto = o.__proto__;
  o.__proto__ = null;
  var result = this.isOkClean( o, prop );
  o.__proto__ = oProto;

  //dirty hack para arrays vacias
  if ( isEmptyArray )
    o.pop();

  return result;
}

Util.instanceOf =
function /* instanceOf */( object, constructor )
{
  while ( object != null )
    {
      if ( object == constructor.prototype )
  return true;
      object = object.__proto__;
    }
  return false;
}

Util.getInstanceProperties =
function /* getInstanceProperties */( obj )
{
  var proto = obj.__proto__;
  var result = [];
  obj.__proto__ = null;
  for ( var i in obj )
    result[ result.length ] = i;
  obj.__proto__ = proto;
  return result;
}

Util.getInstancePropertiesAsHTML =
function /* getInstancePropertiesAsHTML */( obj )
{
  var props = this.getInstanceProperties( obj );
  var result = '';
  for ( var i = 0; i < props.length; i++ )
    result += props[ i] + '<br>\n';
  return result;
}

Util.objectClone =
function /* objectClone */( o ) {
  var o2 = {};
  var proto = o.__proto__;
  o2.__proto__ = proto;
  for ( var p in o ) {
    if ( this.isOkClean( proto, p ) ) continue;
    var pv = o[p];
    if ( pv == proto ) continue;
    o2[ p ] = pv;
  }
 return o2;
}

Util.displayObjectStruct =
function /* displayObjectStruct */( o, s, ind ) {
  if ( ! ind ) ind = "";
  var result = '';
  if ( s ) result += s + ": " + (typeof o) + " ";
  if ( Util.isAny(o) ) {
    if ( o.__proto__ == Object.prototype ) {
      result += "[" + "Object"+ "]" + "<br>\n";
    } else {
      result += "<br>\n";
      result += ind + "constructor: " + Util.getConstructorName(o) + "<br>\n";
      result += ind + "__proto__ -> " + arguments.callee( o.__proto__, s + '.__proto__', ind + "----" );
      result += ind + "__parent__ -> " + arguments.callee( o.__parent__, s + '.__parent__', ind + "----" );
    }
  } else {
    result += "null" + "<br>\n";
  }
  return result;
}

Util.clone =
function /* clone */( o )
{
   var cloned;
  if ( Util.isObject( o ) ) {
     return Util.object_clone( o );
  }
  if ( Util.isArray( o ) ) {
     return Util.array_clone( o );
  }
  if ( Util.isString( o ) ) {
     return new String( o );
  }
  return o;
}


Util.object_clone =
function /* object_clone */( o )
{
   if ( Util.isOk( o.length ) ) {
      return Util.array_clone( o );
   }
   var cloned = {};
   for( var p in o ) {
      cloned[p] = Util.clone(o[p]);
   }
   return cloned;
}

Util.array_clone =
function /* array_clone */( o )
{
   var cloned = [];
   for(var i=0; i<o.length; i++){
      cloned[i] = Util.clone(o[i]);
   }
   return cloned;
}
