i've tried different approaches also but they all fail because the
PropertyDictionary.ExpandProperties uses regex to find ${prop} in
strings, and regex is intrinsically lazy.  i wouldn't dare change
nant.core directly (!), but indirectly... pls. find attached replacement
code for PropertyDictionary.ExpandProperties, as well as test code.  i'm
sorry to not submit a formal patch.  i wanted to submit a testable unit
(to prove i didn't break core code).    

when/if integrating this, just uncomment the Location stuff and the
BuildException line.

HTH

 

> -----Original Message-----
> From: [EMAIL PROTECTED] 
> [mailto:[EMAIL PROTECTED] On Behalf Of 
> Patrick Breen
> Sent: Saturday, December 06, 2003 11:00
> To: [EMAIL PROTECTED]
> Subject: [Nant-users] Property Value Indirection?
> 
> 
> Is there any way to use indirection when fetching the value 
> of a property?  
> 
> I'd like to be able to establish a set of properties to use 
> as data to drive a generic build target implementation.  In 
> the example below, the per product data is limited to 
> version, but there are a handful of properties for each 
> product I'd like to define.  Then, based on which product is 
> active, fetch the appropriate values to drive the build.
> 
> I've experimented with different combinations of $,{,} and 
> using the 'dynamic' attribute without any luck.
> 
> 
> <?xml version="1.0" ?>
> <project name="test" default="test">
>    <property name="Product1.version" value="1" />
>    <property name="Product2.version" value="2" />
>    <property name="Product3.version" value="3" />
>  
>    <property name="products" value="
>       Product1,
>       Product2,
>       Product3" />
>  
>    <foreach item="String" delim="," trim="Both" 
> property="build.product" in="${products}">
>       <echo message="${build.product}" />
>       <echo message="${${build.product}.version}" />
>    </foreach>
> </project>
> 
> 
> 
> 
> -------------------------------------------------------
> This SF.net email is sponsored by: SF.net Giveback Program. 
> Does SourceForge.net help you be more productive?  Does it 
> help you create better code?  SHARE THE LOVE, and help us 
> help YOU!  Click Here: http://sourceforge.net/donate/ 
> _______________________________________________
> Nant-users mailing list
> [EMAIL PROTECTED] 
> https://lists.sourceforge.net/lists/listinfo/n> ant-users
> 
using System;
using System.Collections;
using System.Text;

namespace propParser
{


        class PropertyDictionary : DictionaryBase
        {
   
    /// <summary>
                /// The main entry point for the application.
                /// </summary>
                [STAThread]
                static void Main(string[] args)
                {
      PropertyDictionary Properties = new PropertyDictionary();
      Properties[ "prop1val.prop" ] = "good!";
      Properties[ "prop.1" ] = "prop1val";
      Properties[ "propr0" ] = "nothing";
      Properties[ "prop1" ] = "very good";
      Properties[ "prop2" ] = "very ";
      Properties[ "prop.dangling" ] = "dangling";
      Properties[ "prop.one" ] = "1";
      Properties[ "prop.prop" ] = "prop";
      AssertEquals( "1 test is good!!", Properties.ExpandProperties("1 test is 
${${prop.1}.prop}!")  );
      AssertEquals( "2 test is good!!", Properties.ExpandProperties( "2 test is 
${${${prop.prop}.${prop.one}}.prop}!" ) );
      AssertEquals( "3 test is very good!", Properties.ExpandProperties( "3 test is 
${prop1}!" ) );
      AssertEquals( "4 test is very good!", Properties.ExpandProperties( "4 test is 
${prop2}${${prop.1}.prop}" ) );
      AssertEquals( "5 dangling ${start", Properties.ExpandProperties( "5 dangling 
${start" ) );
      AssertEquals( "6 dangling ${start", Properties.ExpandProperties( "6 
${prop.dangling} ${start" ) );
      AssertEquals( "7 dangling } end", Properties.ExpandProperties( "7 
${prop.dangling} } end" ) );
      try
      {
        Properties.ExpandProperties( " not found: ${bozo}");
        Console.WriteLine( "SHOULD HAVE NOT FOUND bozo" );
      }
      catch {}
      Console.Write( "press enter..." );
      Console.ReadLine();
    }


    static void AssertEquals( string expected, string actual )
    {
      if ( ! expected.Equals( actual ) )
        Console.WriteLine( string.Format( "Expected \"{0}\" but was \"{1}\"", 
expected, actual ) );
    
    }

    public virtual string this[string name] 
    {
      get { return (string) Dictionary[(object) name]; }
      set 
      {
        Dictionary[name] = value;
      }    
    }

    // REAL STUFF STARTS HERE !!!!!!!!

    private string ExpandProperties( string input /*, Location location */)
    {
      // tokenize
      ArrayList tokens = new ArrayList();
      int pos = 0;
      int len;
      for( int i = 0; i < input.Length; i++ )
      {
        len = ( ( input[i]=='$') && (input[i+1]=='{') ) ? 2 : (( input[i]=='}' ) ? 1  
: 0 );
        if ( len > 0 )
        {
          if ( i > pos )
            tokens.Add( input.Substring( pos, i-pos ));
          pos = i + len;
          tokens.Add( input.Substring( i, len ));
          i += len - 1;
        }
      }
      if ( pos < input.Length )
        tokens.Add( input.Substring( pos, input.Length-pos ));
      return propResolve( tokens /*, location */) ;
    }
    
    private string propResolve( ArrayList tokens /*, Location location */)
    {
      bool nothing = false;
      string propertyName = null;
      int start = -1;
      string tok = null;
      while ( ! nothing )
      {
        nothing = true;
        for( int i=0; i < tokens.Count; i++ )
        {
          if ( tokens[i] == null ) continue;
          tok = tokens[i].ToString(); 
          if ( tok == "${" )
          {
            propertyName = string.Empty;
            start = i;
          }
          else if ( ( tok == "}") && (start > -1 ) )
          {
            if ( this[ propertyName ] == null )
//              throw new BuildException(String.Format(CultureInfo.InvariantCulture, 
"Property '{0}' has not been set!", propertyName), location );
              throw new Exception(String.Format( "Property '{0}' has not been set!", 
propertyName));
            tokens[ start ] = this[ propertyName ] ;
            for( int j=start+1; j <= i; j++ )
              tokens[ j ] = null;
            start = -1;
            nothing = false;
          }
          else if ( start > -1 )
          {
            propertyName = string.Concat( propertyName, tok );
          }
        }
      }
      StringBuilder res = new StringBuilder();
      for( int i=0; i < tokens.Count; i++ )
        if ( tokens[i] != null )
          res.Append( tokens[i] );
      return res.ToString();
    }


        }
}

Reply via email to