Skip to content

Commit

Permalink
Merge pull request #5323 from bjhargrave/issues/5322
Browse files Browse the repository at this point in the history
resource: Defer SHA-256 calculation into the future
  • Loading branch information
bjhargrave committed Jul 19, 2022
2 parents 86b426d + 038f0b8 commit 78a26d7
Show file tree
Hide file tree
Showing 16 changed files with 483 additions and 54 deletions.
10 changes: 10 additions & 0 deletions biz.aQute.bnd.util/src/aQute/bnd/unmodifiable/Lists.java
@@ -1,8 +1,11 @@
package aQute.bnd.unmodifiable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Collector;

@SuppressWarnings("unchecked")
public class Lists {
Expand Down Expand Up @@ -71,4 +74,11 @@ public static <E> List<E> copyOf(Collection<? extends E> collection) {
}
return new ImmutableList<E>(collection.toArray());
}

public static <E> Collector<E, ?, List<E>> toList() {
return Collector.of((Supplier<List<E>>) ArrayList::new, List::add, (l, r) -> {
l.addAll(r);
return l;
}, Lists::copyOf);
}
}
13 changes: 13 additions & 0 deletions biz.aQute.bnd.util/src/aQute/bnd/unmodifiable/Sets.java
Expand Up @@ -2,7 +2,10 @@

import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collector;

@SuppressWarnings("unchecked")
public class Sets {
Expand Down Expand Up @@ -69,8 +72,18 @@ public static <E> Set<E> copyOf(Collection<? extends E> collection) {
if (collection.isEmpty()) {
return of();
}
if (collection instanceof Set) {
return new ImmutableSet<E>(collection.toArray());
}
return new ImmutableSet<E>(collection.stream()
.distinct()
.toArray());
}

public static <E> Collector<E, ?, Set<E>> toSet() {
return Collector.of((Supplier<Set<E>>) LinkedHashSet::new, Set::add, (l, r) -> {
l.addAll(r);
return l;
}, Sets::copyOf);
}
}
@@ -1,4 +1,4 @@
@Version("2.0.0")
@Version("2.1.0")
package aQute.bnd.unmodifiable;

import org.osgi.annotation.versioning.Version;
19 changes: 19 additions & 0 deletions biz.aQute.bnd.util/test/aQute/bnd/unmodifiable/ListsTest.java
Expand Up @@ -550,4 +550,23 @@ public void spliterator() throws Exception {
Spliterator.SUBSIZED, Spliterator.NONNULL);
}

@Test
public void collector() {
List<String> source = new ArrayList<>();
source.add("e1");
source.add("e2");
source.add("e1");
List<String> list = source.stream()
.collect(Lists.toList());
source.set(0, "changed");
assertThat(list).hasSize(3)
.containsExactly("e1", "e2", "e1");
assertThat(list.stream()).hasSize(3)
.containsExactly("e1", "e2", "e1");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> list.add("a"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> list.remove("a"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> list.remove("e1"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> list.clear());
}

}
51 changes: 35 additions & 16 deletions biz.aQute.bnd.util/test/aQute/bnd/unmodifiable/SetsTest.java
Expand Up @@ -40,7 +40,7 @@ public void zero() {
public void one() {
Set<String> set = Sets.of("e1");
assertThat(set).hasSize(1)
.containsExactlyInAnyOrder("e1");
.containsExactly("e1");
assertThat(set.stream()).hasSize(1)
.containsExactly("e1");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -53,7 +53,7 @@ public void one() {
public void two() {
Set<String> set = Sets.of("e1", "e2");
assertThat(set).hasSize(2)
.containsExactlyInAnyOrder("e1", "e2");
.containsExactly("e1", "e2");
assertThat(set.stream()).hasSize(2)
.containsExactly("e1", "e2");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -66,7 +66,7 @@ public void two() {
public void three() {
Set<String> set = Sets.of("e1", "e2", "e3");
assertThat(set).hasSize(3)
.containsExactlyInAnyOrder("e1", "e2", "e3");
.containsExactly("e1", "e2", "e3");
assertThat(set.stream()).hasSize(3)
.containsExactly("e1", "e2", "e3");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -79,7 +79,7 @@ public void three() {
public void four() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4");
assertThat(set).hasSize(4)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4");
.containsExactly("e1", "e2", "e3", "e4");
assertThat(set.stream()).hasSize(4)
.containsExactly("e1", "e2", "e3", "e4");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -92,7 +92,7 @@ public void four() {
public void five() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5");
assertThat(set).hasSize(5)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5");
.containsExactly("e1", "e2", "e3", "e4", "e5");
assertThat(set.stream()).hasSize(5)
.containsExactly("e1", "e2", "e3", "e4", "e5");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -105,7 +105,7 @@ public void five() {
public void six() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6");
assertThat(set).hasSize(6)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6");
assertThat(set.stream()).hasSize(6)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -118,7 +118,7 @@ public void six() {
public void seven() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6", "e7");
assertThat(set).hasSize(7)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7");
assertThat(set.stream()).hasSize(7)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -131,7 +131,7 @@ public void seven() {
public void eight() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8");
assertThat(set).hasSize(8)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8");
assertThat(set.stream()).hasSize(8)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -144,7 +144,7 @@ public void eight() {
public void nine() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9");
assertThat(set).hasSize(9)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9");
assertThat(set.stream()).hasSize(9)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -157,7 +157,7 @@ public void nine() {
public void ten() {
Set<String> set = Sets.of("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10");
assertThat(set).hasSize(10)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10");
assertThat(set.stream()).hasSize(10)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -174,7 +174,7 @@ public void entries() {
Set<String> set = Sets.of(entries);
entries[0] = "changed";
assertThat(set).hasSize(11)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10", "e11");
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10", "e11");
assertThat(set.stream()).hasSize(11)
.containsExactly("e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "e10", "e11");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand Down Expand Up @@ -209,7 +209,7 @@ public void copy() {
Set<String> set = Sets.copyOf(source);
source.set(0, "changed");
assertThat(set).hasSize(2)
.containsExactlyInAnyOrder("e1", "e2");
.containsExactly("e1", "e2");
assertThat(set.stream()).hasSize(2)
.containsExactly("e1", "e2");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
Expand All @@ -230,7 +230,7 @@ public void array() {
Set<String> source = Sets.of("e1", "e2", "e3", "e4", "e5");
Object[] array = source.toArray();
assertThat(array).hasSize(5)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5");
.containsExactly("e1", "e2", "e3", "e4", "e5");
}

@Test
Expand All @@ -240,12 +240,12 @@ public void array_string() {
String[] array = source.toArray(target);
assertThat(array).isNotSameAs(target)
.hasSize(5)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5");
.containsExactly("e1", "e2", "e3", "e4", "e5");

target = new String[source.size() + 1];
array = source.toArray(target);
assertThat(array).isSameAs(target)
.containsExactlyInAnyOrder("e1", "e2", "e3", "e4", "e5", null);
.containsExactly("e1", "e2", "e3", "e4", "e5", null);
assertThat(array[target.length - 1]).isNull();
}

Expand Down Expand Up @@ -295,7 +295,7 @@ public void hash_min_value() {

Set<String> set = Sets.of("e1", "polygenelubricants", "GydZG_", "DESIGNING WORKHOUSES", "e5");

assertThat(set).containsExactlyInAnyOrder("e5", "polygenelubricants", "GydZG_", "DESIGNING WORKHOUSES", "e1");
assertThat(set).containsExactly("e1", "polygenelubricants", "GydZG_", "DESIGNING WORKHOUSES", "e5");
}

@Test
Expand Down Expand Up @@ -393,4 +393,23 @@ public void iterator_empty() {
assertThat(holder.set).isFalse();
}

@Test
public void collector() {
List<String> source = new ArrayList<>();
source.add("e1");
source.add("e2");
source.add("e1");
Set<String> set = source.stream()
.collect(Sets.toSet());
source.set(0, "changed");
assertThat(set).hasSize(2)
.containsExactly("e1", "e2");
assertThat(set.stream()).hasSize(2)
.containsExactly("e1", "e2");
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.add("a"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.remove("a"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.remove("e1"));
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() -> set.clear());
}

}
8 changes: 4 additions & 4 deletions biz.aQute.bndlib/src/aQute/bnd/osgi/resource/CapReq.java
@@ -1,16 +1,16 @@
package aQute.bnd.osgi.resource;

import static java.util.Collections.unmodifiableMap;
import static java.util.Objects.requireNonNull;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import org.osgi.resource.Capability;
import org.osgi.resource.Requirement;
import org.osgi.resource.Resource;

import aQute.bnd.unmodifiable.Maps;

abstract class CapReq {
private final String namespace;
private final Resource resource;
Expand All @@ -21,8 +21,8 @@ abstract class CapReq {
CapReq(String namespace, Resource resource, Map<String, String> directives, Map<String, Object> attributes) {
this.namespace = requireNonNull(namespace);
this.resource = resource;
this.directives = unmodifiableMap(new HashMap<>(directives));
this.attributes = unmodifiableMap(new HashMap<>(attributes));
this.directives = Maps.copyOf(directives);
this.attributes = new DeferredValueMap<>(Maps.copyOf(attributes));
}

public String getNamespace() {
Expand Down
Expand Up @@ -150,7 +150,14 @@ private boolean isVersion(Object value, Class<?> versionClass) {
}

public CapReqBuilder addAttributes(Map<? extends String, ? extends Object> attributes) {
attributes.forEach(this::addAttribute);
for (Entry<? extends String, ? extends Object> entry : attributes.entrySet()) {
if (entry instanceof DeferredValueEntry) {
DeferredValueEntry<? extends String, ? extends Object> deferred = (DeferredValueEntry<? extends String, ? extends Object>) entry;
addAttribute(deferred.getKey(), deferred.getDeferredValue());
} else {
addAttribute(entry.getKey(), entry.getValue());
}
}
return this;
}

Expand Down
@@ -0,0 +1,19 @@
package aQute.bnd.osgi.resource;

import java.util.function.Supplier;

class DeferredComparableValue<T extends Comparable<T>> extends DeferredValue<T> implements Comparable<T> {

DeferredComparableValue(Class<T> type, Supplier<? extends T> supplier, int hashCode) {
super(type, supplier, hashCode);
}

@SuppressWarnings("unchecked")
@Override
public int compareTo(T o) {
if (o instanceof DeferredComparableValue) {
o = ((DeferredComparableValue<T>) o).get();
}
return get().compareTo(o);
}
}
50 changes: 50 additions & 0 deletions biz.aQute.bndlib/src/aQute/bnd/osgi/resource/DeferredValue.java
@@ -0,0 +1,50 @@
package aQute.bnd.osgi.resource;

import static java.util.Objects.requireNonNull;

import java.util.function.Supplier;

class DeferredValue<T> implements Supplier<T> {
private final Class<T> type;
private final Supplier<? extends T> supplier;
private final int hashCode;
private T value;

DeferredValue(Class<T> type, Supplier<? extends T> supplier, int hashCode) {
this.type = requireNonNull(type);
this.supplier = requireNonNull(supplier);
this.hashCode = hashCode;
}

@Override
public T get() {
T v = value;
if (v == null) {
return value = supplier.get();
}
return v;
}

Class<T> type() {
return type;
}

@Override
public int hashCode() {
return hashCode;
}

@SuppressWarnings("unchecked")
@Override
public boolean equals(Object obj) {
if (obj instanceof DeferredValue) {
obj = ((DeferredValue<T>) obj).get();
}
return get().equals(obj);
}

@Override
public String toString() {
return String.valueOf(get());
}
}

0 comments on commit 78a26d7

Please sign in to comment.