mirror of https://github.com/apache/maven.git
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 org.apache.maven.plugin.MojoFailureException;
|
|||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
|
@ -51,7 +52,7 @@ import java.util.Properties;
|
|||
* </pre>
|
||||
*
|
||||
* 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
|
||||
* @phase initialize
|
||||
|
@ -176,8 +177,13 @@ public class EvalMojo
|
|||
|
||||
for ( int i = 0; i < expressions.length; i++ )
|
||||
{
|
||||
Object value = ExpressionUtil.evaluate( expressions[i], contexts );
|
||||
PropertyUtil.store( expressionProperties, expressions[i].replace( '/', '.' ), value );
|
||||
Map values = ExpressionUtil.evaluate( expressions[i], contexts );
|
||||
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.Field;
|
|||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
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
|
||||
* ('/'). 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.
|
||||
* The initial segment denotes the root object and the parameter <code>contexts</code> is used to specify which
|
||||
* root objects are available. For instance, if <code>contexts</code> maps the token "project" to a Maven project
|
||||
* The initial segment denotes the root object and the parameter <code>contexts</code> is used to specify which root
|
||||
* 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
|
||||
* project.
|
||||
*
|
||||
* @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
|
||||
* not be <code>null</code>.
|
||||
* @return The value of the expression or <code>null</code> if the expression could not be evaluated.
|
||||
* @param context The object to start expression evaluation at, must not be <code>null</code>.
|
||||
* @return The values of the evaluation, indexed by expression, or an empty map if the segments could not be
|
||||
* 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 )
|
||||
{
|
||||
List segments = Arrays.asList( expression.split( "/", 0 ) );
|
||||
if ( !segments.isEmpty() )
|
||||
{
|
||||
Object context = contexts.get( segments.get( 0 ) );
|
||||
if ( context != null )
|
||||
{
|
||||
value = evaluate( context, segments.subList( 1, segments.size() ) );
|
||||
}
|
||||
}
|
||||
values = evaluate( "", segments, context );
|
||||
}
|
||||
|
||||
return value;
|
||||
return values;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>.
|
||||
* @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() )
|
||||
{
|
||||
value = context;
|
||||
values = Collections.singletonMap( prefix, context );
|
||||
}
|
||||
else if ( context != null )
|
||||
{
|
||||
Object target = null;
|
||||
Map targets = Collections.EMPTY_MAP;
|
||||
String segment = (String) segments.get( 0 );
|
||||
if ( segment.length() <= 0 )
|
||||
{
|
||||
value = context;
|
||||
}
|
||||
else if ( context.getClass().isArray() && Character.isDigit( segment.charAt( 0 ) ) )
|
||||
if ( context.getClass().isArray() && Character.isDigit( segment.charAt( 0 ) ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
int index = Integer.parseInt( segment );
|
||||
target = Array.get( context, index );
|
||||
targets = Collections.singletonMap( segment, Array.get( context, index ) );
|
||||
}
|
||||
catch ( RuntimeException e )
|
||||
{
|
||||
|
@ -118,21 +112,51 @@ class ExpressionUtil
|
|||
try
|
||||
{
|
||||
int index = Integer.parseInt( segment );
|
||||
target = ( (List) context ).get( index );
|
||||
targets = Collections.singletonMap( segment, ( (List) context ).get( index ) );
|
||||
}
|
||||
catch ( RuntimeException e )
|
||||
{
|
||||
// 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
|
||||
{
|
||||
target = getProperty( context, segment );
|
||||
targets = Collections.singletonMap( segment, getProperty( context, segment ) );
|
||||
}
|
||||
|
||||
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 ) );
|
||||
}
|
||||
value = evaluate( target, segments.subList( 1, segments.size() ) );
|
||||
}
|
||||
|
||||
return value;
|
||||
return values;
|
||||
}
|
||||
|
||||
private static String concat( String prefix, String segment )
|
||||
{
|
||||
return ( prefix == null || prefix.length() <= 0 ) ? segment : ( prefix + '/' + segment );
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,35 +47,48 @@ public class ExpressionUtilTest
|
|||
contexts.put( "map", map );
|
||||
contexts.put( "bean", bean );
|
||||
|
||||
assertSame( array, ExpressionUtil.evaluate( "array", contexts ) );
|
||||
assertSame( array, ExpressionUtil.evaluate( "array/", contexts ) );
|
||||
assertSame( list, ExpressionUtil.evaluate( "list", contexts ) );
|
||||
assertSame( map, ExpressionUtil.evaluate( "map", contexts ) );
|
||||
assertSame( bean, ExpressionUtil.evaluate( "bean", contexts ) );
|
||||
assertNull( ExpressionUtil.evaluate( "no-root", contexts ) );
|
||||
assertSame( array, evaluate( "array", contexts ) );
|
||||
assertSame( array, ExpressionUtil.evaluate( "array/", contexts ).get( "array" ) );
|
||||
assertSame( list, evaluate( "list", contexts ) );
|
||||
assertSame( map, evaluate( "map", contexts ) );
|
||||
assertSame( bean, evaluate( "bean", contexts ) );
|
||||
assertNull( evaluate( "no-root", contexts ) );
|
||||
|
||||
assertEquals( new Integer( 3 ), ExpressionUtil.evaluate( "array/length", contexts ) );
|
||||
assertEquals( "three", ExpressionUtil.evaluate( "array/2", contexts ) );
|
||||
assertEquals( new Integer( 5 ), ExpressionUtil.evaluate( "array/2/length", contexts ) );
|
||||
assertNull( ExpressionUtil.evaluate( "array/invalid", contexts ) );
|
||||
assertNull( ExpressionUtil.evaluate( "array/-1", contexts ) );
|
||||
assertNull( ExpressionUtil.evaluate( "array/999", contexts ) );
|
||||
assertEquals( new Integer( 3 ), evaluate( "array/length", contexts ) );
|
||||
assertEquals( "three", evaluate( "array/2", contexts ) );
|
||||
assertEquals( new Integer( 5 ), evaluate( "array/2/length", contexts ) );
|
||||
assertNull( evaluate( "array/invalid", contexts ) );
|
||||
assertNull( evaluate( "array/-1", 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( "-2", ExpressionUtil.evaluate( "list/2", contexts ) );
|
||||
assertNull( ExpressionUtil.evaluate( "list/invalid", contexts ) );
|
||||
assertNull( ExpressionUtil.evaluate( "list/-1", contexts ) );
|
||||
assertNull( ExpressionUtil.evaluate( "list/999", contexts ) );
|
||||
assertEquals( new Integer( 3 ), evaluate( "list/size", contexts ) );
|
||||
assertEquals( "-2", evaluate( "list/2", contexts ) );
|
||||
assertNull( evaluate( "list/invalid", contexts ) );
|
||||
assertNull( evaluate( "list/-1", 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( "value", ExpressionUtil.evaluate( "map/some.key", contexts ) );
|
||||
assertNull( ExpressionUtil.evaluate( "map/invalid", contexts ) );
|
||||
assertEquals( new Integer( 1 ), evaluate( "map/size", contexts ) );
|
||||
assertEquals( "value", evaluate( "map/some.key", contexts ) );
|
||||
assertNull( evaluate( "map/invalid", contexts ) );
|
||||
|
||||
assertEquals( "field", ExpressionUtil.evaluate( "bean/field", contexts ) );
|
||||
assertNull( ExpressionUtil.evaluate( "bean/invalid", contexts ) );
|
||||
assertEquals( "prop", ExpressionUtil.evaluate( "bean/bean/prop", contexts ) );
|
||||
assertEquals( "flag", ExpressionUtil.evaluate( "bean/bean/flag", contexts ) );
|
||||
assertEquals( "arg", ExpressionUtil.evaluate( "bean/bean/arg", contexts ) );
|
||||
assertEquals( "field", evaluate( "bean/field", contexts ) );
|
||||
assertNull( evaluate( "bean/invalid", contexts ) );
|
||||
assertEquals( "prop", evaluate( "bean/bean/prop", contexts ) );
|
||||
assertEquals( "flag", evaluate( "bean/bean/flag", 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()
|
||||
|
|
Loading…
Reference in New Issue