//var MdaradPrototype = Class.create();
//MdaradPrototype.prototype = {
//	selectById: function(id) {
//	    return find(function(s, value) {
//	        return s.@id == value;
//	    })
//	}
//};
//Object.extend(Enumerable.prototype, {
//    selectById: MdaradPrototype.selectById
//});
//Object.extend(Enumerable.prototype, Enumerable);
//
//Object.extend(Enumerable.prototype, {
//    selectById: function(id) {
//        return find(function(s, value) {
//            return s.@id == value;
//        })
//    }
//});

Element.addMethods( {
    selectById: function(value) {
		var object = this;
		if(object instanceof Array) {
			for(var i = 0; i < object.length; i++) {
			   var elem = array[i];
			   if(elem["@id"] == value) {
			       return elem;
			   }
			}
		} else if(object["@id"] != null && object["@id"] == value) {
			return object;
		}
		return null;
    }
});

//Element.addMethods({
//    selectById: function(id) {
//        return find(function(s, value) {
//            return s.@id == value;
//        })
//    }
//}); 


MdaradUtilsPrototype = Class.create();
MdaradUtilsPrototype.prototype = {
    initialize: function() {
    },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used to manipulate window or document
     *************************************************************************
     *************************************************************************
     *************************************************************************/        
    getVisibleHeight: function() {
        var height = window.innerHeight;
        if(!height || height < 0) {
            height = document.documentElement.clientHeight;
        }        
        if(!height || height < 0) {
            height = document.body.clientHeight;
        }
        return height;    
    },
    
    getVisibleWidth: function() {
        var width = window.innerWidth;
        if(!width || width < 0) {
            width = document.documentElement.clientWidth;
        }        
        if(!width || width < 0) {
            width = document.body.clientWidth;
        }
        return width;
    },
    
    changeImageSrc : function (elementId, imgSrc) {
        var element = $(elementId);
        element.src = imgSrc;
        
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used to navigate the DOM
     *************************************************************************
     *************************************************************************
     *************************************************************************/        
    findChild: function(childList, tagName) {
        for(var i = 0; i < childList.length; i++) {
            var child = childList[i];
            if(tagName && child.tagName) {
                if(child.tagName.toLowerCase() == tagName.toLowerCase()) {
                    return child;
                }
            }
        }
        return null;
    },
    
    findChildren: function(childList, tagName) {
        var childArray = new Array();
        for(var i = 0; i < childList.length; i++) {
            var child = childList[i];
            if(tagName && child.tagName) {
                if(child.tagName.toLowerCase() == tagName.toLowerCase()) {
                    childArray.push(child);
                } 
            }
        }
        return $A(childArray);
    },
    
    appendChildren: function(parent, childList) {
        if (parent && childList) {
            for(var i = 0; i < childList.length; i++) {
                var child = childList[i];
                parent.appendChild(child);
            }
         }
    },
    
    deleteChildren: function(parent, childList) {
        if ($(parent) && childList) {
            for(var i = 0; i < childList.length; i++) {
                var child = childList[i];
                parent.removeChild(child);
            }
        }
    },
    
    deleteAllChildren: function(element) {
        if(element) {
            while(element.firstChild) {
                element.removeChild(element.firstChild);
            }
        }
    },
    
    createXMLDocument: function () {
       try {
           if (document.implementation && document.implementation.createDocument) {
               var doc = document.implementation.createDocument("", "", null);
        
               // some versions of Moz do not support the readyState property
               // and the onreadystate event so we patch it!
               if (doc.readyState == null) {
                   doc.readyState = 1;
                   doc.addEventListener("load", function () {
                       doc.readyState = 4;
                       if (typeof doc.onreadystatechange == "function")
                           doc.onreadystatechange();
                   }, false);
               }
               return doc;
           }
           if (window.ActiveXObject) {
               return new ActiveXObject(MdaradUtils.getControlPrefix() + ".XmlDom");
           }
       } catch (ex) {}
       throw new Error("Your browser does not support XmlDocument objects");
    },

    getXMLFragment: function(requestObject, pathPrefix) {
        var returnedDataislandXMLDocument = null;
        //Not IE 
        if (document.implementation && document.implementation.createDocument){
            returnedDataislandXMLDocument = requestObject.responseXML;      
        } 
        //IE
        else if (window.ActiveXObject) {
            try {
                returnedDataislandXMLDocument = new ActiveXObject("MSXML.DomDocument");
            } catch(e) {
                try {
                    returnedDataislandXMLDocument = new ActiveXObject("Msxml2.XMLHTTP");
                } catch(e) {
                    try {
                        returnedDataislandXMLDocument = new ActiveXObject("Microsoft.XMLHTTP");
                    } catch(e) {
                        throw "The ActiveXObject could not be created when retrieving XML document: " + e;
                    }
                }
            }
            returnedDataislandXMLDocument.loadXML(requestObject.responseText);
        }

        var returnedXMLDocumentFragment = null;
        if(returnedDataislandXMLDocument.firstChild && returnedDataislandXMLDocument.firstChild.nodeName == "xml") {
            returnedXMLDocumentFragment = returnedDataislandXMLDocument.childNodes[1];
        } else if(returnedDataislandXMLDocument.firstChild) {
            returnedXMLDocumentFragment = returnedDataislandXMLDocument.firstChild;
        } else {
            returnedXMLDocumentFragment = returnedDataislandXMLDocument;
        }
        
        if(returnedXMLDocumentFragment.tagName == 'Message') {
            var errorCode = returnedXMLDocumentFragment.getAttribute("statusCode");
            if(errorCode == "403") {
                window.location = pathPrefix + '/authentication/display.do?errorMessage=global.login.exception.exception.UnauthorizedUserException';            
            }
        }
        return returnedXMLDocumentFragment;
    },
    
    getControlPrefix: function() {
        var prefixes = ["MSXML2", "MSXML", "MSXML3", "Microsoft"];
        var o, o2;
        for (var i = 0; i < prefixes.length; i++) {
            try {
                // try to create the objects
                o = new ActiveXObject(prefixes[i] + ".XmlHttp");
                o2 = new ActiveXObject(prefixes[i] + ".XmlDom");
                return prefixes[i];
            } catch (ex) {};
        }
       throw new Error("Could not find an installed XML parser");
    },
    
    checkFirstSelectOption: function(selectId) {
        for(var i = 0; i < $(selectId).childNodes.length; i++ ) {
            var child = $(selectId).childNodes[i];
            if(child.nodeType == 1) {
                child.selected = true;
                break;
            }
        }
    },
    
    removeAllSelectOptionsExceptFirst: function(selectId) {
        var select = $(selectId);
        
        for (var i = select.length - 1; i >= 0; i--) {
            var child = select.options[i];
            if(i != 0) {
                select.remove(i);
            }
        }
    },
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used to parse information
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    convertDateToDateString: function(date) {
        var year = date.getFullYear().toString();
        var month = (date.getMonth() + 1).toString();
        if(month.length == 1) {
            month = '0' + month;
        }
        var day = date.getDate().toString();
        if(day.length == 1) {
            day = '0' + day;
        }
        
        return year + '-' + month + '-' + day;
    },

    convertDateToDatetimeString: function(date) {
        var year = date.getFullYear().toString();
        var month = (date.getMonth() + 1).toString();
        if(month.length == 1) {
            month = '0' + month;
        }
        var day = date.getDate().toString();
        if(day.length == 1) {
            day = '0' + day;
        }
        var hours = date.getHours().toString();
        if(hours.length == 1) {
            hours = '0' + hours;
        }
        var minutes = date.getMinutes().toString();
        if(minutes.length == 1) {
            minutes = '0' + minutes;
        }
        
        return year + '-' + month + '-' + day + " " + hours + ":" + minutes;
    },

    convertDateToTimeString: function(date) {
        var hours = date.getHours().toString();
        var minutes = date.getMinutes().toString();
        if(hours.length == 1) {
            hours = '0' + hours;
        }
        if(minutes.length == 1) {
            minutes = '0' + minutes;
        }
        
        return hours + ':' + minutes;
    },
    
    convertDateStringToDate: function(dateString) {
        var date = new Date();
        var dateRegExp = /([0-9][0-9][0-9][0-9])-([0-1]?[0-9])-([0-3]?[0-9])/;
        var dateRegExpArray = dateString.match(dateRegExp);
        var yearValue = dateRegExpArray[1];
        var monthValue = dateRegExpArray[2];
        var dayValue = dateRegExpArray[3];
        
        date.setFullYear(new Number(yearValue));
        date.setMonth(new Number(monthValue) - 1);
        date.setDate(new Number(dayValue));
        date.setHours(new Number(0));
        date.setMinutes(new Number(0));
        date.setSeconds(new Number(0));
        date.setMilliseconds(new Number(0));
        
        return date;
    }, 

    convertDatetimeStringToDate: function(dateString) {
        var date = new Date();
        var dateRegExp = /([0-9][0-9][0-9][0-9])-([0-1]?[0-9])-([0-3]?[0-9])\s([0-2]?[0-9]):([0-5]?[0-9])/;
        var dateRegExpArray = dateString.match(dateRegExp);
        var yearValue = dateRegExpArray[1];
        var monthValue = dateRegExpArray[2];
        var dayValue = dateRegExpArray[3];
        var hoursValue = dateRegExpArray[4];
        var minutesValue = dateRegExpArray[5];
        
        date.setFullYear(new Number(yearValue));
        date.setMonth(new Number(monthValue) - 1);
        date.setDate(new Number(dayValue));
        date.setHours(new Number(hoursValue));
        date.setMinutes(new Number(minutesValue));
        date.setSeconds(new Number(0));
        date.setMilliseconds(new Number(0));
        
        return date;
    }, 
    
    convertTimeStringToDate: function(date, timeString) {
        var dateRegExp = /([0-2]?[0-9]):([0-5]?[0-9])/;
        var dateRegExpArray = timeString.match(dateRegExp);
        var hoursValue = dateRegExpArray[1];
        var minutesValue = dateRegExpArray[2];
        
        date.setHours(hoursValue);
        date.setMinutes(minutesValue);
        return date;
    },
    
    isNumeric : function(strString) {
        //  check for valid numeric strings 
        var strValidChars = "0123456789.-";
        var strChar;
        var blnResult = true;
    
        if (strString.length == 0) return false;
            //  test strString consists of valid characters listed above
            for (i = 0; i < strString.length && blnResult == true; i++) {
                strChar = strString.charAt(i);
                if (strValidChars.indexOf(strChar) == -1) {
                    blnResult = false;
            }
        }
        return blnResult;
    },

        
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used to manage events
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    addEvent: function(elem, evType, func, useCapture) {
        if( elem.addEventListener ) { 
            elem.addEventListener(evType, func, useCapture); 
            return true; 
        } else if( elem.attachEvent ) { 
            var r = elem.attachEvent("on" + evType, func); return r; 
        } else { 
            var onEvt = "on" + evType; 
            var elOldEvFuncs = eval("elem." + onEvt); 
            if( (typeof elem[onEvt]) != 'function' ) { 
                elem[onEvt] = func; } 
            else { 
                elem[onEvt] = function() { 
                    elOldEvFuncs(); 
                    func(); 
                } 
            } 
        } 
    },
    
    generateRandomNumber : function() {
        return Math.floor(Math.random()* 1000000 +1)
    },
    
    getTarget: function(event) {
        var target;
        if (!event) {
            event = window.event;
        }
        
        if (event.target) {
            target = event.target;
        } else if (event.srcElement) {
            target = event.srcElement;
        }
        return target;
    }, 
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * General object methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    cloneObject : function(objectToClone){
        var clonedObject = {};
        for(var i in objectToClone){
            clonedObject[i] = objectToClone[i];
        }
        return clonedObject;
    },
    
    numberFormat: function(num, dec) {
        var mul = Math.pow(10,dec);
        num = num * mul;
        num = Math.round(num);
        num = num/mul;
        
        var numstr=String(num);
        if(numstr.indexOf(".") == -1) {
            numstr = numstr + ".";
            for(nfi = 0; nfi < dec; nfi++) {
                numstr = numstr + "0";
            }
        }
        var decpl = numstr.length - numstr.indexOf(".");
        decpl = decpl - 1;
        if (decpl < dec) {
            for(nfi = decpl; nfi < dec; nfi++) {
                numstr = numstr + "0";
            }
        }
        return (numstr);
    },

    getURLParameter: function(strParamName){
      var strReturn = "";
      var strHref = window.location.href;
      if ( strHref.indexOf("?") > -1 ){
        var strQueryString = strHref.substr(strHref.indexOf("?"));
        var aQueryString = strQueryString.split("&");
        for ( var iParam = 0; iParam < aQueryString.length; iParam++ )
        {
          if (aQueryString[iParam].indexOf(strParamName + "=") > -1 )
          {
            var aParam = aQueryString[iParam].split("=");
            strReturn = aParam[1];
            break;
          }
        }
      }
      return strReturn;
    },
     
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Localization Methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
     getLocaleSuffix: function(locale) {
         if (locale && locale != '')  return '-' + locale;
         else return '';
     },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * XML vs JSON converters
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    xml2json: function(xml, tab) {
       var X = {
          toObj: function(xml) {
             var o = {};
             if (xml.nodeType==1) {   // element node ..
                if (xml.attributes.length)   // element with attributes  ..
                   for (var i=0; i<xml.attributes.length; i++)
                      o["@"+xml.attributes[i].nodeName] = (xml.attributes[i].nodeValue||"").toString();
                if (xml.firstChild) { // element has child nodes ..
                   var textChild=0, cdataChild=0, hasElementChild=false;
                   for (var n=xml.firstChild; n; n=n.nextSibling) {
                      if (n.nodeType==1) hasElementChild = true;
                      else if (n.nodeType==3 && n.nodeValue.match(/[^ \f\n\r\t\v]/)) textChild++; // non-whitespace text
                      else if (n.nodeType==4) cdataChild++; // cdata section node
                   }
                   if (hasElementChild) {
                      if (textChild < 2 && cdataChild < 2) { // structured element with evtl. a single text or/and cdata node ..
                         X.removeWhite(xml);
                         for (var n=xml.firstChild; n; n=n.nextSibling) {
                            if (n.nodeType == 3)  // text node
                               o["#text"] = X.escape(n.nodeValue);
                            else if (n.nodeType == 4)  // cdata node
                               o["#cdata"] = X.escape(n.nodeValue);
                            else if (o[n.nodeName]) {  // multiple occurence of element ..
                               if (o[n.nodeName] instanceof Array)
                                  o[n.nodeName][o[n.nodeName].length] = X.toObj(n);
                               else
                                  o[n.nodeName] = [o[n.nodeName], X.toObj(n)];
                            }
                            else  // first occurence of element..
                               o[n.nodeName] = X.toObj(n);
                         }
                      }
                      else { // mixed content
                         if (!xml.attributes.length)
                            o = X.escape(X.innerXml(xml));
                         else
                            o["#text"] = X.escape(X.innerXml(xml));
                      }
                   }
                   else if (textChild) { // pure text
                      if (!xml.attributes.length)
                         o = X.escape(X.innerXml(xml));
                      else
                         o["#text"] = X.escape(X.innerXml(xml));
                   }
                   else if (cdataChild) { // cdata
                      if (cdataChild > 1)
                         o = X.escape(X.innerXml(xml));
                      else
                         for (var n=xml.firstChild; n; n=n.nextSibling)
                            o["#cdata"] = X.escape(n.nodeValue);
                   }
                }
                if (!xml.attributes.length && !xml.firstChild) o = null;
             }
             else if (xml.nodeType==9) { // document.node
                o = X.toObj(xml.documentElement);
             }
             else
                alert("unhandled node type: " + xml.nodeType);
             return o;
          },
          toJson: function(o, name, ind) {
             var json = name ? ("\""+name+"\"") : "";
             if (o instanceof Array) {
                for (var i=0,n=o.length; i<n; i++)
                   o[i] = X.toJson(o[i], "", ind+"\t");
                json += (name?":[":"[") + (o.length > 1 ? ("\n"+ind+"\t"+o.join(",\n"+ind+"\t")+"\n"+ind) : o.join("")) + "]";
             }
             else if (o == null)
                json += (name&&":") + "null";
             else if (typeof(o) == "object") {
                var arr = [];
                for (var m in o)
                   arr[arr.length] = X.toJson(o[m], m, ind+"\t");
                json += (name?":{":"{") + (arr.length > 1 ? ("\n"+ind+"\t"+arr.join(",\n"+ind+"\t")+"\n"+ind) : arr.join("")) + "}";
             }
             else if (typeof(o) == "string")
                json += (name&&":") + "\"" + o.toString() + "\"";
             else
                json += (name&&":") + o.toString();
             return json;
          },
          innerXml: function(node) {
             var s = ""
             if ("innerHTML" in node)
                s = node.innerHTML;
             else {
                var asXml = function(n) {
                   var s = "";
                   if (n.nodeType == 1) {
                      s += "<" + n.nodeName;
                      for (var i=0; i<n.attributes.length;i++)
                         s += " " + n.attributes[i].nodeName + "='" + (n.attributes[i].nodeValue||"").toString() + "'";
                      if (n.firstChild) {
                         s += ">";
                         for (var c=n.firstChild; c; c=c.nextSibling)
                            s += asXml(c);
                         s += "</"+n.nodeName+">";
                      }
                      else
                         s += "/>";
                   }
                   else if (n.nodeType == 3)
                      s += n.nodeValue;
                   else if (n.nodeType == 4)
                      s += "<![CDATA[" + n.nodeValue + "]]>";
                   return s;
                };
                for (var c=node.firstChild; c; c=c.nextSibling)
                   s += asXml(c);
             }
             return s;
          },
          escape: function(txt) {
             return txt.replace(/[\\]/g, "\\\\")
                       .replace(/[\"]/g, "\\\"")
                       .replace(/[\n]/g, '\\n')
                       .replace(/[\r]/g, '\\r');
          },
          removeWhite: function(e) {
             e.normalize();
             for (var n = e.firstChild; n; ) {
                if (n.nodeType == 3) {  // text node
                   if (!n.nodeValue.match(/[^ \f\n\r\t\v]/)) { // pure whitespace text node
                      var nxt = n.nextSibling;
                      e.removeChild(n);
                      n = nxt;
                   }
                   else
                      n = n.nextSibling;
                }
                else if (n.nodeType == 1) {  // element node
                   X.removeWhite(n);
                   n = n.nextSibling;
                }
                else                      // any other node
                   n = n.nextSibling;
             }
             return e;
          }
       };
       if (xml.nodeType == 9) // document node
          xml = xml.documentElement;
       var json = X.toJson(X.toObj(X.removeWhite(xml)), xml.nodeName, "\t");
       return "{" + tab + (tab ? json.replace(/\t/g, tab) : json.replace(/\t|\n/g, "")) + "}";
    },

    json2xml: function(o, tab) {
       var toXml = function(v, name, ind) {
          var xml = "";
          if (v instanceof Array) {
             for (var i=0, n=v.length; i<n; i++)
                xml += ind + toXml(v[i], name, ind+"\t") + "\n";
          }
          else if (typeof(v) == "object") {
             var hasChild = false;
             xml += ind + "<" + name;
             for (var m in v) {
                if (m.charAt(0) == "@")
                   xml += " " + m.substr(1) + "='" + v[m].toString() + "'";
                else
                   hasChild = true;
             }
             xml += hasChild ? ">" : "/>";
             if (hasChild) {
                for (var m in v) {
                   if (m == "#text")
                      xml += v[m];
                   else if (m == "#cdata")
                      xml += "<![CDATA[" + v[m] + "]]>";
                   else if (m.charAt(0) != "@")
                      xml += toXml(v[m], m, ind+"\t");
                }
                xml += (xml.charAt(xml.length-1)=="\n"?ind:"") + "</" + name + ">";
             }
          }
          else {
             xml += ind + "<" + name + ">" + v.toString() +  "</" + name + ">";
          }
          return xml;
       }, xml="";
       for (var m in o)
          xml += toXml(o[m], m, "");
       return tab ? xml.replace(/\t/g, tab) : xml.replace(/\t|\n/g, "");
    },
    
    jsonElementArray: function(element) {
        if(element instanceof Array) {
            return element;
        } else {
            return $A([element]);
        }
    },
    
    jsonLocalizedValue: function(localeElementXMLNodes, locale) {
        if (localeElementXMLNodes) {
            // find the xml localized element and populate the dom element
            for(var i = 0; i < localeElementXMLNodes.length; i++) {
                var elementXMLNode = localeElementXMLNodes[i];
                if (locale == elementXMLNode["@xml:lang"]) {
                    return elementXMLNode["#text"];         
                }
            }
        }
        
        return null;
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Other methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    logException: function(e) {
        if(typeof e == "string") {
            console.error("Error: " + e);
        } else {
            console.error("Error: " + e.message + "\n" + e.stack);
        }
    }
     
     
     
     
};
MdaradUtils = new MdaradUtilsPrototype();
MdaradCalendarHandler = Class.create();
Object.extend(MdaradCalendarHandler.prototype, {
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Initialization methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    DEFAULT_ERROR_LABEL_ID: "org.mdarad.framework.global.forward.failure.message",
    
    DEFAULT_SUCCESS_LABEL_ID: "org.mdarad.framework.global.forward.success.message",

    DEFAULT_WORKING_LABEL_ID: "org.mdarad.framework.global.forward.working.message",
    
    WORKING_STATUS: "working",
    
    ERROR_STATUS: "error",
    
    SUCCESS_STATUS: "success",

    WARNING_STATUS: "warning",
    
    MODAL_NOTIFICATION_ID: "modal_notification",

    MODAL_ALERT_ID: "modal_alert",

    MODAL_SUCCESS_ID: "modal_success",
        
    initialize : function () {
        this.initializeMdaradCalendarHandlerPrototype ();
    },
    
    initializeMdaradCalendarHandlerPrototype : function () {
	    this.calendarObjForForm = new DHTMLSuite.calendar({
	        callbackFunctionOnDayClick: 'MdaradCalendarHandler.getDateFromCalendar',
	        isDragable:true,
	        displayTimeBar:true
	    });     
    },    
    
    calendarObjForm: null,    
     
     /**
      * Calendar options are: 
      * buttonObject: the button on which is associated the calendar
      * inputObject: the input to be filled by the value of the calendar
      * displayTime: boolean 
      * onClose: method to call after the onclose
      */
    pickDate: function(calendarOptions) {
    	var inputObject = calendarOptions.inputObject;
    	var buttonObj = calendarOptions.buttonObject;
    	var displayTime = calendarOptions.displayTime;
    	var onClose = calendarOptions.onClose;
    	
        this.calendarObjForForm.setCalendarPositionByHTMLElement(inputObject,0,inputObject.offsetHeight+2);
        
        if(displayTime && displayTime == true) {
            this.calendarObjForForm.setInitialDateFromInput(inputObject,'yyyy-mm-dd hh:ii');
            this.calendarObjForForm.displayTimeBar = true;
        } else {
        	this.calendarObjForForm.setInitialDateFromInput(inputObject,'yyyy-mm-dd');
            this.calendarObjForForm.displayTimeBar = false;
        } 
        
        this.calendarObjForForm.addHtmlElementReference('myDate',inputObject); 
        
        if(this.calendarObjForForm.isVisible()){
            this.calendarObjForForm.hide();
        } else{
            this.calendarObjForForm.resetViewDisplayedMonth();
            this.calendarObjForForm.display();
        }
        if(onClose) {       
            this.calendarObjForForm.setCallbackFunctionOnClose(onClose);
        } else {
        	this.calendarObjForForm.setCallbackFunctionOnClose(null);
        }
    },
    
    getDateFromCalendar: function(inputArray) {
        var references = this.calendarObjForForm.getHtmlElementReferences();
        references.myDate.value = inputArray.year + '-' + inputArray.month + '-' + inputArray.day + ' ' + inputArray.hour + ':' + inputArray.minute;
        this.calendarObjForForm.hide();  
    }   
});
MdaradCalendarHandler = new MdaradCalendarHandler();MdaradMessageHandler = Class.create();
Object.extend(MdaradMessageHandler.prototype, {
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Initialization methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    DEFAULT_ERROR_LABEL_ID: "org.mdarad.framework.global.forward.failure.message",
    
    DEFAULT_SUCCESS_LABEL_ID: "org.mdarad.framework.global.forward.success.message",

    DEFAULT_WORKING_LABEL_ID: "org.mdarad.framework.global.forward.working.message",
    
    WORKING_STATUS: "working",
    
    ERROR_STATUS: "error",
    
    SUCCESS_STATUS: "success",

    WARNING_STATUS: "warning",
    
    MODAL_NOTIFICATION_ID: "modal_notification",

    MODAL_ALERT_ID: "modal_alert",

    MODAL_SUCCESS_ID: "modal_success",
        
    initialize : function () {
        this.initializeMdaradMessageHandlerPrototype ();
    },
    
    initializeMdaradMessageHandlerPrototype : function () {
        this.alerts= new Array();
        this.successes = new Array();
        this.notifications = new Array();
    },    
    
    notifications: null,
    alerts: null,
    successes: null,
     
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Working Notification
     *************************************************************************
     *************************************************************************
     *************************************************************************/    
    getModalNotification: function() {
        return this.getElementFromList(this.MODAL_NOTIFICATION_ID, this.notifications);
    },

    getNotification: function(messageDomId) {
        return this.getElementFromList(messageDomId, this.notifications);
    },
    
    deleteNotification: function(element) {
        this.notifications = this.deleteElementFromList(element, this.notifications);        
    },

    /*
     * old params : resourceHandler, messageDomId, isModal
     */
    addNotification: function(messageDomId, messageContentOptions, dialogOptions) {
    	var instance = this;
        if (messageContentOptions == null) {
            messageContentOptions = $H({});
        }
        
        if (dialogOptions == null) {
            dialogOptions = $H({});
        }

        dialogOptions.isModal = dialogOptions.isModal != null? dialogOptions.isModal : true;

        //Get theme for window
        var windowCssClass;  
        if(dialogOptions && dialogOptions.windowCssClass) {
            windowCssClass = dialogOptions.windowCssClass
        } else if(WINDOW_JS_CLASS_NAME && WINDOW_JS_CLASS_NAME != '') {
            windowCssClass = WINDOW_JS_CLASS_NAME;
        } else {
            windowCssClass = "alphacube";
        }

        if(dialogOptions.isModal) {
        	var modalNotification = instance.getModalNotification();
            if(modalNotification == null) {
            	//Create notification with dialog
                modalNotification = {
                    messageDomId: this.MODAL_NOTIFICATION_ID,
                    requiredNotifications: parseInt(1),
                    dialog: Dialog.info(
	                    "<img class='notification' src='" + messageContentOptions.resourceHandler.pathPrefix + "/static/img/progressbar.gif'/>", 
	                    {
	                        isDomContent: false,
							windowParameters: { 
	                            className: windowCssClass, 
	                            width:309, 
	                            height:123, 
						        showEffect: Effect.Appear,
						        showEffectOptions: { 
						            duration: 0.1
						        },
						        hideEffect: Effect.Fade,
						        hideEffectOptions: {
						        	duration: 0.1
						        }
							}	                        
	                    }) 
                };
//                modalNotification.dialog.setZIndex(3000);
                this.notifications.push(modalNotification);
            } else {
                modalNotification.requiredNotifications += parseInt(1);                
            }
        } else {
            var notification = instance.getNotification(messageDomId);
        	if(notification == null) {
                notification = {
                    messageDomId: messageDomId,
                    requiredNotifications: parseInt(1)
                };
	            //Display message
	            instance.clearAndDisplayMessageFromResource(messageContentOptions.resourceHandler, 
	                this.DEFAULT_WORKING_LABEL_ID,
	                this.WORKING_STATUS,
	                messageDomId
	            );
                this.notifications.push(notification);
        	} else {
                notification.requiredNotifications += parseInt(1);                
        	}          
        } 
    },
    
    removeNotification: function(messageDomId) {
    	var instance = this;
    	//Look if such a notification exists (if not found it is probably a modal)
    	var notification = instance.getNotification(messageDomId);
    	
    	//Modal
    	if(!notification) {
    		notification = instance.getModalNotification();
    		if(notification) {
	            setTimeout(function() {
	                notification.requiredNotifications -=  parseInt(1);
	                if(notification.requiredNotifications == 0) {
                        Windows.close(notification.dialog.getId());
	                    instance.deleteNotification(notification);
	                }
	            }, 10);
    		}
    	} 
    	//Included message
    	else {
            notification.requiredNotifications -=  parseInt(1);
            if(notification.requiredNotifications == 0) {
                //Remove message
                instance.removeMessage(instance.WORKING_STATUS, messageDomId);
                instance.deleteNotification(notification);
            }
        }
    },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Alert messages
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    getModalAlert: function() {
        return this.getElementFromList(this.MODAL_ALERT_ID, this.alerts);
    },

    getAlert: function(messageDomId) {
        return this.getElementFromList(messageDomId, this.alerts);
    },
    
    deleteAlert: function(element) {
        this.alerts = this.deleteElementFromList(element, this.alerts);        
    },

    /* 
     * old params  resourceHandler, messageDomId, isModal, messageKey, attributeLabel, bundle, paramResourceArray, content
     * 
     * dialogOptions : isModal, okCallback
     * 
     */
    addAlert: function(messageDomId, messageContentOptions, dialogOptions) {
        var instance = this;

        if (messageContentOptions == null) {
            messageContentOptions = $H({});
        }
        
        if (dialogOptions == null) {
            dialogOptions = $H({});
        }

        messageContentOptions.messageKey = messageContentOptions.messageKey != null? messageContentOptions.messageKey : this.DEFAULT_ERROR_LABEL_ID
        

        dialogOptions.isModal = dialogOptions.isModal != null? dialogOptions.isModal : false;

        //Get theme for window
        var windowCssClass;  
        if(dialogOptions && dialogOptions.windowCssClass) {
            windowCssClass = dialogOptions.windowCssClass
        } else if(WINDOW_JS_CLASS_NAME && WINDOW_JS_CLASS_NAME != '') {
            windowCssClass = WINDOW_JS_CLASS_NAME;
        } else {
            windowCssClass = "alphacube";
        }

        if(dialogOptions.isModal) {
            setTimeout(function() {
	            var modalAlert = instance.getModalAlert();
	            if(modalAlert == null) {
	                //Create notification with dialog
	                var parentDiv = "<div id='alertNotification' class='messages'/>";
	                modalAlert = {
	                    messageDomId: instance.MODAL_ALERT_ID,
	                    dialog: Dialog.alert(parentDiv, {
	                        onOk: function() {
	                            instance.removeAlert(messageDomId);
	                            if (dialogOptions.okCallback != null) {
	                                dialogOptions.okCallback.call(instance);
	                            }
	                        },
	                        isDomContent: false,
                            windowParameters: { 
	                            className: windowCssClass, 
	                            width:400, 
	                            height:200, 
                                showEffect: Effect.Appear,
                                showEffectOptions: { 
                                    duration: 0.1
                                },
                                hideEffect: Effect.Fade,
                                hideEffectOptions: {
                                    duration: 0.1
                                }
                            }                           
	                    }) 
	                };
//	                modalAlert.dialog.setZIndex(3000);
	                instance.alerts.push(modalAlert);
	            } 
	            if(!messageContentOptions.content) {
		            //Create message                
		            instance.displayMessageFromResource(messageContentOptions.resourceHandler, 
		                messageContentOptions.messageKey,
		                instance.ERROR_STATUS,
		                "alertNotification",
		                messageContentOptions.attributeLabel,
		                messageContentOptions.bundle,
		                messageContentOptions.paramResourceArray
		            );      
	            } else {
	            	instance.displayMessage(instance.ERROR_STATUS, "alertNotification", messageContentOptions.content);
	            }
            }, 10);
        } else {
            var alertElement = instance.getAlert(messageDomId);
            if(alertElement == null) {
                alertElement = {
                    messageDomId: messageDomId
                };
                this.alerts.push(alertElement);
            } 
            
            if(!(messageContentOptions.content)) {
	            //Display message
	            this.clearAndDisplayMessageFromResource(messageContentOptions.resourceHandler, 
	                messageContentOptions.messageKey,
	                this.ERROR_STATUS,
	                messageDomId,
	                messageContentOptions.attributeLabel,
	                messageContentOptions.bundle,
	                messageContentOptions.paramResourceArray
	            );          
            } else {
                instance.clearAndDisplayMessage(instance.ERROR_STATUS, messageDomId, messageContentOptions.content);
            }
        } 
    },
    
    removeAlert: function(messageDomId) {
        var instance = this;
        //Look if such an alert exists (if not found it is probably a modal)
        var alertElement = instance.getAlert(messageDomId);
        
        //Modal
        if(!alertElement) {
            alertElement = instance.getModalAlert();
            if(alertElement) {
                setTimeout(function() {
                    Windows.close(alertElement.dialog.getId());
                    instance.deleteAlert(alertElement);
                }, 10);
            }
        } 
        //Included message
        else {
            //Remove message
            instance.removeMessage(instance.ERROR_STATUS, messageDomId);
            instance.deleteAlert(alertElement);
        }
    },    
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Success message
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    getModalSuccess: function() {
        return this.getElementFromList(this.MODAL_SUCCESS_ID, this.successes);
    },

    getSuccess: function(messageDomId) {
        return this.getElementFromList(messageDomId, this.successes);
    },
    
    deleteSuccess: function(element) {
        this.successes = this.deleteElementFromList(element, this.successes);     
    },

    /* 
     * old params messageDomId, resourceHandler, messageDomId, isModal, messageKey, attributeLabel, bundle, paramResourceArray, content
     */
    addSuccess: function(messageDomId, messageContentOptions, dialogOptions) {
        var instance = this;

        if (messageContentOptions == null) {
            messageContentOptions = $H({});
        }
        
        if (dialogOptions == null) {
            dialogOptions = $H({});
        }

        messageContentOptions.messageKey = messageContentOptions.messageKey != null? messageContentOptions.messageKey : this.DEFAULT_SUCCESS_LABEL_ID
        dialogOptions.isModal = dialogOptions.isModal != null? dialogOptions.isModal : false;

        //Get theme for window
        var windowCssClass;  
        if(dialogOptions && dialogOptions.windowCssClass) {
            windowCssClass = dialogOptions.windowCssClass
        } else if(WINDOW_JS_CLASS_NAME && WINDOW_JS_CLASS_NAME != '') {
            windowCssClass = WINDOW_JS_CLASS_NAME;
        } else {
            windowCssClass = "alphacube";
        }

        if(dialogOptions.isModal) {
            setTimeout(function() {
	            var modalSuccess = instance.getModalSuccess();
	            if(modalSuccess == null) {
	                //Create notification with dialog
	                var parentDiv = "<div id='successNotification' class='messages'/>";
	                modalSuccess = {
	                    messageDomId: instance.MODAL_SUCCESS_ID,
	                    dialog: Dialog.alert(parentDiv, {
	                        onOk: instance.removeSuccess.bind(instance, messageDomId),
	                        isDomContent: false,
                            windowParameters: { 
                            className: windowCssClass, 
                            width:400, 
                            height:150, 
                                showEffect: Effect.Appear,
                                showEffectOptions: { 
                                    duration: 0.1
                                },
                                hideEffect: Effect.Fade,
                                hideEffectOptions: {
                                    duration: 0.1
                                }
                            }                           
	                    }) 
	                };
//	                modalSuccess.dialog.setZIndex(3000);
	                instance.successes.push(modalSuccess);
	            } 
	            if(!messageContentOptions.content) {
		            //Create message                
		            instance.clearAndDisplayMessageFromResource(messageContentOptions.resourceHandler, 
		                messageContentOptions.messageKey,
		                instance.SUCCESS_STATUS,
		                "successNotification",
		                messageContentOptions.attributeLabel,
		                messageContentOptions.bundle,
		                messageContentOptions.paramResourceArray
		            );          
	            } else {
	                instance.clearAndDisplayMessage(instance.SUCCESS_STATUS, "alertNotification", messageContentOptions.content);
	            }
            }, 10);
        } else {
            var success = instance.getSuccess(messageDomId);
            if(success == null) {
                success = {
                    messageDomId: messageDomId
                };
                this.alerts.push(success);
            } 
            if(!messageContentOptions.content) {
	            //Display message
	            this.clearAndDisplayMessageFromResource(messageContentOptions.resourceHandler, 
	                messageContentOptions.messageKey,
	                this.SUCCESS_STATUS,
	                messageDomId,
	                messageContentOptions.attributeLabel,
	                messageContentOptions.bundle,
	                messageContentOptions.paramResourceArray
	            );          
            } else {
                instance.clearAndDisplayMessage(instance.SUCCESS_STATUS, messageDomId, messageContentOptions.content);
            }
        } 
    },
    
    removeSuccess: function(messageDomId) {
        var instance = this;
        //Look if such an alert exists (if not found it is probably a modal)
        var success = instance.getSuccess(messageDomId);
        
        //Modal
        if(!success) {
            success = instance.getModalSuccess();
            if(success) {
                setTimeout(function() {
                    Windows.close(success.dialog.getId());
                    instance.deleteSuccess(success);
                }, 10);
            }
        } 
        //Included message
        else {
            //Remove message
            instance.removeMessage(instance.SUCCESS_STATUS, messageDomId);
            instance.deleteSuccess(success);
        }
    },   
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Inquiry messages
     *************************************************************************
     *************************************************************************
     *************************************************************************/
     
     /*
      * old params : resourceHandler, messageKey, okKey, cancelKey, okCallback
      */
    addInquiry: function(messageContentOptions, dialogOptions) {
        var instance = this;

        if (messageContentOptions == null) {
            messageContentOptions = $H({});
        }
        
        if (dialogOptions == null) {
            dialogOptions = $H({});
        }

        setTimeout(function() {
            var parentDiv = "<div id='inquiryNotification' class='messages'/>";

	        //Get theme for window
	        var windowCssClass;  
	        if(dialogOptions && dialogOptions.windowCssClass) {
	            windowCssClass = dialogOptions.windowCssClass
	        } else if(WINDOW_JS_CLASS_NAME && WINDOW_JS_CLASS_NAME != '') {
	            windowCssClass = WINDOW_JS_CLASS_NAME;
	        } else {
	            windowCssClass = "alphacube";
	        }

            //Create Dialog
            var win = Dialog.confirm(parentDiv, {
                className: windowCssClass, 
                width:400, 
                height:150, 
                onOk: dialogOptions.okCallback,
                isDomContent: false
            });
//            win.setZIndex(3000);
            MdaradMessageHandler.clearAndDisplayMessageFromResource(messageContentOptions.resourceHandler, 
                messageContentOptions.messageKey,
                MdaradMessageHandler.WARNING_STATUS,
                "inquiryNotification"
            );          
        }, 10);
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Method used to display error message
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    clearAndDisplayMessageFromResource : function(resourceHandler, resourceId, statusId, messageDomId, attributeLabel, bundle, paramResourceArray) {
        this.removeAllMessages(messageDomId);
        var messageInformation = MdaradResourceHandlerUtils.getResourceHash(resourceId, attributeLabel, bundle).merge({
            messageInfo: {
                status: statusId, 
                messageDOMElementId: messageDomId
            }        
        });
        return resourceHandler.updateResource(messageInformation, paramResourceArray);
    }, 

    displayMessageFromResource : function(resourceHandler, resourceId, statusId, messageDomId, attributeLabel, bundle, paramResourceArray) {
        var messageInformation = MdaradResourceHandlerUtils.getResourceHash(resourceId, attributeLabel, bundle).merge({
            messageInfo: {
                status: statusId, 
                messageDOMElementId: messageDomId
            }        
        });
        return resourceHandler.updateResource(messageInformation, paramResourceArray);
    },
        
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Common Methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/    
    getElementFromList: function(messageDomId, elementList) {
        for(var i=0; i < elementList.length; i++) {
            var currentElement = elementList[i];
            if(currentElement.messageDomId == messageDomId) {
                return currentElement;
            } 
        }
        return null;
    },
    
    deleteElementFromList: function(element, elementList) {
        for(var i=0; i < elementList.length; i++) {
            var currentElement = elementList[i];
            if(currentElement.messageDomId == element.messageDomId) {
                elementList[i] = null;
            } 
        }
        return elementList.compact();
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Method used to display error message
     *************************************************************************
     *************************************************************************
     *************************************************************************/

    clearAndDisplayMessage : function(statusId, messageDOMElementId, content) {
    	this.removeAllMessages(messageDOMElementId);
    	this.displayMessage(statusId, messageDOMElementId, content);
    },

    displayMessage : function(statusId, messageDOMElementId, content) {
        // status can be either : working, warning, success, error
        if(!content && statusId == "error") {
            content = 'An unexpected error occured';
        }        
        var messages = $(messageDOMElementId);

        // Hide the div
        Element.hide($(messageDOMElementId));

        //Create ol if not present        
        var olNode = MdaradUtils.findChild(messages.childNodes, "ol");
        if(!olNode) {
            olNode = Builder.node("ol");
            messages.appendChild(olNode);
        }
        var messageLIElement = Builder.node('li', {className: statusId}, content);

        // Repaint the div
        if (statusId == 'success') {

            Effect.Appear($(messageDOMElementId));
            //Effect.Fade($(messageDOMElementId),  {delay: 10.0, queue: 'end'});
        } else {
            Effect.Appear($(messageDOMElementId));
        }
        // Append to DOM
        olNode.appendChild(messageLIElement);
    },
    
    removeMessage: function(statusId, messageDomElementId) {
        var messages = $(messageDomElementId);

        var olNode = MdaradUtils.findChild(messages.childNodes, "ol");
        if(olNode) {
            //Remove the messages matching the status
            document.getElementsByClassName(statusId, olNode).each(function(elementToRemove) {
                olNode.removeChild(elementToRemove);
            });
        }
        if(olNode.childNodes.length == 0) {
            messages.removeChild(olNode);
        }
    },

    removeAllMessages: function(messageDomElementId) {
        var messages = $(messageDomElementId);

        var olNode = MdaradUtils.findChild(messages.childNodes, "ol");
        if(olNode) {
            //Remove the messages matching the status
            MdaradUtils.deleteAllChildren(olNode);
        }
    }    
});
MdaradMessageHandler = new MdaradMessageHandler();
Window.keepMultiModalWindow = true;MdaradBase = Class.create();
MdaradBase.prototype = {

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * CONSTANTS
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    NEW_ID_PREFIX: 'new-',

    VALUE_SUFFIX : '-value',
    
    VALUES_SUFFIX : '-values',

    BUTTON_SUFFIX : '-button',
    
    PREFIX_SEPARATOR: '-',
    
    MESSAGES_SUFFIX: '-messages',

    DATE_SUFFIX : '-date',

    TIME_SUFFIX : '-time',

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Initialization methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    initialize : function (configuration) {
        this.initializeMdaradBase (configuration);
    },
    
    initializeMdaradBase : function (configuration) {
        if(configuration.form) this.form = configuration.form;
        if(configuration.pathPrefix) this.pathPrefix = configuration.pathPrefix;
        if(configuration.domIdPrefix) this.domIdPrefix = configuration.domIdPrefix;
        if(configuration.instanceId) this.instanceId = configuration.instanceId;
        if(configuration.generalMessageDomId) this.generalMessageDomId = configuration.generalMessageDomId;
        if(configuration.resourceHandler) this.resourceHandler = configuration.resourceHandler;
        if(configuration.localizationContext) this.localizationContext = configuration.localizationContext;
    },    

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * General attributes
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    form: null,
    pathPrefix: "",
    domIdPrefix : "",
    instanceId : null,
    generalMessageDomId : null,
    resourceHandler: null,
    localizationContext: null

};
MdaradXMLBase = Class.create();
Object.extend(Object.extend(MdaradXMLBase.prototype, MdaradBase.prototype),
{
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * CONSTANTS
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    CONTROL_PANEL_SUFFIX : '-controlpanel',
    
    ELEMENT_TYPE_ENTITY : 0,
    
    ELEMENT_TYPE_SINGLE_COMPOSITION : 1,
    
    ELEMENT_TYPE_MULTIPLE_COMPOSITION : 2,
    
    ELEMENT_TYPE_SAVEABLE_COMPOSITION : 4,
    
    DEFAULT_MULTIPLE_ASSOCIATION_SIZE: 4,
    

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Initialization methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    initialize : function (configuration) {
        this.initializeMdaradXMLBase (configuration);
    },
    
    initializeMdaradXMLBase : function (configuration) {
        this.initializeMdaradBase(configuration);
        
        this.messageHashMap = new Object();
        if(configuration.pathPrefix) this.pathPrefix = configuration.pathPrefix;
        if(configuration.baseURI) this.baseURI = configuration.baseURI;
        if(configuration.elementType) this.elementType = configuration.elementType;
        if(configuration.parent) this.parent = configuration.parent;
        
        if (this.instanceId == null) {
            this.instanceId = this.generateNewInstanceId();
        }
        
        if (configuration.generalMessageDomId) {
            this.generalMessageDomId = configuration.generalMessageDomId;
        } else {
            this.generalMessageDomId = this.getInstanceDomId() +'-general' + this.MESSAGES_SUFFIX;
        }
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * General attributes
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    messages: null,
    instanceIdField: null,
    baseURI: null,
    elementType: this.ELEMENT_TYPE_ENTITY,
    parent: null,
    

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Util methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    generateNewInstanceId: function() {
        return this.NEW_ID_PREFIX + MdaradUtils.generateRandomNumber();
    },
    
    checkForNewInstanceId: function(id) {
        if (id == null || id == "" || (id && id.substring(0, this.NEW_ID_PREFIX.length) == this.NEW_ID_PREFIX)) {
            return true;
        }
        return false;
    },
    
    getDomIdInstanceSuffix : function() {
        var id = this.instanceId
        if (id == null) {
            id = '';
        }

        return '[' + id + ']'; 
    },
    
    getInstanceDomId : function() {
        alert("This is an abstract class. Must implement method getInstanceDomId in concrete object "); 
    },

    createMessagesFormNode: function (messageIdPrefix) {
        return Builder.node("div", {id: messageIdPrefix + this.MESSAGES_SUFFIX, className: 'messages'});
    },    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods that fetches an instance
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    fetchInstance : function() {
        var instance = this;
        var id = instance.instanceId;
        
        // ENSURE THE ID IS NOT FOR A NEW INSTANCE
        if (this.checkForNewInstanceId(id) == true) {
            id = '';
        }
        
        var URI = this.pathPrefix + this.baseURI + "/xml/fetch.do";
        var AJAXRequest = new Ajax.Request(
           URI,
           {
               method: "get",
               parameters: {id: id},
               requestHeaders: ['cache-control','no-cache','pragma','no-cache', 'content-type', 'application/xml'],
               onSuccess: function() {
                   instance.handleFetchInstanceResponseSuccess(arguments[0]);
               },
               onFailure: function() {
                   instance.handleFetchInstanceResponseError(arguments[0]);
               }
            }
       );
    },
    
    handleFetchInstanceResponseError : function(request) {
        MdaradMessageHandler.addAlert(this.generalMessageDomId, $H({resourceHandler: this.resourceHandler}));
    },
    
    handleFetchInstanceResponseSuccess : function(requestObject) {
        alert("This is an abstract class. Must implement method handleFetchInstanceResponseSuccess in concrete object "); 
    }
});
    MdaradResourceHandler = Class.create();
MdaradResourceHandler.prototype = 
{
    initialize : function (configuration) {
        this.initializeMdaradResourceHandler (configuration);
    },
    
    initializeMdaradResourceHandler : function (configuration) {
        if(configuration.generalMessageDomId) this.generalMessageDomId = configuration.generalMessageDomId;
        if(configuration.pathPrefix) this.pathPrefix = configuration.pathPrefix;

        this.resourceMap = new Array();
    },

    resourceMap: null,
    pathPrefix: null,
    generalMessageDomId: null,
        
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Fetch the resources and modify content of an attribute or element of the dom
     * (from backend if necessary)
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    fetchResources: function(resourceRequestArray) {
        var instance = this;
        var xmlDoc = this.createXMLResourceCollectionRequestNode(resourceRequestArray);
        var URI = instance.pathPrefix + "/resources/xml.do";
        var AJAXRequest = new Ajax.Request(
           URI,
           {
               asynchronous: false,
               method: "post",
               postBody: xmlDoc,
               requestHeaders: ['cache-control','no-cache','pragma','no-cache', 'content-type', 'application/xml'],
               onSuccess: function(requestObject) {
                   instance.handleFetchResourcesSuccess(requestObject, resourceRequestArray);
               },
               onFailure: function(requestObject) {
                   instance.handleFetchResourcesError(requestObject);
               }
            }
        );
    },
    

    handleFetchResourcesError: function(requestObject) {
        MdaradMessageHandler.displayMessage('error', this.generalMessageDomId);
    }, 

    handleFetchResourcesSuccess: function(requestObject, resourceRequestArray) {
        try {
            var xmlDocument = MdaradUtils.getXMLFragment(requestObject, this.pathPrefix);
            //Make sure it is the correct format
            if(xmlDocument.tagName == 'collection') {
                var resourceNodes = MdaradUtils.findChildren(xmlDocument.childNodes, 'resource');
                for(var i = 0; i < resourceNodes.length; i++) {
                    var resourceElement = resourceNodes[i];
                    for(var j = 0; j < resourceRequestArray.length; j++) {
                        var resourceRequestElement = resourceRequestArray[j];
                        if(resourceRequestElement.key == resourceElement.getAttribute("key") && resourceRequestElement.bundle == resourceElement.getAttribute("bundle")) {
                        
                            //Add the resource to the cache
                            try {
                                var value = "";
                                var valueElement = MdaradUtils.findChild(resourceElement.childNodes, "value");
                                if(valueElement && valueElement.childNodes[0]) {
                                    value = valueElement.childNodes[0].data;
                                }
                                var resourceHash = new Hash({
                                    'key': resourceElement.getAttribute('key'),
                                    'bundle': resourceElement.getAttribute('bundle'),
                                    'value': value
                                });
                                this.addResource(resourceHash);
                                resourceRequestElement.value = resourceHash.value;
                                
                                //Call the callback on the element
                                this.updateResourceRequest(resourceRequestElement);
                           } catch(e) {
                               MdaradUtils.logException(e)
                               MdaradMessageHandler.displayMessage('error', this.generalMessageDomId, "Could not find resource: " + resourceElement.getAttribute('key'));
                           }
                        }
                    }
                }
            }             
            // Check if an error occured
            else if(xmlDocument.tagName == 'Message') {
                MdaradMessageHandler.displayMessage('error', this.generalMessageDomId, xmlDocument.firstChild.nodeValue);
            } 
            else {
                throw("Unknown format");
            }
        } catch(e) {
            MdaradUtils.logException(e)
            MdaradMessageHandler.displayMessage('error', this.generalMessageDomId);
        }
    },


    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Create XML document for resource fetching
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    createXMLResourceCollectionRequestNode: function(resourceRequestArray) {
        var xmlDoc = MdaradUtils.createXMLDocument();
        var collectionNode = xmlDoc.createElement("collection");
        xmlDoc.appendChild(collectionNode);
        
        for(var i = 0; i < resourceRequestArray.length; i++) {
            var currentResourceRequest = resourceRequestArray[i];
            var paramsNode = null;
            if(currentResourceRequest.params && currentResourceRequest.params.length > 0) {
                paramsNode = Mdarad.Builder.node(xmlDoc, "params");
                for(var j=0; j < currentResourceRequest.params.length; j++) {
                    var paramNode = Mdarad.Builder.node(xmlDoc, "param", currentResourceRequest.params[j].value);
                    paramsNode.appendChild(paramNode);
                }
            }
            var resourceNode = null;
            if(!currentResourceRequest.bundle) {
                resourceNode = Mdarad.Builder.node(xmlDoc, "resource", {
                        key: currentResourceRequest.key
                });
            } else {
                resourceNode = Mdarad.Builder.node(xmlDoc, "resource", {
                        key: currentResourceRequest.key,
                        bundle: currentResourceRequest.bundle                
                });
            }
            if(paramsNode != null) {
                resourceNode.appendChild(paramsNode);
            }
            collectionNode.appendChild(resourceNode);
        }
        return xmlDoc;
    },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Fetch the resources to add as parameters to
     * another resource callback(from backend if necessary)
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    fetchResourcesAsResourceParams: function(toFetchArray, cachedArray, destinationResourceHash, messageInfoHash) {
        var instance = this;
        var xmlDoc = this.createXMLResourceCollectionRequestNode(toFetchArray);
        var URI = instance.pathPrefix + "/resources/xml.do";
        var AJAXRequest = new Ajax.Request(
           URI,
           {
               asynchronous: false,
               method: "post",
               postBody: xmlDoc,
               requestHeaders: ['cache-control','no-cache','pragma','no-cache', 'content-type', 'application/xml'],
               onSuccess: function(requestObject) {
                   instance.handleFetchResourcesAsResourceParamsSuccess(requestObject, toFetchArray, cachedArray, destinationResourceHash, messageInfoHash);
               },
               onFailure: function(requestObject) {
                   instance.handleFetchResourcesAsResourceParamsError(requestObject);
               }
            }
        );
    },
    

    handleFetchResourcesAsResourceParamsError: function(requestObject) {
        MdaradMessageHandler.displayMessage('error', this.generalMessageDomId);
    }, 

    handleFetchResourcesAsResourceParamsSuccess: function(requestObject, toFetchArray, cachedArray, destinationResourceHash, messageInfoHash) {
        try {
            var xmlDocument = MdaradUtils.getXMLFragment(requestObject, this.pathPrefix);
    
            //Make sure it is the correct format
            if(xmlDocument.tagName == 'collection') {
                var resourceNodes = MdaradUtils.findChildren(xmlDocument.childNodes, 'resource');
                
                //Update the request array with the values
                for(var i = 0; i < resourceNodes.length; i++) {
                    var resourceElement = resourceNodes[i];
                    for(var j = 0; j < toFetchArray.length; j++) {
                        var resourceRequestElement = toFetchArray[j];
                        if(resourceRequestElement.key == resourceElement.getAttribute("key") && resourceRequestElement.bundle == resourceElement.getAttribute("bundle")) {
                        
                            //Add the resource to the cache
                            var resourceHash = new Hash({
                                'key': resourceElement.getAttribute('key'),
                                'bundle': resourceElement.getAttribute('bundle'),
                                'value': MdaradUtils.findChild(resourceElement.childNodes, "value").textContent
                            });
                            this.addResource(resourceHash);                            
                            cachedArray.push(resourceHash);
                        }
                    }
                }
                
                //Once we have the params, fetch the resource
                destinationResourceHash.params = cachedArray;
                this.fetchResources([destinationResourceHash]);
            }             
            // Check if an error occured
            else if(xmlDocument.tagName == 'Message') {
                MdaradMessageHandler.displayMessage('error', this.generalMessageDomId, xmlDocument.firstChild.nodeValue);
            } 
            else {
                throw("Unknown format");
            }
        } catch(e) {
            MdaradUtils.logException(e)
            MdaradMessageHandler.displayMessage('error', this.generalMessageDomId);
        }
    },
        
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Public methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/

    updateResource: function(resourceHash, paramResourceArray) {
        //If there are parameters, always go to backend
        if(paramResourceArray && paramResourceArray.length > 0) {
            this.updateResourceWithRessourceParams(resourceHash, paramResourceArray);
        } 
        //Otherwise check cache first
        else {
            var cacheHash = this.getResource(resourceHash);
            //Fetch from backend
            if(cacheHash == null) {
                var resourceRequestArray = new Array();
                resourceRequestArray.push(resourceHash);
                this.fetchResources(resourceRequestArray);
            }
            //Update the element now
            else {
                resourceHash.merge({value: cacheHash.value});
                this.updateResourceRequest(resourceHash);
            }
        }        
    }, 
        
    updateResources: function(resourceRequestArray) {
        var toFetchArray = new Array();
        for(var i = 0; i < resourceRequestArray.length; i++) {
            var cacheHash = this.getResource(resourceRequestArray[i]);
            
            //Fetch from backend
            if(cacheHash == null) {
                toFetchArray.push(resourceRequestArray[i]);
            }
            //Update the element now
            else {
                resourceRequestArray[i].merge({value: cacheHash.value});
                this.updateResourceRequest(resourceRequestArray[i]);
            }
        }
        if(toFetchArray.length > 0) {
            this.fetchResources(toFetchArray);
        }
    },
     
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Update resource callbacks
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    updateResourceRequest: function(resourceHash) {
        if(resourceHash.messageInfo == null) {
            if(resourceHash.attributeLabel) {
                this.updateElementAttribute(resourceHash.element, resourceHash.attributeLabel, resourceHash.value);
            } else if(resourceHash.element) {
                this.updateElementText(resourceHash.element, resourceHash.value);
            } else {
              // update nothing                
            }

        } else {
            this.addResourceMessage(resourceHash);
        }
    },
     
    updateElementAttribute: function(element, attributeLabel, attributeValue) {
        element.setAttribute(attributeLabel, attributeValue);
    },
    
    updateElementText: function(element, textValue) {
        //Remove all text nodes
        for(var i = 0; i < element.childNodes.length; i++) {
            var childNode = element.childNodes[i];
            if(childNode.nodeType == 3) {
                element.removeChild(childNode);
            }
        }
        element.appendChild(document.createTextNode(textValue));
    },
    
    addResourceMessage: function(resourceHash) {
        var messageInfo = resourceHash.messageInfo;
        MdaradMessageHandler.displayMessage(messageInfo.status, messageInfo.messageDOMElementId, resourceHash.value);
    }, 
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Private methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    
    addResource: function(resourceHash) {
        var cacheHash = this.getResource(resourceHash);
        if(cacheHash != null) {
            if(cacheHash.value != resourceHash.value) {
                cacheHash.value = resourceHash.value;
            }
        } else {
            this.resourceMap[this.resourceMap.length] = resourceHash;
        }        
    },
    
    updateResourceWithRessourceParams: function(destinationResourceHash, resources) {
        //Check if the params are already in the cache
        var toFetchArray = new Array();
        var cachedArray = new Array();
        for(var i = 0; i < resources.length; i++) {
            if(resources[i].value) {
                cachedArray.push(resources[i]);
            } else {
                var cacheHash = this.getResource(resources[i]);
                
                //Fetch from backend
                if(cacheHash == null) {
                    toFetchArray.push(resources[i]);
                }
                //Add to already known values
                else {
                    cachedArray.push(cacheHash);
                }
            }
        }
        if(toFetchArray.length > 0) {
            this.fetchResourcesAsResourceParams(toFetchArray, cachedArray, destinationResourceHash);
        } else {
            destinationResourceHash.params = cachedArray;
            this.fetchResources([destinationResourceHash]);
        }
    },

    getResource: function(resourceHash) {
        for(var i = 0; i < this.resourceMap.length; i++) {
            var mapResource = this.resourceMap[i];
            if(mapResource.key == resourceHash.key && mapResource.bundle == resourceHash.bundle) {
                return mapResource;
            }
        }
        return null;
    }
};

var MdaradResourceHandlerUtils = {
	DEFAULT_RESOURCE_BUNDLE: "rsrc.application",
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used to manage resources to update
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    addResourceToResourceList: function(resourceListRequest, resourceId, elementNode, attributeLabel, bundle) {
        // convert to dom element if it is a DOM id     
        elementNode = $(elementNode);
        resourceListRequest.push(MdaradResourceHandlerUtils.getResourceHashForElement(resourceId, elementNode, attributeLabel, bundle));
     },
     
    getResourceHashForElement: function(resourceId, elementNode, attributeLabel, bundle) {
        var resourceHashWithoutElement = MdaradResourceHandlerUtils.getResourceHash(resourceId, attributeLabel, bundle);
        return resourceHashWithoutElement.merge({element: elementNode});
    },
    
    getResourceHash: function(resourceId, attributeLabel, bundle) {
        if(!bundle) {
             bundle = this.DEFAULT_RESOURCE_BUNDLE
        }
        if(!attributeLabel) {
            return new Hash({
                key: resourceId,
                bundle: bundle
            });
        } 
         
        else {
            return new Hash({
                key: resourceId,
                bundle: bundle,
                attributeLabel: attributeLabel
            });
         }
    }
};
MdaradXMLFormMapper = Class.create();
Object.extend(Object.extend(MdaradXMLFormMapper.prototype, MdaradXMLBase.prototype),
{
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Initialization methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    initialize : function (configuration) {
        this.initializeMdaradXMLFormMapper (configuration);
    },
    
    initializeMdaradXMLFormMapper : function (configuration) {
        this.initializeMdaradXMLBase(configuration);
        
        this.messageHashMap = new Object();
        if(configuration.form != null) this.form = configuration.form;
        if(configuration.parent != null) this.parent = configuration.parent;
        if(configuration.isReadOnly != null) this.isReadOnly = configuration.isReadOnly;

        this.setValidator();
    },

    parent: null,
    isReadOnly: null,
        
    initializeForm : function(){
        this.setupPopup();
        this.createFormElements();
        this.postCreationActions();
        this.populateAssociationChoices();
        this.fetchInstance();
    },
    
    postCreationActions: function() {
    	
    },
    
    autocompleterPostCreationAction: function(options) {
        new Mdarad.Autocompleter(
            options.elementPrefix + '-entry' + this.VALUE_SUFFIX,
            options.elementPrefix + '-selection' + this.VALUE_SUFFIX,
            options.elementPrefix + '-choices', 
            this.pathPrefix + options.uri, 
            {
                callback: this.autocompleterPostCreationActionCallback.bind(this, options),
                classType: options.classType
            }
        );
    },
    
    autocompleterPostCreationActionCallback: function(options, input, queryString) {
        return new Hash().merge({
            key: options.property, 
            value: input.value,
            type: options.classFQN,
            operator: 'START_WITH'
        });
    },
     
    setupPopup: function() {
        alert("This is an abstract class. Must implement method setupPopup in concrete object "); 
    },
    
    populateAssociationChoices : function () {
        alert("This is an abstract class. Must implement method populateAssociationChoices in concrete object "); 
    },
    
    setValidator: function(instanceId) {
        alert("This is an abstract class. Must implement method setValidator in concrete object "); 
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * General attributes
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    validator: null,
    

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Save XML form
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    saveForm: function(event, options) {
        //Save will be called (as a callback) if all validations succeed
        var validationGroupId = MdaradUtils.generateRandomNumber()
        var validationArguments = new Hash({
            validationGroupId: validationGroupId,
            onCompletion: this.executeSave.bind(this, validationGroupId, options)
        });
        this.validator.validateBeforeCompletion(validationArguments);
    },
    
    
    executeSave: function(validationGroupId, options) {
        //Save only if all the validations were succesful
        if(this.validator.isGroupValidationSuccessful(validationGroupId)) {
            var instance = this;
            var xmlDoc = instance.populateXMLFromForm();
            var id = instance.instanceId;
            // ENSURE THE ID IS NOT FOR A NEW INSTANCE
            if (this.checkForNewInstanceId(id) == true) {
                id = '';
            }
            
            MdaradMessageHandler.addNotification(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}), $H({isModal: true}));
            
            var URI = instance.pathPrefix + instance.baseURI + "/xml/save.do?id=" + id;
            var AJAXRequest = new Ajax.Request(
               URI,
               {
                   method: "post",
                   postBody: xmlDoc,
                   requestHeaders: ['cache-control','no-cache','pragma','no-cache', 'content-type', 'application/xml'],
                   onSuccess: function() {
                       instance.handleFormSaveResponseSuccess(arguments[0], options);
                       MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
                   },
                   onFailure: function() {
                       instance.handleFormSaveResponseError(arguments[0]);
                       MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
                   }
                }
           );
        }
    },
    
    handleFormSaveResponseError: function(requestObject) {
        MdaradMessageHandler.addAlert(this.generalMessageDomId, $H({resourceHandler: this.resourceHandler}));
    }, 
    
    handleFormSaveResponseSuccess: function(requestObject, options) {
        var instance = this;
        try {
            var xmlDocument = MdaradUtils.getXMLFragment(requestObject, this.pathPrefix);
    
            // Only check if an error occured
            if(xmlDocument.tagName == 'Message') {
                MdaradMessageHandler.displayMessage(MdaradMessageHandler.ERROR_STATUS, instance.generalMessageDomId, xmlDocument.firstChild.nodeValue);
            } else {
                if (options && options.closePopup == true) {
                    instance.closePopup();
                    MdaradMessageHandler.addSuccess(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}));
                //If the id was modified, recreate the dom
                } else {
                    instance.instanceId = xmlDocument.getAttribute('id');
                    
                    // recreate DOM from xml file
                    instance.deleteFormElements();
                    instance.setValidator();
                    instance.initializeForm();

                    // populate the form
                    instance.populateFormFromXML(xmlDocument);
                }
                // refresh the list of user transactions
                instance.parent.refreshList();
                MdaradMessageHandler.addSuccess(instance.parent.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}));
            }
        } catch(e) {
            MdaradUtils.logException(e)
            MdaradMessageHandler.addAlert( instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}));
        }
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used to fetch the select lists and set them as options
     *************************************************************************
     *************************************************************************
     *************************************************************************/
     setSelectOptions: function(selectId, URI, labelId, messageDomId, isHidden) {
         try {
            var instance = this;
            MdaradMessageHandler.addNotification(messageDomId, $H({resourceHandler: this.resourceHandler}), $H({isModal:false}));
            var AJAXRequest = new Ajax.Request(
                 URI,
                 {
                     method: "get",
                     asynchronous: false,
                     requestHeaders: ['cache-control','no-cache','pragma','no-cache'],
                     onFailure: function() {
                         instance.handleSetSelectOptionsError(arguments[0], labelId, messageDomId);
                         MdaradMessageHandler.removeNotification(messageDomId);
                     },
                     onSuccess: function() {
                         instance.handleSetSelectOptionsSuccess(arguments[0], selectId, labelId, messageDomId, isHidden);
                         MdaradMessageHandler.removeNotification(messageDomId);
                     }
                 }
            );
        }catch(e) {
            MdaradUtils.logException(e);
            MdaradMessageHandler.addAlert(instance.generalMessageDomId, $H({resourceHandler: this.resourceHandler}));
        }
    },

    handleSetSelectOptionsError: function(requestObject, labelId, messageDomId) {
        MdaradMessageHandler.addAlert(messageDomId, $H({resourceHandler: this.resourceHandler, messageKey: "errors.unableToLoadOptionList", paramResourceArray: [MdaradResourceHandlerUtils.getResourceHash(labelId)]}));
    },
    handleSetSelectOptionsSuccess: function(requestObject, selectId, labelId, messageDomId, isHidden) {
        try {
            this.populateOptions(requestObject, selectId, isHidden);
        } catch(e) {
            MdaradUtils.logException(e)
            this.handleSetSelectOptionsError(requestObject, labelId, messageDomId);
        }
    },
    populateOptions: function(requestObject, selectId, isHidden) {
        var returnedXMLDocumentFragment = MdaradUtils.getXMLFragment(requestObject, this.pathPrefix);
        var resultsNodes = MdaradUtils.findChild(returnedXMLDocumentFragment.childNodes, 'results');     
        var entityNodes = resultsNodes.childNodes;

        var selectElement = $(selectId);
        if(selectElement) {
            if(isHidden) {
                selectElement.style.display = "none";
            }
            for(var i = 0; i < entityNodes.length; i++) {
                if (entityNodes[i].nodeType == 1) {
                    var option = Builder.node('option', {
                        value: entityNodes[i].getAttribute('id')
                    }, entityNodes[i].getAttribute('label'));
                    selectElement.appendChild(option);
                }
            }
            
            //When finished set first as selected
            if(selectElement.options.length > 0) {
               selectElement.options[0].selected = 'selected';
            }
        }
    },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Populate XML File from Form
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    populateXMLFromForm: function() {
        var xmlDoc = MdaradUtils.createXMLDocument();
        xmlDoc.appendChild(this.createXMLRootEntityNode(xmlDoc));
        return xmlDoc;
    },

    createXMLRootEntityNode: function(xmlDoc) {
        alert("This is an abstract class. Must implement method createXMLRootEntityNode in concrete objec"); 
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Populate Form from XML
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    populateFormFromXML: function(xmlDoc, isParent) {
        alert("This is an abstract class. Must implement method in concrete object populateFormFromXML"); 
    },
    
    populateStringFormElementFromXML : function(elementXMLNode, elementDomId) {
        if (elementXMLNode && elementXMLNode.firstChild) {
            $(elementDomId).value = elementXMLNode.firstChild.nodeValue;
        } else {
            $(elementDomId).value = '';        
        }
    },

    populateDateFormElementFromXML : function(elementXMLNode, elementDomId) {
        if (elementXMLNode && elementXMLNode.firstChild) {
            $(elementDomId).value = elementXMLNode.firstChild.nodeValue;
        } else {
            $(elementDomId).value = '';        
        }
    },

    populateDatetimeFormElementFromXML : function(elementXMLNode, elementDomId) {
        if (elementXMLNode && elementXMLNode.firstChild) {
            //Convert date to string
            var date = new Date();
            date.setTime(elementXMLNode.firstChild.nodeValue);
            
            $(elementDomId).value = MdaradUtils.convertDateToDatetimeString(date);
        } else {
            $(elementDomId).value = '';        
        }
    },

    populateHiddenFormElementFromXML : function(elementXMLNode, elementDomId, fieldsetDomId) {
    
        //Set the hidden field
        if (elementXMLNode && elementXMLNode.firstChild) {
            $(elementDomId).value = elementXMLNode.firstChild.nodeValue;
        } else {
            $(elementDomId).value = '';        
        }
        
        //Set the span for the value
        var spanNode = MdaradUtils.findChild($(fieldsetDomId).childNodes, "span");
        if(spanNode) {
            spanNode.remove();
        }
        $(fieldsetDomId).appendChild(Builder.node("span", [
            $(elementDomId).value 
        ]));
    },
    
    /**
     * Populate an element that has input field and a label element with the same name
     */
    populateReadOnlyElementFromXML : function(elementXMLNode, elementDomId) {
        if (elementXMLNode && elementXMLNode.firstChild) {
            var value = elementXMLNode.firstChild.nodeValue;
            MdaradUtils.deleteAllChildren($(elementDomId + "-label"));
            $(elementDomId + "-label").appendChild(document.createTextNode(value));
            if ($(elementDomId)) {
                $(elementDomId).value=value;
            }
        } else {
            MdaradUtils.deleteAllChildren(elementDomId);        
        }
    },
    
    /**
     * Populate an element with the node from xml file.  It removes the child node before
     * adding a text node with date from xml.
     * @param elementXMLNode
     * @param elementDomId
     * @param defaultValue Value that is used if the xml node is null.
     */
    populateReadOnlyNodeFromXML : function(elementXMLNode, elementDomId, defaultValue) {

        var value = null;
        // xml node is present
        if (elementXMLNode && elementXMLNode.firstChild) {
            value = elementXMLNode.firstChild.nodeValue;
        }
        
        this.populateReadOnlyNode(value, elementDomId, defaultValue);
    },
    
    populateReadOnlyNodeFromLocalizedXML : function(localeElementXMLNodes, elementDomId, defaultValue) {
        if(this.localizationContext == null) {
            throw "ERROR: LocalizationContext must not be null";
        } else {
            var locale = this.localizationContext.currentLocale;
            if(locale == null) {
                locale = this.localizationContext.defaultLocale;
            }
            
            if (localeElementXMLNodes) {
                // find the xml localized element and populate the dom element
                for(var i = 0; i < localeElementXMLNodes.length; i++) {
                    var elementXMLNode = localeElementXMLNodes[i];
                    if(locale == elementXMLNode.getAttribute('xml:lang')) {
                        this.populateReadOnlyNodeFromXML(elementXMLNode, elementDomId, defaultValue);
                        break;
                    }
                }
                
            } else {
                this.populateReadOnlyNode("", elementDomId, defaultValue);
            }
        }
    },
    
    /**
     * Populate an element with the node from xml file.  It removes the child node before
     * adding a text node with date from xml.
     * @param elementXMLNode
     * @param elementDomId
     * @param defaultValue Value that is used if the xml node is null.
     */
    populateReadOnlyNumberNodeFromXML : function(elementXMLNode, elementDomId, nbDecimal, defaultValue) {
           
        var value = null;
        // xml node is present
        if (elementXMLNode && elementXMLNode.firstChild) {
            value = elementXMLNode.firstChild.nodeValue;
            if(MdaradUtils.isNumeric(value) == true) {
                value = MdaradUtils.numberFormat(value, nbDecimal);
            } else {
                throw ("Node is not a numeric type");
            }
        }
        
        this.populateReadOnlyNode(value, elementDomId, defaultValue);
    },
    
    /**
     * Populate a dom element with the value passed as argument.  It removes the child node before
     * adding a text node with value date.
     * @param value
     * @param elementDomId
     * @param defaultValue Value that is used if the xml node is null.
     */
    populateReadOnlyNode : function(value, elementDomId, defaultValue) {
        if ($(elementDomId)) {
            MdaradUtils.deleteAllChildren($(elementDomId));
            // apply default value
            if (value == null) {
                value = defaultValue
            }
            
            // add a text node to dom element
            if (value != null) {
                $(elementDomId).appendChild(document.createTextNode(value));
            }
        } else {
            throw ("The elementDomId " + elementDomId + " doesn't exist.");
        }
    },
    

    populateReadOnlyAssociationFromXML : function(elementXMLNode, elementDomId, idAttName, labelAttName) {
        if (idAttName == null || idAttName == "") {
            idAttName = "refid";
        }

        if (labelAttName == null || labelAttName == "") {
            labelAttName = "label";
        }        
        
        if (elementXMLNode && elementXMLNode.firstChild) {
            $(elementDomId + "-label").appendChild(document.createTextNode(elementXMLNode.firstChild.getAttribute(labelAttName)));
            $(elementDomId).value=elementXMLNode.firstChild.getAttribute(idAttName);
        } else {
            MdaradUtils.deleteAllChildren(elementDomId);        
        }
    },
    
    populateReadOnlyMultipleAssociationFromXML : function(elementXMLNode, elementDomId) {
        var idCSV = "";
        var labelCSV = "";

        //Create csv for hidden field and label        
        for(var i = 0; i < elementXMLNode.childNodes.length; i++) {
            var child = elementXMLNode.childNodes[i];
            var id = child.getAttribute('refid');
            var label = child.getAttribute('label');
            
            idCSV += id;
            labelCSV += label;

            if((i+1) < elementXMLNode.childNodes.length) {
                idCSV += ",";
                labelCSV += ",";
            }
        }
        
        //Write CSVs
        $(elementDomId).value = idCSV;
        $(elementDomId + "-label").appendChild(document.createTextNode(labelCSV));
    },
    
    populateStringFormElementFromXMLLocalized : function(localeElementXMLNodes, elementDomId) {
        if (localeElementXMLNodes) {
            for(var i = 0; i < localeElementXMLNodes.length; i++) {
                var elementXMLNode = localeElementXMLNodes[i];
                $(elementDomId + '-' + elementXMLNode.getAttribute('xml:lang')).value = elementXMLNode.firstChild.nodeValue;
            }
            
        } else {
            if(this.localizationContext == null) {
                throw "ERROR: LocalizationContext must not be null";
            } else {
                for(var i = 0; i < this.localizationContext.getLocales().length; i++) {
                    $(elementDomId + '-' + this.localizationContext.getLocales()[i]).value = '';
                }
            }
        }
    },
    
    populateSelectFormElementFromXML : function(elementXMLNode, elementDomId) {
        var selectElement = $(elementDomId);
        if (elementXMLNode) {
            for(var i = 0; i < selectElement.options.length; i++) {
                var option = selectElement.options[i];
                option.selected = false;
                for(var j = 0; j < elementXMLNode.childNodes.length; j++) {
                    var child = elementXMLNode.childNodes[j];
                    var id = child.getAttribute('refid');
                    if (option.value == id) {
                        option.selected = true;
                        break;
                    }
                }
            }
        }
    },
    
    populateHighVolumeAssociationFormElementFromXML: function(elementXMLNode, elementDomIdPrefix) {
        var valueElement = $(elementDomIdPrefix + "-entry" + this.VALUE_SUFFIX);
        var idElement = $(elementDomIdPrefix + "-selection" + this.VALUE_SUFFIX);
        if (elementXMLNode) {
            var child = elementXMLNode.firstChild;
            var id = child.getAttribute('refid');
            var value = child.getAttribute("label");
            
            valueElement.value = value;
            idElement.value = id;
        }
    },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * JSON METHODS
     *************************************************************************
     *************************************************************************
     *************************************************************************/

    populateReadOnlyElement : function(value, elementDomId) {
        if (value && value != '') {
            MdaradUtils.deleteAllChildren($(elementDomId + "-label"));
            $(elementDomId + "-label").appendChild(document.createTextNode(value));
            if ($(elementDomId)) {
                $(elementDomId).value=value;
            }
        } else {
            MdaradUtils.deleteAllChildren(elementDomId);        
        }
    },
    
    populateStringFormElement : function(value, elementDomId) {
        if (value && value != '') {
            $(elementDomId).value = value;
        } else {
            $(elementDomId).value = '';        
        }
    },
    
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods that fetches an instance
     *************************************************************************
     *************************************************************************
     *************************************************************************/

    handleFetchInstanceResponseSuccess : function(requestObject) {
        try {
            var returnedXMLDocumentFragment = MdaradUtils.getXMLFragment(requestObject, this.pathPrefix);
            this.populateFormFromXML(returnedXMLDocumentFragment);
        } catch(e) {
            MdaradUtils.logException(e)
            this.handleSetSelectOptionsError(requestObject, labelId, messageDomId);
        }
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used to create Popup
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    popupWindow: null,
    
    initializePopup: function(popupIdPrefix) {
        var popupElement = $(popupIdPrefix + "-popup");
        
        if (popupElement != null) {
            popupElement.remove();
        }
        this.form = Builder.node('form', {id: popupIdPrefix + "-edit"});
        var popupElement =
            Builder.node('div', {id: popupIdPrefix + "-popup", className: "userpanel-popup", style: "display: none"}, [
                Builder.node('div', {id: this.generalMessageDomId, className: "messages"}),
                Builder.node('div', {id: popupIdPrefix + "form"}, [
                    this.form
                ])
            ]);
        var body = $$("body")[0];
        body.appendChild(popupElement);
    },

    createPopup: function(popupIdPrefix, titleId, popupOptions) {
        
        //Get theme for window
        var windowCssClass;  
        if(popupOptions && popupOptions.windowCssClass) {
            windowCssClass = popupOptions.windowCssClass
        } else if(WINDOW_JS_CLASS_NAME && WINDOW_JS_CLASS_NAME != '') {
            windowCssClass = WINDOW_JS_CLASS_NAME;
        } else {
            windowCssClass = "alphacube";
        }

        var zIndex = (popupOptions && popupOptions.zIndex) ? popupOptions.zIndex : 2000; 
        var maxWidth = (popupOptions && popupOptions.maxWidth) ? popupOptions.maxWidth : 800; 
        var maxHeight = (popupOptions && popupOptions.maxHeight) ? popupOptions.maxHeight : 500; 
        var minWidth = (popupOptions && popupOptions.minWidth) ? popupOptions.minWidth : 600; 
        var minHeight = (popupOptions && popupOptions.minHeight) ? popupOptions.minHeight : 50; 
        var title = (popupOptions && popupOptions.title) ? popupOptions.title : ""; 
        var showEffect = (popupOptions && popupOptions.showEffect) ? popupOptions.showEffect : Effect.BlindDown; 
        var hideEffect = (popupOptions && popupOptions.hideEffect) ? popupOptions.hideEffect : Effect.SwitchOff; 
        var resizable = (popupOptions && popupOptions.resizable) ? popupOptions.resizable : true; 
        var draggable = (popupOptions && popupOptions.draggable) ? popupOptions.draggable : true; 
        var minimizable = (popupOptions && popupOptions.minimizable) ? popupOptions.minimizable : false; 
        var maximizable = (popupOptions && popupOptions.maximizable) ? popupOptions.maximizable : false; 
        var wiredDrag = (popupOptions && popupOptions.wiredDrag) ? popupOptions.wiredDrag : false; 
        
        var popupElement = $(popupIdPrefix + "-popup");
        var win = this.popupWindow; 
        if(!win) {
            win = new Window({
                className: windowCssClass, 
                zIndex: zIndex,
                maxWidth: maxWidth,
                maxHeight: maxHeight,
                minWidth: minWidth,
                minHeight: minHeight, 
                title: title, 
                showEffect: showEffect, 
                hideEffect: hideEffect,
                resizable: resizable, 
                draggable: draggable, 
                minimizable: minimizable,
                maximizable: maximizable,
                wiredDrag: wiredDrag
            });
            win.setCloseCallback(this.closePopup.bind(this));
            win.setContent(popupIdPrefix + "-popup", true, true);
            win.showCenter(true);    
        } else {
            this.resizePopup();
        }
                
        //Set title
        var titles = document.getElementsByClassName("title_window", $(win.getId()));
        for(var i = 0; i < titles.length; i++) {
            var title = titles[i];
            this.resourceHandler.updateResource(MdaradResourceHandlerUtils.getResourceHashForElement(titleId, title));
        }   
        
        this.popupWindow = win;
    },
    
    closePopup: function() {
        //Remove popup
        if(this.popupWindow) {
            var contentId = this.popupWindow.getContent().firstChild.id;
            this.popupWindow.hide();
            this.popupWindow.destroy();
            
            //Remove content
            $(contentId).remove();
            this.popupWindow = null;
        }
    },
    
    resizePopup: function() {
        var instance = this;
        if(instance.popupWindow != null) {
            setTimeout(function() {
                instance.popupWindow.updateWidth();
                instance.popupWindow.updateHeight();
            }, 10);
        } else {
            if(instance.parent != null && instance.parent.resizePopup) {
                instance.parent.resizePopup();
            }
        }
    },
    
    getVisibleHeight: function() {
        //Get Height of visible window
        var height = window.innerHeight;
        if(!height || height < 0) {
            height = document.documentElement.clientHeight;
        }        
        if(!height || height < 0) {
            height = document.body.clientHeight;
        }
        return height;    
    },
    
    getVisibleWidth: function() {
        //Get Widthof visible window
        var width = window.innerWidth;
        if(!width || width < 0) {
            width = document.documentElement.clientWidth;
        }        
        if(!width || width < 0) {
            width = document.body.clientWidth;
        }
        return width;    
    },
    /*************************************************************************
     * Methods used to create the form elements of a mapper
     *************************************************************************/
    deleteFormElements: function() {
        MdaradUtils.deleteAllChildren(this.form);
    },
     
    createFormElements: function() {
        if(this.form) {
            var childNodes = this.createFormChildNodes();
            if (childNodes) {
                this.form.appendChild(childNodes);
            }
        }
    },
    
    createFormChildNodes: function() {
        alert("This is an abstract class. Must implement method createFormChildNodes in concrete object "); 
    },

    
    /*************************************************************************
     * Methods used to create common legend element
     *************************************************************************/
    createLegendFormNode: function (legendId, isRequired, resourceListRequest) {
        var className = '';
        if (isRequired) {
            className = "required";
        }
        var elementNode = Builder.node("legend", {className: className});
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, legendId, elementNode);    
        return elementNode;
    },
    
    /*************************************************************************
     * Methods used to create standard id field
     *************************************************************************/
    createIdField: function(domIdPrefix) {
        var input = this.createHiddenFieldFormNode(domIdPrefix + '-id');
        if (this.instanceId) {
            input.value = this.instanceId;
        }
        
        return input;
    },

    /*************************************************************************
     * Methods used to create common fields for an instance
     *************************************************************************/
    createInstanceFieldset: function(domIdPrefix, legendId, resourceListRequest) {
        var controlPanel = this.createInstanceControlPanel(domIdPrefix, resourceListRequest);
        if (this.elementType == this.ELEMENT_TYPE_SINGLE_COMPOSITION) {
            controlPanel = this.createSingleCompositionControlPanel(domIdPrefix);
        } else if (this.elementType == this.ELEMENT_TYPE_MULTIPLE_COMPOSITION) {
            controlPanel = this.createMultipleCompositionControlPanel(domIdPrefix);
        }
        
        this.instanceIdField = this.createIdField(domIdPrefix);
        var fieldsetNode = Builder.node("fieldset", {id: domIdPrefix , className: 'instance'}, [
                                    this.createMessagesFormNode(domIdPrefix + '-general'),
                                    controlPanel,
                                    this.instanceIdField
                                 ]);
        return fieldsetNode;
    },
    
    /*************************************************************************
     * Methods used to create different types of control panels
     *************************************************************************/
    createInstanceControlPanel: function(domIdPrefix, resourceListRequest) {
        var controlPanel;
        if (this.isReadOnly == false) {
            controlPanel = this.createSaveableCompositionInstanceControlPanel(domIdPrefix, resourceListRequest);
        }
        return controlPanel;
    },

    createSaveableCompositionInstanceControlPanel: function(domIdPrefix, resourceListRequest) {
        var elementNode = Builder.node("span");
        
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.form.save", elementNode);
        
        var saveLink =  Builder.node("a", {id: domIdPrefix + this.CONTROL_PANEL_SUFFIX + '-save', className: 'controlpanel-save', href:'javascript:void(0)'});
        saveLink.appendChild(elementNode);        
        saveLink.onclick = this.saveForm.bind(this);

        var saveCloseNode = Builder.node("span");
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.form.saveClose", saveCloseNode);
        var saveCloseLink =  Builder.node("a", {id: domIdPrefix + this.CONTROL_PANEL_SUFFIX + '-saveClose', className: 'controlpanel-saveClose', href:'javascript:void(0)'});
        saveCloseLink.appendChild(saveCloseNode);
        var options = $H({closePopup: true});
        saveCloseLink.onclick = this.saveForm.bind(this, null, options);

        var cancelNode = Builder.node("span");
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.form.cancel", cancelNode);
        var cancelLink =  Builder.node("a", {id: domIdPrefix + this.CONTROL_PANEL_SUFFIX + '-cancel', className: 'controlpanel-cancel', href:'javascript:void(0)'});
        cancelLink.appendChild(cancelNode);        
        cancelLink.onclick = this.closePopup.bind(this);
        
        var controlPanel =
            Builder.node("ul", {className: 'controlpanel'}, [
                Builder.node("li", [
                    cancelLink
                ]),
                Builder.node("li", [
                    saveLink
                ]),
                Builder.node("li", [
                    saveCloseLink
                ])
            ]);
        return controlPanel;
    },
    
    createMultipleCompositionControlPanel : function(domIdPrefix) {
        var deleteLink =  Builder.node("a", {id: domIdPrefix + this.CONTROL_PANEL_SUFFIX + '-delete', className: 'controlpanel-delete', href:'javascript:void(0)'}, [
                            Builder.node("span", 'Delete')
                        ]);
 
        deleteLink.onclick = this.deleteCompositionHandler.bind(this);
        
        var controlPanel =
            Builder.node("ul", {id: domIdPrefix + this.CONTROL_PANEL_SUFFIX, className: 'controlpanel'}, [
                Builder.node("li", [
                    deleteLink
                ])
            ]);
        return controlPanel;
    },
    
    createSingleCompositionControlPanel : function(domIdPrefix) {
        var controlPanel =
            Builder.node("ul", {id: domIdPrefix + this.CONTROL_PANEL_SUFFIX, className: 'controlpanel'});
        return controlPanel;
    },
    
    createSetCompositionControlPanelNode: function(elementId, setHandler, resourceListRequest) {
        var elementNode = Builder.node('span');

        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.set", elementNode);

        var setLink = Builder.node('a', {id : elementId + this.CONTROL_PANEL_SUFFIX + '-set', className: 'controlpanel-set', href: 'javascript:void(0)'});
        setLink.appendChild(elementNode);
        setLink.onclick = setHandler.bind(this);
        
        var controlPanel = 
            Builder.node('ul', {id: elementId + this.CONTROL_PANEL_SUFFIX, className:'controlpanel'}, [
                Builder.node('li', [
                    setLink
                ])
            ]);

        return controlPanel;
    },
    
    createRemoveCompositionControlPanelNode: function(elementId, removeHandler, resourceListRequest) {
        var elementNode = Builder.node('span');

        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.remove", elementNode);

        var removeLink = Builder.node('a', {id : elementId + this.CONTROL_PANEL_SUFFIX + '-remove', className: 'controlpanel-remove', href: 'javascript:void(0)'});
        removeLink.onclick = removeHandler.bind(this);
        removeLink.appendChild(elementNode);
        
        var controlPanel = 
            Builder.node('ul', {id: elementId + this.CONTROL_PANEL_SUFFIX, className:'controlpanel'}, [
                Builder.node('li', [
                    removeLink
                ])
            ]);

        return controlPanel;
    },
    
    /*************************************************************************
     * Methods used to create different types of fieldset
     *************************************************************************/
    createReadOnlyFieldsetNode: function(elementId, labelId, resourceListRequest) {
        var returnedNode = 
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createMessagesFormNode(elementId),
                this.createFieldLabelFormNode(labelId, false, resourceListRequest),
                Builder.node("span", {id: elementId + this.VALUE_SUFFIX + "-label", className: 'attribute'}),
                this.createHiddenFieldFormNode(elementId)
            ]);
        return returnedNode;
    },

    createHiddenFieldsetNode: function(elementId) {
        var returnedNode = 
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createHiddenFieldFormNode(elementId)
            ]);
        return returnedNode;
    },
     
    createDefaultFieldFormNode : function(elementId, inputType, onBlurHandler, labelId, isRequired, resourceListRequest) {
        var inputNode = this.createInputNode(elementId, inputType, onBlurHandler);
        var returnedNode =
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createMessagesFormNode(elementId),
                this.createFieldLabelFormNode(labelId, isRequired, resourceListRequest),
                inputNode
            ]);

        return returnedNode;
    },

    
    createStringFieldFormNode : function(elementId, onBlurHandler, labelId, isRequired, resourceListRequest) {
        return this.createDefaultFieldFormNode(elementId, 'text', onBlurHandler, labelId, isRequired, resourceListRequest);
    },

    createDateFieldFormNode : function(elementId, onBlurHandler, labelId, isRequired, resourceListRequest) {
        var inputNode = Builder.node('input', {
            type: "text", 
            id: elementId + this.VALUE_SUFFIX, 
            name: elementId + this.VALUE_SUFFIX,
            size: "10",
            maxlength: "10"
        });
        
        var returnedNode =
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createMessagesFormNode(elementId),
                this.createFieldLabelFormNode(labelId, isRequired, resourceListRequest),
                inputNode,
                Builder.node("input", {
                    id: elementId + this.BUTTON_SUFFIX, 
                    type: "button", 
                    onclick: "MdaradCalendarHandler.pickDate({buttonObject: this, inputObject: $('" + elementId + this.VALUE_SUFFIX + "')})",
                    value: "..."
                })
            ]);
        
        if (onBlurHandler) {
            inputNode.onchange = onBlurHandler;
        }
        return returnedNode;
    },

    createDatetimeFieldFormNode : function(elementId, onBlurHandler, labelId, isRequired, resourceListRequest) {
        var inputDateNode = Builder.node('input', {
            type: "text", 
            id: elementId + this.VALUE_SUFFIX, 
            name: elementId + this.VALUE_SUFFIX,
            size: "16",
            maxlength: "16"
        });
        
        var returnedNode =
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createMessagesFormNode(elementId),
                this.createFieldLabelFormNode(labelId, isRequired, resourceListRequest),
                inputDateNode,
                Builder.node("input", {
                    id: elementId + this.BUTTON_SUFFIX, 
                    type: "button", 
                    onclick: "MdaradCalendarHandler.pickDate({buttonObject: this, inputObject: $('" + elementId + this.VALUE_SUFFIX + "'), displayTimeBar: true})",
                    value: "..."
                })
            ]);
        
        if (onBlurHandler) {
            inputDateNode.onchange = onBlurHandler;
        }
        return returnedNode;
    },
    
    createLocalizedTextAreaFieldFormNode: function(elementId, onBlurHandlers, labelId, isRequired, resourceListRequest) {
        var returnedNode =
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createMessagesFormNode(elementId),
                this.createLegendFormNode(labelId, isRequired, resourceListRequest),
            ]);


        var inputList = new Array();
        if (this.localizationContext == null) {
            throw "LocalizationContext object was not initialized in the Mapper";
        }
        
        for(var i = 0; i < this.localizationContext.getLocales().length; i++) {
            var locale = this.localizationContext.getLocales()[i];
            var inputId = elementId + this.VALUE_SUFFIX + MdaradUtils.getLocaleSuffix(locale);
            var inputNode = Builder.node('textarea', {id: inputId, name: inputId});
            // get the handler for the locale
            if (onBlurHandlers) {
                for(var j = 0; j < onBlurHandlers.length; j++) {
                    if (onBlurHandlers[j].locale == locale) {
                        inputNode.onblur = onBlurHandlers[j].handler;
                    }
                }
            }
            var fieldSetNode = 
                Builder.node('fieldset', {id: elementId + MdaradUtils.getLocaleSuffix(locale), className: 'locale'}, [
                    this.createMessagesFormNode(elementId + MdaradUtils.getLocaleSuffix(locale)),
                    this.createFieldLabelFormNode('org.mdarad.framework.global.locale.' + locale, false, resourceListRequest, 'locale'),
                    inputNode
                ]);
            returnedNode.appendChild(fieldSetNode);
        }

        return returnedNode;        
    },
    
    createLocalizedStringFieldFormNode : function(elementId, onBlurHandlers, labelId, isRequired, resourceListRequest) {
        var returnedNode =
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createMessagesFormNode(elementId),
                this.createLegendFormNode(labelId, isRequired, resourceListRequest),
            ]);


        var inputList = new Array();
        if (this.localizationContext == null) {
            throw "LocalizationContext object was not initialized in the Mapper";
        }
        
        for(var i = 0; i < this.localizationContext.getLocales().length; i++) {
            var locale = this.localizationContext.getLocales()[i];
            var inputId = elementId + this.VALUE_SUFFIX + MdaradUtils.getLocaleSuffix(locale);
            var inputNode = Builder.node('input', {type: "text", id: inputId, name: inputId});
            // get the handler for the locale
            if (onBlurHandlers) {
                for(var j = 0; j < onBlurHandlers.length; j++) {
                    if (onBlurHandlers[j].locale == locale) {
                        inputNode.onblur = onBlurHandlers[j].handler;
                    }
                }
            }
            var fieldSetNode = 
                Builder.node('fieldset', {id: elementId + MdaradUtils.getLocaleSuffix(locale), className: 'locale'}, [
                    this.createMessagesFormNode(elementId + MdaradUtils.getLocaleSuffix(locale)),
                    this.createFieldLabelFormNode('org.mdarad.framework.global.locale.' + locale, false, resourceListRequest, 'locale'),
                    inputNode
                ]);
            returnedNode.appendChild(fieldSetNode);
        }

        return returnedNode;
    },
    
    
    createHiddenFieldFormNode : function(elementId) {
        return this.createInputNode(elementId, 'hidden');
    },
    
    createPasswordFieldFormNode : function(elementId, onBlurHandler, labelId, isRequired, resourceListRequest) {
        return this.createDefaultFieldFormNode(elementId, 'password', onBlurHandler, labelId, isRequired, resourceListRequest);
    },
    
    /*************************************************************************
     * Methods used to create an input node (alone, no fieldset)
     *************************************************************************/
    createInputNode : function(elementId, inputType, onBlurHandler) {
        var inputNode = Builder.node('input', {type: inputType, id: elementId + this.VALUE_SUFFIX, name: elementId + this.VALUE_SUFFIX});
        if (onBlurHandler) {
            MdaradUtils.addEvent(inputNode, "blur", onBlurHandler);
//            inputNode.onblur = onBlurHandler;
        }
        
        return inputNode
    },
    
    /*************************************************************************
     * Methods used to create a label node
     *************************************************************************/
    createFieldLabelFormNode : function(labelId, isRequired, resourceListRequest, cssClassName) {
        var className = '';
        if (cssClassName) {
            className = cssClassName;
        }
        if (isRequired) {
            className += " required";
        }
        var elementNode = Builder.node("label", {className: className});        
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, labelId, elementNode);
        return elementNode;
    
    },
    
    /*************************************************************************
     * Methods that create a select element alone, without any fieldset.
     *************************************************************************/
    createSelectNode: function(elementId, onBlurHandler, labelMap, isMultiple, resourceListRequest, size) {
        var selectElement = Builder.node('select', {id: elementId + this.VALUE_SUFFIX, name: elementId + this.VALUE_SUFFIX, size: size});
        if (isMultiple) {
            selectElement.multiple = "true";
            selectElement.id = selectElement.id + 's';
            selectElement.name = selectElement.name + 's';            
        }
        
        if (onBlurHandler) {
            selectElement.onblur = onBlurHandler;
            selectElement.onchange = onBlurHandler;
        }
        if(isMultiple == false) {
            var option = Builder.node('option', {value: ''});
            MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, labelMap.selectLabelId, option);
            selectElement.appendChild(option);
        }
        
        return selectElement;
    },
     
    /*************************************************************************
     * Methods used to represent associations and compositions
     *************************************************************************/
    createSelectFieldNode: function(elementId, onBlurHandler, labelMap, isRequired, isMultiple, resourceListRequest, size) {
        var selectElement = this.createSelectNode(elementId, onBlurHandler, labelMap, isMultiple, resourceListRequest, size);

        var returnedNode =
            Builder.node('fieldset', {id:elementId, className: 'attribute'}, [
                this.createMessagesFormNode(elementId),
                this.createFieldLabelFormNode(labelMap.setOrAddLabelId, isRequired, resourceListRequest),
                selectElement
            ]);
        return returnedNode;
    },
    
    createSimpleAssociationFieldNode : function(elementId, onBlurHandler, labelMap, isRequired, resourceListRequest) {
        return this.createSelectFieldNode(elementId, onBlurHandler, labelMap, isRequired, false, resourceListRequest, 1);
    },
    
    createMultipleAssociationFieldNode : function(elementId, onBlurHandler, labelMap, isRequired, resourceListRequest, size) {
        if(size == null) {
            size = this.DEFAULT_MULTIPLE_ASSOCIATION_SIZE;
        }
        return this.createSelectFieldNode(elementId, onBlurHandler, labelMap, isRequired, true, resourceListRequest, size);
    },

    createHighVolumeAssociationFieldsetNode: function(elementId, onBlurHandler, labelId, isRequired, resourceListRequest) {
        var returnedNode = 
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createStringFieldFormNode(elementId + "-entry", onBlurHandler, labelId, isRequired, resourceListRequest),                
                this.createHiddenFieldFormNode(elementId + "-selection"),
                Builder.node("div", {id: elementId + "-choices", className: "autocomplete"})
            ]);
        return returnedNode;
    },

    changeControlPanel: function(oldControlPanel, newControlPanel) {
        if (oldControlPanel) {
            var parent = oldControlPanel.parentNode;
            parent.replaceChild(newControlPanel,oldControlPanel);
        }
    },
    
    createSingleCompositionFieldNode : function(elementId, setHandler, labelId, resourceListRequest) {
        var returnedNode =
            Builder.node('fieldset', {id:elementId, className: 'composition'}, [
                this.createLegendFormNode(labelId, false, resourceListRequest),
                this.createSetCompositionControlPanelNode(elementId, setHandler, resourceListRequest),
                Builder.node('div', {id: elementId + '-instances', className:'instances'})
            ]);
        return returnedNode;
    },
    
    createMultipleCompositionFieldNode : function(elementId, addHandler, labelId, resourceListRequest) {
        var spanNode = Builder.node('span');
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.add", spanNode);

        var addLink = Builder.node('a', {id : elementId + this.CONTROL_PANEL_SUFFIX + '-add', className: 'controlpanel-add', href: 'javascript:void(0)'});
        addLink.onclick = addHandler.bind(this);
        addLink.appendChild(spanNode);
        
        var returnedNode =
            Builder.node('fieldset', {id:elementId, className: 'composition'}, [
                this.createLegendFormNode(labelId, false, resourceListRequest),
                Builder.node('ul', {className:'controlpanel'}, [
                    Builder.node('li', [
                        addLink
                    ])
                ]),
                Builder.node('div', {id: elementId + '-instances', className:'instances'})
            ]);
        return returnedNode;
    
    },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Create View nodes
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    createDefaultFieldViewNode : function(elementId, labelId, isRequired, resourceListRequest) {
        var returnedNode =
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createFieldLabelFormNode(labelId, isRequired, resourceListRequest),
                Builder.node('span', $(elementId + this.VALUE_SUFFIX).value)
            ]);

        return returnedNode;
    },

    createSelectionFieldViewNode : function(elementId, labelId, isRequired, resourceListRequest) {
        var selectionLabel = "";
        var selectionNodeChildren = $(elementId + this.VALUE_SUFFIX).childNodes;
        for(var i = 0; i < selectionNodeChildren.length; i++) {
            if(selectionNodeChildren[i].selected == true) {
                selectionLabel = selectionNodeChildren[i].text;            
            }
        }
        var returnedNode =
            Builder.node('fieldset', {id: elementId, className: 'attribute'}, [
                this.createFieldLabelFormNode(labelId, isRequired, resourceListRequest),
                Builder.node('span', selectionLabel)
            ]);

        return returnedNode;
    },
        
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used as handler for the different buttons in the form
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    deleteCompositionHandler : function(event) {
        var instance = this;
        var toBeRemoved = $(instance.getInstanceDomId());
        
        if (toBeRemoved) {
            var parentNode = toBeRemoved.parentNode;
            parentNode.removeChild(toBeRemoved);
        }
        
        // remove validator from parent list
        var parentMapper = instance.parent;
        var validatorLists = parentMapper.validator.getValidatorLists();
        
        for(var i = 0; i < validatorLists.length; i++) {
            parentMapper.validator.removeValidator(instance.validator, validatorLists[i]);
        }
        
        var parentHandler = instance.parent.removeMapperHandler;
        
        parentHandler.call(parentMapper, instance);
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Method that removes a mapper from a list of mappers
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    removeMapper: function(mapper, mapperList) {
        for(var i = 0; i < mapperList.length; i++) {
            if(mapperList[i].instanceId == mapper.instanceId) {
                if (mapperList.length > 1) {
                    // remove element from array
                    for(var j = i; j < mapperList.length - 1; j++) {
                        mapperList[j] = mapperList[j+1];
                    }
                }
                mapperList.length = mapperList.length - 1;
            }
        }
    }
});
    MdaradXMLViewer = Class.create();
Object.extend(Object.extend(MdaradXMLViewer.prototype, MdaradXMLBase.prototype),
{
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Initialization methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    initialize : function (configuration) {
        this.initializeMdaradXMLViewer (configuration);
    },
    
    initializeMdaradXMLViewer : function (configuration) {
        this.initializeMdaradXMLBase(configuration);
        
        if(configuration.baseElement) this.baseElement = configuration.baseElement;
    },
    
    display : function(){
        alert("This is an abstract class. Must implement method display in concrete object "); 
    },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * General attributes
     *************************************************************************
     *************************************************************************
     *************************************************************************/
     baseElement: null, 
    
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods that fetches an instance
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    handleFetchInstanceResponseSuccess : function(requestObject) {
        alert("This is an abstract class. Must implement method handleFetchInstanceResponseSuccess in concrete object "); 
    }
    
});
    MdaradFormValidator = Class.create();
Object.extend(Object.extend(MdaradFormValidator.prototype, MdaradBase.prototype),
{
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * CONSTANTS
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    VALIDATION_REQUIRED_SUFFIX: '-required',

    VALIDATION_UNIQUE_SUFFIX: '-unique',

    VALIDATION_PASSWORD_FORMAT_SUFFIX: '-passwordFormat',

    VALIDATION_STRING_FORMAT_SUFFIX: '-stringFormat',

    VALIDATION_INTEGER_FORMAT_SUFFIX: '-integerFormat',

    VALIDATION_FLOAT_FORMAT_SUFFIX: '-floatFormat',

    VALIDATION_PERCENTAGE_FORMAT_SUFFIX: '-percentageFormat',

    VALIDATION_DATE_FORMAT_SUFFIX: '-dateFormat',

    VALIDATION_DATETIME_FORMAT_SUFFIX: '-datetimeFormat',

    VALIDATION_EMAIL_FORMAT_SUFFIX: '-emailFormat',

    VALIDATION_LOCALE_FORMAT_SUFFIX: '-localeFormat',

    VALIDATION_URI_FORMAT_SUFFIX: '-uriFormat',
    
    VALIDATION_VALUE_IN_RANGE_SUFFIX: '-valueInRange',
    
    VALIDATION_HUGE_ASSOCIATION_SUFFIX: '-hugeAssociation',

    initialize : function (configuration) {
        this.initializeMdaradFormValidator (configuration);
    },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Initialization methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/    
    initializeMdaradFormValidator : function (configuration) {
        this.initializeMdaradBase(configuration);
        
        this.pendingValidations = new Array();
    },    

    pendingValidations: null,
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used for multiple composition validation
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    
    containsValidator: function(validator, validatorList) {
        for(var i = 0; i < validatorList.length; i++) {
            if(validatorList[i].id == validator.instanceId) {
                return true;
            }
        }
        return false;
    }, 
    
    removeValidator: function(validator, validatorList) {
        for(var i = 0; i < validatorList.length; i++) {
            if(validatorList[i].id == validator.instanceId) {
                if (validatorList.length > 1) {
                    // remove element from array
                    for(var j = i; j < validatorList.length - 1; j++) {
                        validatorList[j] = validatorList[j+1];
                    }
                }
                validatorList.length = validatorList.length - 1;
            }
        }
    },

    
    /* Return an Array of Validator Lists */
    getValidatorLists: function() {
        alert("This method (getValidatorList)is abstract and should be overwritten in concrete classes");
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Total validation (before an action is called)
     *
     * This method should receive in the groupValidationArguments hash: 
     * - validationGroupId : The group that will be used to determine which validation 
     *                       is in progress
     * - onCompletion: The method that will be called if the validation is successful
     *
     * How it works: For every validation, a pendingValidation needs to be created
     * before the actual validation.  When the validation executes, it will mark
     * those validations as "treated" and whether they are successful or not.
     * After each validation, the validation will check if all the validations in 
     * its group are "treated".  If so, it will call the onCompletion method passed
     * as in the validationArguments hash.
     * 
     * The complexity with this system is to always keep the pendingValidations in sync
     * with the actual validations.  Therefore, if we add a validation, we need to 
     * also add a pendingValidation (in the getPendingValidations method).
     *
     *************************************************************************
     *************************************************************************
     *************************************************************************/
     validateBeforeCompletion: function(groupValidationArguments) {
        groupValidationArguments = this.preProcessValidation(groupValidationArguments, this.generalMessageDomId);
        
        //Add the calling context to the arguments
        groupValidationArguments.callingContext = this;

        //Set the pending validations
        this.pendingValidations = this.pendingValidations.concat(this.getPendingValidations(groupValidationArguments));        
        
        //Validate
        this.validate(groupValidationArguments);
     },
     
     getPendingValidations: function(groupValidationArguments) {
        alert("This method (getPendingValidations)is abstract and should be overwritten in concrete classes");
     },
     
     validate: function(validationArguments) {
        alert("This method (validate)is abstract and should be overwritten in concrete classes");
     },
    
     createPendingValidation: function(validationArguments, validationId) {
        var newPendingValidation = ({
            validationId: validationId,
            validationGroupId: validationArguments.validationGroupId,
            onCompletion: validationArguments.onCompletion,
            pending: true,
            successful: false,
            locale: validationArguments.locale
        });
        return newPendingValidation;
    }, 
    
     closePendingValidation: function(successful, validationArguments) {
        for(var i = 0; i < this.pendingValidations.length; i++) {
            var currentValidation = this.pendingValidations[i];
            if((currentValidation.validationId == validationArguments.validationId)
                    && (currentValidation.validationGroupId == validationArguments.validationGroupId)) {
                currentValidation.pending = false;
                currentValidation.successful = successful;
            }
        }
    },
    
    removeGroupValidationsFromPending: function(validationGroupId) {
        for(var i = 0; i < this.pendingValidations.length; i++) {
            var currentValidation = this.pendingValidations[i];
            if(currentValidation.validationGroupId == validationGroupId) {
                this.pendingValidations[i] = null;
            }
        }
        this.pendingValidations = this.pendingValidations.compact();
    },
    
    isGroupValidationComplete: function(validationGroupId) {
        var allCompleted = true;
        for(var i = 0; i < this.pendingValidations.length; i++) {
            var currentValidation = this.pendingValidations[i];
            if(currentValidation.validationGroupId == validationGroupId) {
                allCompleted = allCompleted && !currentValidation.pending;
            }
        }
        return allCompleted;
    },

    isGroupValidationSuccessful: function(validationGroupId) {
        var successful = 0;
        var count = 0;
        for(var i = 0; i < this.pendingValidations.length; i++) {
            var currentValidation = this.pendingValidations[i];
            if(currentValidation.validationGroupId == validationGroupId) {
                count++;
                if(!currentValidation.pending && currentValidation.successful) {
                    successful++;
                }
            }
        }
        return (successful == count);
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods used for validation
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    validate: function() {
        alert("This method is abstract and should be overwritten in concrete classes");
    },
    
    preProcessValidation: function(validationArguments, currentMessageDomId) {
        var localValidationArguments = new Array();
        if(validationArguments != null) {
            localValidationArguments = MdaradUtils.cloneObject(validationArguments);
        } 
        localValidationArguments.isModal = true;
        if(!localValidationArguments.messageDomId) {
            localValidationArguments.messageDomId = currentMessageDomId;
            localValidationArguments.isModal = false;

            //Clear the error messages
            this.clearElementValidationErrorMessages(currentMessageDomId);
        }
        if(!localValidationArguments.onSuccess) {
            localValidationArguments.onSuccess = null;
        }
        return localValidationArguments;
    },
    
    addValidationError: function(messageDomId, errorLabelId, paramResourceArray, isModal) {
        MdaradMessageHandler.addAlert(messageDomId, $H({resourceHandler: this.resourceHandler, messageKey: errorLabelId, paramResourceArray: paramResourceArray}), $H({isModal: isModal}));
    },

    clearValidationErrorMessages: function() {
        this.messageHashMap = new Object();
        var messageDoms = document.getElementsByClassName("messages");
        for(var i = 0; i < messageDoms.length; i++) {
            MdaradUtils.deleteAllChildren(messageDoms[i]);
        }
    },

    clearElementValidationErrorMessages: function(messageDomId) {
        this.messageHashMap = new Object();
        MdaradUtils.deleteAllChildren($(messageDomId));
    },

    completeValidation: function(successful, validationArguments) {
    	try {
	        //Take action (if from other context use it for completion)
	        var callingContext = this;
	        if(validationArguments.callingContext) {
	            callingContext = validationArguments.callingContext;
	        }
	        callingContext.completeValidationExecution(successful, validationArguments);
    	} catch(e) {
            MdaradUtils.logException(e)
            MdaradMessageHandler.addAlert(callingContext.generalMessageDomId, $H({resourceHandler: callingContext.resourceHandler}));
    	}
    },
    
    completeValidationExecution: function(successful, validationArguments) {
        //Execute the validation
        if(successful) {
            if(validationArguments.onSuccess) {
                validationArguments.onSuccess.call();
            }
        } else {
            if(validationArguments.onFailure) {
                validationArguments.onFailure.call();
            }
        }
        //If in a group validation, check if they are all complete
        if(validationArguments.validationGroupId) {
            //Complete the current validation
            this.closePendingValidation(successful, validationArguments);
            
            //Check if they are all complete (to call onCompletionMethod)
            if(this.isGroupValidationComplete(validationArguments.validationGroupId)) {
                validationArguments.onCompletion.call();
                this.removeGroupValidationsFromPending(validationArguments.validationGroupId);      
            }
        }
    },

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Concrete validation methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/

    _preProcessGenericValidation: function(errorMethod, validationArguments) {
        //Create clone not to modify the arguments reference
        var localValidationArguments = MdaradUtils.cloneObject(validationArguments);
        
        if(!localValidationArguments.onFailure) {
            localValidationArguments.onFailure = errorMethod;
        }
        
        return localValidationArguments;
    }, 
    
    validateRequiredField: function(labelId, fieldDomId, validationArguments) {
        var errorMsgKey = "errors.required";
        var parameterArray = [MdaradResourceHandlerUtils.getResourceHash(labelId)];
        if (validationArguments.locale) {
            errorMsgKey = "errors.required.localized";  
            parameterArray.push({value: validationArguments.locale});
        }
    
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, errorMsgKey, parameterArray, validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);
        
        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_REQUIRED_SUFFIX;
        
        //Verify that it validates
        var field = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        localValidationArguments.validationField = fieldDomId;
        var validates = true;
        if(!field || field == "") {
            validates = false;
        } 
        this.completeValidation(validates, localValidationArguments);
    },

    validateUniqueField: function(labelId, fieldDomId, uri, validationArguments) {
        var parameterArray = new Array();
        if (validationArguments.locale) {
            parameterArray.push({value: validationArguments.locale});
        }
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, labelId, parameterArray, validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_UNIQUE_SUFFIX;

        var instance = this;
        var field = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var AJAXRequest = new Ajax.Request(
           uri,
           {
               method: "get",
               requestHeaders: ['cache-control','no-cache','pragma','no-cache'],
               onSuccess: function(requestObject) {
                   instance.handleValidateUniqueFieldSuccess(requestObject, true, localValidationArguments);
               },
               onFailure: function(requestObject) {
                   instance.handleValidateUniqueFieldError(requestObject, true, localValidationArguments);
               }
            }
       );
    },
    
    handleValidateUniqueFieldSuccess: function(requestObject, successful, validationArguments) {
        var xmlDocument = MdaradUtils.getXMLFragment(requestObject, this.pathPrefix);
        //If there is an error message, it is because it was found
        if(xmlDocument.tagName == 'Message') {
            this.completeValidation(true, validationArguments);               
        } else {
            //Must make sure that is not the current element (same id)
            var receivedId = xmlDocument.getAttribute("id");
                
            var currentIdElement = $(this.domIdPrefix + "id" + this.VALUE_SUFFIX);
            if(currentIdElement) {
	            var currentId = currentIdElement.value;
	            
	            //...if so the validation is ok for it is possible to save over your own unique attribute
	            if(receivedId == currentId) {
	                this.completeValidation(true, validationArguments);               
	            } else {
	                this.completeValidation(false, validationArguments);               
	            }
	        } else {
                this.completeValidation(false, validationArguments);               
	        }
        }
    },

    handleValidateUniqueFieldError: function(requestObject, successful, validationArguments) {
        validationArguments.onFailure = this.addValidationError.bind(this, validationArguments.messageDomId, "global.system.exception", null, validationArguments.isModal);
        this.completeValidation(false, validationArguments);               
    },
    
    validateStringFormat: function(labelId, fieldDomId, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.string", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_STRING_FORMAT_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var field = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(field && field != "") {
            if(!field.match(/.*/)) {
                validates = false;
            }
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },
        
    validatePasswordFormat: function(labelId, fieldDomId, uri, validationArguments) {
        var parameterArray = new Array();
        if (validationArguments.locale) {
            parameterArray.push({value: validationArguments.locale});
        }
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.password", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_PASSWORD_FORMAT_SUFFIX;

        var instance = this;
        var field = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var AJAXRequest = new Ajax.Request(
           uri,
           {
               method: "get",
               requestHeaders: ['cache-control','no-cache','pragma','no-cache'],
               onSuccess: function(requestObject) {
                   instance.handleValidatePasswordFieldSuccess(requestObject, true, localValidationArguments);
               },
               onFailure: function(requestObject) {
                   instance.handleValidatePasswordFieldError(requestObject, true, localValidationArguments);
               }
            }
       );
    },
    
    handleValidatePasswordFieldSuccess: function(requestObject, successful, validationArguments) {
        var xmlDocument = MdaradUtils.getXMLFragment(requestObject, this.pathPrefix);
        if(xmlDocument.tagName == 'Message') {
            var messageValue = xmlDocument.firstChild.nodeValue;
            if(messageValue == "true") {
                this.completeValidation(true, validationArguments);               
            } else {
                this.completeValidation(false, validationArguments);
            }
        } else {
            this.completeValidation(false, validationArguments);
        }
    },

    handleValidatePasswordFieldError: function(requestObject, successful, validationArguments) {
        validationArguments.onFailure = this.addValidationError.bind(this, validationArguments.messageDomId, "global.system.exception", null, validationArguments.isModal);
        this.completeValidation(false, validationArguments);               
    },
    
    validateIntegerFormat: function(labelId, fieldDomId, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.integer", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_INTEGER_FORMAT_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var field = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(field && field != "") {
            if(!field.match(/^[+-]?\d+$/)) {
                validates = false;
            }
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },

    validateFloatFormat: function(labelId, fieldDomId, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.float", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_FLOAT_FORMAT_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var field = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(field && field != "") {
            if(!field.match(/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)) {
                validates = false;
            }
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },

    validatePercentageFormat: function(labelId, fieldDomId, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.percentage", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_PERCENTAGE_FORMAT_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var field = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(field && field != "") {
            if(!field.match(/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/)) {
                validates = false;
            }
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },
    validateLocaleFormat: function(labelId, fieldDomId, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.locale", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_LOCALE_FORMAT_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var field = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(field && field != "") {
            if(!field.match(/\w\w/)) {
                validates = false;
            }
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },

    validateUriFormat: function(labelId, fieldDomId, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.uri", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_URI_FORMAT_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var field = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(field && field != "") {
            if(!field.match(/.+/)) {
                validates = false;
            }
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },

    validateDateFormat: function(labelId, fieldDomId, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.date", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_DATE_FORMAT_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var date = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(date && date != "") {
            if(!date.match(/([0-9][0-9][0-9][0-9])-([0-1]?[0-9])-([0-3]?[0-9])/)) {
                validates = false;
            }
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },
    
    validateDatetimeFormat: function(labelId, fieldDomId, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.datetime", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_DATETIME_FORMAT_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var date = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(date && date != "") {
            if(!date.match(/([0-9][0-9][0-9][0-9])-([0-1]?[0-9])-([0-3]?[0-9])\s([0-2]?[0-9]):([0-5]?[0-9])/)) {
                validates = false;
            }
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },
    
    validateEmailFormat: function(labelId, fieldDomId, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.email", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_EMAIL_FORMAT_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var email = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(email && email != "") {
            if(!email.match(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/)) {
                validates = false;
            }
        }        
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },
    
    validateValueInRange: function(labelId, fieldDomId, startValue, endValue, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.range", [MdaradResourceHandlerUtils.getResourceHash(labelId), $H({value: startValue}), $H({value: endValue})], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        //Set validation id
        localValidationArguments.validationId = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale) + this.VALIDATION_VALUE_IN_RANGE_SUFFIX;

        //Verify that it validates
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var value = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var validates = true;
        if(value < startValue || value >= endValue) {
            validates = false;
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    },
    
    getLocalizedDomId: function(fieldDomId, locale) {
        return fieldDomId + MdaradUtils.getLocaleSuffix(locale);
    },
    
    validateHugeAssociation: function(labelId, fieldDomIdPrefix, validationArguments) {
        var errorMethod = this.addValidationError.bind(this, validationArguments.messageDomId, "errors.invalidHugeAssociationSelection", [MdaradResourceHandlerUtils.getResourceHash(labelId)], validationArguments.isModal);
        var localValidationArguments = this._preProcessGenericValidation(errorMethod, validationArguments);

        var fieldDomId = fieldDomIdPrefix + "-entry" + this.VALUE_SUFFIX;
        var fieldDomIdSelection = fieldDomIdPrefix + "-selection" + this.VALUE_SUFFIX;
        
        //Set validation id
        localValidationArguments.validationId = fieldDomIdPrefix + this.VALIDATION_HUGE_ASSOCIATION_SUFFIX;

        //Verify that both or none are set
        localValidationArguments.validationField = this.getLocalizedDomId(fieldDomId, localValidationArguments.locale);
        var value = $(this.getLocalizedDomId(fieldDomId, localValidationArguments.locale)).value;
        var selection = $(fieldDomIdSelection).value;
        var validates = true;
        if(((value != null && value != "") && (selection == null || selection == "")) || ((value == null || value == "") && (selection != null && selection != ""))) {
            validates = false;
        }
        //Take action
        this.completeValidation(validates, localValidationArguments);
    }

});
    MdaradXMLListFilterMapper = Class.create();
Object.extend(Object.extend(MdaradXMLListFilterMapper.prototype, MdaradXMLBase.prototype),
{
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Initialization methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    initialize : function (configuration) {
        this.initializeMdaradXMLListFilterMapper (configuration);
    },
    
    initializeMdaradXMLListFilterMapper : function (configuration) {
        this.initializeMdaradXMLBase(configuration);
        
        if(configuration.listCallback) this.listCallback = configuration.listCallback;        
    },        
                
    listCallback: null,
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Filter Form Creation Methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    createListFilterForm: function(resourceListRequest) {
        var filterSubmitButton = Builder.node("input", {
        	type: "button"
        });    	
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, 'org.mdarad.framework.resources.header.find.legend', filterSubmitButton, "value");
        filterSubmitButton.onclick = this.listCallback;
        
        var filterFormContainer = Builder.node("div", {
    	        className: "filter"
    	    }, [
                Builder.node("form", {className: "filter-form"}, [
                    this.createFilterChildNodes(resourceListRequest),
                    filterSubmitButton
                ])
            ]
        );
        return filterFormContainer; 
    },
    
    createFilterChildNodes: function(resourceListRequest) {
        alert("This is an abstract class. Must implement method createFilterChildNodes in concrete object ");
    }, 
    	    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Criteria retrieval method
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    getCriteria: function() {
        alert("This is an abstract class. Must implement method getCriteria in concrete object ");
    }

});
    MdaradXMLListMapper = Class.create();
Object.extend(Object.extend(MdaradXMLListMapper.prototype, MdaradXMLBase.prototype),
{
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Initialization methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    initialize : function (configuration) {
        this.initializeMdaradXMLListMapper (configuration);
    },
    
    initializeMdaradXMLListMapper : function (configuration) {
        this.initializeMdaradBase(configuration);
        
        this.messageHashMap = new Object();
        if(configuration.listDiv) this.listDiv = configuration.listDiv;
        if(configuration.baseURI) this.baseURI = configuration.baseURI;
        if (configuration.generalMessageDomId) {
            this.generalMessageDomId = configuration.generalMessageDomId;
        } else {
            this.generalMessageDomId = this.getDomContentPrefix() +'general' + this.MESSAGES_SUFFIX;
        }
        
        this.setFilterMapper();
    },        
    
    getInstanceName : function(elementNode) {
        alert("This is an abstract class. Must implement method getInstanceName in concrete object "); 
    },
        
    getDomContentPrefix : function(elementNode) {
        var id = "";
        if(elementNode && elementNode.getAttribute("id")) {
            id = elementNode.getAttribute("id");
        }
        return this.getDomContentPrefixFromId(id);
    },
    
    getDomContentPrefixFromId : function(id) {
        id = "[" + id + "]";
        return this.getInstanceName() + id + this.PREFIX_SEPARATOR;
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * General attributes
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 
    baseURI: null,
    listDiv: null,
    filterMapper: null,
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Display Methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/ 

    setFilterMapper: function(instanceId) {
        alert("This is an abstract class. Must implement method setFilterMapper in concrete object "); 
    },
    
    displayList: function() {
        try {
            this.createListElements();
	        this.fetchInstances();
	    } catch(e) {
            MdaradUtils.logException(e);
	        MdaradMessageHandler.addAlert(this.generalMessageDomId, $H({resourceHandler: this.resourceHandler}));
	    }
    },
    
    clearList: function() {
        var tbodyDomElement = $("tbody-" + this.getInstanceName());
        if(tbodyDomElement) {
            MdaradUtils.deleteAllChildren(tbodyDomElement);
        }
    },
    
    refreshList: function() {
        this.clearList();
        try {
    	    this.fetchInstances();
	    } catch(e) {
            MdaradUtils.logException(e);
	        MdaradMessageHandler.addAlert(this.generalMessageDomId, $H({resourceHandler: this.resourceHandler}));
	    }
    },
    
    createListElements: function() {
        if(this.listDiv) {
            var listChildNodes = this.createListChildNodes();
            for(var i=0; i < listChildNodes.length; i++) {
                this.listDiv.appendChild(listChildNodes[i]);
            }
        }
    },
    
    createListChildNodes: function() {
        var childNodes = new Array();

        //Create the list (and gather the resources that are updated as soon as completed)
        var resourceListRequest = new Array();

        //Add filter form
        var filterNode = null;
        if(this.filterMapper && this.filterMapper.getCriteria() != null) {
            filterNode = this.filterMapper.createListFilterForm(resourceListRequest);
        }

        //Top Actions container
        var topActionsContainerDiv = this.createActionsContainerDiv(resourceListRequest);
        
        //Top Multiple Actions container
        var topMultipleActionsContainerDiv = this.createMultipleActionsContainerDiv(resourceListRequest);        
        
        //Top Multiple Selection container
        var topMultipleSelectionContainerDiv = this.createMultipleSelectionContainerDiv(resourceListRequest);

        //List itself 
        var listTable = this.createListTable(resourceListRequest);
        
        //Bottom Multiple Selection container
        var bottomMultipleSelectionContainerDiv = this.createMultipleSelectionContainerDiv(resourceListRequest);

        //Bottom Mutliple Actions container
        var bottomMultipleActionsContainerDiv = this.createMultipleActionsContainerDiv(resourceListRequest);        

        //Bottom Actions container
        var bottomActionsContainerDiv = this.createActionsContainerDiv(resourceListRequest);
        
        //Add nodes to list
        
        if (filterNode != null) {
            childNodes.push(filterNode);
        }
        childNodes.push(topActionsContainerDiv);
        childNodes.push(topMultipleActionsContainerDiv);
        childNodes.push(topMultipleSelectionContainerDiv);
        childNodes.push(listTable);
        childNodes.push(bottomMultipleSelectionContainerDiv);
        childNodes.push(bottomMultipleActionsContainerDiv);
        childNodes.push(bottomActionsContainerDiv);

        this.resourceHandler.updateResources(resourceListRequest);

        return childNodes;
    }, 

    createActionsContainerDiv : function(resourceListRequest) {
        var instance = this;
        var actionsContainerDiv = Builder.node("div", {className: "actions-container"});
    
        var actionsContainerExplanationSpan = Builder.node("span", {className: "actions-explanation"});
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.actions.container", actionsContainerExplanationSpan);

        var actionsContainerAddSpanLink = Builder.node("a", {href: "javascript:void(0);"});
        actionsContainerAddSpanLink.onclick = instance.showElementMapper.bind(instance, null, false);
        var actionsContainerAddSpan = Builder.node("span", 
            {className: "actions-add"},
            [actionsContainerAddSpanLink]
        );
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.add", actionsContainerAddSpanLink);

        actionsContainerDiv.appendChild(actionsContainerExplanationSpan);
        actionsContainerDiv.appendChild(actionsContainerAddSpan);
        return actionsContainerDiv;
    },

    createMultipleActionsContainerDiv : function(resourceListRequest) {
        var multipleActionsContainerDiv = Builder.node("div", {className: "multiple-actions-container"});
    
        var multipleActionsContainerExplanationSpan = Builder.node("span", {className: "multiple-action-explanation"});
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.multipleActionsContainer", multipleActionsContainerExplanationSpan);

        var multipleActionsContainerDeleteSpan = Builder.node("span", 
            {className: "multiple-action-delete"}
        );
        var multipleActionsContainerDeleteSpanLink = Builder.node("a", {href: "javascript:void(0);"}, [multipleActionsContainerDeleteSpan]);
        multipleActionsContainerDeleteSpanLink.onclick = this.deleteSelectedElements.bind(this);
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.delete", multipleActionsContainerDeleteSpan);

        multipleActionsContainerDiv.appendChild(multipleActionsContainerExplanationSpan);
        multipleActionsContainerDiv.appendChild(multipleActionsContainerDeleteSpanLink);
        return multipleActionsContainerDiv;
    },
    
    createMultipleSelectionContainerDiv : function(resourceListRequest) {
        var instance = this;
        var multipleSelectionContainerDiv = Builder.node("div", {className: "multiple-selection-container"});

        var multipleSelectionContainerExplanationSpan = Builder.node("span", {className: "multiple-selection-explanation"});
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.multipleSelectionContainer", multipleSelectionContainerExplanationSpan);

        var multipleSelectionContainerAllSpanLink = Builder.node("a", {href: "javascript:void(0);"});
        multipleSelectionContainerAllSpanLink.onclick = this.selectAll.bind(this);
        var multipleSelectionContainerAllSpan = Builder.node("span", 
            {className: "multiple-selection-all"}, 
            [multipleSelectionContainerAllSpanLink]
        );
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.multipleSelectionContainer.all", multipleSelectionContainerAllSpanLink);

        var multipleSelectionContainerSeparatorSpan = Builder.node("span", ", ");

        var multipleSelectionContainerNoneSpanLink = Builder.node("a", {href: "javascript:void(0);"});
        multipleSelectionContainerNoneSpanLink.onclick = this.selectNone.bind(this);
        var multipleSelectionContainerNoneSpan = Builder.node("span", 
            {className: "multiple-selection-none"}, 
            [multipleSelectionContainerNoneSpanLink]
        );
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.multipleSelectionContainer.none", multipleSelectionContainerNoneSpanLink);

        multipleSelectionContainerDiv.appendChild(multipleSelectionContainerExplanationSpan);
        multipleSelectionContainerDiv.appendChild(multipleSelectionContainerAllSpan);
        multipleSelectionContainerDiv.appendChild(multipleSelectionContainerSeparatorSpan);
        multipleSelectionContainerDiv.appendChild(multipleSelectionContainerNoneSpan);
        return multipleSelectionContainerDiv;
    },
    
    createActionsDescriptor: function(resourceListRequest) {
        var controlPanelContainerTh = Builder.node("th", {
            className: "list-header-actions"  
        });
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.actions", controlPanelContainerTh);
        return controlPanelContainerTh;
    },

    createSelectionDescriptor: function(resourceListRequest) {
        var selectionContainerTh = Builder.node("th", {
            className: "list-header-selection"	
        });
        MdaradResourceHandlerUtils.addResourceToResourceList(resourceListRequest, "org.mdarad.framework.resources.list.multipleSelectionContainer.header", selectionContainerTh);
        return selectionContainerTh;
    },
    
    createListTable: function(resourceListRequest) {
        var listTable = Builder.node("table", {className: "list", id: this.getInstanceName()});

        var listTableThead = Builder.node("thead", this.createTheadRowsArray(resourceListRequest));       
        listTable.appendChild(listTableThead);
        
        var listTableTbody = Builder.node("tbody", {className: "instances", id: "tbody-" + this.getInstanceName()});
        listTable.appendChild(listTableTbody);
        
        return listTable;
    },
    
    createTheadRowsArray: function(resourceListRequest) {
        var rowsArray = new Array();
        
        //Descriptors row
        var fieldDescriptors = new Array();
        fieldDescriptors.push(this.createSelectionDescriptor(resourceListRequest));
        fieldDescriptors.push(this.createActionsDescriptor(resourceListRequest));
        fieldDescriptors = fieldDescriptors.concat(this.createFieldDescriptors(resourceListRequest));
        
        rowsArray.push(Builder.node("tr", fieldDescriptors));
        
        return rowsArray;
    },
    
    createFieldDescriptors: function(resourceListRequest) {
        alert("This is an abstract class. Must implement method createFieldDescriptors in concrete object "); 
    },    
    
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Methods that fetches an instance
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    fetchInstances : function() {
        var instance = this;
        var URI = instance.pathPrefix + this.baseURI + "/xml/list.do";
        MdaradMessageHandler.addNotification(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}));
        var AJAXRequest = new Ajax.Request(
           URI,
           {
               method: "get",
               requestHeaders: ['cache-control','no-cache','pragma','no-cache', 'content-type', 'application/xml'],
               onSuccess: function() {
                   instance.handleFetchInstancesResponseSuccess(arguments[0]);
                   MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
               },
               onFailure: function() {
                   instance.handleFetchInstancesResponseError(arguments[0]);
                   MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
               }
           }
       );
    },
    
    handleFetchInstancesResponseError : function(request) {
        var instance = this;
        try {
            MdaradMessageHandler.addAlert(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}));
        } catch(e) {
            MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
            MdaradMessageHandler.addAlert(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}));
            MdaradUtils.logException(e);
        }
    },
    
    handleFetchInstancesResponseSuccess : function(requestObject) {
    	var instance = this;
        try {
	        var returnedXMLDocumentFragment = MdaradUtils.getXMLFragment(requestObject, instance.pathPrefix);
	        instance.populateListFromXML(returnedXMLDocumentFragment);
        } catch(e) {
            MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
            MdaradMessageHandler.addAlert(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}));
            MdaradUtils.logException(e);
        }
    },    

    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Populate List from XML
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    populateListFromXML: function(xmlNode) {
        try {
            var resultsNode = MdaradUtils.findChild(xmlNode.childNodes, "results");
            
            //Create a row for each result in the Node
            var tbodyDomElement = $("tbody-" + this.getInstanceName());
            
            for(var i = 0; i < resultsNode.childNodes.length; i++) {
                if(resultsNode.childNodes[i].nodeType == 1) {
                    var currentRow = Builder.node("tr", {
                        className: "instance",
                        id: this.getDomContentPrefix(resultsNode.childNodes[i])
                    });
                    
                    //Selection checkbox
                    currentRow.appendChild(this._populateSelectionCheckBoxElement(resultsNode.childNodes[i]));
                    
                    //Actions element
                    currentRow.appendChild(this._populateActionsElement(resultsNode.childNodes[i]));
                    
                    //Content elements
                    var contentNodes = this.populateContentElements(resultsNode.childNodes[i]);
                    contentNodes.each(function(contentNode) {
                        currentRow.appendChild(contentNode);
                    });

                    tbodyDomElement.appendChild(currentRow);
                }
            }
        } catch(e) {
            MdaradUtils.logException(e);
            MdaradMessageHandler.addAlert(this.generalMessageDomId, $H({resourceHandler: this.resourceHandler}));
        }
    },

    populateContentElements: function(xmlDoc) {
        alert("This is an abstract class. Must implement method in concrete object populateContentElements"); 
    },
    
    _populateSelectionCheckBoxElement: function(elementNode) {
        return Builder.node("td", { 
                id: this.getDomContentPrefix(elementNode) + "selectionCheckbox",
                name: this.getDomContentPrefix(elementNode) + "selectionCheckbox"
            },
            [Builder.node("input", {type: "checkbox", className: "selectionCheckbox", value: elementNode.getAttribute("id")})]
        );
    }, 

    _populateActionsElement: function(elementNode) {
    	var instance = this;
        var viewImg = Builder.node("img", {
            src: this.pathPrefix + "/static/img/viewButton.jpg",
            id: this.getDomContentPrefix(elementNode) + "controlpanel-view",
            className: "controlpanel-view"
        });
        viewImg.onclick = instance.showElementMapper.bind(instance, elementNode.getAttribute("id"), true);
        var editImg = Builder.node("img", {
            src: this.pathPrefix + "/static/img/editButton.gif",
            href: "javascript:void(0)",
            id: this.getDomContentPrefix(elementNode) + "controlpanel-edit",
            className: "controlpanel-edit"
        });
        editImg.onclick = instance.showElementMapper.bind(instance, elementNode.getAttribute("id"), false);
        var deleteImg = Builder.node("img", {
            src: this.pathPrefix + "/static/img/deleteButton.gif",
            href: "javascript:void(0)",
            id: this.getDomContentPrefix(elementNode) + "controlpanel-delete",
            className: "controlpanel-delete"
        });
        deleteImg.onclick = instance.deleteElement.bind(instance, elementNode.getAttribute("id"));
        
        this.resourceHandler.updateResource(MdaradResourceHandlerUtils.getResourceHashForElement("org.mdarad.framework.resources.list.view", viewImg, "alt"));
        this.resourceHandler.updateResource(MdaradResourceHandlerUtils.getResourceHashForElement("org.mdarad.framework.resources.list.edit", editImg, "alt"));
        this.resourceHandler.updateResource(MdaradResourceHandlerUtils.getResourceHashForElement("org.mdarad.framework.resources.list.delete", deleteImg, "alt"));
        
        return Builder.node("td", {className: "controlpanelContainer"},[
            Builder.node("ul", {className: "controlPanel"},[
//                Builder.node("a", { href: "javascript:void(0)"}, [
//                    viewImg
//                ]),
                Builder.node("a", { href: "javascript:void(0)"}, [
                	editImg
                ]),
                Builder.node("a", { href: "javascript:void(0)"}, [
                	deleteImg
                ])
            ])
        ]);
    }, 
    createAttributeContentElement: function(attributeName, elementNode) {
        var attributeValue = "";
        var attribute = MdaradUtils.findChild(elementNode.childNodes, attributeName);
        if(attribute) {
            var attributeValue = "";
            if(attribute && attribute.childNodes[0]) {
                attributeValue = attribute.childNodes[0].data;
            }
        }
        return this.createContentElement(attributeName, attributeValue, elementNode);
    },

    createDateAttributeContentElement: function(attributeName, elementNode) {
        var attributeValue = "";
        var attribute = MdaradUtils.findChild(elementNode.childNodes, attributeName);
        if(attribute) {
            var attributeValue = "";
            if(attribute && attribute.childNodes[0]) {
                attributeValue = attribute.childNodes[0].data;
            }
        }
        return this.createContentElement(attributeName, attributeValue, elementNode);
    },

    createDatetimeAttributeContentElement: function(attributeName, elementNode) {
        var attributeValue = "";
        var attribute = MdaradUtils.findChild(elementNode.childNodes, attributeName);
        if(attribute) {
            var attributeValue = "";
            if(attribute && attribute.childNodes[0]) {
                //Convert date to string
                var date = new Date();
                date.setTime(attribute.childNodes[0].data);
                attributeValue = MdaradUtils.convertDateToDateString(date) + " " + MdaradUtils.convertDateToTimeString(date);
            }
        }
        return this.createContentElement(attributeName, attributeValue, elementNode);
    },


    createAssociationContentElement: function(associationName, className, elementNode) {
        var elementLabel = "";
        var associationChild = MdaradUtils.findChild(elementNode.childNodes, associationName);
        if(associationChild) {
            var elementChild = MdaradUtils.findChild(associationChild.childNodes, className);
            if(elementChild) {
                elementLabel = elementChild.getAttribute("label");
            }
        }
        return this.createContentElement(associationName, elementLabel, elementNode);
    },

    createContentElement: function(elementName, value, elementNode) {
        var toReturnNode = Builder.node("td", 
            {className: "attribute", id: this.getDomContentPrefix(elementNode) + elementName},
            value
        );
        return toReturnNode;
    },
    
    /*************************************************************************
     *************************************************************************
     *************************************************************************
     * Select methods
     *************************************************************************
     *************************************************************************
     *************************************************************************/
    selectAll: function() {
        var checkboxes = document.getElementsByClassName("selectionCheckbox");
        checkboxes.each(function(checkbox) {
            checkbox.checked = true;
        });
    },
    
    selectNone: function() {
        var checkboxes = document.getElementsByClassName("selectionCheckbox");
        checkboxes.each(function(checkbox) {
            checkbox.checked = false;
        });
    },
    
    deleteSelectedElements: function() {
        var instance = this;

        //Create an element node for each selected element
        var xmlDoc = MdaradUtils.createXMLDocument();
        var elementNodes = new Array();
        var checkboxes = document.getElementsByClassName("selectionCheckbox");
        checkboxes.each(function(checkbox) {
            if(checkbox.checked) {
                //Must create a placeholder for all selected elements
                elementNodes.push(Mdarad.Builder.node(xmlDoc, instance.getInstanceName(), {
                    refid: checkbox.getAttribute("value"),
                    label: ""
                }));
            }
        });    
        if(elementNodes.length > 0) {
            //Create an xmlDocument to hold the selected elements
            xmlDoc.appendChild(Mdarad.Builder.node(xmlDoc, "collection", [elementNodes]));

            //Create inquiry with callback
            MdaradMessageHandler.addInquiry($H({
                                                resourceHandler:this.resourceHandler,
                                                messageKey: "org.mdarad.framework.resources.list.instance.delete.warning"
                                            }),
                                            $H({okCallback: instance.executeDeleteSelectedElements.bind(instance, xmlDoc)}));
        } else {
            MdaradMessageHandler.addAlert(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler, messageKey: "org.mdarad.framework.resources.list.instance.actions.noneSelected"}), $H({isModal: true}));
        }
    }, 
    
    executeDeleteSelectedElements: function(xmlDoc) {
        var instance = this;
        var URI = instance.pathPrefix + instance.baseURI + "/xml/multipleDelete.do";

        //Close inquiry before putting notification message
        Dialog.closeInfo();
        MdaradMessageHandler.addNotification(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}));
        
        var AJAXRequest = new Ajax.Request(
           URI,
           {
               method: "post",
               postBody: xmlDoc,
               requestHeaders: ['cache-control','no-cache','pragma','no-cache', 'content-type', 'application/xml'],
               onSuccess: function(requestObject) {
                   instance.handleDeleteSelectedElementsSuccess(requestObject);
                   MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
               },
               onFailure: function(requestObject) {
                   instance.handleDeleteSelectedElementsError(requestObject);
                   MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
               }
            }
       );
    },
    
    handleDeleteSelectedElementsError: function(requestObject) {
        MdaradMessageHandler.addAlert(this.generalMessageDomId, $H({resourceHandler: this.resourceHandler}));
    },

    handleDeleteSelectedElementsSuccess: function(requestObject) {
        var instance = this;
        try {
            var xmlDocument = MdaradUtils.getXMLFragment(requestObject, instance.pathPrefix);
    
            // Only check if an error occured
            if(xmlDocument && xmlDocument.tagName == 'Message') {
                MdaradMessageHandler.addAlert(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler, content: xmlDocument.firstChild.nodeValue}), $H({isModal: false}));
            } else {
                //Successful
                MdaradUtils.deleteAllChildren($(instance.generalMessageDomId));
                MdaradMessageHandler.addSuccess(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}), $H({isModal: false}));
                
                //Refetch list and display
                instance.refreshList();
            }
        } catch(e) {
            MdaradUtils.logException(e);
            MdaradMessageHandler.addAlert(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}), $H({isModal: false}));
        }
    },

    showElementMapper : function(elementId, isReadOnly) {
        alert("This is an abstract class. Must implement method showElementMapper in concrete object "); 
    },
    
    deleteElement: function(elementId) {
        var instance = this;

        MdaradMessageHandler.addInquiry(
                    $H({
                        resourceHandler:this.resourceHandler,
                        messageKey: "org.mdarad.framework.resources.list.instance.delete.warning"
                    }),
                    $H({okCallback: instance.executeDeleteElement.bind(instance, elementId)}));       
    },

    executeDeleteElement: function(elementId) {
        var instance = this;
        var URI = instance.pathPrefix + instance.baseURI + "/xml/delete.do?id=" + elementId;
        
        //Close inquiry before putting notification message
        Dialog.closeInfo();
        MdaradMessageHandler.addNotification(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}));
        
        var AJAXRequest = new Ajax.Request(
           URI,
           {
               method: "get",
               requestHeaders: ['cache-control','no-cache','pragma','no-cache', 'content-type', 'application/xml'],
               onSuccess: function(requestObject) {
                   instance.handleDeleteElementSuccess(requestObject);
                   MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
               },
               onFailure: function(requestObject) {
                   instance.handleDeleteElementError(requestObject);
                   MdaradMessageHandler.removeNotification(instance.generalMessageDomId);
               }
            }
       );
    },
    
    handleDeleteElementError: function(requestObject) {
        MdaradMessageHandler.addAlert(this.generalMessageDomId, $H({resourceHandler: this.resourceHandler}));
    },

    handleDeleteElementSuccess: function(requestObject) {
        var instance = this;
        try {
            var xmlDocument = MdaradUtils.getXMLFragment(requestObject, instance.pathPrefix);
    
            // Only check if an error occured
            var success = false;
            if(xmlDocument && xmlDocument.tagName == 'Message') {
            	var statusCode = xmlDocument.getAttribute("statusCode");
            	if(statusCode && statusCode == "200") {
	                //Successful
	                MdaradMessageHandler.addSuccess(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}), $H({isModal: false}));
	                
	                //Refetch list and display
	                instance.refreshList();
	                success = true;
            	}
            } 
            if(!success) {
                MdaradMessageHandler.addAlert(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler, content: xmlDocument.firstChild.nodeValue}), $H({isModal: false}));
            }
        } catch(e) {
            MdaradUtils.logException(e);
            MdaradMessageHandler.addAlert(instance.generalMessageDomId, $H({resourceHandler: instance.resourceHandler}), $H({isModal: false}));
        }
    }
});
    MdaradLocalizationContext = Class.create();
Object.extend(Object.extend(MdaradLocalizationContext.prototype, MdaradBase.prototype),
{
    initialize : function (configuration) {
        this.initializeMdaradLocalizationContext(configuration);
    },
    
    initializeMdaradLocalizationContext : function (configuration) {
        this.initializeMdaradBase(configuration);
        
        if(configuration.defaultLocale) {
            this.defaultLocale = configuration.defaultLocale;
        }
        
        if(configuration.currentLocale) {
            this.currentLocale = configuration.currentLocale;
        }
        this._locales = new Array();
        this.defaultLocale = "en";
    },
    
    defaultLocale : null,
    currentLocale : null,
    _locales : null,
    
    addLocale : function(locale) {
        if(locale) {
            this._locales.push(locale);
        } else {
            throw "The locale cannot be null when added to localization context";
        }
    },
    
    removeLocale : function(locale) {
    	for(var i = 0; i < this._locales.length; i++) {
            if(this._locales[i] == locale) {
                this._locales[i] == null;
                break;
            }
    	}
    	this._locales = this._locales.compact();
    },
    
    getLocales : function() {
        return this._locales;
    }
});