function validKey(key) {
  if (key == "equals") return false;
  if (key == "hashCode") return false;
  return true;
}

Object.prototype.equals = function(object) {
  return (this == object && (typeof(this) == typeof(object)));
};

String.prototype.equals = function(object) {
  return (this+"" == object+"");
};

String.prototype.trim = function() {
  var str = new String(this.toString());
  var textRE1 = /^\s*([^\s][^\0]*)$/;
  var textRE2 = /^([^\0]*[^\s])\s*$/;

  if (textRE1.test(str)) {
    str = RegExp.$1;
  }
  if (textRE2.test(str)) {
    str = RegExp.$1;
  }
  return str;
};


Array.prototype.add = function(object) {
  this.push(object);
  return true;
}

Array.prototype.addAll = function(array) {
  var changed = false;
  for (var i in array) {
    changed = this.add(array[i]) || changed;
  }
  return changed;
}

Array.prototype.removeAll = function(array) {
  var changed = false;
  for (var i in array) {
    changed = this.remove(array[i]) || changed;
  }
  return changed;
}

Array.prototype.retainAll = function(array) {
  var changed = false;
  for (var i in array) {
    var el = array[i];
    if (!collection.contains(el)) {
      changed = true;
      i.remove();
    }
  }
  return changed;
}


Array.prototype.addAtIndex = function(index, object) {
  if ((index < 0) || (index > this.size())) {
    throw new Error("Index is out of bounds");
  }
  this.splice(index, 0, object);
}

Array.prototype.set = function(index, object) {
  if (index < 0 || index >= this.size()) {
    throw new Error("Index is out of bounds");
  }
  var oldValue = this[index];
  this[index] = object;
  return oldValue;
}

Array.prototype.contains = function(object) {
  for (var i=0; i<this.length; i++) {
    if (object.equals(this[i])) {
      return true;
    }
  }
  return false;
}

Array.prototype.remove = function(object) {
  for (var i=0; i<this.length; i++) {
    if (object.equals(this[i])) {
      this.removeAtIndex(i);
      return true;
    }
  }
  return false;
}

Array.prototype.removeAtIndex = function(index) {
  if (index < 0 || index >= this.size()) {
    throw new Error("Index is out of bounds");
  }
  var oldValue = this[index];
  this.splice(index, 1);
  return oldValue;
}

Array.prototype.size = function() {
  return this.length;
}

Array.prototype.get = function(index) {
  if (index < 0 || index >= this.size()) {
    throw new Error("Index is out of bounds");
  }
  return this[index];
}

Array.prototype.indexOf = function(object) {
  for (var i=0; i<this.length; i++) {
    if (object.equals(this[i])) {
      return i;
    }
  }
  return -1;
}

Array.prototype.clear = function() {
  this.splice(0, this.length);
}

Array.prototype.equals = function(list) {
  if (this.size() != list.size()) return false;

  for (var i=0; i<this.size(); i++) {
    var e1 = this.get(i);
    var e2 = list.get(i);
    if (e1 == null) {
      if (e2 != null) return false;
    }
    else {
      if (!e1.equals(e2)) return false;
    }
  }
  return true;
}

Array.prototype.join = function(delimiter) {
  if (this.length == 0) return "";

  var ret = "";
  for (var i=0; i<this.length; i++) {
    ret += this[i] + delimiter;
  }
  return ret.substring(0, ret.length-delimiter.length);
}
