/** * Copyright (c) 2016, All Contributors (see CONTRIBUTORS file) * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ package com.eventsourcing.queries; import com.eventsourcing.Entity; import com.eventsourcing.EntityHandle; import com.eventsourcing.index.EntityIndex; import com.googlecode.cqengine.attribute.Attribute; import com.googlecode.cqengine.attribute.SimpleAttribute; import com.googlecode.cqengine.query.Query; import com.googlecode.cqengine.query.option.QueryOptions; import com.googlecode.cqengine.query.simple.SimpleQuery; import lombok.Getter; import java.util.Iterator; public abstract class ComparingQuery<O extends Entity, A extends Comparable<A>> extends SimpleQuery<EntityHandle<O>, A> { private EntityHandle<O> target = null; protected abstract boolean isBetterValue(A value, A targetValue); @Override protected int calcHashCode() { return attribute.hashCode(); } private void ensureTargetIsFound(Attribute<EntityHandle<O>, A> attribute, QueryOptions queryOptions) { if (target == null) { Iterable<EntityHandle<O>> collection = queryOptions.get(Iterable.class); if (collection == null) { throw new RuntimeException( toString() + " has to be supported by the target index or queryOptions should" + " include IndexedCollection key"); } Iterator<EntityHandle<O>> iterator = collection.iterator(); A targetValue = null; while (iterator.hasNext()) { EntityHandle<O> next = iterator.next(); Iterable<A> values = attribute.getValues(next, queryOptions); for (A value : values) { if (target == null || isBetterValue(value, targetValue)) { target = next; targetValue = value; } } } } } public ComparingQuery(EntityIndex<O, A> index) { super(index.getAttribute()); } @Override protected boolean matchesNonSimpleAttribute(Attribute<EntityHandle<O>, A> attribute, EntityHandle<O> object, QueryOptions queryOptions) { ensureTargetIsFound(attribute, queryOptions); return target.uuid().equals(object.uuid()); } @Override protected boolean matchesSimpleAttribute(SimpleAttribute<EntityHandle<O>, A> attribute, EntityHandle<O> object, QueryOptions queryOptions) { return matchesNonSimpleAttribute(attribute, object, queryOptions); } }