/*
 * <copyright>
 *  Copyright (c) 2001 by Hyperwave AG
 * </copyright>
 *
 * <file>
 *  Name:        Resource.js
 *  Created:     2001-01-14
 *  $Id: Resource.js,v 1.9.2.2 2005/08/19 07:26:54 mmair Exp $
 * </file>
 */

initPackage ( "com.hyperwave.res" );
loadClass ( "com.hyperwave.res.AbstractResource" );
loadClass ( "com.hyperwave.res.ResourceReader" );
loadClass ( "com.hyperwave.res.ScopedMap" );

//----------------------------------------------------------------------
/**
 * Class represents a simple resource which contains a template with 
 * placeholders as well as string resources. 
 */
// <JSClass Name="com.hyperwave.res.Resource">

  //--------------------------------------------------------------------
  /**
   * Constructs a simple [compound] resource by means of
   * an empty template or a string template.
   * @param aParam: void | Object: contains the template's key
   * @param aParam.templateKey_: void | String:
   *   the template key.
   */
  com.hyperwave.res.Resource = function ( aParam )
  {
    if ( aParam == "__proto__" )
      return;

    this.base$ = com.hyperwave.res.AbstractResource;
    this.base$ ( aParam );

    if ( aParam != null )
    {
      if ( aParam.templateKey_ )
        this.templateKey_ = aParam.templateKey_;
      if ( aParam.defaultReader_ )
        this.defaultReader_ = aParam.defaultReader_;
    }
    else
    {
      this.templateKey_ = null;
      this.defaultReader_ = null;
    }

    /**
     * The children of this resource.
     */
    this.resMap_ = null;

    /**
      * The resource's default template. This template will
      * be taken if no other template can be found.
      */
    this.defaultTemplate_ = null;

    /**
     * The Cache of this resource if it has already been evaluated
     */
    this.cachedString_ = null;
  }
  class$ = doInherit ( com.hyperwave.res.Resource,
                       com.hyperwave.res.AbstractResource );

  //--------------------------------------------------------------------
  /**
   * Set the parent resource of the current resource. This is done
   * to <i>join</i> the (scoped) resource maps for the latter
   * placeholder evaluation.
   * @param theParentRes: com.hyperwave.res.ScopedMap: the parent
   *   resource's map.
   */
  class$._setParent = function ( theParentRes )
  {
    if ( this.resMap_ != null )
    {
      this.error_ = new com.hyperwave.res.ResourceException (
        "Program Error - Resource added twice!" );
      return true;
    }
    this.resMap_ = new com.hyperwave.res.ScopedMap ( theParentRes );

    this.error_ = null;
    return false;
  }

  //--------------------------------------------------------------------
  /**
   * Make the resource a root resource. This marks the resource as the root
   * of a resource tree. <B>REQUIRED:</B> call before assigning resources to 
   * the scoped resource map (using <code>setRes()</code> or 
   * <code>readAll()</code>).
   */
  class$.makeRoot = function ()
  {
    this._setParent ();
    //
    // LNI specific part:
    //   Read in system wide text resources automatically.
    //   The definition of these resources can be found in
    //     lib/share/ResourceManager/ResourceManager.js.
    //
    if (typeof ResourceManager != "undefined")
    {
      this.readAll(ResourceManager.static_.getSystemResourceReader());
    }    
  }

  //--------------------------------------------------------------------
  /**
   * Reads a resource reader's templates and strings into the 
   * resource's (scoped) map. Note that the reader's values 
   * override already set values!
   * @param aReader: com.hyperwave.res.AbstractResourceReader:
   *   the reader which is used to get the resources.
   */
  class$.readAll = function ( aReader )
  {
    if ( aReader.error_ != null )
      this.error_ = new com.hyperwave.res.ResourceException (
        "com.hyperwave.res.Resource: readAll with an erroneus Reader? " + 
        aReader.error_ );

    aReader.initIteration ();
    while ( aReader.hasNextKey () )
    {
      var key = aReader.getNextKey ();
      this.setRes ( key, aReader.getRes ( key ) );
    }
  }

  //--------------------------------------------------------------------
  /**
   * Tells the resource by what a certain placeholder should be replaced.
   * This function is normally used by readers and applications. Readers
   * assign language strings and templates - applications assign
   * application specific data and child resource nodes.
   * The resource or template is then assigned to the internal
   * <i>resource map</i>.
   * @param aKey: String: key of the placeholder 
   * @param aRes: com.hyperwave.res.AbstractResource: 
   *               replacement for the specified placeholder (can also be of type
   *               <CODE>com.hyperwave.res.Template</CODE>)
   */
  class$.setRes = function ( aKey, aRes )
  {
    // if someone is trying to assign something unknown - raise an error and leave
    if (typeof aRes == "undefined") {
      this.error_ = new com.hyperwave.res.ResourceException (
        "com.hyperwave.res.Resource: Method setRes was called with undefined value for key: " + aKey );
      return;
    }
    
    if ( typeof aRes._setParent == 'function')
      aRes._setParent ( this.resMap_ );

    if ( this.resMap_ == null ) {
      this.error_ = new com.hyperwave.res.ResourceException (
        "com.hyperwave.res.Resource: Resource not added or set to root!" );
    }
    else 
      this.resMap_.set ( aKey, aRes );
  }
  
  class$.getRes = function ( aKey ) {
    return this.resMap_.get ( aKey );
  }

  //--------------------------------------------------------------------
  /**
   * Evaluates a resource to a string. This is done in two steps:
   * Firstly, a template for the resource must be found. This is done
   * by means of the initial <code>templateKey_</code> and the resource
   * maps. If no template can be found the resource tries to
   * find the template using its <code>defaultReader_</code>.
   * The template's placeholders are replaced according to the
   * data of the scoped resource map. The resulting string is returned.
   * @param forceRebuild: Boolean: if true the string representation
   *                 is built up newly, the cached version is not used.
   * @return String: the resulting string.
   */
  class$.toString = function ( forceRebuild )
  {
    if ( (typeof forceRebuild != "undefined") && (forceRebuild == true) )
      this.cachedString_ = null;
    
    if ( this.cachedString_ )
      return this.cachedString_;

    if ( this.templateKey_ == null )
      return ( this.error_ = new com.hyperwave.res.ResourceException (
        "com.hyperwave.res.Resource: No templateKey was defined for Resource." ) ).toString();

    if ( this.resMap_ == null )
      return ( this.error_ = new com.hyperwave.res.ResourceException (
        "com.hyperwave.res.Resource: Resource not added or set to root!" ) ).toString();

    var template = this.resMap_.get ( this.templateKey_ );
    if ( template == null )
    {
      if ( this.defaultReader_ == null )
      {
        return ( this.error_ = new com.hyperwave.res.ResourceException (
          "com.hyperwave.res.Resource: No template reader to read default template. Used template key: "  + this.templateKey_ + 
          ( this.error_ != null ? ( "Previous (uncaught?) error: " + this.error_ ) : "" ) ) );
      }
      template = this.defaultReader_.getRes ( this.templateKey_ );
      if ( this.defaultReader_.error_ || 
           template == null || 
           template.isTemplate_ == false )
      {
        this.error_ = new com.hyperwave.res.ResourceException (
          "com.hyperwave.res.Resource: No template found for key '" + 
          this.templateKey_ + "'." );
        if ( this.defaultReader_.error_ )
          this.error_.pushError ( this.defaultReader_.error_ );
        return this.error_;
      }
    }

    this.error_ = null;
    this.cachedString_ = template.fill ( this.resMap_ );
    return this.cachedString_;
  }

  //--------------------------------------------------------------------
  /**
   * Main function to test the resource mechanism.
   */
  class$.static_.main = function ()
  {
    gEvalCount = 0;
    writelnError ( "Generating Data ..." );
    var data = {};
    data.date_ = String (new Date().valueOf());
    data.buttonText_ = "This is the full featured Button text";
    data.logoText_ = "base.logotext";
    data.footerLogoText_ = "footer.logotext";
    data.headerLogoText_ = "header.logotext";
    data.table_ = [];
    var table1_ = [ 
      { person: "Tarek", shoeSize: "47" },
      { person: "Martin", shoeSize: "52" },
      { person: "J&uuml;rgen", shoeSize: "530" },
      { person: "Werner", shoeSize: "205" },
      { person: "Simon", shoeSize: "22" }
      ];
    for ( var i = 0; i < 1; ++i )
      data.table_ = data.table_.concat ( table1_ );

    writelnError ( "Making Resource Readers ..." )
    var templ_reader = new com.hyperwave.res.ResourceReader ( { lrcFileName_: "htmlres1.lrc" } );
    var lang_reader = new com.hyperwave.res.ResourceReader ( { lrcFileName_: "restable1.lrc" } );
//    if ( templ_reader.error_ )
//    {
//      writelnError ( "Error in reader: " + templ_reader.error_ );
//      return;
//    }
//    if ( lang_reader.error_ )
//    {
//      writelnError ( "Error in reader: " + lang_reader.error_ );
//      return;
//    }

    start_tist = new Date().valueOf();
    writelnError ( start_tist + ": Start" );

    var res = new com.hyperwave.res.Resource ( { templateKey_:"main" } );
    res.makeRoot ();
    res.readAll ( templ_reader );
    res.readAll ( lang_reader );
    res.setRes ( "date", data.date_ );
    res.setRes ( "ButtonText", data.buttonText_ );
    res.setRes ( "table", data.table_ );
    res.setRes ( "logoText", data.logoText_ );

    var headerx = new com.hyperwave.res.Resource ( { templateKey_:"header" } );
    var footerx = new com.hyperwave.res.Resource ( { templateKey_:"footer" } );
    res.setRes ( "headerx", headerx );
    res.setRes ( "footerx", footerx );

    headerx.setRes ( "logoText", data.headerLogoText_ );
    footerx.setRes ( "logoText", data.footerLogoText_ );

    var out = res.toString();
    write ( out );
    writelnError ( "Evals: " + gEvalCount );
    writelnError ( "Chars: " + out.length );

    stop_tist = new Date().valueOf();
    writelnError ( stop_tist + ": End of prepare: duration=" + 
                   (stop_tist - start_tist) );

  }
// </JSClass>
//----------------------------------------------------------------------

/* End of "com.hyperwave.res.Resource.js" */

