Skip to content

Commit

Permalink
Bump version and fix warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
minborg committed Sep 14, 2015
1 parent b79408c commit 09b796a
Show file tree
Hide file tree
Showing 6 changed files with 110 additions and 92 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -31,7 +31,7 @@


<groupId>com.speedment</groupId> <groupId>com.speedment</groupId>
<artifactId>speedment</artifactId> <artifactId>speedment</artifactId>
<version>2.1.1-SNAPSHOT</version> <version>2.1.1</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/com/speedment/SpeedmentVersion.java
Expand Up @@ -30,7 +30,7 @@ public final class SpeedmentVersion {


private static final String IMPLEMENTATION_TITLE = "Speedment"; private static final String IMPLEMENTATION_TITLE = "Speedment";
private static final String IMPLEMENTATION_VENDOR = "Speedment Inc."; // "Speedment, Inc." difficult to enter into POM because of ',' private static final String IMPLEMENTATION_VENDOR = "Speedment Inc."; // "Speedment, Inc." difficult to enter into POM because of ','
private static final String IMPLEMENTATION_VERSION = "2.1.0"; private static final String IMPLEMENTATION_VERSION = "2.1.1";
private static final boolean PRODUCTION_MODE = true; private static final boolean PRODUCTION_MODE = true;


// private static final String SPECIFICATION_TITLE = "Speedment"; // private static final String SPECIFICATION_TITLE = "Speedment";
Expand Down
Expand Up @@ -35,81 +35,80 @@
import java.util.stream.Stream; import java.util.stream.Stream;


/** /**
* A store for a particular type of entity. The store can be used to retreive * A store for a particular type of entity. The store can be used to retreive
* subsets of all entities based on a standard operator. For an example, the * subsets of all entities based on a standard operator. For an example, the
* subset of all entities that have a value 'id' greater than 100 or the * subset of all entities that have a value 'id' greater than 100 or the subset
* subset of all entities with the value 'date' lesser than '2015-01-01'. * of all entities with the value 'date' lesser than '2015-01-01'.
* <p> * <p>
* Retreiving a subset is an O(1) operator and results in a {@code Stream}. The * Retreiving a subset is an O(1) operator and results in a {@code Stream}. The
* stream can then be traversed in linear time. It is therefore recommended to * stream can then be traversed in linear time. It is therefore recommended to
* retreive the smallest subset first and apply less specific filters later on. * retreive the smallest subset first and apply less specific filters later on.
* <p> * <p>
* A store can be modified using the {@link #add(java.lang.Object)} and * A store can be modified using the {@link #add(java.lang.Object)} and
* {@link #remove(java.lang.Object)} methods. The current implementation of * {@link #remove(java.lang.Object)} methods. The current implementation of
* these methods <b>are not thread safe</b>! * these methods <b>are not thread safe</b>!
* *
* @author Emil * @author Emil
* @param <ENTITY> the type of entity to store * @param <ENTITY> the type of entity to store
*/ */
public class OnHeapStore<ENTITY> { public class OnHeapStore<ENTITY> {


private final Map<ReferenceComparableField<ENTITY, ? extends Comparable<?>>, private final Map<ReferenceComparableField<ENTITY, ? extends Comparable<?>>, SortedMap<? extends Comparable<?>, Set<ENTITY>>> stores;
SortedMap<? extends Comparable<?>, Set<ENTITY>>> stores;

/** /**
* Constructs the store and populates it with all the static fields of type * Constructs the store and populates it with all the static fields of type
* {@link ReferenceComparableField} found in the specified class. * {@link ReferenceComparableField} found in the specified class.
* *
* @param entityClass the entity class this store is for * @param entityClass the entity class this store is for
*/ */
public OnHeapStore(Class<ENTITY> entityClass) { public OnHeapStore(Class<ENTITY> entityClass) {
requireNonNull(entityClass); requireNonNull(entityClass);
stores = new ConcurrentHashMap<>(); stores = new ConcurrentHashMap<>();
populateByReflection(entityClass); populateByReflection(entityClass);
} }

/** /**
* Adds the specified entity to the store. * Adds the specified entity to the store.
* <p> * <p>
* Observe that this method is currently <b>not threadsafe!</b> * Observe that this method is currently <b>not threadsafe!</b>
* *
* @param entity the entity to add * @param entity the entity to add
*/ */
public void add(ENTITY entity) { public void add(ENTITY entity) {
requireNonNull(entity); requireNonNull(entity);
MapStream.of(stores) MapStream.of(stores)
.forEach((field, store) -> addEntity(field, store, entity)); .forEach((field, store) -> addEntity(field, store, entity));
} }

/** /**
* Removed the specified entity from the store. * Removed the specified entity from the store.
* <p> * <p>
* Observe that this method is currently <b>not threadsafe!</b> * Observe that this method is currently <b>not threadsafe!</b>
* *
* @param entity the entity to remove. * @param entity the entity to remove.
*/ */
public void remove(ENTITY entity) { public void remove(ENTITY entity) {
requireNonNull(entity); requireNonNull(entity);
MapStream.of(stores) MapStream.of(stores)
.forEach((field, store) -> removeEntity(field, store, entity)); .forEach((field, store) -> removeEntity(field, store, entity));
} }

/** /**
* Returns a stream of subsets of this store based on the specified field, * Returns a stream of subsets of this store based on the specified field,
* operator and value. If no entities match, an empty stream will be * operator and value. If no entities match, an empty stream will be
* returned. None of the in parameters can be {@code null}. * returned. None of the in parameters can be {@code null}.
* *
* @param <V> the type of the value * @param <V> the type of the value
* @param predicate the predicate to use * @param predicate the predicate to use
* @return a stream of matching entities * @return a stream of matching entities
*/ */
public <V extends Comparable<V>> Stream<ENTITY> where( public <V extends Comparable<V>> Stream<ENTITY> where(
ComparablePredicateBuilder predicate) { ComparablePredicateBuilder<ENTITY, V> predicate) {

final ReferenceComparableField field = predicate.getField(); final ReferenceComparableField<ENTITY, V> field = predicate.getField();
final V value = (V) predicate.getOperand(); final V value = predicate.getOperand();
final ComparableOperator operator = predicate.getComparableOperator(); final ComparableOperator operator = predicate.getComparableOperator();

if (operator instanceof StandardComparableOperator) { if (operator instanceof StandardComparableOperator) {
return where(field, (StandardComparableOperator) operator, value); return where(field, (StandardComparableOperator) operator, value);
} else { } else {
Expand All @@ -123,68 +122,71 @@ public <V extends Comparable<V>> Stream<ENTITY> where(
* Returns a stream of subsets of this store based on the specified field, * Returns a stream of subsets of this store based on the specified field,
* operator and value. If no entities match, an empty stream will be * operator and value. If no entities match, an empty stream will be
* returned. None of the in parameters can be {@code null}. * returned. None of the in parameters can be {@code null}.
* *
* @param <V> the type of the value * @param <V> the type of the value
* @param field the field to compare * @param field the field to compare
* @param operator the operator to use for comparing * @param operator the operator to use for comparing
* @param value the value to compare with * @param value the value to compare with
* @return a stream of matching entities * @return a stream of matching entities
*/ */
public <V extends Comparable<V>> Stream<ENTITY> where( public <V extends Comparable<V>> Stream<ENTITY> where(
ReferenceComparableField<ENTITY, V> field, ReferenceComparableField<ENTITY, V> field,
StandardComparableOperator operator, StandardComparableOperator operator,
V value) { V value) {

requireNonNulls(field, operator, value); requireNonNulls(field, operator, value);


// This cast should be safe as long as the map has not been manipulated // This cast should be safe as long as the map has not been manipulated
// outside this class. The store should not be null as long as the field // outside this class. The store should not be null as long as the field
// is a valid field retreived by reflection. // is a valid field retreived by reflection.
final SortedMap<V, Set<ENTITY>> store = @SuppressWarnings("unchecked")
(SortedMap<V, Set<ENTITY>>) stores.get(field); final SortedMap<V, Set<ENTITY>> store
= (SortedMap<V, Set<ENTITY>>) stores.get(field);


switch (operator) { switch (operator) {
case EQUAL : case EQUAL:
return fromStore(store, value).stream(); return fromStore(store, value).stream();

case NOT_EQUAL : case NOT_EQUAL:
return MapStream.of(store) return MapStream.of(store)
.filter((k, v) -> !Objects.equals(k, value)) .filter((k, v) -> !Objects.equals(k, value))
.flatMapValue((k, set) -> set.stream()) .flatMapValue((k, set) -> set.stream())
.values(); .values();

case GREATER_THAN : case GREATER_THAN:
return MapStream.of(store.tailMap(value)) return MapStream.of(store.tailMap(value))
.flatMapValue((k, set) -> set.stream()) .flatMapValue((k, set) -> set.stream())
.values(); .values();

case GREATER_OR_EQUAL : case GREATER_OR_EQUAL:
return Stream.concat( return Stream.concat(
fromStore(store, value).stream(), fromStore(store, value).stream(),
MapStream.of(store.tailMap(value)) MapStream.of(store.tailMap(value))
.flatMapValue((k, set) -> set.stream()) .flatMapValue((k, set) -> set.stream())
.values() .values()
); );

case LESS_THAN : case LESS_THAN:
return MapStream.of(store.headMap(value)) return MapStream.of(store.headMap(value))
.flatMapValue((k, set) -> set.stream()) .flatMapValue((k, set) -> set.stream())
.values(); .values();

case LESS_OR_EQUAL : case LESS_OR_EQUAL:
return Stream.concat( return Stream.concat(
fromStore(store, value).stream(), fromStore(store, value).stream(),
MapStream.of(store.headMap(value)) MapStream.of(store.headMap(value))
.flatMapValue((k, set) -> set.stream()) .flatMapValue((k, set) -> set.stream())
.values() .values()
);

default:
throw new UnsupportedOperationException(
"Unknown standard comparable operator '" + operator + "'."
); );

default : throw new UnsupportedOperationException(
"Unknown standard comparable operator '" + operator + "'."
);
} }
} }


@SuppressWarnings("unchecked")
private void populateByReflection(Class<ENTITY> entityClass) { private void populateByReflection(Class<ENTITY> entityClass) {
Stream.of(entityClass.getDeclaredFields()) Stream.of(entityClass.getDeclaredFields())
.filter(f -> f.isAccessible()) .filter(f -> f.isAccessible())
Expand All @@ -201,39 +203,41 @@ private void populateByReflection(Class<ENTITY> entityClass) {
throw new SpeedmentException("Could not access field.", ex); throw new SpeedmentException("Could not access field.", ex);
} }
}) })

// Should be safe to throw as the following has been assured: // Should be safe to throw as the following has been assured:
// (i) f is a ReferenceComparableField // (i) f is a ReferenceComparableField
// (ii) The declared class is ENTITY // (ii) The declared class is ENTITY
// (iii) Only comparable values can be type params of // (iii) Only comparable values can be type params of
// ReferenceComparableField // ReferenceComparableField
.map(f -> (ReferenceComparableField<ENTITY, ? extends Comparable<?>>) f) .map(f -> (ReferenceComparableField<ENTITY, ? extends Comparable<?>>) f)

.forEach(f -> stores.put(f, new ConcurrentSkipListMap<>())); .forEach(f -> stores.put(f, new ConcurrentSkipListMap<>()));
} }

private static <ENTITY, V extends Comparable<V>> void addEntity( private static <ENTITY, V extends Comparable<V>> void addEntity(
ReferenceComparableField<ENTITY, ? extends Comparable<?>> field, ReferenceComparableField<ENTITY, ? extends Comparable<?>> field,
SortedMap<? extends Comparable<?>, Set<ENTITY>> store, SortedMap<? extends Comparable<?>, Set<ENTITY>> store,
ENTITY entity) { ENTITY entity) {


@SuppressWarnings("unchecked")
final V value = (V) field.get(entity); final V value = (V) field.get(entity);
@SuppressWarnings("unchecked")
final SortedMap<V, Set<ENTITY>> typedStore = (SortedMap<V, Set<ENTITY>>) store; final SortedMap<V, Set<ENTITY>> typedStore = (SortedMap<V, Set<ENTITY>>) store;

fromStore(typedStore, value).add(entity); fromStore(typedStore, value).add(entity);
} }

private static <ENTITY, V extends Comparable<V>> void removeEntity( private static <ENTITY, V extends Comparable<V>> void removeEntity(
ReferenceComparableField<ENTITY, ? extends Comparable<?>> field, ReferenceComparableField<ENTITY, ? extends Comparable<?>> field,
SortedMap<? extends Comparable<?>, Set<ENTITY>> store, SortedMap<? extends Comparable<?>, Set<ENTITY>> store,
ENTITY entity) { ENTITY entity) {


@SuppressWarnings("unchecked")
final V value = (V) field.get(entity); final V value = (V) field.get(entity);
@SuppressWarnings("unchecked")
final SortedMap<V, Set<ENTITY>> typedStore = (SortedMap<V, Set<ENTITY>>) store; final SortedMap<V, Set<ENTITY>> typedStore = (SortedMap<V, Set<ENTITY>>) store;

fromStore(typedStore, value).remove(entity); fromStore(typedStore, value).remove(entity);
} }

private static <ENTITY, V extends Comparable<V>> Set<ENTITY> fromStore(SortedMap<V, Set<ENTITY>> store, V value) { private static <ENTITY, V extends Comparable<V>> Set<ENTITY> fromStore(SortedMap<V, Set<ENTITY>> store, V value) {
return store.computeIfAbsent(value, v -> new HashSet<>()); return store.computeIfAbsent(value, v -> new HashSet<>());
} }
Expand Down
44 changes: 28 additions & 16 deletions src/main/java/com/speedment/internal/core/stream/MapStream.java
Expand Up @@ -245,11 +245,13 @@ public MapStream<K, V> sorted(Comparator<? super Map.Entry<K, V>> comparator) {
return this; return this;
} }


public MapStream<K, V> sorted(ToIntBiFunction<? super K, ? super V> comparator) { public MapStream<K, V> sortedByKey(Comparator<K> comparator) {
inner = inner.sorted((e1, e2) inner = inner.sorted(byKeyOnly(comparator));
-> comparator.applyAsInt(e1.getKey(), e1.getValue()) return this;
- comparator.applyAsInt(e2.getKey(), e2.getValue()) }
);
public MapStream<K, V> sortedByValue(Comparator<V> comparator) {
inner = inner.sorted(byValueOnly(comparator));
return this; return this;
} }


Expand Down Expand Up @@ -338,24 +340,26 @@ public <K2> MapStream<K2, List<V>> groupBy(Function<V, K2> grouper) {
public Optional<Map.Entry<K, V>> min(Comparator<? super Map.Entry<K, V>> comparator) { public Optional<Map.Entry<K, V>> min(Comparator<? super Map.Entry<K, V>> comparator) {
return inner.min(comparator); return inner.min(comparator);
} }


public Optional<Map.Entry<K, V>> min(ToIntBiFunction<? super K, ? super V> comparator) { public Optional<Map.Entry<K, V>> minByKey(Comparator<K> comparator) {
return inner.min((e1, e2) return inner.min(byKeyOnly(comparator));
-> comparator.applyAsInt(e1.getKey(), e1.getValue()) }
- comparator.applyAsInt(e2.getKey(), e2.getValue())
); public Optional<Map.Entry<K, V>> minByValue(Comparator<V> comparator) {
return inner.min(byValueOnly(comparator));
} }


@Override @Override
public Optional<Map.Entry<K, V>> max(Comparator<? super Map.Entry<K, V>> comparator) { public Optional<Map.Entry<K, V>> max(Comparator<? super Map.Entry<K, V>> comparator) {
return inner.max(comparator); return inner.max(comparator);
} }


public Optional<Map.Entry<K, V>> max(ToIntBiFunction<? super K, ? super V> comparator) { public Optional<Map.Entry<K, V>> maxByKey(Comparator<K> comparator) {
return inner.max((e1, e2) return inner.max(byKeyOnly(comparator));
-> comparator.applyAsInt(e1.getKey(), e1.getValue()) }
- comparator.applyAsInt(e2.getKey(), e2.getValue())
); public Optional<Map.Entry<K, V>> maxByValue(Comparator<V> comparator) {
return inner.max(byValueOnly(comparator));
} }


@Override @Override
Expand Down Expand Up @@ -458,4 +462,12 @@ public List<Map.Entry<K, V>> toList() {
private MapStream(Stream<Map.Entry<K, V>> inner) { private MapStream(Stream<Map.Entry<K, V>> inner) {
this.inner = inner; this.inner = inner;
} }

private static <K, V> Comparator<Map.Entry<K, V>> byKeyOnly(Comparator<K> comparator) {
return (a, b) -> comparator.compare(a.getKey(), b.getKey());
}

private static <K, V> Comparator<Map.Entry<K, V>> byValueOnly(Comparator<V> comparator) {
return (a, b) -> comparator.compare(a.getValue(), b.getValue());
}
} }
Expand Up @@ -208,8 +208,10 @@ public CloseImpl(Runnable r) {
} }


@Override @Override
public void close() throws Exception { public void close() {
r.run();
r.run();

} }


} }
Expand Down
Expand Up @@ -34,7 +34,7 @@
*/ */
public class SpeedmentVersionTest { public class SpeedmentVersionTest {


private static final String EXPECTED_IMPLEMENTATION_VERSION = "2.1.0"; private static final String EXPECTED_IMPLEMENTATION_VERSION = "2.1.1";
private static final String EXPECTED_SPECIFICATION_VERSION = "2.1"; private static final String EXPECTED_SPECIFICATION_VERSION = "2.1";


public SpeedmentVersionTest() { public SpeedmentVersionTest() {
Expand Down

0 comments on commit 09b796a

Please sign in to comment.