/*
 * HashSet is a collection objects
 * It makes no guarantees as to the iteration order of the set;
 */

function HashSet(){
	this.objects = new Array();
	this.type = "HashSet";
}

HashSet.prototype.add = function( obj ){
   if(typeof(obj) == "object"){
   		this.objects.push( obj );
   		return true;
   }else{
   		return false;
   }
}

HashSet.prototype.addAll = function( col ){
	var type = getExactType(col);
	if(type == "HashSet" || type == "ObjectSet"){
		var a = col.toArray();
		for(var i = 0; i < a.length; i++){
			this.add(a[i]);
		}
		return true;
	}else{
		return false;
	}
}

HashSet.prototype.clear = function(){
   this.objects = new Array();
}

HashSet.prototype.cloneObject = function(){
   var newHashSet = new HashSet();
   for(var i = 0; i < this.objects.length; i++){
		newHashSet.add(this.objects[i]);
	}
	return newHashSet;
}

HashSet.prototype.contains = function(obj){
	for(var i = 0; i < this.objects.length; i++){
		if (obj == this.objects[i]) {
			return true;
		}
	}
	return false;
}

HashSet.prototype.containsAll = function( col ){
	var type = getExactType(col);
	if(type == "HashSet" || type == "ObjectSet"){
		var a = col.toArray();
		var result = true;
		for(var i = 0; i < a.length; i++){
			if(!this.contains(a[i])){
				return false;
			}
		}
		return result;
	}else{
		return false;
	}
}

HashSet.prototype.isEmpty = function(){
	return this.size() == 0;
}

HashSet.prototype.iterator = function(){
	return new Iterator(this);
}

HashSet.prototype.remove = function ( obj ){
   var temp = this.objects;
   this.objects = new Array();
   var result = false;
   for(var i = 0; i < temp.length; i++){
		if (obj != temp[i]) {
			this.objects.add(temp[i]);
		}else{
			result = true;
		}
	}
	return result;
}

HashSet.prototype.containsAll = function( col ){
	var type = getExactType(col);
	if(type == "HashSet" || type == "ObjectSet"){
		var a = col.toArray();
		var result = true;
		for(var i = 0; i < a.length; i++){
			if(!this.remove(a[i])){
				return false;
			}
		}
		return result;
	}else{
		return false;
	}
}

HashSet.prototype.size = function(){
   return this.objects.length;
}

HashSet.prototype.toArray = function(array){
	if (array == null){
   		array = new Array();
 	}
	if(typeof(array) != "Array"){
   		var array = new Array();
    }
    for(var i = 0; i < this.objects.length; i++){
		array.push(this.objects[i]);
	}
	return array;
}

HashSet.prototype.retainAll = function( col ){
	var type = getExactType(col);
	if(type == "HashSet" || type == "ObjectSet"){
		var tmp = new HashSet();
		for(var i = 0; i < this.objects.length; i++){
			if(!col.contains(this.objects[i])){
				tmp.add(this.objects[i]);
			}
		}
		return this.removeAll(tmp);
	}else{
		return false;
	}		
}

HashSet.prototype.toXML = function(){
	var xml = "";
	for(var i = 0; i < this.objects.length; i++){
        var obj = this.objects[i];
        if(typeof(obj.toXML) != "function"){
        	throw "can´t transform object of type "+getExactType(obj)+" to xml, because the type don´t implement a toXML method";
        }else{
        	xml += obj.toXML();
        }
    }
    if(xml != ""){
        xml = "<re4:objects>"+xml+"</re4:objects>";
    }
    xml = '<?xml version="1.0" encoding="utf-8"?><re4:'+this.type+' xmlns:re4="http://www.re4.com/XMLSchema">'+xml+'</re4:'+this.type+'>';
	return xml;
}

/*
 * ObjectSet is a collection of unique comparable objects 
 */

function ObjectSet(){
	this.objects = new Array();
	this.type = "ObjectSet";
}
        
// ObjectSet inherit HashSet
ObjectSet.prototype = new HashSet();

// overwrite add method
ObjectSet.prototype.add = function( obj ){
   if(typeof(obj) == "object"){
   		var pos = null;
   		for(var i = 0; i < this.objects.length; i++){
			if (obj == this.objects[i]) {
				pos = i;
        		break;
			}
		}
        if(pos != null){
        	this.objects[pos] = obj;
        }else{
        	this.objects.push(obj);
        }
        return true;
   }else{
   		return false;
   }
}

/*
 * Iterator
 */

function Iterator(col){
	this.items = col;
	this.position = 0;
	this.removeSupported = false;
	this.lastItem = -1;
}

Iterator.prototype.remove = function(){
   if(!this.removeSupported){
		throw "can´t remove object by iterator; because the next method has not yet been called, " + 
				"or the remove method has already been called after the last call to the next method";
	}else{
		this.removeSupported = false;
	}
	var a = this.items.toArray();
	var item = a[this.position];
	this.items.remove(item);
	this.lastItem = -1;
}

Iterator.prototype.hasNext = function(){
   var result = false;
	if(this.position < this.items.size()){
		result = true;
	}
	return result;
}

Iterator.prototype.getNext = function(){
   if(this.position < 0 && this.position >= this.items.size()){
		throw "the iteration has no next element";
	}
	var a = this.items.toArray();
	var item = a[this.position];
	this.removeSupported = true;
	this.lastItem = this.position;
	this.position++;
	return item;
}
