KEYCLOAK-17781 Make exists and notExists collection aware

This commit is contained in:
mhajas 2021-05-12 09:53:59 +02:00 committed by Hynek Mlnařík
parent eb3bd8bbb5
commit b8565408ca
5 changed files with 29 additions and 16 deletions

View file

@ -1534,7 +1534,7 @@ public abstract class MapRealmAdapter<K> extends AbstractRealmModel<MapRealmEnti
@Override
public Stream<ClientInitialAccessModel> getClientInitialAccesses() {
return entity.getClientInitialAccesses().map(MapClientInitialAccessEntity::toModel);
return entity.getClientInitialAccesses().stream().map(MapClientInitialAccessEntity::toModel);
}
@Override

View file

@ -16,6 +16,7 @@
*/
package org.keycloak.models.map.realm;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@ -1024,7 +1025,7 @@ public class MapRealmEntity<K> implements AbstractEntity<K> {
return removed;
}
public Stream<MapClientInitialAccessEntity> getClientInitialAccesses() {
return clientInitialAccesses.values().stream();
public Collection<MapClientInitialAccessEntity> getClientInitialAccesses() {
return clientInitialAccesses.values();
}
}

View file

@ -106,14 +106,34 @@ class CriteriaOperator {
if (value != null && value.length != 0) {
throw new IllegalStateException("Invalid argument: " + Arrays.toString(value));
}
return Objects::nonNull;
return CriteriaOperator::collectionAwareExists;
}
private static boolean collectionAwareExists(Object checkedObject) {
if (checkedObject instanceof Collection) {
return !((Collection<?>) checkedObject).isEmpty();
}
return Objects.nonNull(checkedObject);
}
public static Predicate<Object> notExists(Object[] value) {
if (value != null && value.length != 0) {
throw new IllegalStateException("Invalid argument: " + Arrays.toString(value));
}
return Objects::isNull;
return CriteriaOperator::collectionAwareNotExists;
}
private static boolean collectionAwareNotExists(Object checkedObject) {
if (Objects.isNull(checkedObject)) return true;
if (checkedObject instanceof Collection) {
return ((Collection<?>) checkedObject).isEmpty();
}
return false;
}
public static Predicate<Object> in(Object[] value) {

View file

@ -90,7 +90,7 @@ public class MapFieldPredicates {
static {
put(REALM_PREDICATES, RealmModel.SearchableFields.NAME, MapRealmEntity::getName);
put(REALM_PREDICATES, RealmModel.SearchableFields.CLIENT_INITIAL_ACCESS, MapFieldPredicates::checkRealmsWithClientInitialAccess);
put(REALM_PREDICATES, RealmModel.SearchableFields.CLIENT_INITIAL_ACCESS, MapRealmEntity::getClientInitialAccesses);
put(REALM_PREDICATES, RealmModel.SearchableFields.COMPONENT_PROVIDER_TYPE, MapFieldPredicates::checkRealmsWithComponentType);
put(CLIENT_PREDICATES, ClientModel.SearchableFields.REALM_ID, MapClientEntity::getRealmId);
@ -462,14 +462,6 @@ public class MapFieldPredicates {
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
}
private static MapModelCriteriaBuilder<Object, MapRealmEntity<Object>, RealmModel> checkRealmsWithClientInitialAccess(MapModelCriteriaBuilder<Object, MapRealmEntity<Object>, RealmModel> mcb, Operator op, Object[] values) {
if (op != Operator.EXISTS) {
throw new CriterionNotSupportedException(RealmModel.SearchableFields.CLIENT_INITIAL_ACCESS, op);
}
Function<MapRealmEntity<Object>, ?> getter = MapRealmEntity::hasClientInitialAccess;
return mcb.fieldCompare(Boolean.TRUE::equals, getter);
}
private static MapModelCriteriaBuilder<Object, MapRealmEntity<Object>, RealmModel> checkRealmsWithComponentType(MapModelCriteriaBuilder<Object, MapRealmEntity<Object>, RealmModel> mcb, Operator op, Object[] values) {
String providerType = ensureEqSingleValue(RealmModel.SearchableFields.COMPONENT_PROVIDER_TYPE, "component_provider_type", op, values);
Function<MapRealmEntity<Object>, ?> getter = realmEntity -> realmEntity.getComponents().anyMatch(component -> component.getProviderType().equals(providerType));

View file

@ -99,9 +99,9 @@ public interface ModelCriteriaBuilder<M> {
* can be an array (via an implicit conversion of the vararg), a {@link Collection} or a {@link Stream}.
*/
IN,
/** Is not null */
/** Is not null and, in addition, in case of collection not empty */
EXISTS,
/** Is null */
/** Is null or, in addition, in case of collection empty */
NOT_EXISTS,
}