mirror of https://github.com/apache/maven.git
o Optimized the cache around the hotspot in interpolation somewhat
git-svn-id: https://svn.apache.org/repos/asf/maven/maven-3/trunk@1376085 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
31285e3b68
commit
100bbd031b
|
@ -22,7 +22,9 @@ package org.apache.maven.model.interpolation;
|
||||||
import org.apache.maven.model.Model;
|
import org.apache.maven.model.Model;
|
||||||
import org.apache.maven.model.building.ModelBuildingRequest;
|
import org.apache.maven.model.building.ModelBuildingRequest;
|
||||||
import org.apache.maven.model.building.ModelProblem.Severity;
|
import org.apache.maven.model.building.ModelProblem.Severity;
|
||||||
|
import org.apache.maven.model.building.ModelProblem.Version;
|
||||||
import org.apache.maven.model.building.ModelProblemCollector;
|
import org.apache.maven.model.building.ModelProblemCollector;
|
||||||
|
import org.apache.maven.model.building.ModelProblemCollectorRequest;
|
||||||
import org.codehaus.plexus.component.annotations.Component;
|
import org.codehaus.plexus.component.annotations.Component;
|
||||||
import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
|
import org.codehaus.plexus.interpolation.InterpolationPostProcessor;
|
||||||
import org.codehaus.plexus.interpolation.Interpolator;
|
import org.codehaus.plexus.interpolation.Interpolator;
|
||||||
|
@ -41,19 +43,16 @@ import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import org.apache.maven.model.building.ModelProblem;
|
|
||||||
import org.apache.maven.model.building.ModelProblem.Version;
|
|
||||||
import org.apache.maven.model.building.ModelProblemCollectorRequest;
|
|
||||||
|
|
||||||
@Component( role = ModelInterpolator.class )
|
@Component( role = ModelInterpolator.class )
|
||||||
public class StringSearchModelInterpolator
|
public class StringSearchModelInterpolator
|
||||||
extends AbstractStringBasedModelInterpolator
|
extends AbstractStringBasedModelInterpolator
|
||||||
{
|
{
|
||||||
|
|
||||||
private static final Map<Class<?>, Field[]> fieldsByClass =
|
private static final Map<Class<?>, InterpolateObjectAction.CacheItem> cachedEntries =
|
||||||
new ConcurrentHashMap<Class<?>, Field[]>( 80, 0.75f, 2 ); // Empirical data from 3.x, actual =40
|
new ConcurrentHashMap<Class<?>, InterpolateObjectAction.CacheItem>( 80, 0.75f, 2 );
|
||||||
private static final Map<Class<?>, Boolean> fieldIsPrimitiveByClass =
|
// Empirical data from 3.x, actual =40
|
||||||
new ConcurrentHashMap<Class<?>, Boolean>( 62, 0.75f, 2 ); // Empirical data from 3.x, actual 31
|
|
||||||
|
|
||||||
public Model interpolateModel( Model model, File projectDir, ModelBuildingRequest config,
|
public Model interpolateModel( Model model, File projectDir, ModelBuildingRequest config,
|
||||||
ModelProblemCollector problems )
|
ModelProblemCollector problems )
|
||||||
|
@ -69,8 +68,8 @@ public class StringSearchModelInterpolator
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<? extends ValueSource> valueSources = createValueSources( model, projectDir, config, problems );
|
List<? extends ValueSource> valueSources = createValueSources( model, projectDir, config, problems );
|
||||||
List<? extends InterpolationPostProcessor> postProcessors = createPostProcessors( model, projectDir,
|
List<? extends InterpolationPostProcessor> postProcessors =
|
||||||
config );
|
createPostProcessors( model, projectDir, config );
|
||||||
|
|
||||||
InterpolateObjectAction action =
|
InterpolateObjectAction action =
|
||||||
new InterpolateObjectAction( obj, valueSources, postProcessors, this, problems );
|
new InterpolateObjectAction( obj, valueSources, postProcessors, this, problems );
|
||||||
|
@ -96,9 +95,13 @@ public class StringSearchModelInterpolator
|
||||||
{
|
{
|
||||||
|
|
||||||
private final LinkedList<Object> interpolationTargets;
|
private final LinkedList<Object> interpolationTargets;
|
||||||
|
|
||||||
private final StringSearchModelInterpolator modelInterpolator;
|
private final StringSearchModelInterpolator modelInterpolator;
|
||||||
|
|
||||||
private final List<? extends ValueSource> valueSources;
|
private final List<? extends ValueSource> valueSources;
|
||||||
|
|
||||||
private final List<? extends InterpolationPostProcessor> postProcessors;
|
private final List<? extends InterpolationPostProcessor> postProcessors;
|
||||||
|
|
||||||
private final ModelProblemCollector problems;
|
private final ModelProblemCollector problems;
|
||||||
|
|
||||||
public InterpolateObjectAction( Object target, List<? extends ValueSource> valueSources,
|
public InterpolateObjectAction( Object target, List<? extends ValueSource> valueSources,
|
||||||
|
@ -129,6 +132,12 @@ public class StringSearchModelInterpolator
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private String interpolate( String value )
|
||||||
|
{
|
||||||
|
return modelInterpolator.interpolateInternal( value, valueSources, postProcessors, problems );
|
||||||
|
}
|
||||||
|
|
||||||
private void traverseObjectWithParents( Class<?> cls, Object target )
|
private void traverseObjectWithParents( Class<?> cls, Object target )
|
||||||
{
|
{
|
||||||
if ( cls == null )
|
if ( cls == null )
|
||||||
|
@ -136,73 +145,189 @@ public class StringSearchModelInterpolator
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( cls.isArray() )
|
CacheItem cacheEntry = getCacheEntry( cls );
|
||||||
|
if ( cacheEntry.isArray() )
|
||||||
{
|
{
|
||||||
evaluateArray( target );
|
evaluateArray( target, this );
|
||||||
}
|
}
|
||||||
else if ( isQualifiedForInterpolation( cls ) )
|
else if ( cacheEntry.isQualifiedForInterpolation )
|
||||||
{
|
{
|
||||||
for ( Field currentField : getFields( cls ) )
|
cacheEntry.interpolate( target, problems, this );
|
||||||
{
|
|
||||||
Class<?> type = currentField.getType();
|
|
||||||
if ( isQualifiedForInterpolation( currentField, type ) )
|
|
||||||
{
|
|
||||||
synchronized ( currentField )
|
|
||||||
{
|
|
||||||
interpolateField( cls, target, currentField, type );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
traverseObjectWithParents( cls.getSuperclass(), target );
|
traverseObjectWithParents( cls.getSuperclass(), target );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void interpolateField( Class<?> cls, Object target, Field field, Class<?> type )
|
|
||||||
|
private CacheItem getCacheEntry( Class<?> cls )
|
||||||
|
{
|
||||||
|
CacheItem cacheItem = cachedEntries.get( cls );
|
||||||
|
if ( cacheItem == null )
|
||||||
|
{
|
||||||
|
cacheItem = new CacheItem( cls );
|
||||||
|
cachedEntries.put( cls, cacheItem );
|
||||||
|
}
|
||||||
|
return cacheItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isQualifiedForInterpolation( Class<?> cls )
|
||||||
|
{
|
||||||
|
return !cls.getName().startsWith( "java" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isQualifiedForInterpolation( Field field, Class<?> fieldType )
|
||||||
|
{
|
||||||
|
if ( Map.class.equals( fieldType ) && "locations".equals( field.getName() ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fieldType.isPrimitive() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !"parent".equals( field.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void evaluateArray( Object target, InterpolateObjectAction ctx )
|
||||||
|
{
|
||||||
|
int len = Array.getLength( target );
|
||||||
|
for ( int i = 0; i < len; i++ )
|
||||||
|
{
|
||||||
|
Object value = Array.get( target, i );
|
||||||
|
if ( value != null )
|
||||||
|
{
|
||||||
|
if ( String.class == value.getClass() )
|
||||||
|
{
|
||||||
|
String interpolated = ctx.interpolate( (String) value );
|
||||||
|
|
||||||
|
if ( !interpolated.equals( value ) )
|
||||||
|
{
|
||||||
|
Array.set( target, i, interpolated );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ctx.interpolationTargets.add( value );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class CacheItem
|
||||||
|
{
|
||||||
|
private final boolean isArray;
|
||||||
|
|
||||||
|
private final boolean isQualifiedForInterpolation;
|
||||||
|
|
||||||
|
private final CacheField[] fields;
|
||||||
|
|
||||||
|
private boolean isQualifiedForInterpolation( Class<?> cls )
|
||||||
|
{
|
||||||
|
return !cls.getName().startsWith( "java" );
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isQualifiedForInterpolation( Field field, Class<?> fieldType )
|
||||||
|
{
|
||||||
|
if ( Map.class.equals( fieldType ) && "locations".equals( field.getName() ) )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( fieldType.isPrimitive() )
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !"parent".equals( field.getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
CacheItem( Class clazz )
|
||||||
|
{
|
||||||
|
this.isQualifiedForInterpolation = isQualifiedForInterpolation( clazz );
|
||||||
|
this.isArray = clazz.isArray();
|
||||||
|
List<CacheField> fields = new ArrayList<CacheField>();
|
||||||
|
for ( Field currentField : clazz.getDeclaredFields() )
|
||||||
|
{
|
||||||
|
Class<?> type = currentField.getType();
|
||||||
|
if ( isQualifiedForInterpolation( currentField, type ) )
|
||||||
|
{
|
||||||
|
if ( String.class == type )
|
||||||
|
{
|
||||||
|
if ( !Modifier.isFinal( currentField.getModifiers() ) )
|
||||||
|
{
|
||||||
|
fields.add( new StringField( currentField ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( Collection.class.isAssignableFrom( type ) )
|
||||||
|
{
|
||||||
|
fields.add( new CollectionField( currentField ) );
|
||||||
|
}
|
||||||
|
else if ( Map.class.isAssignableFrom( type ) )
|
||||||
|
{
|
||||||
|
fields.add( new MapField( currentField ) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fields.add( new ObjectField( currentField ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
this.fields = fields.toArray( new CacheField[fields.size()] );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void interpolate( Object target, ModelProblemCollector problems,
|
||||||
|
InterpolateObjectAction interpolateObjectAction )
|
||||||
|
{
|
||||||
|
for ( CacheField field : fields )
|
||||||
|
{
|
||||||
|
field.interpolate( target, problems, interpolateObjectAction );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isArray()
|
||||||
|
{
|
||||||
|
return isArray;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static abstract class CacheField
|
||||||
|
{
|
||||||
|
protected final Field field;
|
||||||
|
|
||||||
|
CacheField( Field field )
|
||||||
|
{
|
||||||
|
this.field = field;
|
||||||
|
}
|
||||||
|
|
||||||
|
void interpolate( Object target, ModelProblemCollector problems,
|
||||||
|
InterpolateObjectAction interpolateObjectAction )
|
||||||
|
{
|
||||||
|
synchronized ( field )
|
||||||
{
|
{
|
||||||
boolean isAccessible = field.isAccessible();
|
boolean isAccessible = field.isAccessible();
|
||||||
field.setAccessible( true );
|
field.setAccessible( true );
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if ( String.class == type )
|
doInterpolate( target, interpolateObjectAction );
|
||||||
{
|
|
||||||
interpolateStringField( target, field );
|
|
||||||
}
|
|
||||||
else if ( Collection.class.isAssignableFrom( type ) )
|
|
||||||
{
|
|
||||||
interpolateCollectionField( target, field );
|
|
||||||
}
|
|
||||||
else if ( Map.class.isAssignableFrom( type ) )
|
|
||||||
{
|
|
||||||
interpolateMapField( target, field );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Object value = field.get( target );
|
|
||||||
if ( value != null )
|
|
||||||
{
|
|
||||||
if ( field.getType().isArray() )
|
|
||||||
{
|
|
||||||
evaluateArray( value );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
interpolationTargets.add( value );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch ( IllegalArgumentException e )
|
catch ( IllegalArgumentException e )
|
||||||
{
|
{
|
||||||
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE)
|
interpolateObjectAction.problems.add(
|
||||||
.setMessage( "Failed to interpolate field3: " + field + " on class: " + cls.getName())
|
new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage(
|
||||||
.setException(e));
|
"Failed to interpolate field3: " + field + " on class: "
|
||||||
|
+ field.getType().getName() ).setException(
|
||||||
|
e ) ); // todo: Not entirely the same message
|
||||||
}
|
}
|
||||||
catch ( IllegalAccessException e )
|
catch ( IllegalAccessException e )
|
||||||
{
|
{
|
||||||
problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE)
|
interpolateObjectAction.problems.add(
|
||||||
.setMessage( "Failed to interpolate field4: " + field + " on class: " + cls.getName())
|
new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage(
|
||||||
.setException(e));
|
"Failed to interpolate field4: " + field + " on class: "
|
||||||
|
+ field.getType().getName() ).setException( e ) );
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -210,29 +335,53 @@ public class StringSearchModelInterpolator
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void interpolateStringField( Object target, Field field )
|
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract void doInterpolate( Object target, InterpolateObjectAction ctx )
|
||||||
|
throws IllegalAccessException;
|
||||||
|
}
|
||||||
|
|
||||||
|
static final class StringField
|
||||||
|
extends CacheField
|
||||||
|
{
|
||||||
|
StringField( Field field )
|
||||||
|
{
|
||||||
|
super( field );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void doInterpolate( Object target, InterpolateObjectAction ctx )
|
||||||
throws IllegalAccessException
|
throws IllegalAccessException
|
||||||
{
|
{
|
||||||
String value = (String) field.get( target );
|
String value = (String) field.get( target );
|
||||||
if ( value == null || Modifier.isFinal( field.getModifiers() ) )
|
if ( value == null )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
String interpolated =
|
String interpolated = ctx.interpolate( value );
|
||||||
modelInterpolator.interpolateInternal( value, valueSources, postProcessors, problems );
|
|
||||||
|
|
||||||
if ( !interpolated.equals( value ) )
|
if ( !interpolated.equals( value ) )
|
||||||
{
|
{
|
||||||
field.set( target, interpolated );
|
field.set( target, interpolated );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void interpolateCollectionField( Object target, Field field )
|
static final class CollectionField
|
||||||
|
extends CacheField
|
||||||
|
{
|
||||||
|
CollectionField( Field field )
|
||||||
|
{
|
||||||
|
super( field );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void doInterpolate( Object target, InterpolateObjectAction ctx )
|
||||||
throws IllegalAccessException
|
throws IllegalAccessException
|
||||||
{
|
{
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" ) Collection<Object> c = (Collection<Object>) field.get( target );
|
||||||
Collection<Object> c = (Collection<Object>) field.get( target );
|
|
||||||
if ( c == null || c.isEmpty() )
|
if ( c == null || c.isEmpty() )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -257,8 +406,7 @@ public class StringSearchModelInterpolator
|
||||||
}
|
}
|
||||||
else if ( String.class == value.getClass() )
|
else if ( String.class == value.getClass() )
|
||||||
{
|
{
|
||||||
String interpolated =
|
String interpolated = ctx.interpolate( (String) value );
|
||||||
modelInterpolator.interpolateInternal( (String) value, valueSources, postProcessors, problems );
|
|
||||||
|
|
||||||
if ( !interpolated.equals( value ) )
|
if ( !interpolated.equals( value ) )
|
||||||
{
|
{
|
||||||
|
@ -274,21 +422,30 @@ public class StringSearchModelInterpolator
|
||||||
c.add( value );
|
c.add( value );
|
||||||
if ( value.getClass().isArray() )
|
if ( value.getClass().isArray() )
|
||||||
{
|
{
|
||||||
evaluateArray( value );
|
evaluateArray( value, ctx );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
interpolationTargets.add( value );
|
ctx.interpolationTargets.add( value );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void interpolateMapField( Object target, Field field )
|
static final class MapField
|
||||||
|
extends CacheField
|
||||||
|
{
|
||||||
|
MapField( Field field )
|
||||||
|
{
|
||||||
|
super( field );
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void doInterpolate( Object target, InterpolateObjectAction ctx )
|
||||||
throws IllegalAccessException
|
throws IllegalAccessException
|
||||||
{
|
{
|
||||||
@SuppressWarnings( "unchecked" )
|
@SuppressWarnings( "unchecked" ) Map<Object, Object> m = (Map<Object, Object>) field.get( target );
|
||||||
Map<Object, Object> m = (Map<Object, Object>) field.get( target );
|
|
||||||
if ( m == null || m.isEmpty() )
|
if ( m == null || m.isEmpty() )
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
@ -305,8 +462,7 @@ public class StringSearchModelInterpolator
|
||||||
|
|
||||||
if ( String.class == value.getClass() )
|
if ( String.class == value.getClass() )
|
||||||
{
|
{
|
||||||
String interpolated =
|
String interpolated = ctx.interpolate( (String) value );
|
||||||
modelInterpolator.interpolateInternal( (String) value, valueSources, postProcessors, problems );
|
|
||||||
|
|
||||||
if ( !interpolated.equals( value ) )
|
if ( !interpolated.equals( value ) )
|
||||||
{
|
{
|
||||||
|
@ -322,79 +478,46 @@ public class StringSearchModelInterpolator
|
||||||
}
|
}
|
||||||
else if ( value.getClass().isArray() )
|
else if ( value.getClass().isArray() )
|
||||||
{
|
{
|
||||||
evaluateArray( value );
|
evaluateArray( value, ctx );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
interpolationTargets.add( value );
|
ctx.interpolationTargets.add( value );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Field[] getFields( Class<?> cls )
|
static final class ObjectField
|
||||||
|
extends CacheField
|
||||||
{
|
{
|
||||||
Field[] fields = fieldsByClass.get( cls );
|
private final boolean isArray;
|
||||||
if ( fields == null )
|
|
||||||
|
ObjectField( Field field )
|
||||||
{
|
{
|
||||||
fields = cls.getDeclaredFields();
|
super( field );
|
||||||
fieldsByClass.put( cls, fields );
|
this.isArray = field.getType().isArray();
|
||||||
}
|
|
||||||
return fields;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isQualifiedForInterpolation( Class<?> cls )
|
@Override
|
||||||
|
void doInterpolate( Object target, InterpolateObjectAction ctx )
|
||||||
|
throws IllegalAccessException
|
||||||
{
|
{
|
||||||
return !cls.getName().startsWith( "java" );
|
Object value = field.get( target );
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isQualifiedForInterpolation( Field field, Class<?> fieldType )
|
|
||||||
{
|
|
||||||
if ( Map.class.equals( fieldType ) && "locations".equals( field.getName() ) )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Boolean primitive = fieldIsPrimitiveByClass.get( fieldType );
|
|
||||||
if ( primitive == null )
|
|
||||||
{
|
|
||||||
primitive = fieldType.isPrimitive();
|
|
||||||
fieldIsPrimitiveByClass.put( fieldType, primitive );
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( primitive )
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return !"parent".equals( field.getName() );
|
|
||||||
}
|
|
||||||
|
|
||||||
private void evaluateArray( Object target )
|
|
||||||
{
|
|
||||||
int len = Array.getLength( target );
|
|
||||||
for ( int i = 0; i < len; i++ )
|
|
||||||
{
|
|
||||||
Object value = Array.get( target, i );
|
|
||||||
if ( value != null )
|
if ( value != null )
|
||||||
{
|
{
|
||||||
if ( String.class == value.getClass() )
|
if ( isArray )
|
||||||
{
|
{
|
||||||
String interpolated =
|
evaluateArray( value, ctx );
|
||||||
modelInterpolator.interpolateInternal( (String) value, valueSources, postProcessors,
|
|
||||||
problems );
|
|
||||||
|
|
||||||
if ( !interpolated.equals( value ) )
|
|
||||||
{
|
|
||||||
Array.set( target, i, interpolated );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
interpolationTargets.add( value );
|
ctx.interpolationTargets.add( value );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue