Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.redisson.liveobject.LiveObjectSearch Maven / Gradle / Ivy
Go to download
Easy Redis Java client and Real-Time Data Platform. Valkey compatible. Sync/Async/RxJava3/Reactive API. Client side caching. Over 50 Redis based Java objects and services: JCache API, Apache Tomcat, Hibernate, Spring, Set, Multimap, SortedSet, Map, List, Queue, Deque, Semaphore, Lock, AtomicLong, Map Reduce, Bloom filter, Scheduler, RPC
/**
* Copyright (c) 2013-2024 Nikita Koksharov
*
* Licensed 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.
*/
package org.redisson.liveobject;
import org.redisson.RedissonObject;
import org.redisson.RedissonScoredSortedSet;
import org.redisson.RedissonSet;
import org.redisson.RedissonSetMultimap;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RSet;
import org.redisson.api.RSetMultimap;
import org.redisson.api.condition.Condition;
import org.redisson.command.CommandAsyncExecutor;
import org.redisson.liveobject.condition.*;
import org.redisson.liveobject.resolver.NamingScheme;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.BiFunction;
/**
*
* @author Nikita Koksharov
*
*/
public class LiveObjectSearch {
private final CommandAsyncExecutor commandExecutor;
public LiveObjectSearch(CommandAsyncExecutor commandExecutor) {
this.commandExecutor = commandExecutor;
}
private Set traverseAnd(ANDCondition condition, NamingScheme namingScheme, Class> entityClass) {
Set allIds = new HashSet();
List eqNames = new ArrayList();
Map, Number> gtNumericNames = new HashMap<>();
Map, Number> geNumericNames = new HashMap<>();
Map, Number> ltNumericNames = new HashMap<>();
Map, Number> leNumericNames = new HashMap<>();
Map, Number> eqNumericNames = new HashMap<>();
for (Condition cond : condition.getConditions()) {
if (cond instanceof EQCondition) {
EQCondition eqc = (EQCondition) cond;
String indexName = namingScheme.getIndexName(entityClass, eqc.getName());
if (eqc.getValue() instanceof Number) {
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
eqNumericNames.put(values, (Number) eqc.getValue());
} else {
RSetMultimap map = new RedissonSetMultimap<>(namingScheme.getCodec(), commandExecutor, indexName);
RSet values = map.get(eqc.getValue());
eqNames.add(((RedissonObject) values).getRawName());
}
}
if (cond instanceof LTCondition) {
LTCondition ltc = (LTCondition) cond;
String indexName = namingScheme.getIndexName(entityClass, ltc.getName());
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
ltNumericNames.put(values, ltc.getValue());
}
if (cond instanceof LECondition) {
LECondition lec = (LECondition) cond;
String indexName = namingScheme.getIndexName(entityClass, lec.getName());
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
leNumericNames.put(values, lec.getValue());
}
if (cond instanceof GECondition) {
GECondition gec = (GECondition) cond;
String indexName = namingScheme.getIndexName(entityClass, gec.getName());
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
geNumericNames.put(values, gec.getValue());
}
if (cond instanceof GTCondition) {
GTCondition gtc = (GTCondition) cond;
String indexName = namingScheme.getIndexName(entityClass, gtc.getName());
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
gtNumericNames.put(values, gtc.getValue());
}
if (cond instanceof ORCondition) {
Collection ids = traverseOr((ORCondition) cond, namingScheme, entityClass);
if (ids.isEmpty()) {
return Collections.emptySet();
}
if (!allIds.isEmpty()) {
allIds.retainAll(ids);
} else {
allIds.addAll(ids);
}
if (allIds.isEmpty()) {
return Collections.emptySet();
}
}
}
if (!eqNames.isEmpty()) {
RSet set = new RedissonSet<>(commandExecutor, eqNames.get(0), null);
Set intersect = set.readIntersection(eqNames.toArray(new String[eqNames.size()]));
if (!allIds.isEmpty()) {
allIds.retainAll(intersect);
if (allIds.isEmpty()) {
return Collections.emptySet();
}
} else {
allIds.addAll(intersect);
}
if (allIds.isEmpty()) {
return allIds;
}
}
if (!checkValueRange(allIds, eqNumericNames, (r, v) -> {
return r.valueRange(v.doubleValue(), true, v.doubleValue(), true);
})) {
return Collections.emptySet();
}
if (!checkValueRange(allIds, gtNumericNames, (r, v) -> {
return r.valueRange(v.doubleValue(), false, Double.POSITIVE_INFINITY, false);
})) {
return Collections.emptySet();
}
if (!checkValueRange(allIds, geNumericNames, (r, v) -> {
return r.valueRange(v.doubleValue(), true, Double.POSITIVE_INFINITY, false);
})) {
return Collections.emptySet();
}
if (!checkValueRange(allIds, ltNumericNames, (r, v) -> {
return r.valueRange(Double.NEGATIVE_INFINITY, false, v.doubleValue(), false);
})) {
return Collections.emptySet();
}
if (!checkValueRange(allIds, leNumericNames, (r, v) -> {
return r.valueRange(Double.NEGATIVE_INFINITY, false, v.doubleValue(), true);
})) {
return Collections.emptySet();
}
return allIds;
}
private boolean checkValueRange(Set allIds, Map, Number> numericNames,
BiFunction, Number, Collection> func) {
if (numericNames.isEmpty()) {
return true;
}
for (Entry, Number> e : numericNames.entrySet()) {
Collection gtIds = func.apply(e.getKey(), e.getValue());
if (gtIds.isEmpty()) {
return false;
}
if (!allIds.isEmpty()) {
allIds.retainAll(gtIds);
if (allIds.isEmpty()) {
return false;
}
} else {
allIds.addAll(gtIds);
}
}
return true;
}
private Set traverseOr(ORCondition condition, NamingScheme namingScheme, Class> entityClass) {
Set allIds = new HashSet();
List eqNames = new ArrayList();
Map, Number> ltNumericNames = new HashMap<>();
Map, Number> leNumericNames = new HashMap<>();
Map, Number> gtNumericNames = new HashMap<>();
Map, Number> geNumericNames = new HashMap<>();
Map, Number> eqNumericNames = new HashMap<>();
for (Condition cond : condition.getConditions()) {
if (cond instanceof EQCondition) {
EQCondition eqc = (EQCondition) cond;
String indexName = namingScheme.getIndexName(entityClass, eqc.getName());
if (eqc.getValue() instanceof Number) {
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
eqNumericNames.put(values, (Number) eqc.getValue());
} else {
RSetMultimap map = new RedissonSetMultimap<>(namingScheme.getCodec(), commandExecutor, indexName);
RSet values = map.get(eqc.getValue());
eqNames.add(((RedissonObject) values).getRawName());
}
}
if (cond instanceof GTCondition) {
GTCondition gtc = (GTCondition) cond;
String indexName = namingScheme.getIndexName(entityClass, gtc.getName());
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
gtNumericNames.put(values, gtc.getValue());
}
if (cond instanceof GECondition) {
GECondition gec = (GECondition) cond;
String indexName = namingScheme.getIndexName(entityClass, gec.getName());
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
geNumericNames.put(values, gec.getValue());
}
if (cond instanceof LTCondition) {
LTCondition ltc = (LTCondition) cond;
String indexName = namingScheme.getIndexName(entityClass, ltc.getName());
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
ltNumericNames.put(values, ltc.getValue());
}
if (cond instanceof LECondition) {
LECondition lec = (LECondition) cond;
String indexName = namingScheme.getIndexName(entityClass, lec.getName());
RScoredSortedSet values = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
leNumericNames.put(values, lec.getValue());
}
if (cond instanceof ANDCondition) {
Collection ids = traverseAnd((ANDCondition) cond, namingScheme, entityClass);
allIds.addAll(ids);
}
}
if (!eqNames.isEmpty()) {
RSet set = new RedissonSet<>(commandExecutor, eqNames.get(0), null);
allIds.addAll(set.readUnion(eqNames.toArray(new String[eqNames.size()])));
}
for (Entry, Number> e : eqNumericNames.entrySet()) {
Collection ids = e.getKey().valueRange(e.getValue().doubleValue(), true, e.getValue().doubleValue(), true);
allIds.addAll(ids);
}
for (Entry, Number> e : gtNumericNames.entrySet()) {
Collection ids = e.getKey().valueRange(e.getValue().doubleValue(), false, Double.POSITIVE_INFINITY, false);
allIds.addAll(ids);
}
for (Entry, Number> e : geNumericNames.entrySet()) {
Collection ids = e.getKey().valueRange(e.getValue().doubleValue(), true, Double.POSITIVE_INFINITY, false);
allIds.addAll(ids);
}
for (Entry, Number> e : ltNumericNames.entrySet()) {
Collection ids = e.getKey().valueRange(Double.NEGATIVE_INFINITY, false, e.getValue().doubleValue(), false);
allIds.addAll(ids);
}
for (Entry, Number> e : leNumericNames.entrySet()) {
Collection ids = e.getKey().valueRange(Double.NEGATIVE_INFINITY, false, e.getValue().doubleValue(), true);
allIds.addAll(ids);
}
return allIds;
}
public Set find(Class> entityClass, Condition condition) {
NamingScheme namingScheme = commandExecutor.getObjectBuilder().getNamingScheme(entityClass);
if (condition instanceof EQCondition) {
EQCondition c = (EQCondition) condition;
String indexName = namingScheme.getIndexName(entityClass, c.getName());
if (c.getValue() instanceof Number) {
RScoredSortedSet set = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
double v = ((Number) c.getValue()).doubleValue();
Collection gtIds = set.valueRange(v, true, v, true);
return new HashSet<>(gtIds);
} else {
RSetMultimap map = new RedissonSetMultimap<>(namingScheme.getCodec(), commandExecutor, indexName);
return map.getAll(c.getValue());
}
} else if (condition instanceof GTCondition) {
GTCondition c = (GTCondition) condition;
String indexName = namingScheme.getIndexName(entityClass, c.getName());
RScoredSortedSet set = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
Collection gtIds = set.valueRange(c.getValue().doubleValue(), false, Double.POSITIVE_INFINITY, false);
return new HashSet<>(gtIds);
} else if (condition instanceof GECondition) {
GECondition c = (GECondition) condition;
String indexName = namingScheme.getIndexName(entityClass, c.getName());
RScoredSortedSet set = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
Collection gtIds = set.valueRange(c.getValue().doubleValue(), true, Double.POSITIVE_INFINITY, false);
return new HashSet<>(gtIds);
} else if (condition instanceof LTCondition) {
LTCondition c = (LTCondition) condition;
String indexName = namingScheme.getIndexName(entityClass, c.getName());
RScoredSortedSet set = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
Collection gtIds = set.valueRange(Double.NEGATIVE_INFINITY, false, c.getValue().doubleValue(), false);
return new HashSet<>(gtIds);
} else if (condition instanceof LECondition) {
LECondition c = (LECondition) condition;
String indexName = namingScheme.getIndexName(entityClass, c.getName());
RScoredSortedSet set = new RedissonScoredSortedSet<>(namingScheme.getCodec(), commandExecutor, indexName, null);
Collection gtIds = set.valueRange(Double.NEGATIVE_INFINITY, false, c.getValue().doubleValue(), true);
return new HashSet<>(gtIds);
} else if (condition instanceof ORCondition) {
return traverseOr((ORCondition) condition, namingScheme, entityClass);
} else if (condition instanceof ANDCondition) {
return traverseAnd((ANDCondition) condition, namingScheme, entityClass);
}
throw new IllegalArgumentException();
}
}