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(); } } }