mirror of
https://github.com/apache/maven.git
synced 2025-02-08 19:15:12 +00:00
o Extended plugin to support expressions like "project/dependencies/*/artifactId" to iterate collections
git-svn-id: https://svn.apache.org/repos/asf/maven/core-integration-testing/trunk@949790 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
43b2be7947
commit
aafe8e9c67
@ -26,6 +26,7 @@
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
@ -51,7 +52,7 @@
|
|||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* Expressions that reference non-existing objects or use invalid collection/array indices silently resolve to
|
* Expressions that reference non-existing objects or use invalid collection/array indices silently resolve to
|
||||||
* <code>null</code>.
|
* <code>null</code>. For collections and arrays, the special index "*" can be used to iterate all elements.
|
||||||
*
|
*
|
||||||
* @goal eval
|
* @goal eval
|
||||||
* @phase initialize
|
* @phase initialize
|
||||||
@ -176,8 +177,13 @@ public void execute()
|
|||||||
|
|
||||||
for ( int i = 0; i < expressions.length; i++ )
|
for ( int i = 0; i < expressions.length; i++ )
|
||||||
{
|
{
|
||||||
Object value = ExpressionUtil.evaluate( expressions[i], contexts );
|
Map values = ExpressionUtil.evaluate( expressions[i], contexts );
|
||||||
PropertyUtil.store( expressionProperties, expressions[i].replace( '/', '.' ), value );
|
for ( Iterator it = values.keySet().iterator(); it.hasNext(); )
|
||||||
|
{
|
||||||
|
Object key = it.next();
|
||||||
|
Object value = values.get( key );
|
||||||
|
PropertyUtil.store( expressionProperties, key.toString().replace( '/', '.' ), value );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -48,65 +51,56 @@ class ExpressionUtil
|
|||||||
* Evaluates the specified expression. Expressions are composed of segments which are separated by a forward slash
|
* Evaluates the specified expression. Expressions are composed of segments which are separated by a forward slash
|
||||||
* ('/'). Each segment specifies a (public) bean property of the current object and drives the evaluation further
|
* ('/'). Each segment specifies a (public) bean property of the current object and drives the evaluation further
|
||||||
* down the object graph. For lists, arrays and maps segments can additionally specify the index/key of an element.
|
* down the object graph. For lists, arrays and maps segments can additionally specify the index/key of an element.
|
||||||
* The initial segment denotes the root object and the parameter <code>contexts</code> is used to specify which
|
* The initial segment denotes the root object and the parameter <code>contexts</code> is used to specify which root
|
||||||
* root objects are available. For instance, if <code>contexts</code> maps the token "project" to a Maven project
|
* objects are available. For instance, if <code>contexts</code> maps the token "project" to a Maven project
|
||||||
* instance, the expression "project/build/resources/0/directory" specifies the first resource directory of the
|
* instance, the expression "project/build/resources/0/directory" specifies the first resource directory of the
|
||||||
* project.
|
* project.
|
||||||
*
|
*
|
||||||
* @param expression The expression to evaluate, may be <code>null</code>.
|
* @param expression The expression to evaluate, may be <code>null</code>.
|
||||||
* @param contexts The possible root objects for the expression evaluation, indexed by their identifying token, must
|
* @param context The object to start expression evaluation at, must not be <code>null</code>.
|
||||||
* not be <code>null</code>.
|
* @return The values of the evaluation, indexed by expression, or an empty map if the segments could not be
|
||||||
* @return The value of the expression or <code>null</code> if the expression could not be evaluated.
|
* evaluated.
|
||||||
*/
|
*/
|
||||||
public static Object evaluate( String expression, Map contexts )
|
public static Map evaluate( String expression, Object context )
|
||||||
{
|
{
|
||||||
Object value = null;
|
Map values = Collections.EMPTY_MAP;
|
||||||
|
|
||||||
if ( expression != null && expression.length() > 0 )
|
if ( expression != null && expression.length() > 0 )
|
||||||
{
|
{
|
||||||
List segments = Arrays.asList( expression.split( "/", 0 ) );
|
List segments = Arrays.asList( expression.split( "/", 0 ) );
|
||||||
if ( !segments.isEmpty() )
|
values = evaluate( "", segments, context );
|
||||||
{
|
|
||||||
Object context = contexts.get( segments.get( 0 ) );
|
|
||||||
if ( context != null )
|
|
||||||
{
|
|
||||||
value = evaluate( context, segments.subList( 1, segments.size() ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Evaluates the given expression segments against the specified object.
|
* Evaluates the given expression segments against the specified object.
|
||||||
*
|
*
|
||||||
* @param context The object to evaluate the segments against, may be <code>null</code>.
|
* @param prefix The expression prefix that led to the current context, must not be <code>null</code>.
|
||||||
* @param segments The expression segments to evaluate, must not be <code>null</code>.
|
* @param segments The expression segments to evaluate, must not be <code>null</code>.
|
||||||
* @return The value of the evaluation or <code>null</code> if the segments could not be evaluated.
|
* @param context The object to evaluate the segments against, may be <code>null</code>.
|
||||||
|
* @return The values of the evaluation, indexed by expression, or an empty map if the segments could not be
|
||||||
|
* evaluated.
|
||||||
*/
|
*/
|
||||||
private static Object evaluate( Object context, List segments )
|
private static Map evaluate( String prefix, List segments, Object context )
|
||||||
{
|
{
|
||||||
Object value = null;
|
Map values = Collections.EMPTY_MAP;
|
||||||
|
|
||||||
if ( segments.isEmpty() )
|
if ( segments.isEmpty() )
|
||||||
{
|
{
|
||||||
value = context;
|
values = Collections.singletonMap( prefix, context );
|
||||||
}
|
}
|
||||||
else if ( context != null )
|
else if ( context != null )
|
||||||
{
|
{
|
||||||
Object target = null;
|
Map targets = Collections.EMPTY_MAP;
|
||||||
String segment = (String) segments.get( 0 );
|
String segment = (String) segments.get( 0 );
|
||||||
if ( segment.length() <= 0 )
|
if ( context.getClass().isArray() && Character.isDigit( segment.charAt( 0 ) ) )
|
||||||
{
|
|
||||||
value = context;
|
|
||||||
}
|
|
||||||
else if ( context.getClass().isArray() && Character.isDigit( segment.charAt( 0 ) ) )
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
int index = Integer.parseInt( segment );
|
int index = Integer.parseInt( segment );
|
||||||
target = Array.get( context, index );
|
targets = Collections.singletonMap( segment, Array.get( context, index ) );
|
||||||
}
|
}
|
||||||
catch ( RuntimeException e )
|
catch ( RuntimeException e )
|
||||||
{
|
{
|
||||||
@ -118,21 +112,51 @@ else if ( ( context instanceof List ) && Character.isDigit( segment.charAt( 0 )
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
int index = Integer.parseInt( segment );
|
int index = Integer.parseInt( segment );
|
||||||
target = ( (List) context ).get( index );
|
targets = Collections.singletonMap( segment, ( (List) context ).get( index ) );
|
||||||
}
|
}
|
||||||
catch ( RuntimeException e )
|
catch ( RuntimeException e )
|
||||||
{
|
{
|
||||||
// invalid index, just ignore
|
// invalid index, just ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ( ( context instanceof Collection ) && "*".equals( segment ) )
|
||||||
|
{
|
||||||
|
targets = new LinkedHashMap();
|
||||||
|
int index = 0;
|
||||||
|
for ( Iterator it = ( (Collection) context ).iterator(); it.hasNext(); index++ )
|
||||||
|
{
|
||||||
|
targets.put( Integer.toString( index ), it.next() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( context.getClass().isArray() && "*".equals( segment ) )
|
||||||
|
{
|
||||||
|
targets = new LinkedHashMap();
|
||||||
|
for ( int index = 0, n = Array.getLength( context ); index < n; index++ )
|
||||||
|
{
|
||||||
|
targets.put( Integer.toString( index ), Array.get( context, index ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
target = getProperty( context, segment );
|
targets = Collections.singletonMap( segment, getProperty( context, segment ) );
|
||||||
}
|
|
||||||
value = evaluate( target, segments.subList( 1, segments.size() ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
values = new LinkedHashMap();
|
||||||
|
for ( Iterator it = targets.keySet().iterator(); it.hasNext(); )
|
||||||
|
{
|
||||||
|
Object key = it.next();
|
||||||
|
Object target = targets.get( key );
|
||||||
|
values.putAll( evaluate( concat( prefix, String.valueOf( key ) ),
|
||||||
|
segments.subList( 1, segments.size() ), target ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String concat( String prefix, String segment )
|
||||||
|
{
|
||||||
|
return ( prefix == null || prefix.length() <= 0 ) ? segment : ( prefix + '/' + segment );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,35 +47,48 @@ public void testEvaluate()
|
|||||||
contexts.put( "map", map );
|
contexts.put( "map", map );
|
||||||
contexts.put( "bean", bean );
|
contexts.put( "bean", bean );
|
||||||
|
|
||||||
assertSame( array, ExpressionUtil.evaluate( "array", contexts ) );
|
assertSame( array, evaluate( "array", contexts ) );
|
||||||
assertSame( array, ExpressionUtil.evaluate( "array/", contexts ) );
|
assertSame( array, ExpressionUtil.evaluate( "array/", contexts ).get( "array" ) );
|
||||||
assertSame( list, ExpressionUtil.evaluate( "list", contexts ) );
|
assertSame( list, evaluate( "list", contexts ) );
|
||||||
assertSame( map, ExpressionUtil.evaluate( "map", contexts ) );
|
assertSame( map, evaluate( "map", contexts ) );
|
||||||
assertSame( bean, ExpressionUtil.evaluate( "bean", contexts ) );
|
assertSame( bean, evaluate( "bean", contexts ) );
|
||||||
assertNull( ExpressionUtil.evaluate( "no-root", contexts ) );
|
assertNull( evaluate( "no-root", contexts ) );
|
||||||
|
|
||||||
assertEquals( new Integer( 3 ), ExpressionUtil.evaluate( "array/length", contexts ) );
|
assertEquals( new Integer( 3 ), evaluate( "array/length", contexts ) );
|
||||||
assertEquals( "three", ExpressionUtil.evaluate( "array/2", contexts ) );
|
assertEquals( "three", evaluate( "array/2", contexts ) );
|
||||||
assertEquals( new Integer( 5 ), ExpressionUtil.evaluate( "array/2/length", contexts ) );
|
assertEquals( new Integer( 5 ), evaluate( "array/2/length", contexts ) );
|
||||||
assertNull( ExpressionUtil.evaluate( "array/invalid", contexts ) );
|
assertNull( evaluate( "array/invalid", contexts ) );
|
||||||
assertNull( ExpressionUtil.evaluate( "array/-1", contexts ) );
|
assertNull( evaluate( "array/-1", contexts ) );
|
||||||
assertNull( ExpressionUtil.evaluate( "array/999", contexts ) );
|
assertNull( evaluate( "array/999", contexts ) );
|
||||||
|
assertEquals( 3, ExpressionUtil.evaluate( "array/*", contexts ).size() );
|
||||||
|
assertEquals( "one", ExpressionUtil.evaluate( "array/*", contexts ).get( "array/0" ) );
|
||||||
|
assertEquals( "two", ExpressionUtil.evaluate( "array/*", contexts ).get( "array/1" ) );
|
||||||
|
assertEquals( "three", ExpressionUtil.evaluate( "array/*", contexts ).get( "array/2" ) );
|
||||||
|
|
||||||
assertEquals( new Integer( 3 ), ExpressionUtil.evaluate( "list/size", contexts ) );
|
assertEquals( new Integer( 3 ), evaluate( "list/size", contexts ) );
|
||||||
assertEquals( "-2", ExpressionUtil.evaluate( "list/2", contexts ) );
|
assertEquals( "-2", evaluate( "list/2", contexts ) );
|
||||||
assertNull( ExpressionUtil.evaluate( "list/invalid", contexts ) );
|
assertNull( evaluate( "list/invalid", contexts ) );
|
||||||
assertNull( ExpressionUtil.evaluate( "list/-1", contexts ) );
|
assertNull( evaluate( "list/-1", contexts ) );
|
||||||
assertNull( ExpressionUtil.evaluate( "list/999", contexts ) );
|
assertNull( evaluate( "list/999", contexts ) );
|
||||||
|
assertEquals( 3, ExpressionUtil.evaluate( "list/*", contexts ).size() );
|
||||||
|
assertEquals( "0", ExpressionUtil.evaluate( "list/*", contexts ).get( "list/0" ) );
|
||||||
|
assertEquals( "-1", ExpressionUtil.evaluate( "list/*", contexts ).get( "list/1" ) );
|
||||||
|
assertEquals( "-2", ExpressionUtil.evaluate( "list/*", contexts ).get( "list/2" ) );
|
||||||
|
|
||||||
assertEquals( new Integer( 1 ), ExpressionUtil.evaluate( "map/size", contexts ) );
|
assertEquals( new Integer( 1 ), evaluate( "map/size", contexts ) );
|
||||||
assertEquals( "value", ExpressionUtil.evaluate( "map/some.key", contexts ) );
|
assertEquals( "value", evaluate( "map/some.key", contexts ) );
|
||||||
assertNull( ExpressionUtil.evaluate( "map/invalid", contexts ) );
|
assertNull( evaluate( "map/invalid", contexts ) );
|
||||||
|
|
||||||
assertEquals( "field", ExpressionUtil.evaluate( "bean/field", contexts ) );
|
assertEquals( "field", evaluate( "bean/field", contexts ) );
|
||||||
assertNull( ExpressionUtil.evaluate( "bean/invalid", contexts ) );
|
assertNull( evaluate( "bean/invalid", contexts ) );
|
||||||
assertEquals( "prop", ExpressionUtil.evaluate( "bean/bean/prop", contexts ) );
|
assertEquals( "prop", evaluate( "bean/bean/prop", contexts ) );
|
||||||
assertEquals( "flag", ExpressionUtil.evaluate( "bean/bean/flag", contexts ) );
|
assertEquals( "flag", evaluate( "bean/bean/flag", contexts ) );
|
||||||
assertEquals( "arg", ExpressionUtil.evaluate( "bean/bean/arg", contexts ) );
|
assertEquals( "arg", evaluate( "bean/bean/arg", contexts ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Object evaluate( String expression, Object context )
|
||||||
|
{
|
||||||
|
return ExpressionUtil.evaluate( expression, context ).get( expression );
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetProperty()
|
public void testGetProperty()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user