/*
 * Copyright (c) Hyperwave GmbH 2010. All rights reserved.
 * Object.js,v 1.10 2003/04/23 09:29:14 szwoelf Exp
 *
 * The following functions form the Object JavaScript 1.2 environment.
 *
 * <copyright>
 *  Copyright (c) Hyperwave GmbH 2010
 * </copyright>
 *
 * $Id: Object.js 157941 2010-08-20 09:50:09Z cgoess $
 */

if ( typeof ojs != "undefined" )
{
  var text = "Illegal State: double include of Object.js";
  alert(text);
  throw text;
}

var ua$ = navigator.userAgent.toLowerCase();
var ua_isSafari$ = (ua$.indexOf("safari") >= 0);
var ua_isKonqueror$ = (ua$.indexOf("konqueror") >= 0);
var ua_isFireFox$ = (ua$.indexOf("firefox") >= 0);
var ua_isMicrosofInternetExplorer$ = (ua$.indexOf("msie") >= 0);

LANG_OBJECTJS_REGEXP_WHITESPACESLINESTART = new RegExp("^ *", "g");
LANG_OBJECTJS_REGEXP_WHITESPACESLINEEND   = new RegExp(" *$", "g");

/*
 * "zoom factor" - uncomment these lines when measuring memory leaks:
 *
var s = "1234567890";
var zoom = [];
for ( var i = 0; i < 18; ++i )
{
  zoom[zoom.length] = s = s + s;
}
//zoom = null;
*/

/**
 * This function can be used to create instances of classes which are
 * not native in JavaScript (unlike Function, Object, Array,...).
 * It can be used instead of the JavaScript <code>new</code> operator.
 * 
 * @param aClass: Function: the constructor function of the class to
 *   instantiate.  
 * 
 * @deprecated since 2002-12-03.
 *   Reasons:
 *   <ul>
 *     <li>JavaScript 1.3 isn't required anymore. 
 *     <li>JavaScript constructors seem to work quite well now ;-).
 *   </ul>
 */
function newInstanceOf ( aClass )
{
  // ... and if this something might be a constructor function of a
  // class
  if ( typeof (aClass) != "function" )
  {
    // an exception should be thrown, but to use the function on 
    // client and server side, returns only null
    return null;
  }

  // create a new instance of the wished class using the new keyword
  // CAUTION: only 5 parameters are allowed in a constructor!
  var myObj;
  switch ( arguments.length - 1 )
  {
  case 0:
    myObj = new aClass ();
    break;
  case 1:
    myObj = new aClass ( arguments[1] );
    break;
  case 2:
    myObj = new aClass ( arguments[1], arguments[2] );
    break;
  case 3:
    myObj = new aClass ( arguments[1], arguments[2], arguments[3] );
    break;
  case 4:
    myObj = new aClass ( arguments[1], arguments[2], arguments[3],
                         arguments[4] );
    break;
  case 5:
    myObj = new aClass ( arguments[1], arguments[2], arguments[3],
                         arguments[4], arguments[5] );
    break;
  default:
    return null;
  }
  return myObj;
}

/** 
 * This function implements ECMA conform inheritance for JavaScript
 * classes. This inheritance covers all topics concerning
 * prototyping, such as: 
 * <UL>
 *   <LI>access to prototyped members of the baseClass.</LI> 
 *   <LI>It adds a <code>static_</code> object holding all static
 *       properties and methods to the derivedClass. Takes also care
 *       about retrieving static members of the super class by
 *       accessing these via the using the  derived Class.</LI>
 *   <LI>It adds a handle to the base Class (super_) to enable access
 *       to eventually overridden baseClassfunctions.</LI>
 * </UL>
 * 
 * Invariant: We cannot assign the <code>super_</code> property to
 *   the <code>static_</code> or the prototype chain. The reason
 *   can be explained by the following example.
 * 
 *   If one derives Class C from Class B and
 *                  Class B from Class A. Now he or she can
 *   instantiate an object o of Class C. Any method inherited from
 *   Class B called in the scope of object o will have Class B
 *   as <code>super</code> (because it was asigned to the prototype
 *   chain or the "static chain"). In fact the programmer will expect 
 *   Class A in this case! </p>
 *   A possible solution: the super_ property will be assigned
 *   to the classes constructors and methods of super classes are
 *   called explicitly by method indirection. The following example
 *   shows this solution:
 * 
 * <pre>
 * ClassB
 * {
 *   method aMethod ( ... )
 *   {
 *     // call super method ...
 *     this._indirectedmethod_ = ClassB.super_.aMethod;
 *     this._indirectedmethod_ ( ... );
 *     delete this._indirectedmethod_;
 *   }
 * }
 * </pre>
 *
 * Note: although this function and kind of class definition works
 * quite well it is recommended to use the class definition syntax
 * since object JavaScript 1.2.
 * 
 * @since Object JavaScript 1.0
 * 
 * @param derivedClass: Function: the constructor function of the
 *   class to derive
 * @param baseClass: Function: the constructor function of the base class 
 */
function doInherit ( derivedClass, baseClass )
{
  if ( baseClass == null )
  {
    if ( doInherit.base_ != null )
      baseClass = doInherit.base_;
  }
  
  // Inheritance ... ?
  if ( baseClass != null )
  {
    // ECMA Inheritance, nothing JavaScript specific used.
    // call the constructor with "__proto__" to give it a 
    // chance to differ between calls for instantiation and 
    // calls for inheritance (this one)
    derivedClass.prototype = new baseClass ( "__proto__" );

    // "Repair" constructor (a JavaScript internally used property)
    derivedClass.prototype.constructor = derivedClass;
  
    // Linking back the Super Class:
    derivedClass.super_ = baseClass.prototype;
  }
  else
    derivedClass.prototype.constructor = derivedClass;

  // Static part: always assign a default static_ object to a new class
  var static_constructor = function () {
    this.class_ = derivedClass;
  };

  // Inherit the new static <b>OBJECT</b> from the
  // Baseclasses' static object (if existent).
  if ( baseClass != null && baseClass.static_ != null )
    static_constructor.prototype = baseClass.static_;

  // Now construct the Static object (with the inheritance
  // defined above) and link it both to the derived class
  // AND to the prototype of this class!
  derivedClass.static_ = 
    derivedClass.prototype.static_ = new static_constructor;

  // now get the Class name ...
  if ( initPackage.lastPackage_ )
  {
    var cur_package = initPackage.packageList_ [initPackage.lastPackage_];
    var package_name = initPackage.lastPackage_ + ".";
    
    for ( var i in cur_package )
    {
      if ( cur_package [i] == derivedClass )
      {
        derivedClass.prototype.static_.className_ = package_name + i;
        return derivedClass.prototype;
      }
    }
  }

  // no Class name can be determined. In these cases we use
  // the "undefined" value.
  derivedClass.prototype.static_.className_ = "undefined";
  return derivedClass.prototype;
}

/** 
 * Initializes a <code>package</code> within the current scope.
 * The scope depends on the current environment e.g. the
 * browser JavaScript engine. <p>
 *
 * This implementation uses the browser's <code>window</code> object
 * as the default scope. <b>Note</b> that each Frame or Frameset has
 * its own window object and its own function definitions. Hence you
 * have to load classes and initialize packages in each window,
 * framesets and obviously all (i)frames where the class mechanism is
 * used.
 * 
 * @param String: aPackageName: a string defining a package
 *   name with sub-packages e.g. "com.hw.util".
 * 
 * @return Object: the package object that serves as an associative
 *   array for classes. 
 */
function initPackage ( aPackageName )
{
  initPackage.lastPackage_ = aPackageName;

  if ( initPackage.packageList_ [aPackageName] )
    return initPackage.packageList_ [aPackageName];
  
  var packages = aPackageName.split ( "." );
  var root_pkg_name = packages [0];
  var cur_package = window [root_pkg_name];

  if ( !cur_package )
    cur_package = window [root_pkg_name] = {};
  initPackage.rootPackageList_ [root_pkg_name] = cur_package;

  for ( var i = 1; i < packages.length; ++i )
  {
    if ( cur_package [ packages [i] ] == null )
      cur_package [ packages [i] ] = {};
    cur_package = cur_package [ packages [i] ];
  }
  
  initPackage.packageList_ [aPackageName] = cur_package;

  if (aPackageName.indexOf("com.hyperwave.") == 0 || aPackageName == "com.hyperwave") {
    window.hw = window.com.hyperwave;
    initPackage.rootPackageList_.hw = window.com.hyperwave;
  }

  return cur_package;
}

/** 
 * Initialize the Packaging system and create the <code>ojs.object</code>
 * class.
 */
initPackage.packageList_ = {};
initPackage.rootPackageList_ = {};
initPackage.lastPackage_ = null;

/**
 * Take care about initializing package "ojs" (in case that addTopToClasspath 
 * was not used).
 */ 
initPackage("ojs");

  /** 
   * Constructor for all JavaScript Objects. This constructor is 
   * considered to be empty because any check for "__proto__" would
   * be senseless.
   */
  ojs.Object = function ()
  {
  };
  class$ = doInherit ( ojs.Object );
  
  /** 
   * Returns true if a class is an instance of another class. The
   * other class might be given by a class object (strong) or a class
   * string (weak). Strong means, that the class is of this type and
   * the class is defined in the same scope. A weak check might result
   * in a result that is true even the class is defined in another
   * scope (or window).
   * 
   * @signature (aClass:Function)
   * @signature (aClassName:string)
   * 
   * @param aClass a class defined by its constructor function like
   *   <code>ojs.Object</code>.
   * @param aClassName a class defined by its class name like
   * <code>&quot;ojs.Object&quot;</code>.
   */
  class$.instanceOf = function ( aClass )
  {
    if ( typeof aClass == "function" )
    {
      var class_iter = this.constructor;
      while ( class_iter != null )
      {
        if ( class_iter.static_ == aClass.static_ )
          return true;
        class_iter = class_iter.super_;
      }
    }
    else if ( typeof aClass == "string" )
    {
      var class_iter = this.constructor;
      while ( class_iter != null )
      {
        if ( class_iter.static_.getClassName () == aClass )
          return true;
        class_iter = class_iter.super_;
      }
    }
    
    return false;
  };
  
  /** 
   * Returns a function that redirects to the given method
   * in the specified scope. This can be used in event handlers or other
   * techniqeus that require callback functions.
   *
   * @param aScope: Object: the object that provides the scope
   * @param aMethod: Function: the function that should be called in the 
   * given scope
   *  
   * @return Function: a function that redirects to the given method
   * in the specified scope
   */
  class$.static_.getMethodRedirector = function ( aScope, aMethod )
  {
    return function()
    {
      return aMethod.apply(aScope, arguments);
    };
  };


  class$.static_.__cloneableTypes__ = {addKeyValue: function (key, value) {
    this[key] = value;
  }};
  class$.static_.__cloneableTypes__.addKeyValue("undefined", 1);
  class$.static_.__cloneableTypes__.addKeyValue("null", 1);
  class$.static_.__cloneableTypes__.addKeyValue("string", 1);
  class$.static_.__cloneableTypes__.addKeyValue("number", 1);
  class$.static_.__cloneableTypes__.addKeyValue("boolean", 1);
  class$.static_.__cloneableTypes__.addKeyValue("array", 1);
  class$.static_.__cloneableTypes__.addKeyValue("object", 1);
  delete class$.static_.__cloneableTypes__.addKeyValue;
  /** 
   * Returns a clone of the object. Useful to avoid cross-frame references.
   * Besides primitive objects (strings, numbers, booleans
   * and linear arrays of such types) also "real" objects are supported. If such and
   * object is given, first it is checked for the existance of a <code>clone</code>
   * method which is called if it found. Otherwise this method is called recursively
   * for all properties of the object (which makes it obvious that only own data structures
   * should be cloned, not references to DOM objects or a window).
   * 
   * @param anObject: Object: the object that should be cloned
   * @param aWindowScope: Object | void: the browser window object that defines the target frame/window
   *   where the clone should be created (default is <code>window</code>)
   *
   * @return Object: a clone of the given object
   */
  class$.static_.clone = function ( anObject, aWindowScope )
  {
    var scope = aWindowScope || window;
    var type = class$.static_.getType(anObject);
    switch ( type )
    {
      case "undefined": 
        return void(0);
      case "null": 
        return null;
      case "string": 
        return scope.String(anObject);
      case "number": 
        return scope.Number(anObject);
      case "boolean": 
        return scope.Boolean(anObject);
      case "array": 
        var a = scope.newInstanceOf(scope.Array);
        for ( var i = 0; i < anObject.length; ++i )
          a[i] = class$.static_.clone(anObject[i], scope);
        return a;
      case "object":
        if ( anObject instanceof Date )
          return anObject.clone(scope);
        if ( anObject.clone && (class$.static_.getType(anObject.clone) == "function") )
          return anObject.clone(scope);
        var o = scope.newInstanceOf(scope.Object);
        for ( var i in anObject )
        {
          if ( anObject.hasOwnProperty && !anObject.hasOwnProperty(i) ) // the first check is for Safari?!
            continue;
          if ( this.__cloneableTypes__[class$.static_.getType(anObject[i])] )
            o[i] = class$.static_.clone(anObject[i], scope);
        }
        return o;
      default: throw "Unsupported object type for clone: " + type;
    }
  };

  /** 
   * Returns the full qualified class name of the class.
   * 
   * @return string: a string containing the class name.
   */
  class$.static_.getClassName = function ()
  {
    return this.className_;
  };

  /**
   * Returns the type of the given object. It can be used if <code>typeof</code> is not exact
   * enough. The following return strings are supported (they should be self explanatory):
   * <ul>
   *   <li>undefined</li>
   *   <li>null</li>
   *   <li>string</li>
   *   <li>number</li>
   *   <li>boolean</li>
   *   <li>array</li>
   *   <li>function</li>
   *   <li>object (for everything else)</li>
   * </ul>
   * 
   * @param anObject: Object: the object for determining its type
   
   * @return String: the type of anObject
   */
  class$.static_.getType = function ( anObject ) 
  {
    var index, id;
    var type_of_result = typeof anObject; 

    if (type_of_result == "undefined")
      return type_of_result;
    if (anObject == null)
      return "null";
    if ((type_of_result == "object" || anObject.constructor == "[function]") || (anObject.constructor == "(Internal function)")) 
    {
      // Konqueror only returns "[function]" whereas Safari returns "(Internal function)"
      var ctor_str = (anObject.constructor + "").toLowerCase();
      var type_str = null;

      function doIt ( theReference, theType )
      {
        if ( anObject.constructor === theReference.constructor ||         // rest
             ctor_str.indexOf("function " + theType) >= 0 ) // IE with addTopToClasspath
        {
          type_str = theType;
          return true;
        }
        return false;
      }
      
      if ( doIt ( [], "array" ) )
        return type_str;
      else if ( doIt ( "", "string" ) )
        return type_str;
      else if ( doIt ( true, "boolean" ) )
        return type_str;
      else if ( doIt ( new Number(1), "number" ) )
        return type_str;

//      if (anObject.constructor === new Function().constructor ||
//          (document.all && (typeof anObject.constructor == "undefined" || typeof anObject.constructor == "object") && (anObject + "").indexOf("function(") >= 0)) // IE
      if ( (typeof anObject.call != "undefined") && (typeof anObject.apply != "undefined") )
        return "function";
      else
        return "object";
    }
    else
    {
      return type_of_result;
    }
  };
  doInherit.base_ = ojs.Object;
   
/** 
 * Loads a class or a package into the current scope. The function
 * was prepared for dynamic class loading and is deprecated now.
 * 
 * @param String: aClassName: a string defining a class name
 *   or even a whole package.
 * 
 * @deprecated since Object JavaScript 1.2.
 *  Reasons:
 *  <ul>
 *    <li>
 *      Dynamic class loading is considered to be too complex because
 *      on the server side the constraints will provide a JavaScript
 *      hell even for very experienced programmers. On the client side
 *      class loading can only be done synchronously which is in fact
 *      only a technique that can be done during the loading of a page
 *      or by applets. During page loading we cannot use constructors
 *      or constructor functions because an additional (dynamically
 *      written) &lt;script src...&gt; will only be valid in the next
 *      script block. Applets could be used synchronously but only
 *      after applet initialization. Hence we should keep our hands
 *      from such techniques. If ever we could re-use the "loadClass"
 *      mechanism to do this.
 *  </ul>
 * @see #addTopToClasspath()
 */
function loadClass ( aClassName )
{
}

/** 
 * This function implements ECMA conform inheritance for JavaScript
 * classes like <code>doInherit</code> does. The underlying method is
 * a little bit different from doInherit because we write a class
 * within a function body. This body looks like:
 *
 * <pre>
 * function xyz ( class$ )
 * {
 *   class$.method = function ( ... )
 *   {
 *   }
 * }
 * </pre>
 *
 * This function is called <b>class definition function</b>. It is
 * associated with a class name by means of
 * <code>defineClass</code>. Here all necessary constructs for a
 * <i>real</i> ECMA conform inheritance are produced and the
 * constructor (that is either explicitly defined with a method called
 * constructor or that is otherwise implicitly constructed) is
 * accociated with the package and the class name.</p>
 * 
 * <p>This implementation relies on the internals of <code>doInherit
 * </code> because the needs of this function are somewhat different.
 * <code>doInherit</code> implies that it has a constructor function
 * and returns the class prototype. <code>defineClass</code> implies
 * that the static object is inherited correctly and no class
 * constructor exists. Hence we have to copy the internals of 
 * <code>doInherit</code> Another dependency is the <code>initPackage
 * </code> function - this function is used to initialize the
 * classes' packages.
 *
 * @signature (String aClassName, Function theDefinition)
 * @signature (String aClassName, String baseClass, Function
 *   theDefinition)
 * @signature (String aClassName, Function baseClass, Function
 *   theDefinition)
 *
 * @param aClassName a string defining the whole qualified class name
 * @param theDefinition the definition function of the class to be
 *   defined
 * @param baseClass the super class of the new class
 * 
 * @since Object JavaScript 1.2
 */
function defineClass ( aClassName, arg2, arg3 )
{
  if ( defineClass.classCache_ [aClassName] )
  {
    // class already defined
    var text = "Illegal State: class " + aClassName + " already defined.\n" +
               "Further double includes will be ignored.";
    if ( !defineClass.ignoreClassDuplicates_ )
    {
      defineClass.ignoreClassDuplicates_ = true;
      alert(text);
      throw text;
    }
    // in case double includes should be ignored silently return
    return;
  }

  // Rename unnamed parameters 
  var baseClass;
  var theDefinition = arg2;
  if ( arg3 )
  {
    theDefinition = arg3;
    baseClass = arg2;
  }

  // Separate Class and Package Name ...
  var sep = /^((.*)\.)?([^.]+)$/;
  var arr = sep.exec ( aClassName );
  var package_name = arr [2];
  var unqualified_class_name = arr [3];
  var class_package;

  if ( package_name )
    class_package = initPackage ( package_name );
  else {
    initPackage("__default__");
    class_package = window;
  }

  // get the *real* baseClass object. But be aware of classes that
  // have not been created by defineClass ...
  if ( baseClass == null )
    baseClass = doInherit.base_;
  else
    if ( typeof baseClass == "string" )
    {
      var desired = defineClass.classCache_ [baseClass];
      if ( desired )
        baseClass = desired;
      else
        try
        {
          var class_function;
          class_function = eval ( baseClass );
//          if ( typeof class_function != "function" )
//            class_function = top.eval ( baseClass );
          if ( typeof class_function != "function" )
            throw baseClass + " is not a function";
          baseClass = class_function;
        }
        catch ( e )
        {
          var text = "'" + baseClass + "' is not a class (" + e + ")";
          alert(text);
          throw text;
        }
    }
//else if ( typeof baseClass == "undefined" ) 
//  baseClass = top.eval(baseClass.static_.getClassName());
  
  // Step 1: Static - always assign a default static_ object to a new
  // class.
  var static_constructor = function() {};
  // [The former technique of using the Function constructor does not work with Konqueror/Safari.]

  var base_static_onclassload, base_static_onfinalization;

  // Inherit the new static <b>OBJECT</b> from the
  // Baseclasses' static object (if existent).
  if ( baseClass != null && baseClass.static_ != null )
  {
    static_constructor.prototype = baseClass.static_;
    base_static_onclassload = baseClass.static_.onClassLoad;
    base_static_onfinalization = baseClass.static_.onFinalization;
  }

  // ECMA Inheritance, nothing JavaScript specific used.
  // call the constructor with "__proto__" to give it a 
  // chance to differ between calls for instantiation and 
  // calls for inheritance (this one)
  var class_prototype;
  if ( baseClass != null )
    class_prototype = new baseClass ( "__proto__" );
  else
    class_prototype = {};

  // Step 2: Initialize the "class" object and call the class
  // definition function.
  class_prototype.super_ = baseClass.prototype;
  class_prototype.superConstructor_ = baseClass;
  class_prototype.static_ = new static_constructor;
  class_prototype.static_.className_ = aClassName;
  var mark_constructor = class_prototype.constructor;

  theDefinition ( class_prototype );

  // Step 3: get/make the constructor (if any) and "wire" the prototype
  // chain.
  if ( class_prototype.constructor == mark_constructor )
    class_prototype.constructor = 
      function () 
      { 
        if (baseClass)
          baseClass.apply (this, arguments);
      };

  var derived_class;
  defineClass.classCache_ [aClassName]
    = class_package [unqualified_class_name]
    = derived_class 
      = class_prototype.constructor;
  derived_class.prototype = class_prototype;

  if ( !package_name ) {
    initPackage.packageList_["__default__"][unqualified_class_name]=derived_class;
  }


  // Step 4: Link the static object both to the derived class
  // AND to the prototype of this class!
  derived_class.static_ = 
    derived_class.prototype.static_ = class_prototype.static_;
  derived_class.super_ = baseClass.prototype;

  // Step 5: Call the static_.onClassLoad method (if it exists)
  if ( class_prototype.static_.onClassLoad != base_static_onclassload )
    class_prototype.static_.onClassLoad ();
  
  // Step 6: register the static finalizer method (if it exists)
  if ( class_prototype.static_.onFinalization != base_static_onfinalization )
    defineClass.finalizerList_[defineClass.finalizerList_.length] = 
      { function_: class_prototype.static_.onFinalization, scope_: class_prototype.static_ };
      
  class_package = null;
}
defineClass.classCache_ = {};
defineClass.finalizerList_ = [];
defineClass.ignoreClassDuplicates_ = true;

//--------------------------------------------------------------------
//                   Class Finalization & Logging
//--------------------------------------------------------------------

defineClass.doLog = function ( aText )
{
  if ( typeof top.debug_ != "undefined" )
  {
    top.debug_.debug ( aText ); // change level to info or whatever
  }
};

// Internal window load handler. Necessary for IE to be able to "move" the unload handler
// from "onbeforeunload" to "onunload". (The beforeunload event is triggered even if the user
// closes the window before the load event has been triggered, but causes problems in IE 6 SP2
// with content disposition.)
defineClass.loadHandler = function( anEvent )
{
  defineClass.doLog ( "Start of loadHandler(), window:" + window.name );

  // dispatch the uda load event via the uda window instance
  try
  {
    if (com.hyperwave.uda && com.hyperwave.uda.core && com.hyperwave.uda.core.Window) {
      var staticUdaWindow_ = com.hyperwave.uda.core.Window.static_;
    }
    else {
      var staticUdaWindow_ = null;
    }
  }
  catch ( e )
  {
    // no classes, no uda window
    defineClass.doLog ( "Load event could not be dispatched because UDA not loaded" );
  }
  if ( staticUdaWindow_ )
  {
    staticUdaWindow_.dispatchLoadEvent(window, anEvent ? anEvent : window.event);
    defineClass.doLog ( "Load event dispatched successfully" );
  }
  
  if ( window.detachEvent ) // browser dependency - only in IE we need to change the internal unload handler
  {
    window.attachEvent("onunload", defineClass.unloadHandler);
    window.detachEvent("onbeforeunload", defineClass.unloadHandler);
    defineClass.doLog ( "changed internal event from beforeunlod to unload" );
  }
  defineClass.doLog ( "End of loadHandler(), window:" + window.name );
};

//Internal window unload handler. Necessary to be able to include the finalizer mechanism.
defineClass.unloadHandler = function( anEvent )
{
  defineClass.doLog ( "Start of unloadHandler(), window:" + window.name );

  // dispatch the uda unload event via the uda window instance
  try
  {
    if (com.hyperwave.uda && com.hyperwave.uda.core && com.hyperwave.uda.core.Window) {
      var staticUdaWindow_ = com.hyperwave.uda.core.Window.static_;
    }
    else {
      var staticUdaWindow_ = null;
    }    
  }
  catch ( e )
  {
    // no classes, no uda window
    defineClass.doLog ( "Unload event could not be dispatched because UDA not loaded" );
  }
  if ( staticUdaWindow_ )
  {
    staticUdaWindow_.dispatchUnloadEvent(window, anEvent ? anEvent : window.event);
    defineClass.doLog ( "Unload event dispatched successfully" );
  }
  
  defineClass.finalize(window);
  if ( window.detachEvent )
    window.detachEvent("onbeforeunload", defineClass.unloadHandler);
  else if ( window.removeEventListener )
    window.removeEventListener("unload", defineClass.unloadHandler, false);
  else
    window["onunload"] = null;

  if ( window.CollectGarbage )
    window.CollectGarbage ();    
  defineClass.doLog ( "End of unloadHandler(), window:" + window.name );
};

// The finalizer method.
defineClass.finalize = function( aWindow )
{
  defineClass.doLog ( "Start finalize(), window:" + window.name + ", aWindow: " + aWindow.name );

  // call all registered <code>static_.onFinalization</code> methods
  for ( var i = 0; i < defineClass.finalizerList_.length; ++i )
  {
    try
    {
      defineClass.doLog ( "Finalize Class:" + defineClass.finalizerList_[i].scope_.getClassName() );
      defineClass.finalizerList_[i].function_.call(defineClass.finalizerList_[i].scope_, aWindow);
    }
    catch ( e )
    {
      defineClass.doLog ( "Error during finalization, Class:" + defineClass.finalizerList_[i].scope_.getClassName() );
    }
  }
    
  // if we are within the frameset with addTopToClasspath also notify top
  if ( window != top )
  {
    if ( top.defineClass )
      top.defineClass.finalize ( window );
    registry$._registry = [];
  }
  else if ( window == aWindow && window == top )
    registry$._registry = [];
  defineClass.doLog ( "End finalize(), window:" + window.name + ", aWindow: " + aWindow.name );
};

// Add the internal load and unload event handler:
if ( window.attachEvent )  //# browser dependency IE
{
  window.attachEvent("onload", defineClass.loadHandler);
  window.attachEvent("onbeforeunload", defineClass.unloadHandler);
}
else if ( window.addEventListener && !(ua_isSafari$ || ua_isKonqueror$))  //# browser dependency W3C
{
  window.addEventListener("load", defineClass.loadHandler, false);
  window.addEventListener("unload", defineClass.unloadHandler, false);
}
else //# browser dependency Konqueror compatible
{
  window.onload = defineClass.loadHandler;
  window.onunload = defineClass.unloadHandler;
}

//--------------------------------------------------------------------
//                   Window Close Overloading
//--------------------------------------------------------------------
if ( window.CollectGarbage )  // online necessary in IE (and dangerous in Mozilla)
{
  window.close = function ()
  {
    closeChecker.close_ = true;
  };
  
  function closeChecker ()
  {
    if ( closeChecker.close_ )
    {
      defineClass.doLog ( "Triggered closeChecker(), window:" + window.name );
      clearInterval ( closeChecker.id_ );
  
      document.open ();
      document.writeln ( "<script>window.close();<\/script>" );
      document.close ();
      
      defineClass.doLog ( "End closeChecker, window:" + window.name );
    }
  }
  
  closeChecker.id_ = setInterval ( closeChecker, 250 );
}

//--------------------------------------------------------------------
//                        Unique ID Generator
//--------------------------------------------------------------------
function getUniqueId()
{
  if ( window != top && top.getUniqueId )
    return top.getUniqueId();
  else
    return getUniqueId._uniqueIdCounter$++;
}
getUniqueId._uniqueIdCounter$ = new Date().valueOf();

//--------------------------------------------------------------------
//                       Global Object Registry
//--------------------------------------------------------------------
function registry$()
{
}
registry$._registry = [];

/**
 * Puts an object into the registry. This object is associated with a browser window.
 * The method returns the unique identifier that can be used in <code>registry$.get</code>.
 * The registry is distributed over the frames of a frameset in a way that each frame holds
 * the objects that are associated with this frame.<p>
 * Mind that if an object has already been put into the registry it will be contained twice
 * which should be avoided (but due to performance issues there is no lookup before adding it)!
 *
 * @param anObject: object: an object that should be stored in the registry and associated with
 *   the returned id
 * @param aWindow: object | void: an optional argument that defines the window where the object resides,
 *   the default is the window where Object.js is loaded
 *
 * @return int: a unique identifier for the registered object
 */
registry$.put = function(anObject, aWindow)
{
  var win = aWindow || window;
  if ( (win != window) && win.registry$ )
    return win.registry$.put(anObject, win);
  else 
  {
    var id = getUniqueId();
    registry$._registry[id] = anObject;
    return id;
  }
};

/**
 * Returns the object registered with the given identifier or <code>null</code> if none is found.
 * The identifier should be obtained when registering via <code>registry$.put</code>.<br>
 * This implementation first looks for an entry in the local registry and if none is found it starts
 * with the lookup in the top frame, which searches all its subframes.
 *
 * @param anId: int: a unique identifier that was returned by <code>registry$.put</code>
 *
 * @return Object: the object registered with the given identifier or <code>null</code>
 *   if none is found
 */
registry$.get = function(anId)
{
  if ( registry$._registry[anId] )      //1st, search in local frame
    return registry$._registry[anId];
  else if ( top.registry$ )             //2nd, search via top registry (if there is one)
    return top.registry$._get(anId);
  else                                  //3rd, search in sub frames (very unlikely)
    return registry$._get(anId);
};

/**
 * Helper method that returns the object registered with the given identifier or <code>null</code> if none is found.
 * The identifier should be obtained when registering via <code>registry$.put</code>.<br>
 * This implementation first looks for an entry in the local registry and if none is found it starts
 * with the lookup in all its subframes (even recursive in those that did not load Object.js).
 *
 * @param anId: int: a unique identifier that was returned by <code>registry$.put</code>
 * @param aFrame: Object: an optional frame reference that is used internally
 *
 * @return Object: the object registered with the given identifier or <code>null</code>
 *   if none is found
 */
registry$._get = function(anId, aFrame)
{
  var aFrame = aFrame || window;
  
  if ( registry$._registry[anId] )
    return registry$._registry[anId];
  else if ( aFrame.frames && (aFrame.frames.length > 0) )
  {
    // search in all frames:
    for ( var i = 0; i < aFrame.frames.length; ++i )
    {
      if ( aFrame.frames[i].registry$ && aFrame.frames[i].registry$._registry )
      {
        var obj = aFrame.frames[i].registry$._get(anId);
        if ( obj )
          return obj;
      }
      else
      {
        var obj = registry$._get(anId, aFrame.frames[i]);
        if ( obj )
          return obj;
      }
    }
    return null;
  }
  return null;
};

/**
 * Removes the object that was registered with the given identifier from the registry. 
 * If there is no such object, the registry is not touched. If such an object exists
 * it is returned (otherwise <code>null</code> is returned).
 *
 * @param anId: int: a unique identifier that was returned by <code>registry$.put</code>
 *
 * @return Object: the object registered with the given identifier that has been removed 
 *   or <code>null</code> if none is found
 */
registry$.remove = function(anId)
{
  if ( top.registry$ )
    return top.registry$._remove(anId);
  else
    return registry$._remove(anId); 
};
 
/**
 * Helper method that removes the object that was registered with the given identifier 
 * from the registry. If there is no such object, the registry is not touched. If such an object exists
 * it is returned (otherwise <code>null</code> is returned).
 *
 * @param anId: int: a unique identifier that was returned by <code>registry$.put</code>
 * @param aFrame: Object: an optional frame reference that is used internally
 *
 * @return Object: the object registered with the given identifier that has been removed 
 *   or <code>null</code> if none is found
 */
registry$._remove = function(anId, aFrame)
{
  var aFrame = aFrame || window;
   
  if ( registry$._registry[anId] )
  {
    var obj = registry$._registry[anId];
    delete registry$._registry[anId];
    return obj;
  }
  else if ( aFrame.frames && aFrame.frames.length > 0 )
  {
    // search in all frames:
    for ( var i = 0; i < aFrame.frames.length; ++i )
    {
      if ( aFrame.frames[i].registry$ && aFrame.frames[i].registry$._registry )
      {
        var obj = aFrame.frames[i].registry$._remove(anId);
        if ( obj )
          return obj;
      }
      else
        return registry$._remove(anId, aFrame.frames[i]);
    }
    return null;
  }
};
 
//--------------------------------------------------------------------
//                   HAF Compatibility Library
//--------------------------------------------------------------------
// The following functions are used to extend the default behavior
// of the JavaScript Engine. These are mostly encoders and decoders
// for UTF8 and escaped UTF8.

// IMPORTANT:
// Note that these functions are to be synched in ojs.js, ojs1.js
// and within the Clientlib (Object.js).

// Global variable that is true if lambda expressions are
// supoorted.


/**
 * Encodes a character string (that exists of UCS2 characters) to
 * a character string that is UTF8 encoded. The characters of the
 * source string are transcoded to their one, two or three "byte"
 * representation in UTF8. As a consequence the final string contains
 * only characters with codes between 0 and 255.<p>
 *
 * For example: the German umlaut &?uml; (small "o" with quotes) has
 *   the UCS2 (Unicode) character code 246. Constructing a string
 *   with this character can be done by
 *     <code>String.fromCharCode (246)</code>.
 *   If this string is converted with this function this character
 *   is transcoded to its 2-byte representation in UTF-8 (195, 182).
 *   The resulting string will contain 2 characters with the character
 *   codes above.
 *
 * This implementation uses two strategies:
 * <ul>
 *   <li>For IS6.2 and lower it uses JavaScript Lambda Expressions to get
 *     better performance for long strings (in comparision to normal
 *     string operations).
 *   <li>For DANTE+ the built in method "fromEncoding" (C++) is used
 *     to get another boost (approx. 30 times faster).
 * </ul>
 *
 * @param theText: string: The text that has to be transcoded to
 *   UTF8.
 * @return string: the converted string.
 */
encodeUtf8 = function ( theText )
{
  return theText.replace ( /(.)|(\s)/g, encodeUtf8.lambdaEncode );
};

// Internal Lambda Funtion for encodeUTF8. This Lambda function
// matches any character and translates the character to one
// two or three byte representations concerning to the UTF8
// algorithm. Note that this function must be kept in sync
// with the regular expression of the caller.
encodeUtf8.lambdaEncode = function ( c1 )
{
  var c = c1.charCodeAt(0);

  // alle Zeichen von 0-127 => 1byte
  if (c < 128)
    return c1;

  // alle Zeichen von 127 bis 2047 => 2byte
  if (c < 2048)
    return ( String.fromCharCode((c >> 6) | 192)
             + String.fromCharCode((c & 63) | 128) );

  // alle Zeichen von 2048 bis 66536 => 3byte
  return ( String.fromCharCode((c >> 12) | 224)
           + String.fromCharCode(((c >> 6) & 63) | 128)
           + String.fromCharCode((c & 63) | 128) );
};

/**
 * Checks whether a string is UTF8 encoded or not. This is done
 * with a Regular Expression that matches UTF8-patterns.The following
 * constraints have to be fulfilled:
 *
 * <ul>
 *   <li>The string has to contain only characters with codes between 0 and
 *     255.
 *   <li>The patterns must be conform to the UTF8 encoding for UCS2. This
 *     means that only 1, 2 or 3 Byte representations are allowed.
 * </ul>
 *
 * @param theText: string: The text that has to be checked.
 * @return boolean: true if the text is a UTF-8 text.
 */
function testUtf8 ( theText )
{
  pattern =
    /([\x00-\x7F])|([\xC0-\xDF][\x80-\xBF])|([\xE0-\xEF][\x80-\xBF][\x80-\xBF])/g;
  var res = theText.replace ( pattern, "" );
  return res.length == 0;
}

/**
 * Decodes an UTF-8 encoded string into the internal JavaScript
 * (UCS-2) representation. It forms the inverse function of
 * <code>encodeUtf8</code>.
 *
 * This implementation uses either lambda expressions or simple
 * array operations.
 *
 * @param theText: string: a text that should be decoded from
 *   UTF-8 representation back to "JavaScript".
 * @return string: the decoded string. Note that the
 *   original text will be returned if the text is not a "real"
 *   UTF-8 string.
 */
decodeUtf8 = function (theText)
{
  if ( !testUtf8 ( theText ) )
    return theText;
  pattern = /([\xC0-\xDF][\x80-\xBF])|([\xE0-\xEF][\x80-\xBF][\x80-\xBF])/g;

  return theText.replace ( pattern, decodeUtf8.lambdaDecode );
};

// Internal lambda function that matches the two byte or three
// byte sequences and constructs the original character.
// The parameters of these function depend on the regular expression
// of the decodeUtf8 function.

decodeUtf8.lambdaDecode = function ( whole, two, three )
{
  if ( two )
  {
    c = two.charCodeAt (0);
    c2 = two.charCodeAt(1);
    return String.fromCharCode(((c & 31) << 6) | (c2 & 63));
  }

  if ( three )
  {
    c = three.charCodeAt (0);
    c2 = three.charCodeAt(1);
    c3 = three.charCodeAt(2);
    return String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
  }
};

/**
 * Encodes an arbitrary URI path by encoding its path components.
 * The path will be splitted and then encoded by means of
 * "encodeURIComponent". Finally it will be returned by
 * joining the segments with slashes.
 *
 * @param aURI: string: the path segments that should be encoded
 * @return string: the encoded path information
 */

function encodeURIPath ( aURI )
{
  var components = aURI.split('/');
  for (var i=0; i<components.length; i++) {

    components[i] = encodeURIComponent(components[i]);
  }
  return components.join('/');
}

/** 
 * IE 5.5 compatibility library.
 * This library defines the two methods <code>apply</code> and
 * <code>call</code> for IE 5.5. Note that since IE 6.0 and obviously
 * for all Netscape derivates this will work well. The code for both
 * functions is similar to <code>newInstanceOf</code> and is
 * deprecated per definition.
 */

if ( !Function.prototype.apply )
  Function.prototype.apply = function ( theObject, theArguments )
  {
    theObject.$f$ = this;
    var ret;
    switch ( theArguments.length )
    {
      case 0:
        ret = theObject.$f$ ();
        break;
      case 1:
        ret = theObject.$f$ ( theArguments [0] );
        break;
      case 2:
        ret = theObject.$f$ ( theArguments [0], theArguments [1] );
        break;
      case 3:
        ret = theObject.$f$ ( theArguments [0], theArguments [1], theArguments [2] );
        break;
      case 4:
        ret = theObject.$f$ ( theArguments [0], theArguments [1], theArguments [2], theArguments [3] );
        break;
      case 5:
        ret = theObject.$f$ ( theArguments [0], theArguments [1], theArguments [2], theArguments [3], theArguments [4] );
        break;
    }
    delete theObject.$f$;
    return ret;
  };
  
if ( !Function.prototype.call )
  Function.prototype.call = function ( theObject )
  {
    theObject.$f$ = this;
    var ret;
    switch ( arguments.length )
    {
      case 1:
        ret = theObject.$f$ ();
        break;
      case 2:
        ret = theObject.$f$ ( arguments [1] );
        break;
      case 3:
        ret = theObject.$f$ ( arguments [1], arguments [2] );
        break;
      case 4:
        ret = theObject.$f$ ( arguments [1], arguments [2], arguments [3] );
        break;
      case 5:
        ret = theObject.$f$ ( arguments [1], arguments [2], arguments [3], arguments [4] );
        break;
      case 6:
        ret = theObject.$f$ ( arguments [1], arguments [2], arguments [3], arguments [4], arguments [5] );
        break;
    }
    delete theObject.$f$;
    return ret;
  };

/**
 * Returns an array holding all functions that participate in the current execution stack.
 * The first element holds the last entry in the stack and so on (as it is typical for stack traces).
 * Attention: Does not work for Safari at the moment
 * (no arguments.caller and only provides the ECMA properties name and message for error objects),
 * it always returns an empty array there.<p>
 * Example:<br>
 * <code>
 * function a(str1, str2) {
 *   return b(str1);
 * }
 *   
 * function b(aString) {
 *   return c(aString);
 * }
 *   
 * c = function(anotherString) {
 *   return getStackTrace();
 * }
 * </code>
 * Calling <code>a(x,y)</code> returns the following entries:
 * <code>
 * anonymous(anotherString)
 * b(aString) 
 * a(str1, str2)
 * </code>
 * Remark: The Mozilla implementation does not hold the function parameters as abstract variables
 * but the concrete values.
 *
 * @return String[]: an array of stack trace entries
 */
function getStackTrace()
{
  // per default, we ignore one stack trace entry (the one of getStackTrace itself):
  var ignoredEntries = arguments.length > 0 ? arguments[0] : 1;
  var ret_val = [];
  var regexp = /function([^{}]+)/;

  if ( typeof(arguments.caller) != "undefined" )
  { // IE, not ECMA
    // FIXXXME: arguments.caller is null in the case of OJS 1.2 (works if getStackTrace is a simple function)
    for (var a = arguments.caller; a != null; a = a.caller) 
    {
      var func = a.callee.toString().match( regexp )[0];
      ret_val[ret_val.length] = ((func == null) || (func.length == 0) ? "anonymous" : func);
      if ( a.caller == a )
      {
        ret_val[ret_val.length] = "*";
        break;
      }
    }
  }
  else 
  { // Mozilla, not ECMA - fake an exception so we can get Mozilla's error stack
    var test_exception;
    try
    {
      this_throws.an_exception;
    }
    catch(test_exception)
    {
      var m, name;

      if ( !test_exception || !test_exception.stack ) // Safari
        return ret_val;

      var stacklist = test_exception.stack.split("\n");

      for ( var i = 0; i < stacklist.length - 1; ++i )
      {
        var framedata = stacklist[i];

        m = framedata.match(/^(\w*)\s*\(\s*([^\)]*)/);

        if ( !m || m.length < 2 )
          continue;

        name = m[1] || "anonymous";

        ret_val[ret_val.length] = name + "(" + (m.length > 2 ? m[2] : "") + ")";
      }
      // remove ignored entries
      if ( ignoredEntries )
        ret_val = ret_val.slice(ignoredEntries);
    }
  }
  return ret_val;
}

/**
 * Safari compatibility library.
 * This library defines the method <code>hasOwnProperty</code> which returns
 * <code>true</code> if an object has a noninherited property with the given name.
 */
if ( !Object.prototype.hasOwnProperty )
{
  Object.prototype.hasOwnProperty = function ( thePropertyName )
  {
    return (typeof this[thePropertyName] != "undefined") && (this.constructor.prototype[thePropertyName] == null);
  };
}

// Timestamp/TimeOfDay/DayMonthYear data types.
/**
 * Extends the Date type with member variable <code>type_</code>.
 * Allows to define the type during construction.
 * 
 * @param type: int: The type represented by this Date instance. Possible values are
 *   0 for unmodified Date behavior, 1 for TimeStamp, 2 for YearMonthDay and 3 for TimeOfDay.
 *   
 * @return Date: the Date instance itself
 */
Date.prototype.initType = function(type)
{
  this.type_ = type;
  return this;
};

/**
 * Returns the type of the Date instance.
 * 
 * @return int: The type represented by this Date instance. Possible values are
 *   0 for unmodified Date behavior, 1 for TimeStamp, 2 for YearMonthDay and 3 for TimeOfDay.
 */
Date.prototype.getType = function()
{
  if ( !this.type_ )
    return 0;
  return this.type_;
};

//Make Date Objects "cloneable"
Date.prototype.clone = function ( scope ) 
{
  var scope = scope || window;
  return scope.newInstanceOf ( scope.Date, this.valueOf () ).initType( this.getType() ); 
};

//Rename all windows if mode is not disabled 
//(by setting global variable <code>gRenameWindows_</code> to <code>false</code>):
if (typeof gRenameWindows_ != "undefined" && gRenameWindows_ === true)
{
  if ( window != top && window.name )
    window.name = window.name + "_" + top.name;
  else if ( window == top && (!window.name || (window.name.indexOf("hw_top_") < 0)) )
    window.name = ("hw_top_" + document.location.host + "_" + document.location.pathname.replace(/\/.*^/, "")).replace(/\W/g, "") + getUniqueId();
}

var gChangeLevel1={addKeyValue: function (key, value) {
    this[key] = value;
  }};
gChangeLevel1.addKeyValue("\u0041", "a");
gChangeLevel1.addKeyValue("\u0061", "a");
gChangeLevel1.addKeyValue("\u00c6", "ae");
gChangeLevel1.addKeyValue("\u00e6", "ae");
gChangeLevel1.addKeyValue("\u00e1", "a");
gChangeLevel1.addKeyValue("\u00c1", "a");
gChangeLevel1.addKeyValue("\u00e0", "a");
gChangeLevel1.addKeyValue("\u00c0", "a");
gChangeLevel1.addKeyValue("\u00e2", "a");
gChangeLevel1.addKeyValue("\u00c2", "a");
gChangeLevel1.addKeyValue("\u00e5", "a");
gChangeLevel1.addKeyValue("\u00c5", "a");
gChangeLevel1.addKeyValue("\u00e4", "a");
gChangeLevel1.addKeyValue("\u00c4", "a");
gChangeLevel1.addKeyValue("\u00e3", "a");
gChangeLevel1.addKeyValue("\u00c3", "a");
gChangeLevel1.addKeyValue("\u0043", "c");
gChangeLevel1.addKeyValue("\u0063", "c");
gChangeLevel1.addKeyValue("\u00e7", "c");
gChangeLevel1.addKeyValue("\u00c7", "c");
gChangeLevel1.addKeyValue("\u0044", "d");
gChangeLevel1.addKeyValue("\u0064", "d");
gChangeLevel1.addKeyValue("\u00d0", "d");
gChangeLevel1.addKeyValue("\u00f0", "d");
gChangeLevel1.addKeyValue("\u0065", "e");
gChangeLevel1.addKeyValue("\u0045", "e");
gChangeLevel1.addKeyValue("\u00e9", "e");
gChangeLevel1.addKeyValue("\u00c9", "e");
gChangeLevel1.addKeyValue("\u00e8", "e");
gChangeLevel1.addKeyValue("\u00c8", "e");
gChangeLevel1.addKeyValue("\u00ea", "e");
gChangeLevel1.addKeyValue("\u00ca", "e");
gChangeLevel1.addKeyValue("\u00eb", "e");
gChangeLevel1.addKeyValue("\u00cb", "e");
gChangeLevel1.addKeyValue("\u0049", "i");
gChangeLevel1.addKeyValue("\u0069", "i");
gChangeLevel1.addKeyValue("\u00ed", "i");
gChangeLevel1.addKeyValue("\u00cd", "i");
gChangeLevel1.addKeyValue("\u00ec", "i");
gChangeLevel1.addKeyValue("\u00cc", "i");
gChangeLevel1.addKeyValue("\u00ee", "i");
gChangeLevel1.addKeyValue("\u00ce", "i");
gChangeLevel1.addKeyValue("\u00ef", "i");
gChangeLevel1.addKeyValue("\u00cf", "i");
gChangeLevel1.addKeyValue("\u004f", "o");
gChangeLevel1.addKeyValue("\u006f", "o");
gChangeLevel1.addKeyValue("\u00d8", "o");
gChangeLevel1.addKeyValue("\u00f8", "o");
gChangeLevel1.addKeyValue("\u00f3", "o");
gChangeLevel1.addKeyValue("\u00d3", "o");
gChangeLevel1.addKeyValue("\u00f2", "o");
gChangeLevel1.addKeyValue("\u00d2", "o");
gChangeLevel1.addKeyValue("\u00f4", "o");
gChangeLevel1.addKeyValue("\u00d4", "o");
gChangeLevel1.addKeyValue("\u00f5", "o");
gChangeLevel1.addKeyValue("\u00f6", "o");
gChangeLevel1.addKeyValue("\u00d6", "o");
gChangeLevel1.addKeyValue("\u0053", "s");
gChangeLevel1.addKeyValue("\u0073", "s");
gChangeLevel1.addKeyValue("\u00df", "ss");
gChangeLevel1.addKeyValue("\u0055", "u");
gChangeLevel1.addKeyValue("\u0075", "u");
gChangeLevel1.addKeyValue("\u00fa", "u");
gChangeLevel1.addKeyValue("\u00da", "u");
gChangeLevel1.addKeyValue("\u00f9", "u");
gChangeLevel1.addKeyValue("\u00d9", "u");
gChangeLevel1.addKeyValue("\u00fb", "u");
gChangeLevel1.addKeyValue("\u00db", "u");
gChangeLevel1.addKeyValue("\u00fc", "u");
gChangeLevel1.addKeyValue("\u00dc", "u");
gChangeLevel1.addKeyValue("\u0059", "y");
gChangeLevel1.addKeyValue("\u0079", "y");
gChangeLevel1.addKeyValue("\u00fd", "y");
gChangeLevel1.addKeyValue("\u00dd", "y");
gChangeLevel1.addKeyValue("\u00ff", "y");
gChangeLevel1.addKeyValue("\u00f1", "n");
gChangeLevel1.addKeyValue("\u00d1", "n");
gChangeLevel1.addKeyValue("-", "");
gChangeLevel1.addKeyValue("'", "");
gChangeLevel1.addKeyValue("!", "");
gChangeLevel1.addKeyValue('"', "");
gChangeLevel1.addKeyValue("#", "");
gChangeLevel1.addKeyValue("$", "");
gChangeLevel1.addKeyValue("%", "");
gChangeLevel1.addKeyValue("&", "");
gChangeLevel1.addKeyValue("'", "");
gChangeLevel1.addKeyValue("(", "");
gChangeLevel1.addKeyValue(")", "");
gChangeLevel1.addKeyValue("*", "");
gChangeLevel1.addKeyValue("+", "");
gChangeLevel1.addKeyValue(",", "");
gChangeLevel1.addKeyValue("-", "");
gChangeLevel1.addKeyValue(".", "");
gChangeLevel1.addKeyValue("/", "");
gChangeLevel1.addKeyValue(":", "");
gChangeLevel1.addKeyValue(";", "");
gChangeLevel1.addKeyValue("<", "");
gChangeLevel1.addKeyValue("=", "");
gChangeLevel1.addKeyValue(">", "");
gChangeLevel1.addKeyValue("?", "");
gChangeLevel1.addKeyValue("@", "");
gChangeLevel1.addKeyValue("[", "");
gChangeLevel1.addKeyValue("\\", "");
gChangeLevel1.addKeyValue("]", "");
gChangeLevel1.addKeyValue("^", "");
gChangeLevel1.addKeyValue("_", "");
gChangeLevel1.addKeyValue("`", "");
gChangeLevel1.addKeyValue("{", "");
gChangeLevel1.addKeyValue("|", "");
gChangeLevel1.addKeyValue("}", "");
gChangeLevel1.addKeyValue("~", "");
delete gChangeLevel1.addKeyValue;

var gChangeLevel2={addKeyValue: function (key, value) {
    this[key] = value;
  }};
gChangeLevel2.addKeyValue("\u0041", "a\000");//A
gChangeLevel2.addKeyValue("\u0061", "a\000");//a
gChangeLevel2.addKeyValue("\u00c6", "ae");//Ã
gChangeLevel2.addKeyValue("\u00e6", "ae");//Ã¦
gChangeLevel2.addKeyValue("\u00e1", "a\001");//Ã¡
gChangeLevel2.addKeyValue("\u00c1", "a\001");//Ã
gChangeLevel2.addKeyValue("\u00e0", "a\002");//Ã 
gChangeLevel2.addKeyValue("\u00c0", "a\002");//Ã
gChangeLevel2.addKeyValue("\u00e2", "a\003");//Ã¢
gChangeLevel2.addKeyValue("\u00c2", "a\003");//Ã
gChangeLevel2.addKeyValue("\u00e5", "a\004");//Ã¥
gChangeLevel2.addKeyValue("\u00c5", "a\004");//Ã
gChangeLevel2.addKeyValue("\u00e4", "a\005");//Ã¤
gChangeLevel2.addKeyValue("\u00c4", "a\005");//Ã
gChangeLevel2.addKeyValue("\u00e3", "a\006");//Ã£
gChangeLevel2.addKeyValue("\u00c3", "a\006");//Ã
gChangeLevel2.addKeyValue("\u0043", "c\000");//C
gChangeLevel2.addKeyValue("\u0063", "c\000");//c
gChangeLevel2.addKeyValue("\u00e7", "c\001");//Ã§
gChangeLevel2.addKeyValue("\u00c7", "c\001");//Ã
gChangeLevel2.addKeyValue("\u0044", "d\000");//D
gChangeLevel2.addKeyValue("\u0064", "d\000");//d
gChangeLevel2.addKeyValue("\u00d0", "d\000");//Ã
gChangeLevel2.addKeyValue("\u00f0", "d\000");//Ã°
gChangeLevel2.addKeyValue("\u0065", "e\000");//e
gChangeLevel2.addKeyValue("\u0045", "e\000");//E
gChangeLevel2.addKeyValue("\u00e9", "e\001");//Ã©
gChangeLevel2.addKeyValue("\u00c9", "e\001");//Ã
gChangeLevel2.addKeyValue("\u00e8", "e\002");//Ã¨
gChangeLevel2.addKeyValue("\u00c8", "e\002");//Ã
gChangeLevel2.addKeyValue("\u00ea", "e\003");//Ãª
gChangeLevel2.addKeyValue("\u00ca", "e\003");//Ã
gChangeLevel2.addKeyValue("\u00eb", "e\004");//Ã«
gChangeLevel2.addKeyValue("\u00cb", "e\004");//Ã
gChangeLevel2.addKeyValue("\u0049", "i\000");//I
gChangeLevel2.addKeyValue("\u0069", "i\000");//i
gChangeLevel2.addKeyValue("\u00ed", "i\001");//Ã­
gChangeLevel2.addKeyValue("\u00cd", "i\001");//Ã
gChangeLevel2.addKeyValue("\u00ec", "i\002");//Ã¬
gChangeLevel2.addKeyValue("\u00cc", "i\002");//Ã
gChangeLevel2.addKeyValue("\u00ee", "i\003");//Ã®
gChangeLevel2.addKeyValue("\u00ce", "i\003");//Ã
gChangeLevel2.addKeyValue("\u00ef", "i\004");//Ã¯
gChangeLevel2.addKeyValue("\u00cf", "i\004");//Ã
gChangeLevel2.addKeyValue("\u004f", "o\000");//O
gChangeLevel2.addKeyValue("\u006f", "o\000");//o
gChangeLevel2.addKeyValue("\u00d8", "o\000");//Ã
gChangeLevel2.addKeyValue("\u00f8", "o\000");//Ã¸
gChangeLevel2.addKeyValue("\u00f3", "o\001");//Ã³
gChangeLevel2.addKeyValue("\u00d3", "o\001");//Ã
gChangeLevel2.addKeyValue("\u00f2", "o\002");//Ã²
gChangeLevel2.addKeyValue("\u00d2", "o\002");//Ã
gChangeLevel2.addKeyValue("\u00f4", "o\003");//Ã´
gChangeLevel2.addKeyValue("\u00d4", "o\003");//Ã
gChangeLevel2.addKeyValue("\u00f5", "o\004");//Ãµ
gChangeLevel2.addKeyValue("\u00f6", "o\005");//Ã¶
gChangeLevel2.addKeyValue("\u00d6", "o\005");//Ã
gChangeLevel2.addKeyValue("\u0053", "s\000");//S
gChangeLevel2.addKeyValue("\u0073", "s\000");//s
gChangeLevel2.addKeyValue("\u00df", "ss");//Ã
gChangeLevel2.addKeyValue("\u0055", "u\001");//U
gChangeLevel2.addKeyValue("\u0075", "u\001");//u
gChangeLevel2.addKeyValue("\u00fa", "u\001");//Ãº
gChangeLevel2.addKeyValue("\u00da", "u\001");//Ã
gChangeLevel2.addKeyValue("\u00f9", "u\002");//Ã¹
gChangeLevel2.addKeyValue("\u00d9", "u\002");//Ã
gChangeLevel2.addKeyValue("\u00fb", "u\003");//Ã»
gChangeLevel2.addKeyValue("\u00db", "u\003");//Ã
gChangeLevel2.addKeyValue("\u00fc", "u\004");//Ã¼
gChangeLevel2.addKeyValue("\u00dc", "u\004");//Ã
gChangeLevel2.addKeyValue("\u0059", "y\000");//Y
gChangeLevel2.addKeyValue("\u0079", "y\000");//y
gChangeLevel2.addKeyValue("\u00fd", "y\001");//Ã½
gChangeLevel2.addKeyValue("\u00dd", "y\001");//Ã
gChangeLevel2.addKeyValue("\u00ff", "y\002");//Ã¿
gChangeLevel2.addKeyValue("\u00f1", "n\001");//Ã±
gChangeLevel2.addKeyValue("\u00d1", "n\001");//Ã
gChangeLevel2.addKeyValue("-", "");
gChangeLevel2.addKeyValue("'", "");
gChangeLevel2.addKeyValue("!", "");
gChangeLevel2.addKeyValue('"', "");
gChangeLevel2.addKeyValue("#", "");
gChangeLevel2.addKeyValue("$", "");
gChangeLevel2.addKeyValue("%", "");
gChangeLevel2.addKeyValue("&", "");
gChangeLevel2.addKeyValue("'", "");
gChangeLevel2.addKeyValue("(", "");
gChangeLevel2.addKeyValue(")", "");
gChangeLevel2.addKeyValue("*", "");
gChangeLevel2.addKeyValue("+", "");
gChangeLevel2.addKeyValue(",", "");
gChangeLevel2.addKeyValue("-", "");
gChangeLevel2.addKeyValue(".", "");
gChangeLevel2.addKeyValue("/", "");
gChangeLevel2.addKeyValue(":", "");
gChangeLevel2.addKeyValue(";", "");
gChangeLevel2.addKeyValue("<", "");
gChangeLevel2.addKeyValue("=", "");
gChangeLevel2.addKeyValue(">", "");
gChangeLevel2.addKeyValue("?", "");
gChangeLevel2.addKeyValue("@", "");
gChangeLevel2.addKeyValue("[", "");
gChangeLevel2.addKeyValue("\\", "");
gChangeLevel2.addKeyValue("]", "");
gChangeLevel2.addKeyValue("^", "");
gChangeLevel2.addKeyValue("_", "");
gChangeLevel2.addKeyValue("`", "");
gChangeLevel2.addKeyValue("{", "");
gChangeLevel2.addKeyValue("|", "");
gChangeLevel2.addKeyValue("}", "");
gChangeLevel2.addKeyValue("~", "");
delete gChangeLevel2.addKeyValue;

//--------------------------------------------------------------------
/**
 * creates an simple compareable string out of an internationalized string
 * This is done using EOR conform rules
 *
 * @param aStr: string: an arbitrary stringthe path segments that should be encoded
 * @return string: the by >< compareable representation of aStr
 */
function intStrKeyLevel1(aStr)
{  // create internationalised sortable string
  var return_str=intStrKeyLevel1.cache_[aStr];
  if (return_str) // return chached version of the string if present
    return return_str;
  var theStr=aStr.replace(LANG_OBJECTJS_REGEXP_WHITESPACESLINESTART,"");
  var theStr=theStr.replace(LANG_OBJECTJS_REGEXP_WHITESPACESLINEEND,"");

var aRegExp=new RegExp("[\u0041\u0061\u00c6\u00e6\u00e1\u00c1\u00e0\u00c0\u00e2\u00c2\u00e5\u00c5\u00e4\u00c4\u00e3\u00c3\u0043\u0063\u00e7\u00c7\u0044\u0064\u00d0\u00f0\u00e9\u0065\u0045\u00c9\u00e8\u00c8\u00ea\u00ca\u00eb\u00cb\u0049\u0069\u00ed\u00cd\u00ec\u00cc\u00ee\u00ce\u00ef\u00cf\u004f\u006f\u00d8\u00f8\u00f3\u00d3\u00f2\u00d2\u00f4\u00d4\u00f5\u00f6\u00d6\u0053\u0073\u00df\u0055\u0075\u00fa\u00da\u00f9\u00d9\u00fb\u00db\u00fc\u00dc\u0059\u0079\u00fd\u00dd\u00ff\u00f1\u00d1\\-\\'\\!\\\"\\#\\%\\&\\'\\(\\)\\*\\+,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~]","g");
  var return_str=theStr.replace ( aRegExp, intStrKeyLevel1.lamdaExp );
  intStrKeyLevel1.cache_[aStr]=return_str;
  return return_str;
}

intStrKeyLevel1.cache_={};
intStrKeyLevel1.lamdaExp = function (key) {
  var ret=gChangeLevel1[key];
  if (typeof ret !="undefined")
    return ret;
  else
    return key;
};
 

function intStrKeyLevel2(aStr)
{  // create internationalised sortable string
  var return_str=intStrKeyLevel2.cache_[aStr];
  if (return_str) // return chached version of the string if present
    return return_str;
  var theStr=aStr.replace(LANG_OBJECTJS_REGEXP_WHITESPACESLINESTART,"");
  var theStr=theStr.replace(LANG_OBJECTJS_REGEXP_WHITESPACESLINEEND,"");

  var aRegExp=new RegExp("[\u0041\u0061\u00c6\u00e6\u00e1\u00c1\u00e0\u00c0\u00e2\u00c2\u00e5\u00c5\u00e4\u00c4\u00e3\u00c3\u0043\u0063\u00e7\u00c7\u0044\u0064\u00d0\u00f0\u00e9\u0065\u0045\u00c9\u00e8\u00c8\u00ea\u00ca\u00eb\u00cb\u0049\u0069\u00ed\u00cd\u00ec\u00cc\u00ee\u00ce\u00ef\u00cf\u004f\u006f\u00d8\u00f8\u00f3\u00d3\u00f2\u00d2\u00f4\u00d4\u00f5\u00f6\u00d6\u0053\u0073\u00df\u0055\u0075\u00fa\u00da\u00f9\u00d9\u00fb\u00db\u00fc\u00dc\u0059\u0079\u00fd\u00dd\u00ff\u00f1\u00d1\\-\\'\\!\\\"\\#\\%\\&\\'\\(\\)\\*\\+\\,\\.\\/\\:\\;\\<\\=\\>\\?\\@\\[\\\\\\]\\^\\_\\`\\{\\|\\}\\~]","g");

  return_str= theStr.replace ( aRegExp, intStrKeyLevel2.lamdaExp );
  intStrKeyLevel2.cache_[aStr]=return_str;
  return return_str;
}

intStrKeyLevel2.cache_={};
intStrKeyLevel2.lamdaExp = function (key) {
  var ret=gChangeLevel2[key];
  if (typeof ret !="undefined")
    return ret;
  else
    return key;
};

//--------------------------------------------------------------------
/**
 * compares two strings using EOR conform rules
 *
 * @param a,b: string: the two strings to compare
 * @return string: -1,0,1 as used for sorting
 */
function compareIntStrings(a,b)
{
  var aa=intStrKeyLevel1(a);
  var bb=intStrKeyLevel1(b);
  if (aa>bb) return 1; 
  else if (aa<bb) return -1;
  
  var aa=intStrKeyLevel2(a);
  var bb=intStrKeyLevel2(b);
  if (aa>bb) return 1; 
  else if (aa<bb) return -1;
  else return 0;
}
/* End of  "Object.js" */

