[MRESOLVER-141] Review index-based access to collections
This closes #76
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDeployer.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDeployer.java
index 78c83ff..4f76175 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDeployer.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultDeployer.java
@@ -27,6 +27,8 @@
import java.util.IdentityHashMap;
import java.util.List;
import static java.util.Objects.requireNonNull;
+
+import java.util.ListIterator;
import java.util.Set;
import javax.inject.Inject;
@@ -257,16 +259,16 @@
processedMetadata.put( metadata, null );
}
- for ( int i = 0; i < artifacts.size(); i++ )
+ for ( ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); )
{
- Artifact artifact = artifacts.get( i );
+ Artifact artifact = iterator.next();
for ( MetadataGenerator generator : generators )
{
artifact = generator.transformArtifact( artifact );
}
- artifacts.set( i, artifact );
+ iterator.set( artifact );
Collection<FileTransformer> fileTransformers =
fileTransformerManager.getTransformersForArtifact( artifact );
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultInstaller.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultInstaller.java
index 38cb2a0..0310524 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultInstaller.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/DefaultInstaller.java
@@ -27,6 +27,7 @@
import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.List;
+import java.util.ListIterator;
import java.util.Set;
import javax.inject.Inject;
@@ -170,16 +171,16 @@
result.addMetadata( metadata );
}
- for ( int i = 0; i < artifacts.size(); i++ )
+ for ( ListIterator<Artifact> iterator = artifacts.listIterator(); iterator.hasNext(); )
{
- Artifact artifact = artifacts.get( i );
+ Artifact artifact = iterator.next();
for ( MetadataGenerator generator : generators )
{
artifact = generator.transformArtifact( artifact );
}
- artifacts.set( i, artifact );
+ iterator.set( artifact );
install( session, trace, artifact );
result.addArtifact( artifact );
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/PrioritizedComponents.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/PrioritizedComponents.java
index fb17b8d..8877bdc 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/PrioritizedComponents.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/PrioritizedComponents.java
@@ -133,13 +133,13 @@
public void list( StringBuilder buffer )
{
- for ( int i = 0; i < components.size(); i++ )
+ int i = 0;
+ for ( PrioritizedComponent<?> component : components )
{
- if ( i > 0 )
+ if ( i++ > 0 )
{
buffer.append( ", " );
}
- PrioritizedComponent<?> component = components.get( i );
buffer.append( component.getType().getSimpleName() );
if ( component.isDisabled() )
{
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java
index 41b5703..0d3187c 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java
@@ -22,6 +22,7 @@
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -320,10 +321,11 @@
{
return false;
}
- for ( int i = 0, n = repos1.size(); i < n; i++ )
+ for ( Iterator<RemoteRepository> it1 = repos1.iterator(), it2 = repos2.iterator();
+ it1.hasNext() && it2.hasNext(); )
{
- RemoteRepository repo1 = repos1.get( i );
- RemoteRepository repo2 = repos2.get( i );
+ RemoteRepository repo1 = it1.next();
+ RemoteRepository repo2 = it2.next();
if ( repo1.isRepositoryManager() != repo2.isRepositoryManager() )
{
return false;
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycle.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycle.java
index 15e1835..42a56c2 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycle.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycle.java
@@ -73,13 +73,14 @@
public String toString()
{
StringBuilder buffer = new StringBuilder( 256 );
- for ( int i = 0, n = dependencies.size(); i < n; i++ )
+ int i = 0;
+ for ( Dependency dependency : dependencies )
{
- if ( i > 0 )
+ if ( i++ > 0 )
{
buffer.append( " -> " );
}
- buffer.append( ArtifactIdUtils.toVersionlessId( dependencies.get( i ).getArtifact() ) );
+ buffer.append( ArtifactIdUtils.toVersionlessId( dependency.getArtifact() ) );
}
return buffer.toString();
}
diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultVersionFilterContext.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultVersionFilterContext.java
index 4488492..bfea062 100644
--- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultVersionFilterContext.java
+++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultVersionFilterContext.java
@@ -21,10 +21,8 @@
import java.util.ArrayList;
import java.util.Collections;
-import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.List;
-import java.util.NoSuchElementException;
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.collection.VersionFilter;
@@ -47,9 +45,7 @@
VersionRangeResult result;
- int count;
-
- byte[] deleted = new byte[64];
+ private List<Version> versions;
DefaultVersionFilterContext( RepositorySystemSession session )
{
@@ -60,40 +56,12 @@
{
this.dependency = dependency;
this.result = result;
- count = result.getVersions().size();
- if ( deleted.length < count )
- {
- deleted = new byte[count];
- }
- else
- {
- for ( int i = count - 1; i >= 0; i-- )
- {
- deleted[i] = (byte) 0;
- }
- }
+ this.versions = new ArrayList<>( result.getVersions() );
}
public List<Version> get()
{
- if ( count == result.getVersions().size() )
- {
- return result.getVersions();
- }
- if ( count <= 1 )
- {
- if ( count <= 0 )
- {
- return Collections.emptyList();
- }
- return Collections.singletonList( iterator().next() );
- }
- List<Version> versions = new ArrayList<>( count );
- for ( Version version : this )
- {
- versions.add( version );
- }
- return versions;
+ return new ArrayList<>( versions );
}
public RepositorySystemSession getSession()
@@ -113,7 +81,7 @@
public int getCount()
{
- return count;
+ return versions.size();
}
public ArtifactRepository getRepository( Version version )
@@ -128,7 +96,7 @@
public Iterator<Version> iterator()
{
- return ( count > 0 ) ? new VersionIterator() : Collections.<Version>emptySet().iterator();
+ return versions.iterator();
}
@Override
@@ -136,80 +104,4 @@
{
return dependency + " " + result.getVersions();
}
-
- private class VersionIterator
- implements Iterator<Version>
- {
-
- private final List<Version> versions;
-
- private final int size;
-
- private int count;
-
- private int index;
-
- private int next;
-
- VersionIterator()
- {
- count = DefaultVersionFilterContext.this.count;
- index = -1;
- next = 0;
- versions = result.getVersions();
- size = versions.size();
- advance();
- }
-
- @SuppressWarnings( "StatementWithEmptyBody" )
- private void advance()
- {
- for ( next = index + 1; next < size && deleted[next] != (byte) 0; next++ )
- {
- // just advancing index
- }
- }
-
- public boolean hasNext()
- {
- return next < size;
- }
-
- public Version next()
- {
- if ( count != DefaultVersionFilterContext.this.count )
- {
- throw new ConcurrentModificationException();
- }
- if ( next >= size )
- {
- throw new NoSuchElementException();
- }
- index = next;
- advance();
- return versions.get( index );
- }
-
- public void remove()
- {
- if ( count != DefaultVersionFilterContext.this.count )
- {
- throw new ConcurrentModificationException();
- }
- if ( index < 0 || deleted[index] == (byte) 1 )
- {
- throw new IllegalStateException();
- }
- deleted[index] = (byte) 1;
- count = --DefaultVersionFilterContext.this.count;
- }
-
- @Override
- public String toString()
- {
- return ( index < 0 ) ? "null" : String.valueOf( versions.get( index ) );
- }
-
- }
-
}
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/PrioritizedComponentsTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/PrioritizedComponentsTest.java
index 764a130..379fe53 100644
--- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/PrioritizedComponentsTest.java
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/PrioritizedComponentsTest.java
@@ -23,6 +23,7 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
+import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -112,4 +113,20 @@
assertSame( comp1, sorted.get( 0 ).getComponent() );
assertSame( comp2, sorted.get( 1 ).getComponent() );
}
+
+ @Test
+ public void testList()
+ {
+ Exception comp1 = new IllegalArgumentException();
+ Exception comp2 = new NullPointerException();
+
+ PrioritizedComponents<Exception> components = new PrioritizedComponents<>( Collections.emptyMap() );
+ components.add( comp1, 1 );
+ components.add( comp2, 0 );
+
+ StringBuilder stringBuilder = new StringBuilder();
+ components.list( stringBuilder );
+
+ assertEquals( "IllegalArgumentException, NullPointerException", stringBuilder.toString() );
+ }
}
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DataPoolTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DataPoolTest.java
index 6baffd2..d8f5524 100644
--- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DataPoolTest.java
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DataPoolTest.java
@@ -25,8 +25,11 @@
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactDescriptorRequest;
import org.eclipse.aether.resolution.ArtifactDescriptorResult;
+import org.eclipse.aether.resolution.VersionRangeRequest;
import org.junit.Test;
+import java.util.Collections;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -64,4 +67,19 @@
assertEquals( result.getAliases(), cached.getAliases() );
}
+ @Test
+ public void testConstraintKey()
+ {
+ VersionRangeRequest request = new VersionRangeRequest();
+ request.setRepositories(
+ Collections.singletonList( new RemoteRepository.Builder( "some-id", "some-type", "http://www.example.com" ).build() )
+ );
+ request.setArtifact( new DefaultArtifact("group:artifact:1.0") );
+
+ DataPool pool = newDataPool();
+
+ Object key1 = pool.toKey( request );
+ Object key2 = pool.toKey( request );
+ assertEquals(key1, key2);
+ }
}
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycleTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycleTest.java
new file mode 100644
index 0000000..53cddc2
--- /dev/null
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCycleTest.java
@@ -0,0 +1,44 @@
+package org.eclipse.aether.internal.impl.collect;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.graph.DefaultDependencyNode;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.graph.DependencyCycle;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class DefaultDependencyCycleTest
+{
+ private static final Dependency FOO_DEPENDENCY = new Dependency( new DefaultArtifact( "group-id:foo:1.0" ), "test" );
+ private static final Dependency BAR_DEPENDENCY = new Dependency( new DefaultArtifact( "group-id:bar:1.0" ), "test" );
+
+ @Test
+ public void testToString()
+ {
+ NodeStack nodeStack = new NodeStack();
+ nodeStack.push( new DefaultDependencyNode( FOO_DEPENDENCY ) );
+ DependencyCycle cycle = new DefaultDependencyCycle( nodeStack, 1, BAR_DEPENDENCY );
+
+ assertEquals( "group-id:foo:jar -> group-id:bar:jar", cycle.toString() );
+ }
+}
\ No newline at end of file
diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultVersionFilterContextTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultVersionFilterContextTest.java
new file mode 100644
index 0000000..b6fbf5f
--- /dev/null
+++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultVersionFilterContextTest.java
@@ -0,0 +1,170 @@
+package org.eclipse.aether.internal.impl.collect;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.eclipse.aether.DefaultRepositorySystemSession;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.internal.test.util.TestVersion;
+import org.eclipse.aether.resolution.VersionRangeRequest;
+import org.eclipse.aether.resolution.VersionRangeResult;
+import org.eclipse.aether.version.Version;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class DefaultVersionFilterContextTest
+{
+ private static final Dependency FOO_DEPENDENCY = new Dependency( new DefaultArtifact( "group-id:foo:1.0" ), "test" );
+ private static final Dependency BAR_DEPENDENCY = new Dependency( new DefaultArtifact( "group-id:bar:1.0" ), "test" );
+
+ @Test
+ public void iteratorOneItem()
+ {
+ DefaultVersionFilterContext context = new DefaultVersionFilterContext( new DefaultRepositorySystemSession() );
+ VersionRangeResult result = new VersionRangeResult( new VersionRangeRequest() );
+ result.addVersion( new TestVersion( "1.0" ) );
+ context.set( FOO_DEPENDENCY, result );
+
+ Iterator<Version> iterator = context.iterator();
+ assertTrue( iterator.hasNext() );
+ assertEquals( new TestVersion( "1.0" ), iterator.next() );
+ }
+
+ @Test
+ public void getCountOneItem()
+ {
+ DefaultVersionFilterContext context = new DefaultVersionFilterContext( new DefaultRepositorySystemSession() );
+ VersionRangeResult result = new VersionRangeResult( new VersionRangeRequest() );
+ result.addVersion( new TestVersion( "1.0" ) );
+ context.set( FOO_DEPENDENCY, result );
+
+ assertEquals(1, context.getCount());
+ }
+
+ @Test
+ public void getOneItem()
+ {
+ DefaultVersionFilterContext context = new DefaultVersionFilterContext( new DefaultRepositorySystemSession() );
+ VersionRangeResult result = new VersionRangeResult( new VersionRangeRequest() );
+ result.addVersion( new TestVersion( "1.0" ) );
+ context.set( FOO_DEPENDENCY, result );
+
+ assertEquals( Collections.singletonList( new TestVersion( "1.0") ), context.get() );
+ }
+
+ @Test
+ public void iteratorDelete()
+ {
+ DefaultVersionFilterContext context = new DefaultVersionFilterContext( new DefaultRepositorySystemSession() );
+ VersionRangeResult result = new VersionRangeResult( new VersionRangeRequest() );
+ result.addVersion( new TestVersion( "1.0" ) );
+ context.set( FOO_DEPENDENCY, result );
+
+ Iterator<Version> iterator = context.iterator();
+ iterator.next();
+ iterator.remove();
+
+ assertEquals( 0, context.getCount() );
+ }
+
+ @Test(expected = NoSuchElementException.class)
+ public void nextBeyondEnd()
+ {
+ DefaultVersionFilterContext context = new DefaultVersionFilterContext( new DefaultRepositorySystemSession() );
+ VersionRangeResult result = new VersionRangeResult( new VersionRangeRequest() );
+ result.addVersion( new TestVersion( "1.0" ) );
+ context.set( FOO_DEPENDENCY, result );
+
+ Iterator<Version> iterator = context.iterator();
+ iterator.next();
+ iterator.next();
+ }
+
+ @Test
+ public void removeOneOfOne()
+ {
+ DefaultVersionFilterContext context = new DefaultVersionFilterContext( new DefaultRepositorySystemSession() );
+ VersionRangeResult result = new VersionRangeResult( new VersionRangeRequest() );
+ result.addVersion( new TestVersion( "1.0" ) );
+ context.set( FOO_DEPENDENCY, result );
+
+ Iterator<Version> iterator = context.iterator();
+ iterator.next();
+ iterator.remove();
+
+ assertEquals( Collections.emptyList(), context.get() );
+ }
+
+ @Test
+ public void removeOneOfTwo()
+ {
+ DefaultVersionFilterContext context = new DefaultVersionFilterContext( new DefaultRepositorySystemSession() );
+ VersionRangeResult result = new VersionRangeResult( new VersionRangeRequest() );
+ result.addVersion( new TestVersion( "1.0" ) );
+ result.addVersion( new TestVersion( "2.0" ) );
+ context.set( FOO_DEPENDENCY, result );
+
+ Iterator<Version> iterator = context.iterator();
+ iterator.next();
+ iterator.remove();
+
+ assertEquals( Collections.singletonList( new TestVersion( "2.0") ), context.get() );
+ }
+
+ @Test
+ public void removeOneOfThree()
+ {
+ DefaultVersionFilterContext context = new DefaultVersionFilterContext( new DefaultRepositorySystemSession() );
+ VersionRangeResult result = new VersionRangeResult( new VersionRangeRequest() );
+ result.addVersion( new TestVersion( "1.0" ) );
+ result.addVersion( new TestVersion( "2.0" ) );
+ result.addVersion( new TestVersion( "3.0" ) );
+ context.set( FOO_DEPENDENCY, result );
+
+ Iterator<Version> iterator = context.iterator();
+ iterator.next();
+ iterator.remove();
+
+ assertEquals( Arrays.asList( new TestVersion( "2.0" ), new TestVersion( "3.0" ) ), context.get() );
+ }
+
+ @Test
+ public void setTwice()
+ {
+ DefaultVersionFilterContext context = new DefaultVersionFilterContext( new DefaultRepositorySystemSession() );
+ VersionRangeResult fooResult = new VersionRangeResult( new VersionRangeRequest() );
+ fooResult.addVersion( new TestVersion( "1.0" ) );
+ context.set( FOO_DEPENDENCY, fooResult );
+
+ VersionRangeResult barResult = new VersionRangeResult( new VersionRangeRequest() );
+ barResult.addVersion( new TestVersion( "1.0" ) );
+ barResult.addVersion( new TestVersion( "2.0" ) );
+ context.set( BAR_DEPENDENCY, barResult );
+
+ assertEquals( Arrays.asList( new TestVersion( "1.0" ), new TestVersion( "2.0" ) ), context.get() );
+ }
+}
\ No newline at end of file
diff --git a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestVersion.java b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestVersion.java
index 7d77a16..8109beb 100644
--- a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestVersion.java
+++ b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestVersion.java
@@ -24,13 +24,13 @@
/**
* Version ordering by {@link String#compareToIgnoreCase(String)}.
*/
-final class TestVersion
+public final class TestVersion
implements Version
{
private String version;
- TestVersion( String version )
+ public TestVersion( String version )
{
this.version = version == null ? "" : version;
}
diff --git a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestVersionConstraint.java b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestVersionConstraint.java
index 0f93a59..9edd1c9 100644
--- a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestVersionConstraint.java
+++ b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/TestVersionConstraint.java
@@ -30,7 +30,7 @@
/**
* A constraint on versions for a dependency.
*/
-final class TestVersionConstraint
+public final class TestVersionConstraint
implements VersionConstraint
{
@@ -43,7 +43,7 @@
*
* @param range The version range, must not be {@code null}.
*/
- TestVersionConstraint( VersionRange range )
+ public TestVersionConstraint( VersionRange range )
{
this.range = requireNonNull( range, "version range cannot be null" );
this.version = null;
@@ -54,7 +54,7 @@
*
* @param version The version, must not be {@code null}.
*/
- TestVersionConstraint( Version version )
+ public TestVersionConstraint( Version version )
{
this.version = requireNonNull( version, "version cannot be null" );
this.range = null;
diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
index 149dc2e..e4471a0 100644
--- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
+++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ConflictResolver.java
@@ -536,9 +536,9 @@
List<DependencyNode> previousParent = null;
int previousDepth = 0;
totalConflictItems += items.size();
- for ( int i = items.size() - 1; i >= 0; i-- )
+ for ( ListIterator<ConflictItem> iterator = items.listIterator( items.size() ); iterator.hasPrevious(); )
{
- ConflictItem item = items.get( i );
+ ConflictItem item = iterator.previous();
if ( item.parent == previousParent )
{
item.depth = previousDepth;
@@ -619,18 +619,20 @@
{
if ( ( changes & NodeInfo.CHANGE_SCOPE ) != 0 )
{
- for ( int i = info.children.size() - 1; i >= 0; i-- )
+ ListIterator<ConflictItem> itemIterator = info.children.listIterator( info.children.size() );
+ while ( itemIterator.hasPrevious() )
{
- ConflictItem item = info.children.get( i );
+ ConflictItem item = itemIterator.previous();
String childScope = deriveScope( item.node, null );
item.addScope( childScope );
}
}
if ( ( changes & NodeInfo.CHANGE_OPTIONAL ) != 0 )
{
- for ( int i = info.children.size() - 1; i >= 0; i-- )
+ ListIterator<ConflictItem> itemIterator = info.children.listIterator( info.children.size() );
+ while ( itemIterator.hasPrevious() )
{
- ConflictItem item = info.children.get( i );
+ ConflictItem item = itemIterator.previous();
boolean childOptional = deriveOptional( item.node, null );
item.addOptional( childOptional );
}
diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/transformer/ConflictResolverTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/transformer/ConflictResolverTest.java
new file mode 100644
index 0000000..40410a3
--- /dev/null
+++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/transformer/ConflictResolverTest.java
@@ -0,0 +1,175 @@
+package org.eclipse.aether.util.graph.transformer;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.eclipse.aether.RepositoryException;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.graph.DefaultDependencyNode;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.graph.DependencyNode;
+import org.eclipse.aether.internal.test.util.TestUtils;
+import org.eclipse.aether.internal.test.util.TestVersion;
+import org.eclipse.aether.internal.test.util.TestVersionConstraint;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+public class ConflictResolverTest
+{
+ @Test
+ public void noTransformationRequired() throws RepositoryException
+ {
+ ConflictResolver resolver = makeDefaultResolver();
+
+ // Foo -> Bar
+ DependencyNode fooNode = makeDependencyNode( "group-id", "foo", "1.0" );
+ DependencyNode barNode = makeDependencyNode( "group-id", "bar", "1.0" );
+ fooNode.setChildren( mutableList( barNode ) );
+
+ DependencyNode transformedNode = resolver.transformGraph(
+ fooNode, TestUtils.newTransformationContext( TestUtils.newSession() )
+ );
+
+ assertSame( fooNode, transformedNode );
+ assertEquals( 1, transformedNode.getChildren().size() );
+ assertSame( barNode, transformedNode.getChildren().get( 0 ) );
+ }
+
+ @Test
+ public void versionClash() throws RepositoryException
+ {
+ ConflictResolver resolver = makeDefaultResolver();
+
+ // Foo -> Bar -> Baz 2.0
+ // |---> Baz 1.0
+ DependencyNode fooNode = makeDependencyNode( "some-group", "foo", "1.0" );
+ DependencyNode barNode = makeDependencyNode( "some-group", "bar", "1.0" );
+ DependencyNode baz1Node = makeDependencyNode( "some-group", "baz", "1.0" );
+ DependencyNode baz2Node = makeDependencyNode( "some-group", "baz", "2.0" );
+ fooNode.setChildren( mutableList( barNode, baz1Node ) );
+ barNode.setChildren( mutableList( baz2Node ) );
+
+ DependencyNode transformedNode = resolver.transformGraph(
+ fooNode, TestUtils.newTransformationContext( TestUtils.newSession() )
+ );
+
+ assertSame( fooNode, transformedNode );
+ assertEquals( 2, fooNode.getChildren().size() );
+ assertSame( barNode, fooNode.getChildren().get( 0 ) );
+ assertTrue( barNode.getChildren().isEmpty() );
+ assertSame( baz1Node, fooNode.getChildren().get( 1 ) );
+ }
+
+ @Test
+ public void derivedScopeChange() throws RepositoryException
+ {
+ ConflictResolver resolver = makeDefaultResolver();
+
+ // Foo -> Bar (test) -> Jaz
+ // |---> Baz -> Jaz
+ DependencyNode fooNode = makeDependencyNode( "some-group", "foo", "1.0" );
+ DependencyNode barNode = makeDependencyNode( "some-group", "bar", "1.0", "test" );
+ DependencyNode bazNode = makeDependencyNode( "some-group", "baz", "1.0" );
+ DependencyNode jazNode = makeDependencyNode( "some-group", "jaz", "1.0" );
+ fooNode.setChildren( mutableList( barNode, bazNode ) );
+
+ List<DependencyNode> jazList = mutableList( jazNode );
+ barNode.setChildren( jazList );
+ bazNode.setChildren( jazList );
+
+ DependencyNode transformedNode = resolver.transformGraph(
+ fooNode, TestUtils.newTransformationContext( TestUtils.newSession() )
+ );
+
+ assertSame( fooNode, transformedNode );
+ assertEquals( 2, fooNode.getChildren().size() );
+ assertSame( barNode, fooNode.getChildren().get( 0 ) );
+ assertEquals( 1, barNode.getChildren().size() );
+ assertSame( jazNode, barNode.getChildren().get( 0 ) );
+ assertSame( bazNode, fooNode.getChildren().get( 1 ) );
+ assertEquals( 1, barNode.getChildren().size() );
+ assertSame( jazNode, barNode.getChildren().get( 0 ) );
+ }
+
+ @Test
+ public void derivedOptionalStatusChange() throws RepositoryException
+ {
+ ConflictResolver resolver = makeDefaultResolver();
+
+ // Foo -> Bar (optional) -> Jaz
+ // |---> Baz -> Jaz
+ DependencyNode fooNode = makeDependencyNode( "some-group", "foo", "1.0" );
+ DependencyNode barNode = makeDependencyNode( "some-group", "bar", "1.0" );
+ barNode.setOptional(true);
+ DependencyNode bazNode = makeDependencyNode( "some-group", "baz", "1.0" );
+ DependencyNode jazNode = makeDependencyNode( "some-group", "jaz", "1.0" );
+ fooNode.setChildren( mutableList( barNode, bazNode ) );
+
+ List<DependencyNode> jazList = mutableList( jazNode );
+ barNode.setChildren( jazList );
+ bazNode.setChildren( jazList );
+
+ DependencyNode transformedNode = resolver.transformGraph(
+ fooNode, TestUtils.newTransformationContext( TestUtils.newSession() )
+ );
+
+ assertSame( fooNode, transformedNode );
+ assertEquals( 2, fooNode.getChildren().size() );
+ assertSame( barNode, fooNode.getChildren().get( 0 ) );
+ assertEquals( 1, barNode.getChildren().size() );
+ assertSame( jazNode, barNode.getChildren().get( 0 ) );
+ assertSame( bazNode, fooNode.getChildren().get( 1 ) );
+ assertEquals( 1, barNode.getChildren().size() );
+ assertSame( jazNode, barNode.getChildren().get( 0 ) );
+ }
+
+ private static ConflictResolver makeDefaultResolver()
+ {
+ return new ConflictResolver(
+ new NearestVersionSelector(), new JavaScopeSelector(), new SimpleOptionalitySelector(), new JavaScopeDeriver()
+ );
+ }
+
+ private static DependencyNode makeDependencyNode( String groupId, String artifactId, String version )
+ {
+ return makeDependencyNode( groupId, artifactId, version, "compile" );
+ }
+
+ private static DependencyNode makeDependencyNode( String groupId, String artifactId, String version, String scope )
+ {
+ DefaultDependencyNode node = new DefaultDependencyNode(
+ new Dependency( new DefaultArtifact( groupId + ':' + artifactId + ':' + version ), scope )
+ );
+ node.setVersion( new TestVersion( version ) );
+ node.setVersionConstraint( new TestVersionConstraint( node.getVersion() ) );
+ return node;
+ }
+
+ private static List<DependencyNode> mutableList(DependencyNode... nodes)
+ {
+ return new ArrayList<>( Arrays.asList( nodes ) );
+ }
+}
\ No newline at end of file