-
Notifications
You must be signed in to change notification settings - Fork 215
/
GetFilterBsonVisitor.java
141 lines (119 loc) · 5.71 KB
/
GetFilterBsonVisitor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
* Copyright (c) 2017 Contributors to the Eclipse Foundation
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.eclipse.ditto.thingsearch.service.persistence.read.expression.visitors;
import static org.eclipse.ditto.thingsearch.service.persistence.PersistenceConstants.DESIRED_PROPERTIES;
import static org.eclipse.ditto.thingsearch.service.persistence.PersistenceConstants.FIELD_ATTRIBUTES_PATH;
import static org.eclipse.ditto.thingsearch.service.persistence.PersistenceConstants.FIELD_DEFINITION;
import static org.eclipse.ditto.thingsearch.service.persistence.PersistenceConstants.FIELD_FEATURES_PATH;
import static org.eclipse.ditto.thingsearch.service.persistence.PersistenceConstants.FIELD_F_ARRAY;
import static org.eclipse.ditto.thingsearch.service.persistence.PersistenceConstants.FIELD_THING;
import static org.eclipse.ditto.thingsearch.service.persistence.PersistenceConstants.PROPERTIES;
import static org.eclipse.ditto.thingsearch.service.persistence.PersistenceConstants.SLASH;
import java.util.List;
import java.util.function.Function;
import javax.annotation.Nullable;
import org.bson.conversions.Bson;
import org.eclipse.ditto.json.JsonPointer;
import org.eclipse.ditto.rql.query.expression.FilterFieldExpression;
import org.eclipse.ditto.rql.query.expression.visitors.FilterFieldExpressionVisitor;
import com.mongodb.client.model.Filters;
/**
* Creates a Mongo Bson object for field-based search criteria.
*/
public final class GetFilterBsonVisitor extends AbstractFieldBsonCreator implements FilterFieldExpressionVisitor<Bson> {
private final Function<String, Bson> predicateFunction;
GetFilterBsonVisitor(final Function<String, Bson> predicateFunction,
@Nullable final List<String> authorizationSubjectIds) {
super(authorizationSubjectIds);
this.predicateFunction = predicateFunction;
}
/**
* Creates a Mongo Bson object for field-based search criteria.
*
* @param expression the expression to create a filter for.
* @param predicateFunction the function for creating the predicate-part (e.g. "eq", "ne", ...) of the criteria
* @param authorizationSubjectIds subject IDs to check for authorization, or null to not restrict visibility at all
* @return the complete Bson for the field-based search criteria
*/
public static Bson apply(final FilterFieldExpression expression,
final Function<String, Bson> predicateFunction,
@Nullable final List<String> authorizationSubjectIds) {
return expression.acceptFilterVisitor(new GetFilterBsonVisitor(predicateFunction, authorizationSubjectIds));
}
/**
* Create Bson without considering authorization.
*
* @param expression the field expression.
* @param predicateFunction the predicate creator.
* @return the filter Bson with no restriction on visibility.
*/
public static Bson sudoApply(final FilterFieldExpression expression,
final Function<String, Bson> predicateFunction) {
return expression.acceptFilterVisitor(new GetFilterBsonVisitor(predicateFunction, null));
}
@Override
public Bson visitAttribute(final String key) {
return matchValue(FIELD_ATTRIBUTES_PATH + key);
}
@Override
public Bson visitFeatureDefinition(final String featureId) {
if (FEATURE_ID_WILDCARD.equals(featureId)) {
return matchWildcardFeatureValue(FIELD_DEFINITION);
} else {
return matchValue(FIELD_FEATURES_PATH + featureId + SLASH + FIELD_DEFINITION);
}
}
@Override
public Bson visitFeatureIdProperty(final String featureId, final String property) {
if (FEATURE_ID_WILDCARD.equals(featureId)) {
return matchWildcardFeatureValue(PROPERTIES + property);
} else {
return matchValue(FIELD_FEATURES_PATH + featureId + PROPERTIES + property);
}
}
@Override
public Bson visitFeatureIdDesiredProperty(final CharSequence featureId, final CharSequence desiredProperty) {
if (FEATURE_ID_WILDCARD.equals(featureId)) {
return matchWildcardFeatureValue(DESIRED_PROPERTIES + desiredProperty);
} else {
return matchValue(FIELD_FEATURES_PATH + featureId + DESIRED_PROPERTIES + desiredProperty);
}
}
@Override
public Bson visitMetadata(final String key) {
// search on _metadata is not supported, return filter that don't match
return Filters.eq("nomatch");
}
@Override
Bson visitPointer(final String pointer) {
return matchValue(pointer);
}
@Override
Bson visitRootLevelField(final String fieldName) {
return predicateFunction.apply(fieldName);
}
private Bson matchValue(final CharSequence key) {
final JsonPointer pointer = JsonPointer.of(key);
final Bson keyValueFilter = predicateFunction.apply(toDottedPath(FIELD_THING, pointer));
return getAuthorizationBson(pointer)
.map(authBson -> Filters.and(keyValueFilter, authBson))
.orElse(keyValueFilter);
}
private Bson matchWildcardFeatureValue(final CharSequence key) {
final JsonPointer pointer = JsonPointer.of(key);
final Bson keyValueFilter = predicateFunction.apply(toDottedPath(pointer));
return getFeatureWildcardAuthorizationBson(pointer)
.map(authBson -> Filters.elemMatch(FIELD_F_ARRAY, Filters.and(keyValueFilter, authBson)))
.orElse(keyValueFilter);
}
}