diff --git a/documentation/src/main/resources/pages/ditto/architecture-services-things-search.md b/documentation/src/main/resources/pages/ditto/architecture-services-things-search.md index 14974b7576..cabd68e7ba 100644 --- a/documentation/src/main/resources/pages/ditto/architecture-services-things-search.md +++ b/documentation/src/main/resources/pages/ditto/architecture-services-things-search.md @@ -34,5 +34,36 @@ Other services can communicate with the things-search service via: ## Persistence -The things-search service maintains its own persistence in which it stores `Things` in an optimized way in order to +The Things-Search service maintains its own persistence in which it stores `Things` in an optimized way in order to provide a full search on arbitrary `Thing` data. + +Things-Search creates the following MongoDB collections: + +* `searchThings`: The search index. +* `searchThingsSyncThings`: A single-document capped collection containing the instant until which `Thing` events are +indexed for sure; expected to be 30 minutes before the current time. +* `searchThingsSyncPolicies`: A single-document capped collection containing the instant until which `Policy` events +are indexed for sure; expected to be 30 minutes before the current time. + +## Migration from Ditto 0.9.0-M1 + +The index schema has changed since Ditto version 0.9.0-M1. Data migration is obligatory to upgrade an existing +installation running Ditto version 0.9.0-M1 or earlier. Expected duration of data migration is 1/60th of the lifetime +of the Ditto installation. + +1. *After* stopping the cluster of Ditto 0.9.0-M1, drop unnecessary collections: +```javascript +db.getCollection('thingEntities').drop(); +db.getCollection('policyBasedSearchIndex').drop(); +db.getCollection('thingsSearchSyncStatePolicies').drop(); +``` + +2. *Before* starting the upgraded Ditto cluster, write into `searchThingsSyncThings` the timestamp when the Ditto cluster started for the first time: +```javascript +var startingTimestamp = new Date(TIMESTAMP-WHEN-DITTO-CLUSTER-STARTED-FOR-THE-FIRST-TIME); // e.g. new Date('2019-01-01T00:00:00.000Z') +db.getCollection('thingsSearchSyncStateThings').renameCollection('searchThingsSyncThings'); +db.getCollection('searchThingsSyncThings').insert({'ts':startingTimestamp}); +``` + +3. Start the upgraded Ditto cluster. All `Thing` events persisted after the timestamp in `searchThingsSyncThings` +will be indexed in the background. diff --git a/model/query/pom.xml b/model/query/pom.xml index eb07865c5b..8be57c2141 100644 --- a/model/query/pom.xml +++ b/model/query/pom.xml @@ -62,6 +62,10 @@ com.github.siom79.japicmp japicmp-maven-plugin + + + true + diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/AttributeExpressionImpl.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/AttributeExpressionImpl.java index 6aa40846e7..1a5142d001 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/AttributeExpressionImpl.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/AttributeExpressionImpl.java @@ -14,17 +14,17 @@ import static java.util.Objects.requireNonNull; +import java.util.Objects; + import org.eclipse.ditto.model.query.expression.visitors.ExistsFieldExpressionVisitor; import org.eclipse.ditto.model.query.expression.visitors.FieldExpressionVisitor; import org.eclipse.ditto.model.query.expression.visitors.FilterFieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.PolicyRestrictedFieldExpressionVisitor; import org.eclipse.ditto.model.query.expression.visitors.SortFieldExpressionVisitor; /** * Expression for an attribute. */ -public class AttributeExpressionImpl implements FilterFieldExpression, SortFieldExpression, ExistsFieldExpression, - PolicyRestrictedFieldExpression { +public class AttributeExpressionImpl implements FilterFieldExpression, SortFieldExpression, ExistsFieldExpression { private final String key; @@ -64,18 +64,9 @@ public T accept(final FieldExpressionVisitor visitor) { return visitor.visitAttribute(key); } - @Override - public T acceptPolicyRestrictedVisitor(final PolicyRestrictedFieldExpressionVisitor visitor) { - return visitor.visitAttribute(key); - } - - @SuppressWarnings("squid:S109") @Override public int hashCode() { - final int prime = 31; - int result = 1; - result = (prime * result) + ((key == null) ? 0 : key.hashCode()); - return result; + return Objects.hash(key); } @SuppressWarnings("squid:MethodCyclomaticComplexity") diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeatureExpressionImpl.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeatureExpressionImpl.java index e8e6083e25..9cd45836e1 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeatureExpressionImpl.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeatureExpressionImpl.java @@ -18,14 +18,11 @@ import org.eclipse.ditto.model.query.expression.visitors.ExistsFieldExpressionVisitor; import org.eclipse.ditto.model.query.expression.visitors.FieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.PolicyRestrictedFieldExpressionVisitor; /** * Field expression for features itself with a given feature id. */ -public class FeatureExpressionImpl implements ExistsFieldExpression, PolicyRestrictedFieldExpression { - - private static final String DOT = "."; +public class FeatureExpressionImpl implements ExistsFieldExpression { private final String featureId; @@ -43,11 +40,6 @@ public T acceptExistsVisitor(final ExistsFieldExpressionVisitor visitor) return visitor.visitFeature(featureId); } - @Override - public T acceptPolicyRestrictedVisitor(final PolicyRestrictedFieldExpressionVisitor visitor) { - return visitor.visitFeature(featureId); - } - @Override public T accept(final FieldExpressionVisitor visitor) { return visitor.visitFeature(featureId); diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeatureIdPropertyExpressionImpl.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeatureIdPropertyExpressionImpl.java index 9fcd98f1c6..b2fad0ba49 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeatureIdPropertyExpressionImpl.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeatureIdPropertyExpressionImpl.java @@ -19,14 +19,13 @@ import org.eclipse.ditto.model.query.expression.visitors.ExistsFieldExpressionVisitor; import org.eclipse.ditto.model.query.expression.visitors.FieldExpressionVisitor; import org.eclipse.ditto.model.query.expression.visitors.FilterFieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.PolicyRestrictedFieldExpressionVisitor; import org.eclipse.ditto.model.query.expression.visitors.SortFieldExpressionVisitor; /** * Field expression for feature properties with a given feature id. */ -public class FeatureIdPropertyExpressionImpl implements SortFieldExpression, FilterFieldExpression, - ExistsFieldExpression, PolicyRestrictedFieldExpression { +public class FeatureIdPropertyExpressionImpl + implements SortFieldExpression, FilterFieldExpression, ExistsFieldExpression { private final String property; private final String featureId; @@ -42,11 +41,6 @@ public FeatureIdPropertyExpressionImpl(final String featureId, final String prop this.featureId = requireNonNull(featureId); } - @Override - public T acceptPolicyRestrictedVisitor(final PolicyRestrictedFieldExpressionVisitor visitor) { - return visitor.visitFeatureIdProperty(featureId, property); - } - @Override public T acceptSortVisitor(final SortFieldExpressionVisitor visitor) { return visitor.visitFeatureIdProperty(featureId, property); diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeaturePropertyExpressionImpl.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeaturePropertyExpressionImpl.java deleted file mode 100644 index 7eaea289bf..0000000000 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FeaturePropertyExpressionImpl.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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.model.query.expression; - -import static java.util.Objects.requireNonNull; - -import java.util.Objects; - -import org.eclipse.ditto.model.query.expression.visitors.ExistsFieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.FieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.FilterFieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.PolicyRestrictedFieldExpressionVisitor; - -/** - * Field expression for feature properties without a given feature id. - */ -public class FeaturePropertyExpressionImpl implements FilterFieldExpression, ExistsFieldExpression, - PolicyRestrictedFieldExpression { - - private final String property; - - /** - * Constructor. - * - * @param property the feature property property. - */ - public FeaturePropertyExpressionImpl(final String property) { - this.property = requireNonNull(property); - } - - /** - * @return the property. - */ - public String getProperty() { - return property; - } - - @Override - public T acceptExistsVisitor(final ExistsFieldExpressionVisitor visitor) { - return visitor.visitFeatureProperty(property); - } - - @Override - public T acceptFilterVisitor(final FilterFieldExpressionVisitor visitor) { - return visitor.visitFeatureProperty(property); - } - - @Override - public T acceptPolicyRestrictedVisitor(final PolicyRestrictedFieldExpressionVisitor visitor) { - return visitor.visitFeatureProperty(property); - } - - @Override - public T accept(final FieldExpressionVisitor visitor) { - return visitor.visitFeatureProperty(property); - } - - @SuppressWarnings("squid:MethodCyclomaticComplexity") - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - if (o == null || getClass() != o.getClass()) { - return false; - } - final FeaturePropertyExpressionImpl that = (FeaturePropertyExpressionImpl) o; - return Objects.equals(property, that.property); - } - - @SuppressWarnings("squid:S109") - @Override - public int hashCode() { - return Objects.hash(property); - } - - @Override - public String toString() { - return "FeaturePropertyExpression [property=" + property + "]"; - } -} diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FieldExpression.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FieldExpression.java index 06a748827c..3e8c8c15cc 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FieldExpression.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FieldExpression.java @@ -12,7 +12,6 @@ */ package org.eclipse.ditto.model.query.expression; - import org.eclipse.ditto.model.query.criteria.CriteriaFactory; import org.eclipse.ditto.model.query.expression.visitors.FieldExpressionVisitor; diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FieldExpressionUtil.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FieldExpressionUtil.java index 1c87adb455..916afc06af 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FieldExpressionUtil.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/FieldExpressionUtil.java @@ -33,11 +33,6 @@ public final class FieldExpressionUtil { */ public static final String FIELD_NAME_THING_ID = "thingId"; - /** - * Owner field name. - */ - public static final String FIELD_NAME_OWNER = "owner"; - /** * namespace field to be saved in field expressions. */ @@ -112,14 +107,11 @@ public static String addAttributesPrefix(final String fieldName) { */ public static final class FeatureField { - private static final Pattern FIELD_NAME_FEATURE_PATTERN1 = Pattern.compile("^features/" + - "(?[^\\*][^/]*)/properties/(?.+)"); + private static final Pattern FIELD_NAME_FEATURE_PATTERN1 = + Pattern.compile("^features/(?[^/]++)/properties/(?.+)"); private static final Pattern FIELD_NAME_FEATURE_PATTERN2 = - Pattern.compile("^features/(?[^\\*][^/]*)"); - - private static final Pattern FIELD_NAME_FEATURE_PATTERN3 = - Pattern.compile("^features/\\*/properties/(?.+)"); + Pattern.compile("^features/(?[^/]++)"); private final boolean matches; private final String featureId; @@ -140,17 +132,9 @@ private FeatureField(final String fieldName) { this.featureId = matcher.group("featureId"); this.property = null; } else { - matcher = FIELD_NAME_FEATURE_PATTERN3.matcher(fieldName); - - if (matcher.matches()) { - this.matches = true; - this.featureId = null; - this.property = matcher.group("property"); - } else { - this.matches = false; - this.featureId = null; - this.property = null; - } + this.matches = false; + this.featureId = null; + this.property = null; } } } diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/PolicyRestrictedFieldExpression.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/PolicyRestrictedFieldExpression.java deleted file mode 100644 index f8d282c805..0000000000 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/PolicyRestrictedFieldExpression.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * 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.model.query.expression; - -import org.eclipse.ditto.model.query.expression.visitors.ExistsFieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.FieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.PolicyRestrictedFieldExpressionVisitor; - -/** - * Policy restriction expression: Used to create a query filter the used policy. - */ -public interface PolicyRestrictedFieldExpression extends ExistsFieldExpression { - - T acceptPolicyRestrictedVisitor(final PolicyRestrictedFieldExpressionVisitor visitor); - - @Override - T acceptExistsVisitor(final ExistsFieldExpressionVisitor visitor); - - @Override - T accept(final FieldExpressionVisitor visitor); -} diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsAclFieldExpressionImpl.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsAclFieldExpressionImpl.java deleted file mode 100644 index a03519ea6e..0000000000 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsAclFieldExpressionImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.model.query.expression; - -import org.eclipse.ditto.model.query.expression.visitors.FieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.FilterFieldExpressionVisitor; - -/** - * Field expression for acl entries. - */ -class ThingsAclFieldExpressionImpl implements FilterFieldExpression { - - @Override - public T acceptFilterVisitor(final FilterFieldExpressionVisitor visitor) { - return visitor.visitAcl(); - } - - @Override - public T accept(final FieldExpressionVisitor visitor) { - return visitor.visitAcl(); - } -} diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactory.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactory.java index f022f01b1a..fbc8b919b4 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactory.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactory.java @@ -14,32 +14,26 @@ /** * Factory for creating {@link FieldExpression}s for thing search. + * The only relevant method is {@code filterByNamespace}; all others are only for tests. */ public interface ThingsFieldExpressionFactory extends FieldExpressionFactory { /** - * Return a exist field expression for the given feature id. - * - * @param featureId the feature id - * @return the exist field expression - */ - ExistsFieldExpression existsByFeatureId(final String featureId); - - /** - * Return a filter field expression for the given feature property key. - * - * @param property the property path - * @return the filter field expression + * @return a filter expression for the given namespace */ - FilterFieldExpression filterByFeatureProperty(final String property); + default FilterFieldExpression filterByNamespace() { + return filterBy(FieldExpressionUtil.FIELD_NAME_NAMESPACE); + } /** - * Return a exist field expression for the given feature property key. + * Return a exist field expression for the given feature id. * - * @param property the property path + * @param featureId the feature id * @return the exist field expression */ - ExistsFieldExpression existsByFeatureProperty(final String property); + default ExistsFieldExpression existsByFeatureId(final String featureId) { + return existsBy("features/" + featureId); + } /** * Return a filter field expression for the given feature id and property key. @@ -48,7 +42,9 @@ public interface ThingsFieldExpressionFactory extends FieldExpressionFactory { * @param property the property path * @return the filter field expression */ - FilterFieldExpression filterByFeatureProperty(final String featureId, final String property); + default FilterFieldExpression filterByFeatureProperty(final String featureId, final String property) { + return filterBy(String.format("features/%s/properties/%s", featureId, property)); + } /** * Return a exist field expression for the given feature id and property key. @@ -57,7 +53,9 @@ public interface ThingsFieldExpressionFactory extends FieldExpressionFactory { * @param property the property path * @return the exist field expression */ - ExistsFieldExpression existsByFeatureProperty(final String featureId, final String property); + default ExistsFieldExpression existsByFeatureProperty(final String featureId, final String property) { + return existsBy(String.format("features/%s/properties/%s", featureId, property)); + } /** * Return a sortOptions field expression for the given feature property key. @@ -66,7 +64,9 @@ public interface ThingsFieldExpressionFactory extends FieldExpressionFactory { * @param property the property path * @return the sortOptions field expression */ - SortFieldExpression sortByFeatureProperty(final String featureId, final String property); + default SortFieldExpression sortByFeatureProperty(final String featureId, final String property) { + return sortBy(String.format("features/%s/properties/%s", featureId, property)); + } /** * Return a filter field expression for the given attribute key. @@ -74,7 +74,9 @@ public interface ThingsFieldExpressionFactory extends FieldExpressionFactory { * @param key the key * @return the filter field expression */ - FilterFieldExpression filterByAttribute(final String key); + default FilterFieldExpression filterByAttribute(final String key) { + return filterBy("attributes/" + key); + } /** * Return a exist field expression for the given attribute key. @@ -82,7 +84,9 @@ public interface ThingsFieldExpressionFactory extends FieldExpressionFactory { * @param key the key * @return the exist field expression */ - ExistsFieldExpression existsByAttribute(final String key); + default ExistsFieldExpression existsByAttribute(final String key) { + return existsBy("attributes/" + key); + } /** * Return a sortOptions field expression for the given attribute key. @@ -90,31 +94,21 @@ public interface ThingsFieldExpressionFactory extends FieldExpressionFactory { * @param key the key * @return the sortOptions field expression */ - SortFieldExpression sortByAttribute(final String key); + default SortFieldExpression sortByAttribute(final String key) { + return sortBy("attributes/" + key); + } /** * @return a filter expression for the thingId field. */ - FilterFieldExpression filterByThingId(); + default FilterFieldExpression filterByThingId() { + return filterBy(FieldExpressionUtil.FIELD_NAME_THING_ID); + } /** * @return a sortOptions expression for the thingId field. */ - SortFieldExpression sortByThingId(); - - /** - * @return a filter expression for acl field. - */ - FilterFieldExpression filterByAcl(); - - /** - * @return a filter expression for global read field. - */ - FilterFieldExpression filterByGlobalRead(); - - /** - * - * @return a filter expression for the given namespace - */ - FilterFieldExpression filterByNamespace(); + default SortFieldExpression sortByThingId() { + return sortBy(FieldExpressionUtil.FIELD_NAME_THING_ID); + } } diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactoryImpl.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactoryImpl.java index d7c41a40ac..4bee7a2e18 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactoryImpl.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactoryImpl.java @@ -58,45 +58,29 @@ public FilterFieldExpression filterBy(final String propertyNameWithOptionalLeadi final Supplier defaultSupplier = () -> (FilterFieldExpression) common(propertyName); return FieldExpressionUtil.parseFeatureField(requireNonNull(propertyName)) - .map(f -> f.getProperty() - .map(property -> f.getFeatureId() + .flatMap(f -> f.getProperty() + .flatMap(property -> // we have a feature id and a property path - .map(id -> (FilterFieldExpression) new FeatureIdPropertyExpressionImpl(id, property)) - // we have a property path - .orElseGet(() -> new FeaturePropertyExpressionImpl(property)) + f.getFeatureId().map(id -> new FeatureIdPropertyExpressionImpl(id, property)) ) - // we have a feature field but no property path, this is invalid for filter operations - .orElseGet(defaultSupplier) ) - // we have no feature at all, continue with the other possibilities .orElseGet(defaultSupplier); } @Override - public ExistsFieldExpression existsBy(final String propertyNameWithOptionalLeadingSlash) - throws IllegalArgumentException { + public ExistsFieldExpression existsBy(final String propertyNameWithOptionalLeadingSlash) { requireNonNull(propertyNameWithOptionalLeadingSlash); final String propertyName = stripLeadingSlash(propertyNameWithOptionalLeadingSlash); return FieldExpressionUtil.parseFeatureField(requireNonNull(propertyName)) - .map(f -> f.getFeatureId() + .flatMap(f -> f.getFeatureId() .map(id -> f.getProperty() - // we have a feature id and a property path - .map(property -> (ExistsFieldExpression) new FeatureIdPropertyExpressionImpl(id, - property)) + .map(property -> + new FeatureIdPropertyExpressionImpl(id, property)) // we have a feature id but no property path .orElseGet(() -> new FeatureExpressionImpl(id)) ) - // we have a feature field but no feature id, means it must be a property path - .orElseGet(() -> (ExistsFieldExpression) f.getProperty() - .map((String property) -> (ExistsFieldExpression) new FeaturePropertyExpressionImpl( - property)) - // at this point, we know that there must be a property, so the following throw should - // never happen and is only there to make the compiler happy: - .orElseThrow(() -> - new IllegalStateException("Illegal state while parsing feature property path.")) - ) ) // we have no feature at all, continue with the other possibilities .orElseGet(() -> (ExistsFieldExpression) common(propertyName)); @@ -141,7 +125,7 @@ private static String stripLeadingSlash(final String propertyName) { * @throws IllegalArgumentException if the property can not be mapped. Because of this, call this method last in the * workflow. */ - private FieldExpression common(final String propertyName) throws IllegalArgumentException { + private FieldExpression common(final String propertyName) { if (FieldExpressionUtil.isAttributeFieldName(propertyName)) { return new AttributeExpressionImpl(FieldExpressionUtil.stripAttributesPrefix(propertyName)); } @@ -154,73 +138,4 @@ private FieldExpression common(final String propertyName) throws IllegalArgument throw new IllegalArgumentException("Unknown property name: " + propertyName); } - @Override - public ExistsFieldExpression existsByFeatureId(final String featureId) { - return new FeatureExpressionImpl(featureId); - } - - @Override - public FilterFieldExpression filterByFeatureProperty(final String property) { - return new FeaturePropertyExpressionImpl(property); - } - - @Override - public ExistsFieldExpression existsByFeatureProperty(final String property) { - return new FeaturePropertyExpressionImpl(property); - } - - @Override - public FilterFieldExpression filterByFeatureProperty(final String featureId, final String property) { - return new FeatureIdPropertyExpressionImpl(featureId, property); - } - - @Override - public ExistsFieldExpression existsByFeatureProperty(final String featureId, final String property) { - return new FeatureIdPropertyExpressionImpl(featureId, property); - } - - @Override - public SortFieldExpression sortByFeatureProperty(final String featureId, final String property) { - return new FeatureIdPropertyExpressionImpl(featureId, property); - } - - @Override - public FilterFieldExpression filterByAttribute(final String key) { - return new AttributeExpressionImpl(key); - } - - @Override - public ExistsFieldExpression existsByAttribute(final String key) { - return new AttributeExpressionImpl(key); - } - - @Override - public SortFieldExpression sortByAttribute(final String key) { - return new AttributeExpressionImpl(requireNonNull(key)); - } - - @Override - public FilterFieldExpression filterByAcl() { - return new ThingsAclFieldExpressionImpl(); - } - - @Override - public FilterFieldExpression filterByGlobalRead() { - return new ThingsGlobalReadsFieldExpressionImpl(); - } - - @Override - public FilterFieldExpression filterByThingId() { - return new SimpleFieldExpressionImpl(FieldExpressionUtil.FIELD_ID); - } - - @Override - public SortFieldExpression sortByThingId() { - return new SimpleFieldExpressionImpl(FieldExpressionUtil.FIELD_ID); - } - - @Override - public FilterFieldExpression filterByNamespace() { - return new SimpleFieldExpressionImpl(FieldExpressionUtil.FIELD_NAMESPACE); - } } diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsGlobalReadsFieldExpressionImpl.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsGlobalReadsFieldExpressionImpl.java deleted file mode 100644 index 63f5646d55..0000000000 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/ThingsGlobalReadsFieldExpressionImpl.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * 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.model.query.expression; - -import org.eclipse.ditto.model.query.expression.visitors.FieldExpressionVisitor; -import org.eclipse.ditto.model.query.expression.visitors.FilterFieldExpressionVisitor; - -/** - * Field expression for global reads. - */ -class ThingsGlobalReadsFieldExpressionImpl implements FilterFieldExpression { - - @Override - public T acceptFilterVisitor(final FilterFieldExpressionVisitor visitor) { - return visitor.visitGlobalReads(); - } - - @Override - public T accept(final FieldExpressionVisitor visitor) { - return visitor.visitGlobalReads(); - } -} diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/ExistsFieldExpressionVisitor.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/ExistsFieldExpressionVisitor.java index 5138fb7966..2f07ddfede 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/ExistsFieldExpressionVisitor.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/ExistsFieldExpressionVisitor.java @@ -17,21 +17,16 @@ /** * Compositional interpreter of {@link ExistsFieldExpression}. */ -public interface ExistsFieldExpressionVisitor - extends PolicyRestrictedFieldExpressionVisitor, SortFieldExpressionVisitor { +public interface ExistsFieldExpressionVisitor extends SortFieldExpressionVisitor { @Override T visitAttribute(final String key); - @Override T visitFeature(final String featureId); @Override T visitFeatureIdProperty(final String featureId, final String property); - @Override - T visitFeatureProperty(final String property); - @Override T visitSimple(final String fieldName); } diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/FieldExpressionVisitor.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/FieldExpressionVisitor.java index 46cfd4dc3f..997552d905 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/FieldExpressionVisitor.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/FieldExpressionVisitor.java @@ -17,8 +17,8 @@ /** * Compositional interpreter of {@link FieldExpression}. */ -public interface FieldExpressionVisitor extends ExistsFieldExpressionVisitor, FilterFieldExpressionVisitor, - PolicyRestrictedFieldExpressionVisitor, SortFieldExpressionVisitor { +public interface FieldExpressionVisitor + extends ExistsFieldExpressionVisitor, FilterFieldExpressionVisitor, SortFieldExpressionVisitor { @Override T visitAttribute(final String key); @@ -29,15 +29,6 @@ public interface FieldExpressionVisitor extends ExistsFieldExpressionVisitor< @Override T visitFeatureIdProperty(final String featureId, final String property); - @Override - T visitFeatureProperty(final String property); - @Override T visitSimple(final String fieldName); - - @Override - T visitAcl(); - - @Override - T visitGlobalReads(); } diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/FilterFieldExpressionVisitor.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/FilterFieldExpressionVisitor.java index bc3c638f4a..8b73ec2624 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/FilterFieldExpressionVisitor.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/FilterFieldExpressionVisitor.java @@ -26,12 +26,6 @@ public interface FilterFieldExpressionVisitor extends SortFieldExpressionVisi @Override T visitFeatureIdProperty(final String featureId, final String property); - T visitFeatureProperty(final String property); - @Override T visitSimple(final String fieldName); - - T visitAcl(); - - T visitGlobalReads(); } diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/PolicyRestrictedFieldExpressionVisitor.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/PolicyRestrictedFieldExpressionVisitor.java deleted file mode 100644 index b66df01092..0000000000 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/PolicyRestrictedFieldExpressionVisitor.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * 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.model.query.expression.visitors; - -import org.eclipse.ditto.model.query.expression.PolicyRestrictedFieldExpression; - -/** - * Compositional interpreter of - * {@link PolicyRestrictedFieldExpression}. - */ -public interface PolicyRestrictedFieldExpressionVisitor { - - T visitAttribute(final String key); - - T visitFeature(final String featureId); - - T visitFeatureIdProperty(final String featureId, final String property); - - T visitFeatureProperty(final String property); -} diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/SortFieldExpressionVisitor.java b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/SortFieldExpressionVisitor.java index ff2924aa08..a5ebc67422 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/SortFieldExpressionVisitor.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/expression/visitors/SortFieldExpressionVisitor.java @@ -12,11 +12,8 @@ */ package org.eclipse.ditto.model.query.expression.visitors; -import org.eclipse.ditto.model.query.expression.PolicyRestrictedFieldExpression; - /** - * Compositional interpreter of - * {@link PolicyRestrictedFieldExpression}. + * Compositional interpreter of * {@link SortFieldExpressionVisitor}. */ public interface SortFieldExpressionVisitor { diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/filter/EnsureMonotonicityVisitor.java b/model/query/src/main/java/org/eclipse/ditto/model/query/filter/EnsureMonotonicityVisitor.java deleted file mode 100644 index 3fb1e074fe..0000000000 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/filter/EnsureMonotonicityVisitor.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * 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.model.query.filter; - -import java.util.stream.Stream; - -import org.eclipse.ditto.model.base.exceptions.InvalidRqlExpressionException; -import org.eclipse.ditto.model.base.headers.DittoHeaders; -import org.eclipse.ditto.model.base.json.JsonSchemaVersion; -import org.eclipse.ditto.model.query.criteria.Criteria; -import org.eclipse.ditto.model.query.criteria.Predicate; -import org.eclipse.ditto.model.query.criteria.visitors.CriteriaVisitor; -import org.eclipse.ditto.model.query.expression.ExistsFieldExpression; -import org.eclipse.ditto.model.query.expression.FilterFieldExpression; - -/** - * Throws an exception if the criteria contains negation (i. e., is not monotone) but the API forbids negation. - */ -public final class EnsureMonotonicityVisitor implements CriteriaVisitor { - - private final DittoHeaders dittoHeaders; - private final boolean norIsForbidden; - - /** - * Creates a test whether the criteria contains NOT for an incompatible API version in the command headers. - * - * @param dittoHeaders The command headers containing the API version to check. - */ - private EnsureMonotonicityVisitor(final DittoHeaders dittoHeaders) { - this.dittoHeaders = dittoHeaders; - norIsForbidden = shouldForbidNorCriteria(); - } - - /** - * Throws an exception if the criteria contains negation (i. e., is not monotone) - * but the HTTP API forbids negation. - * - * @param criteria The criteria to check for negation. - * @param dittoHeaders The command headers containing the API version to check. - * @throws InvalidRqlExpressionException if criteria contains negation but dittoHeaders disallow it. - */ - public static void apply(final Criteria criteria, final DittoHeaders dittoHeaders) { - criteria.accept(new EnsureMonotonicityVisitor(dittoHeaders)); - } - - @Override - public Void visitAnd(final Stream conjuncts) { - // force the stream to evaluate criteria on children - conjuncts.count(); - return null; - } - - @Override - public Void visitAny() { - return null; - } - - @Override - public Void visitExists(final ExistsFieldExpression fieldExpression) { - return null; - } - - @Override - public Void visitField(final FilterFieldExpression fieldExpression, final Predicate predicate) { - return null; - } - - @Override - public Void visitNor(final Stream negativeDisjoints) { - if (norIsForbidden) { - final String message = String.format("The filter operation 'not' is not available in API versions >= %d. " + - "Please rephrase your search query without using 'not'.", getForbiddenSchemaVersion()); - throw InvalidRqlExpressionException.fromMessage(message, dittoHeaders); - } else { - // force the stream to evaluate criteria on children - negativeDisjoints.count(); - return null; - } - } - - @Override - public Void visitOr(final Stream disjoints) { - // force the stream to evaluate criteria on children - disjoints.count(); - return null; - } - - private boolean shouldForbidNorCriteria() { - // should forbid NorCriteria only for API >= 2 - return dittoHeaders.getSchemaVersion() - .map(JsonSchemaVersion::toInt) - .filter(v -> v >= JsonSchemaVersion.V_2.toInt()) - .isPresent(); - } - - private int getForbiddenSchemaVersion() { - final JsonSchemaVersion defaultForbiddenVersion = JsonSchemaVersion.V_2; - return dittoHeaders.getSchemaVersion().orElse(defaultForbiddenVersion).toInt(); - } - -} diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/filter/QueryFilterCriteriaFactory.java b/model/query/src/main/java/org/eclipse/ditto/model/query/filter/QueryFilterCriteriaFactory.java index 3d5a035d93..32cd23807b 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/filter/QueryFilterCriteriaFactory.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/filter/QueryFilterCriteriaFactory.java @@ -14,7 +14,6 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.List; import java.util.Set; import org.eclipse.ditto.model.base.common.ConditionChecker; @@ -43,15 +42,6 @@ public QueryFilterCriteriaFactory(final CriteriaFactory criteriaFactory, this.rqlPredicateParser = new RqlPredicateParser(); } - /** - * Returns the criteria factory with which this query filter criteria factory was created. - * - * @return the criteria factory. - */ - public CriteriaFactory getCriteriaFactory() { - return criteriaFactory; - } - /** * Creates a filter criterion based on a filter string which includes only items in the given namespaces * @@ -66,39 +56,6 @@ public Criteria filterCriteriaRestrictedByNamespaces(final String filter, final return restrictByNamespace(namespaces, filterCriteria); } - /** - * Creates a filter criterion based on a filter string which includes only items related to the given auth - * subjects - * - * @param filter the filter string - * @param dittoHeaders the corresponding command headers - * @param authorisationSubjectIds the auth subjects - * @return a filter criterion based on the filter string which includes only items related to the given auth - * subjects - */ - public Criteria filterCriteriaRestrictedByAcl(final String filter, final DittoHeaders dittoHeaders, - final List authorisationSubjectIds) { - final Criteria filterCriteria = filterCriteria(filter, dittoHeaders); - return restrictByAcl(authorisationSubjectIds, filterCriteria); - } - - /** - * Creates a filter criterion based on a filter string which includes items related to the given auth - * subjects and namespaces - * - * @param filter the filter string - * @param dittoHeaders the corresponding command headers - * @param authorisationSubjectIds the auth subjects - * @param namespaces the namespaces - * @return a filter criterion based on the filter string which includes only items related elated to the given auth - * subjects and namespaces - */ - public Criteria filterCriteriaRestrictedByAclAndNamespaces(final String filter, final DittoHeaders dittoHeaders, - final List authorisationSubjectIds, final Set namespaces) { - final Criteria filterCriteria = filterCriteria(filter, dittoHeaders); - return restrictByNamespace(namespaces, restrictByAcl(authorisationSubjectIds, filterCriteria)); - } - /** * Creates a criterion from the given filter string by parsing it. Headers are passed through for eventual error * information. @@ -112,10 +69,6 @@ public Criteria filterCriteria(final String filter, final DittoHeaders headers) return null == filter ? criteriaFactory.any() : mapCriteria(filter, headers); } - private Criteria restrictByAcl(final List authorisationSubjectIds, Criteria filterCriteria) { - return criteriaFactory.and(Arrays.asList(aclFilterCriteria(authorisationSubjectIds), filterCriteria)); - } - private Criteria restrictByNamespace(final Set namespaces, Criteria filterCriteria) { return criteriaFactory.and(Arrays.asList(namespaceFilterCriteria(namespaces), filterCriteria)); } @@ -127,12 +80,6 @@ private Criteria namespaceFilterCriteria(final Set namespaces) { criteriaFactory.in(new ArrayList<>(namespaces))); } - private Criteria aclFilterCriteria(final List authorisationSubjectIds) { - ConditionChecker.checkNotNull(authorisationSubjectIds); - return criteriaFactory.fieldCriteria(fieldExpressionFactory.filterByAcl(), - criteriaFactory.in(authorisationSubjectIds)); - } - private Criteria mapCriteria(final String filter, final DittoHeaders dittoHeaders) { try { final ParameterPredicateVisitor visitor = diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/things/ExistsThingPredicateVisitor.java b/model/query/src/main/java/org/eclipse/ditto/model/query/things/ExistsThingPredicateVisitor.java index b27df99aa1..5f0dbcb52e 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/things/ExistsThingPredicateVisitor.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/things/ExistsThingPredicateVisitor.java @@ -48,15 +48,6 @@ public Predicate visitFeatureIdProperty(final String featureId, final Str .orElse(false); } - @Override - public Predicate visitFeatureProperty(final String property) { - return thing -> thing.getFeatures() - .map(features -> features.stream() - .anyMatch(feature -> feature.getProperty(property).isPresent()) - ) - .orElse(false); - } - @Override public Predicate visitSimple(final String fieldName) { return thing -> thing.toJson().getValue(fieldName).isPresent(); diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/things/FilterThingPredicateVisitor.java b/model/query/src/main/java/org/eclipse/ditto/model/query/things/FilterThingPredicateVisitor.java index bf5403a04b..a63b49a8c3 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/things/FilterThingPredicateVisitor.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/things/FilterThingPredicateVisitor.java @@ -37,37 +37,17 @@ public static Predicate apply(final FilterFieldExpression expression, @Override public Predicate visitAttribute(final String key) { - return predicateFunction.apply("/attributes/" + key); } @Override public Predicate visitFeatureIdProperty(final String featureId, final String property) { - return predicateFunction.apply("/features/" + featureId + "/properties/" + property); } - @Override - public Predicate visitFeatureProperty(final String property) { - return thing -> thing.getFeatures() - .map(features -> features.stream() - .anyMatch(feature -> feature.getProperty(property).isPresent()) - ) - .orElse(false); - } - @Override public Predicate visitSimple(final String fieldName) { return predicateFunction.apply(fieldName); } - @Override - public Predicate visitAcl() { - return predicateFunction.apply("/acl"); - } - - @Override - public Predicate visitGlobalReads() { - return thing -> true; // not relevant for Thing Predicates - } } diff --git a/model/query/src/main/java/org/eclipse/ditto/model/query/things/ModelBasedThingsFieldExpressionFactory.java b/model/query/src/main/java/org/eclipse/ditto/model/query/things/ModelBasedThingsFieldExpressionFactory.java index e41fcced07..603f16a054 100644 --- a/model/query/src/main/java/org/eclipse/ditto/model/query/things/ModelBasedThingsFieldExpressionFactory.java +++ b/model/query/src/main/java/org/eclipse/ditto/model/query/things/ModelBasedThingsFieldExpressionFactory.java @@ -12,11 +12,14 @@ */ package org.eclipse.ditto.model.query.things; +import static org.eclipse.ditto.model.query.expression.FieldExpressionUtil.FIELD_NAMESPACE; +import static org.eclipse.ditto.model.query.expression.FieldExpressionUtil.FIELD_NAME_THING_ID; + +import java.util.Collections; import java.util.HashMap; import java.util.Map; import org.eclipse.ditto.model.query.expression.ExistsFieldExpression; -import org.eclipse.ditto.model.query.expression.FieldExpressionUtil; import org.eclipse.ditto.model.query.expression.FilterFieldExpression; import org.eclipse.ditto.model.query.expression.SortFieldExpression; import org.eclipse.ditto.model.query.expression.ThingsFieldExpressionFactory; @@ -27,12 +30,13 @@ */ public final class ModelBasedThingsFieldExpressionFactory implements ThingsFieldExpressionFactory { - private static final Map filteringSimpleFieldMappings = new HashMap<>(); + private static final Map filteringSimpleFieldMappings; static { - filteringSimpleFieldMappings.put(FieldExpressionUtil.FIELD_NAME_THING_ID, - FieldExpressionUtil.FIELD_NAME_THING_ID); - filteringSimpleFieldMappings.put(FieldExpressionUtil.FIELD_NAMESPACE, FieldExpressionUtil.FIELD_NAMESPACE); + final Map hashMap = new HashMap<>(); + hashMap.put(FIELD_NAME_THING_ID, FIELD_NAME_THING_ID); + hashMap.put(FIELD_NAMESPACE, FIELD_NAMESPACE); + filteringSimpleFieldMappings = Collections.unmodifiableMap(hashMap); } private final ThingsFieldExpressionFactory delegate; @@ -42,69 +46,17 @@ public ModelBasedThingsFieldExpressionFactory() { } @Override - public ExistsFieldExpression existsByFeatureId( - final String featureId) {return delegate.existsByFeatureId(featureId);} - - @Override - public FilterFieldExpression filterByFeatureProperty( - final String property) {return delegate.filterByFeatureProperty(property);} - - @Override - public ExistsFieldExpression existsByFeatureProperty( - final String property) {return delegate.existsByFeatureProperty(property);} - - @Override - public FilterFieldExpression filterByFeatureProperty( - final String featureId, final String property) { - return delegate.filterByFeatureProperty(featureId, property); + public FilterFieldExpression filterBy(final String propertyName) { + return delegate.filterBy(propertyName); } @Override - public ExistsFieldExpression existsByFeatureProperty( - final String featureId, final String property) { - return delegate.existsByFeatureProperty(featureId, property); + public ExistsFieldExpression existsBy(final String propertyName) { + return delegate.existsBy(propertyName); } @Override - public SortFieldExpression sortByFeatureProperty( - final String featureId, final String property) {return delegate.sortByFeatureProperty(featureId, property);} - - @Override - public FilterFieldExpression filterByAttribute( - final String key) {return delegate.filterByAttribute(key);} - - @Override - public ExistsFieldExpression existsByAttribute( - final String key) {return delegate.existsByAttribute(key);} - - @Override - public SortFieldExpression sortByAttribute( - final String key) {return delegate.sortByAttribute(key);} - - @Override - public FilterFieldExpression filterByThingId() {return delegate.filterByThingId();} - - @Override - public SortFieldExpression sortByThingId() {return delegate.sortByThingId();} - - @Override - public FilterFieldExpression filterByAcl() {return delegate.filterByAcl();} - - @Override - public FilterFieldExpression filterByGlobalRead() {return delegate.filterByGlobalRead();} - - @Override - public FilterFieldExpression filterByNamespace() {return delegate.filterByNamespace();} - - @Override - public FilterFieldExpression filterBy( - final String propertyName) throws IllegalArgumentException {return delegate.filterBy(propertyName);} - - @Override - public ExistsFieldExpression existsBy( - final String propertyName) throws IllegalArgumentException {return delegate.existsBy(propertyName);} - - @Override - public SortFieldExpression sortBy( - final String propertyName) throws IllegalArgumentException {return delegate.sortBy(propertyName);} + public SortFieldExpression sortBy(final String propertyName) { + return delegate.sortBy(propertyName); + } } diff --git a/model/query/src/test/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactoryImplTest.java b/model/query/src/test/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactoryImplTest.java index 5058dc0646..331d4c7950 100644 --- a/model/query/src/test/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactoryImplTest.java +++ b/model/query/src/test/java/org/eclipse/ditto/model/query/expression/ThingsFieldExpressionFactoryImplTest.java @@ -26,25 +26,21 @@ public final class ThingsFieldExpressionFactoryImplTest { private static final String KNOWN_STRING = "KNOWN_STRING"; private static final String KNOWN_FEATURE_ID = "feature1"; private static final String KNOWN_FEATURE = "features/" + KNOWN_FEATURE_ID; - private static final String KNOWN_FEATURE_PROPERTY = "features/*/properties/" + KNOWN_STRING; private static final String KNOWN_FEATURE_PROPERTY_WITH_ID = "features/" + KNOWN_FEATURE_ID + "/properties/" + KNOWN_STRING; private final ThingsFieldExpressionFactory ef = new ThingsFieldExpressionFactoryImpl(); - /** */ @Test(expected = NullPointerException.class) public void filterByWithNullPropertyName() { ef.filterBy(null); } - /** */ @Test(expected = IllegalArgumentException.class) public void filterByWithUnknownPropertyName() { ef.filterBy("unknown"); } - /** */ @Test public void filterByWithFeaturePropertyWithId() { final FieldExpression fieldExpression = ef.filterBy(KNOWN_FEATURE_PROPERTY_WITH_ID); @@ -53,34 +49,21 @@ public void filterByWithFeaturePropertyWithId() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ - @Test - public void filterByWithFeaturePropertyWithoutId() { - final FieldExpression fieldExpression = ef.filterBy(KNOWN_FEATURE_PROPERTY); - - final FilterFieldExpression expected = new FeaturePropertyExpressionImpl(KNOWN_STRING); - assertThat(fieldExpression).isEqualTo(expected); - } - - /** */ @Test(expected = IllegalArgumentException.class) public void filterByWithFeature() { ef.filterBy(KNOWN_FEATURE); } - /** */ @Test(expected = NullPointerException.class) public void existsByWithNullPropertyName() { ef.existsBy(null); } - /** */ @Test(expected = IllegalArgumentException.class) public void existsByWithUnknownPropertyName() { ef.existsBy("unknown"); } - /** */ @Test public void existsByWithFeaturePropertyWithId() { final FieldExpression fieldExpression = ef.existsBy(KNOWN_FEATURE_PROPERTY_WITH_ID); @@ -89,16 +72,6 @@ public void existsByWithFeaturePropertyWithId() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ - @Test - public void existsByWithFeaturePropertyWithoutId() { - final FieldExpression fieldExpression = ef.existsBy(KNOWN_FEATURE_PROPERTY); - - final ExistsFieldExpression expected = new FeaturePropertyExpressionImpl(KNOWN_STRING); - assertThat(fieldExpression).isEqualTo(expected); - } - - /** */ @Test public void existsByWithFeature() { final FieldExpression fieldExpression = ef.existsBy(KNOWN_FEATURE); @@ -107,7 +80,6 @@ public void existsByWithFeature() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ @Test public void existsByWithJsonPointer() { final FieldExpression fieldExpression = ef.existsBy(SLASH + KNOWN_FEATURE); @@ -116,7 +88,6 @@ public void existsByWithJsonPointer() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ @Test public void sortByWithFeatureProperty() { final FieldExpression fieldExpression = ef.sortBy(KNOWN_FEATURE_PROPERTY_WITH_ID); @@ -125,7 +96,7 @@ public void sortByWithFeatureProperty() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ + @Test public void sortByWithJsonPointer() { final FieldExpression fieldExpression = ef.sortBy(SLASH + KNOWN_FEATURE_PROPERTY_WITH_ID); @@ -134,19 +105,11 @@ public void sortByWithJsonPointer() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ @Test(expected = IllegalArgumentException.class) public void sortByWithFeaturePropertyInvalid1() { ef.sortBy(KNOWN_FEATURE); } - /** */ - @Test(expected = IllegalArgumentException.class) - public void sortByWithFeaturePropertyInvalid2() { - ef.sortBy(KNOWN_FEATURE_PROPERTY); - } - - /** */ @Test public void filterByWithAttribute() { final FieldExpression fieldExpression = ef.filterBy(FieldExpressionUtil.addAttributesPrefix(KNOWN_STRING)); @@ -156,7 +119,6 @@ public void filterByWithAttribute() { } - /** */ @Test public void filterByWithThingId() { final FieldExpression fieldExpression = ef.filterBy(FieldExpressionUtil.FIELD_NAME_THING_ID); @@ -165,7 +127,6 @@ public void filterByWithThingId() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ @Test public void filterByWithJsonPointer() { final FieldExpression fieldExpression = ef.filterBy(SLASH + FieldExpressionUtil.FIELD_NAME_THING_ID); @@ -174,18 +135,6 @@ public void filterByWithJsonPointer() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ - @Test - public void filterByFeatureProperty() { - final FilterFieldExpression fieldExpression = ef.filterByFeatureProperty(KNOWN_STRING); - - final FilterFieldExpression expected = - new FeaturePropertyExpressionImpl(KNOWN_STRING); - assertThat(fieldExpression).isEqualTo(expected); - assertThat(fieldExpression).isNotNull().isInstanceOf(FeaturePropertyExpressionImpl.class); - } - - /** */ @Test public void filterByFeatureIdAndProperty() { final FilterFieldExpression fieldExpression = ef.filterByFeatureProperty(KNOWN_FEATURE_ID, KNOWN_STRING); @@ -195,7 +144,6 @@ public void filterByFeatureIdAndProperty() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ @Test public void sortByFeatureProperty() { final SortFieldExpression fieldExpression = ef.sortByFeatureProperty(KNOWN_FEATURE_ID, KNOWN_STRING); @@ -205,19 +153,6 @@ public void sortByFeatureProperty() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ - @Test(expected = NullPointerException.class) - public void filterByFeaturePropertyWithNullKey() { - ef.filterByFeatureProperty(null); - } - - /** */ - @Test(expected = NullPointerException.class) - public void sortByFeaturePropertyWithNullKey() { - ef.sortByFeatureProperty(null, null); - } - - /** */ @Test public void filterByAttribute() { final FilterFieldExpression fieldExpression = ef.filterByAttribute(KNOWN_STRING); @@ -226,7 +161,6 @@ public void filterByAttribute() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ @Test public void sortByAttribute() { final SortFieldExpression fieldExpression = ef.sortByAttribute(KNOWN_STRING); @@ -235,19 +169,6 @@ public void sortByAttribute() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ - @Test(expected = NullPointerException.class) - public void filterByAttributeWithNullKey() { - ef.filterByAttribute(null); - } - - /** */ - @Test(expected = NullPointerException.class) - public void sortByAttributeWithNullKey() { - ef.sortByAttribute(null); - } - - /** */ @Test public void filterByThingId() { final FilterFieldExpression fieldExpression = ef.filterByThingId(); @@ -256,7 +177,6 @@ public void filterByThingId() { assertThat(fieldExpression).isEqualTo(expected); } - /** */ @Test public void sortByThingId() { final SortFieldExpression fieldExpression = ef.sortByThingId(); diff --git a/model/query/src/test/java/org/eclipse/ditto/model/query/things/ThingPredicateVisitorTest.java b/model/query/src/test/java/org/eclipse/ditto/model/query/things/ThingPredicateVisitorTest.java index fc3eca83e3..c365d8458d 100644 --- a/model/query/src/test/java/org/eclipse/ditto/model/query/things/ThingPredicateVisitorTest.java +++ b/model/query/src/test/java/org/eclipse/ditto/model/query/things/ThingPredicateVisitorTest.java @@ -34,10 +34,8 @@ public final class ThingPredicateVisitorTest { private static final CriteriaFactory criteriaFactory = new CriteriaFactoryImpl(); - private static final ThingsFieldExpressionFactory fieldExpressionFactory = - new ModelBasedThingsFieldExpressionFactory(); private static final QueryFilterCriteriaFactory queryFilterCriteriaFactory = - new QueryFilterCriteriaFactory(criteriaFactory, fieldExpressionFactory); + new QueryFilterCriteriaFactory(criteriaFactory, new ModelBasedThingsFieldExpressionFactory()); private static final String MATCHING_THING_ID = "org.eclipse.ditto:foo-matching"; private static final int MATCHING_THING_INTEGER = 42; diff --git a/services/thingsearch/common/src/main/java/org/eclipse/ditto/services/thingsearch/common/util/ConfigKeys.java b/services/thingsearch/common/src/main/java/org/eclipse/ditto/services/thingsearch/common/util/ConfigKeys.java index bae505fe8c..2f15dcb83b 100644 --- a/services/thingsearch/common/src/main/java/org/eclipse/ditto/services/thingsearch/common/util/ConfigKeys.java +++ b/services/thingsearch/common/src/main/java/org/eclipse/ditto/services/thingsearch/common/util/ConfigKeys.java @@ -35,24 +35,6 @@ public final class ConfigKeys { * Prefix for mongoDB config */ private static final String MONGO_CONFIG_PREFIX = SEARCH_PREFIX + "mongodb."; - /** - * Prefix for circuit breaker config. - */ - private static final String MONGO_CIRCUIT_BREAKER_CONFIG_PREFIX = MONGO_CONFIG_PREFIX + "breaker."; - /** - * Max retries config for circuit breaker. - */ - public static final String MONGO_CIRCUIT_BREAKER_FAILURES = MONGO_CIRCUIT_BREAKER_CONFIG_PREFIX + "maxFailures"; - /** - * Call timeout config for circuit breaker. - */ - public static final String MONGO_CIRCUIT_BREAKER_TIMEOUT_CALL = - MONGO_CIRCUIT_BREAKER_CONFIG_PREFIX + "timeout.call"; - /** - * Reset timeout for circuit breaker. - */ - public static final String MONGO_CIRCUIT_BREAKER_TIMEOUT_RESET = - MONGO_CIRCUIT_BREAKER_CONFIG_PREFIX + "timeout.reset"; private static final String MONITORING_PREFIX = MONGO_CONFIG_PREFIX + "monitoring."; /** @@ -79,11 +61,6 @@ public final class ConfigKeys { */ public static final String DELETION_AGE = DELETION_PREFIX + "deletion-age"; - /** - * Whether or not the deletion of marked as deleted Things from the search index is enabled. - */ - public static final String DELETION_ENABLED = DELETION_PREFIX + "enabled"; - /** * Key configuring the interval (as Duration) when marked as deleted Things should be deleted (e.g. once a day). */ @@ -106,16 +83,14 @@ public final class ConfigKeys { public static final String MAX_BULK_SIZE = SEARCH_UPDATER_PREFIX + "max-bulk-size"; /** - * Controls whether thing and policy cache-updates should be active or not. + * Path to configuration of the search updater stream. */ - public static final String CACHE_UPDATES_ACTIVE = SEARCH_UPDATER_PREFIX + "cache-updates.active"; + public static final String UPDATER_STREAM = SEARCH_UPDATER_PREFIX + "stream"; /** - * The interval which defines how long a thing updater is considered active. When not active, the corresponding - * actor can be stopped. + * Lifetime of an idling ThingUpdater. */ - public static final String THINGS_ACTIVITY_CHECK_INTERVAL = SEARCH_UPDATER_PREFIX + - "activity-check-interval"; + public static final String THING_UPDATER_MAX_IDLE_TIME = SEARCH_UPDATER_PREFIX + "max-idle-time"; private static final String SYNC_PREFIX = SEARCH_UPDATER_PREFIX + "sync."; @@ -167,7 +142,6 @@ public final class ConfigKeys { public static final String POLICIES_SYNCER_OUTDATED_ERROR_OFFSET = SYNC_POLICIES_PREFIX + "outdated-error-offset"; - /* * This class is not designed for instantiation. */ diff --git a/services/thingsearch/common/src/main/java/org/eclipse/ditto/services/thingsearch/common/util/KeyEscapeUtil.java b/services/thingsearch/common/src/main/java/org/eclipse/ditto/services/thingsearch/common/util/KeyEscapeUtil.java index 320ab92c1b..90618c304d 100644 --- a/services/thingsearch/common/src/main/java/org/eclipse/ditto/services/thingsearch/common/util/KeyEscapeUtil.java +++ b/services/thingsearch/common/src/main/java/org/eclipse/ditto/services/thingsearch/common/util/KeyEscapeUtil.java @@ -21,8 +21,10 @@ */ public final class KeyEscapeUtil { - public static final String FAKE_DOLLAR = "\uFF04"; - public static final String FAKE_DOT = "\uFF0E"; + private static final String FAKE_TILDA = "~0"; + private static final String FAKE_DOLLAR = "~1"; + + public static final String FAKE_DOT = "~2"; private KeyEscapeUtil() { } @@ -35,6 +37,8 @@ private KeyEscapeUtil() { */ public static String escape(final String str) { requireNonNull(str); - return str.replace("$", FAKE_DOLLAR).replace(".", FAKE_DOT); + return str.replace("~", FAKE_TILDA) + .replace("$", FAKE_DOLLAR) + .replace(".", FAKE_DOT); } } diff --git a/services/thingsearch/common/src/test/java/org/eclipse/ditto/services/thingsearch/common/model/ResultListImplTest.java b/services/thingsearch/common/src/test/java/org/eclipse/ditto/services/thingsearch/common/model/ResultListImplTest.java index e312f8d893..4287daaed4 100644 --- a/services/thingsearch/common/src/test/java/org/eclipse/ditto/services/thingsearch/common/model/ResultListImplTest.java +++ b/services/thingsearch/common/src/test/java/org/eclipse/ditto/services/thingsearch/common/model/ResultListImplTest.java @@ -24,7 +24,7 @@ */ public final class ResultListImplTest { - /** */ + @Test public void hashcodeAndEquals() { EqualsVerifier.forClass(ResultListImpl.class).usingGetClass().verify(); @@ -38,13 +38,13 @@ public void hashcodeAndEquals() { // assertInstancesOf(ResultListImpl.class, areImmutable()); // } - /** */ + @Test(expected = NullPointerException.class) public void constructorWithNull() { new ResultListImpl<>(null, 1); } - /** */ + @Test public void basicUsage() { final int nextPageOffset = 4; diff --git a/services/thingsearch/common/src/test/java/org/eclipse/ditto/services/thingsearch/common/util/KeyEscapeUtilTest.java b/services/thingsearch/common/src/test/java/org/eclipse/ditto/services/thingsearch/common/util/KeyEscapeUtilTest.java index f5b23dd627..a2515b2d33 100644 --- a/services/thingsearch/common/src/test/java/org/eclipse/ditto/services/thingsearch/common/util/KeyEscapeUtilTest.java +++ b/services/thingsearch/common/src/test/java/org/eclipse/ditto/services/thingsearch/common/util/KeyEscapeUtilTest.java @@ -22,10 +22,10 @@ */ public class KeyEscapeUtilTest { - /** */ + @Test public void escape() { assertSame("escapingNotNecessary", KeyEscapeUtil.escape("escapingNotNecessary")); - assertEquals("\uFF04org\uFF0Eeclipse\uFF0Editto", KeyEscapeUtil.escape("$org.eclipse.ditto")); + assertEquals("~1org~2eclipse~2~0ditto", KeyEscapeUtil.escape("$org.eclipse.~ditto")); } } diff --git a/services/thingsearch/persistence/pom.xml b/services/thingsearch/persistence/pom.xml index f934fd1453..1e7e28bc79 100755 --- a/services/thingsearch/persistence/pom.xml +++ b/services/thingsearch/persistence/pom.xml @@ -43,6 +43,10 @@ org.eclipse.ditto ditto-model-base + + org.eclipse.ditto + ditto-model-query + org.eclipse.ditto ditto-model-policies @@ -59,10 +63,6 @@ org.eclipse.ditto ditto-model-thingsearch - - org.eclipse.ditto - ditto-model-query - org.eclipse.ditto @@ -86,6 +86,17 @@ org.eclipse.ditto ditto-services-models-thingsearch + + + org.eclipse.ditto + ditto-services-concierge-util + ${project.version} + + + org.eclipse.ditto + ditto-services-concierge-cache + ${project.version} + org.eclipse.ditto @@ -99,6 +110,10 @@ org.eclipse.ditto ditto-services-utils-persistence + + org.eclipse.ditto + ditto-services-utils-namespaces + com.typesafe.akka diff --git a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/Indices.java b/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/Indices.java index df4459947f..14542f35b3 100644 --- a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/Indices.java +++ b/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/Indices.java @@ -12,26 +12,20 @@ */ package org.eclipse.ditto.services.thingsearch.persistence; -import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_DELETED; -import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_DELETED_FLAG; -import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_FEATURE_PATH_KEY; +import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_DELETE_AT; +import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_GLOBAL_READ; +import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_GRANTED_PATH; import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_ID; -import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_INTERNAL_ACL; -import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_INTERNAL_GLOBAL_READS; import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_NAMESPACE; import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_PATH_KEY; import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_PATH_VALUE; import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_POLICY_ID; import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_POLICY_REVISION; -import static org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants.FIELD_THING_ID; -import static org.eclipse.ditto.services.thingsearch.persistence.read.MongoThingsSearchPersistence.filterNotDeleted; import java.util.Arrays; import java.util.Collections; import java.util.List; -import org.bson.BsonBoolean; -import org.bson.BsonDocument; import org.eclipse.ditto.services.utils.persistence.mongo.indices.Index; import org.eclipse.ditto.services.utils.persistence.mongo.indices.IndexFactory; @@ -45,82 +39,39 @@ private Indices() { } /** - * Indices on {@link PersistenceConstants#THINGS_COLLECTION_NAME}. + * Index for queries with effective filters. */ - public static final class Things { - - private static final Index KEY_VALUE = IndexFactory.newInstance("nfkv", - keys(FIELD_NAMESPACE, FIELD_FEATURE_PATH_KEY, FIELD_PATH_KEY, FIELD_PATH_VALUE, FIELD_ID), false) - .withPartialFilterExpression(filterNotDeleted()); - - private static final Index ACL = IndexFactory.newInstance("acl", - keys(FIELD_INTERNAL_ACL, FIELD_ID), false) - .withPartialFilterExpression(filterNotDeleted()); - - private static final Index GLOBAL_READS = IndexFactory.newInstance("gr", - keys(FIELD_INTERNAL_GLOBAL_READS), false) - .withPartialFilterExpression(filterNotDeleted()); - - private static final Index DELETED = IndexFactory.newInstance("deleted", - keys(FIELD_DELETED_FLAG, FIELD_DELETED), false); - - private static final Index POLICY = IndexFactory.newInstance("policy", - keys(FIELD_POLICY_ID, FIELD_POLICY_REVISION), false) - .withPartialFilterExpression(filterPolicyIdExists()); - - /** - * Gets all defined indices. - * - * @return the indices - */ - public static List all() { - return Collections.unmodifiableList(Arrays.asList(KEY_VALUE, ACL, GLOBAL_READS, DELETED, POLICY)); - } - - private static List keys(final String... keyNames) { - return Collections.unmodifiableList(Arrays.asList(keyNames)); - } - - private Things() { - throw new AssertionError(); - } - - /** - * Create a BSON filter for existent policyId. - * - * @return the BSON filter. - */ - private static BsonDocument filterPolicyIdExists() { - return new BsonDocument(FIELD_POLICY_ID, new BsonDocument("$exists", BsonBoolean.TRUE)); - } - - } + private static final Index KEY_VALUE = IndexFactory.newInstance("key-value", + Arrays.asList(FIELD_GRANTED_PATH, FIELD_PATH_KEY, FIELD_PATH_VALUE, FIELD_ID), false); /** - * Indices on {@link PersistenceConstants#POLICIES_BASED_SEARCH_INDEX_COLLECTION_NAME}. + * Index for queries without effective filters to be executed as scans over all visible things. */ - public static final class Policies { - - private static final Index THING = IndexFactory.newInstance("thingId", - keys(FIELD_THING_ID), false); + private static final Index GLOBAL_READ = IndexFactory.newInstance("global-read", + Collections.singletonList(FIELD_GLOBAL_READ), false); - /** - * Gets all defined indices. - * - * @return the indices - */ - public static List all() { - return Collections.unmodifiableList(Arrays.asList(THING)); - } + /** + * Index for dispatching policy events. + */ + private static final Index POLICY = IndexFactory.newInstance("policyId", + Arrays.asList(FIELD_POLICY_ID, FIELD_POLICY_REVISION), false); - private static List keys(final String... keyNames) { - return Collections.unmodifiableList(Arrays.asList(keyNames)); - } + private static final Index DELETE_AT = IndexFactory.newExpirationIndex(FIELD_DELETE_AT, FIELD_DELETE_AT, 0L); - private Policies() { - throw new AssertionError(); - } + /** + * Index for namespace. + */ + private static final Index NAMESPACE = IndexFactory.newInstance("namespace", + Arrays.asList(FIELD_NAMESPACE, FIELD_ID), false); + /** + * Gets all defined indices. + * + * @return the indices + */ + public static List all() { + return Collections.unmodifiableList( + Arrays.asList(KEY_VALUE, GLOBAL_READ, POLICY, NAMESPACE, DELETE_AT)); } } diff --git a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/PersistenceConstants.java b/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/PersistenceConstants.java index bfe9f02805..da159d20a9 100644 --- a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/PersistenceConstants.java +++ b/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/PersistenceConstants.java @@ -21,56 +21,45 @@ public final class PersistenceConstants { /** - * The thing collection name. + * A dot. */ - public static final String THINGS_COLLECTION_NAME = "thingEntities"; + public static final String DOT = "."; /** - * The policies based search collection name. + * A slash. */ - public static final String POLICIES_BASED_SEARCH_INDEX_COLLECTION_NAME = "policiesBasedSearchIndex"; + public static final String SLASH = "/"; /** - * The collection name for the collection storing state about things sync. + * The thing collection name. */ - public static final String THINGS_SYNC_STATE_COLLECTION_NAME = "thingsSearchSyncStateThings"; + public static final String THINGS_COLLECTION_NAME = "searchThings"; /** - * The collection name for the collection storing state about policies sync. + * The collection name for the collection storing state about things sync. */ - public static final String POLICIES_SYNC_STATE_COLLECTION_NAME = "thingsSearchSyncStatePolicies"; - - public static final String SLASH = "/"; + public static final String THINGS_SYNC_STATE_COLLECTION_NAME = "searchThingsSyncThings"; /** - * Field name for revision. + * The collection name for the collection storing state about policies sync. */ - public static final String FIELD_REVISION = "__rev"; + public static final String POLICIES_SYNC_STATE_COLLECTION_NAME = "searchThingsSyncPolicies"; /** - * Field name for deletion date. + * Field name for revision. */ - public static final String FIELD_DELETED = "__deleted"; + public static final String FIELD_REVISION = "_revision"; - /** - * Field name for deleted flag (boolean). - */ - public static final String FIELD_DELETED_FLAG = "__deletedFlag"; /** * Field name for _id. */ public static final String FIELD_ID = FieldExpressionUtil.FIELD_ID; - /** - * Field name for thing id. - */ - public static final String FIELD_THING_ID = "_thingId"; - /** * Field name for policy id. */ - public static final String FIELD_POLICY_ID = "_policyId"; + public static final String FIELD_POLICY_ID = "policyId"; /** * Field name for policy revision. @@ -92,11 +81,6 @@ public final class PersistenceConstants { */ public static final String FIELD_ATTRIBUTES = "attributes"; - /** - * Field name for attributes with path. - */ - public static final String FIELD_ATTRIBUTES_WITH_PATH = FIELD_ATTRIBUTES + SLASH; - /** * Field name for features. */ @@ -108,58 +92,39 @@ public final class PersistenceConstants { public static final String FIELD_PROPERTIES = "properties"; /** - * Field name for feature properties with starting path. + * Part of the path between feature ID and property key. */ - - public static final String FIELD_PROPERTIES_WITH_STARTING_PATH = SLASH + FIELD_PROPERTIES; - - /** - * Field name for feature properties with starting and ending path. - */ - public static final String FIELD_PROPERTIES_WITH_STARTING_ENDING_PATH = - FIELD_PROPERTIES_WITH_STARTING_PATH + - SLASH; + public static final String PROPERTIES = SLASH + FIELD_PROPERTIES + SLASH; /** * Field name for features. */ - public static final String FIELD_FEATURES_WITH_PATH = FIELD_FEATURES + SLASH; + public static final String FIELD_FEATURES_PATH = SLASH + FIELD_FEATURES + SLASH; /** * Field name for attributes. */ - public static final String FIELD_ATTRIBUTE_PREFIX = "attribute"; + public static final String FIELD_ATTRIBUTE_PREFIX = "attributes"; /** * Field name for attributes. */ - public static final String FIELD_ATTRIBUTE_PREFIX_WITH_ENDING_SLASH = FIELD_ATTRIBUTE_PREFIX + SLASH; + public static final String FIELD_ATTRIBUTES_PATH = SLASH + FIELD_ATTRIBUTE_PREFIX + SLASH; /** - * Field name for feature properties. + * Field name for subject IDs with partial READ permission and are not revoked at root. */ - public static final String FIELD_FEATURE_PROPERTIES_PREFIX = "features/properties"; + public static final String FIELD_GLOBAL_READ = "gr"; /** - * Field name for feature properties. + * Field name for hierarchical attributes for sorting. */ - public static final String FIELD_FEATURE_PROPERTIES_PREFIX_WITH_ENDING_SLASH = - FIELD_FEATURE_PROPERTIES_PREFIX + SLASH; + public static final String FIELD_SORTING = "s"; /** * Field name for internal flat attributes. */ - public static final String FIELD_INTERNAL = "__internal"; - - /** - * Field name for ACL. - */ - public static final String FIELD_ACL = "acl"; - - /** - * Holds the field name for the internal acl field. - */ - public static final String FIELD_INTERNAL_ACL = FIELD_INTERNAL + "." + FIELD_ACL; + public static final String FIELD_INTERNAL = "d"; /** * Field name of attribute's value. @@ -169,183 +134,37 @@ public final class PersistenceConstants { /** * Path to an attribute's value. */ - public static final String FIELD_PATH_ATTRIBUTES_VALUE = FIELD_INTERNAL + "." + FIELD_INTERNAL_VALUE; - - /** - * Field name for revision. - */ - public static final String FIELD_REVISION_VARIABLE = "$" + FIELD_REVISION; - - /** - * Field name for deleted date field. - */ - public static final String FIELD_DELETED_VARIABLE = "$" + FIELD_DELETED; - - /** - * Field name for deleted flag field. - */ - public static final String FIELD_DELETED_FLAG_VARIABLE = "$" + FIELD_DELETED_FLAG; - - /** - * Holds the variable name for attributes in aggregations. - */ - public static final String FIELD_ATTRIBUTES_VARIABLE = "$" + FIELD_ATTRIBUTES; - - /** - * Holds the features variable name used in aggregations. - */ - public static final String FIELD_FEATURES_VARIABLE = "$" + FIELD_FEATURES; - /** - * Field name for features. - */ - public static final String FIELD_FEATURES_PREFIX = "features/"; - - /** - * Holds the internal variable name used in aggregations. - */ - public static final String FIELD_INTERNAL_VARIABLE = "$" + FIELD_INTERNAL; - - /** - * Holds the feature variable name in aggregations. - */ - public static final String FIELD_INTERNAL_FEATURE_VARIABLE = FIELD_INTERNAL_VARIABLE + ".f"; - - /** - * Holds the key variable name used in aggregations. - */ - public static final String FIELD_INTERNAL_KEY_VARIABLE = FIELD_INTERNAL_VARIABLE + ".k"; - - /** - * Holds the variable name for the acl used in aggregations. - */ - public static final String FIELD_INTERNAL_ACL_VARIABLE = FIELD_INTERNAL_VARIABLE + ".acl"; - - /** - * Field name for global reads. - */ - public static final String FIELD_GLOBAL_READS = "gr"; - - /** - * Field name for global reads in the internal array. - */ - public static final String FIELD_INTERNAL_GLOBAL_READS = FIELD_INTERNAL + "." + FIELD_GLOBAL_READS; - - /** - * Path to an attribute's value. - */ - public static final String FIELD_PATH_VALUE = FIELD_INTERNAL + "." + FIELD_INTERNAL_VALUE; + public static final String FIELD_PATH_VALUE = FIELD_INTERNAL + DOT + FIELD_INTERNAL_VALUE; /** - * Field name of attribute's key. + * Field name of a key of an attribute or feature property. */ public static final String FIELD_INTERNAL_KEY = "k"; - /** - * Field name of feature id. - */ - public static final String FIELD_INTERNAL_FEATURE_ID = "f"; - /** * Path to an attributes/properties key. */ - public static final String FIELD_PATH_KEY = FIELD_INTERNAL + "." + FIELD_INTERNAL_KEY; - - /** - * Path to an feature id key. - */ - public static final String FIELD_FEATURE_PATH_KEY = FIELD_INTERNAL + "." + FIELD_INTERNAL_FEATURE_ID; + public static final String FIELD_PATH_KEY = FIELD_INTERNAL + DOT + FIELD_INTERNAL_KEY; /** * Field name for policy read grants. */ - public static final String FIELD_GRANTED = "granted"; - - /** - * Field name for policy read revokes. - */ - public static final String FIELD_REVOKED = "revoked"; - - /** - * Field name for policy resource. - */ - public static final String FIELD_RESOURCE = "resource"; - - /** - * Field name for policy grants. - */ - public static final String FIELD_GRANTS = "grants"; + public static final String FIELD_GRANTED = "g"; /** - * Field name for the granted attribute resource. + * Full path of the granted field. */ - public static final String FIELD_GRANTS_RESOURCE = FIELD_GRANTS + "." + FIELD_RESOURCE; + public static final String FIELD_GRANTED_PATH = FIELD_INTERNAL + DOT + FIELD_GRANTED; /** - * Field name for users with access to a particular granted resource. - */ - public static final String FIELD_GRANTS_GRANTED = FIELD_GRANTS + "." + FIELD_GRANTED; - - /** - * Field name for users with access to a particular revoked resource. - */ - public static final String FIELD_GRANTS_REVOKED = FIELD_GRANTS + "." + FIELD_REVOKED; - - /** - * Field name for policy grants. - */ - public static final String FIELD_GRANTS_VARIABLE = "$" + FIELD_GRANTS; - - /** - * Variable holding the value to lookup the policies index. - */ - public static final String POLICY_INDEX_ID = "policyIndexId"; - - /** - * ID variable used in mongo aggregations. - */ - public static final String ID_VARIABLE = "$" + FIELD_ID; - - /** - * Namespace variable used in mongo aggregations. - */ - public static final String NAMESPACE_VARIABLE = "$" + FIELD_NAMESPACE; - - /** - * Condition used in mongo aggregation. - */ - public static final String IF_NULL_CONDITION = "$ifNull"; - - /** - * Projection type first used in mongo aggregations. - */ - public static final String FIRST_PROJECTION = "$first"; - - /** - * Projection type push used in mongo aggregations. - */ - public static final String PUSH_PROJECTION = "$push"; - - /** - * Grouping type sum used in mongo aggregations. + * Field name for policy read revokes. */ - public static final String SUM_GROUPING = "$sum"; + public static final String FIELD_REVOKED = "r"; /** - * Field holding the count for things within a mongodb aggregation. + * Mark a document for deletion. */ - public static final String COUNT_RESULT_NAME = "thingsCount"; - public static final String SET = "$set"; - public static final String UNSET = "$unset"; - public static final String PUSH = "$push"; - public static final String PULL = "$pull"; - public static final String EACH = "$each"; - public static final String REGEX = "$regex"; - public static final String EXISTS = "$exists"; - public static final String CONCAT = "$concat"; - public static final String DOT = "."; - public static final String REGEX_FIELD_END = "(/|\\z)"; - public static final String REGEX_FIELD_START = "^"; - public static final String REGEX_START_THING_ID = "^(?i)"; + public static final String FIELD_DELETE_AT = "deleteAt"; private PersistenceConstants() { } diff --git a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/AttributesDocumentBuilder.java b/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/AttributesDocumentBuilder.java deleted file mode 100644 index 6c2a565da6..0000000000 --- a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/AttributesDocumentBuilder.java +++ /dev/null @@ -1,153 +0,0 @@ -/* - * 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.services.thingsearch.persistence.mapping; - -import static org.eclipse.ditto.model.base.common.ConditionChecker.argumentNotNull; - -import java.util.ArrayList; -import java.util.List; - -import org.bson.Document; -import org.eclipse.ditto.json.JsonValue; -import org.eclipse.ditto.model.things.Attributes; -import org.eclipse.ditto.services.thingsearch.common.util.KeyEscapeUtil; -import org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants; - -/** - * Builder for attributes. - */ -final class AttributesDocumentBuilder { - - private final Document tDocument; - - private AttributesDocumentBuilder() { - tDocument = new Document(); - tDocument.append(PersistenceConstants.FIELD_INTERNAL, new ArrayList()); - tDocument.append(PersistenceConstants.FIELD_ATTRIBUTES, ThingDocumentMapper.newDocument()); - } - - /** - * Create a new ThingDocumentBuilder. - * - * @return AttributesDocumentBuilder - */ - public static AttributesDocumentBuilder create() { - return new AttributesDocumentBuilder(); - } - - /** - * Adds a map of attributes. - * - * @param attributes the attributes to add - * @return AttributesDocumentBuilder - * @throws NullPointerException if {@code attributes} is {@code null}. - */ - public AttributesDocumentBuilder attributes(final Attributes attributes) { - argumentNotNull(attributes); - - attributes.getKeys().forEach(key -> { - final Object val = attributes.getValue(key).map(ThingDocumentMapper::toValue).orElse(null); - mainAttribute(key.toString(), val); - addInternalAttributes(key.toString(), attributes.getValue(key).orElse(null)); - }); - - return this; - } - - /** - * Adds an attribute. - * - * @param key the key - * @param value the value - * @return AttributesDocumentBuilder - */ - public AttributesDocumentBuilder attribute(final String key, final String value) { - mainAttribute(key, value); - return attributeInternally(key, value); - } - - /** - * Adds an attribute. - * - * @param key the key - * @param value the value - * @return AttributesDocumentBuilder - */ - public AttributesDocumentBuilder attribute(final String key, final Number value) { - mainAttribute(key, value); - return attributeInternally(key, value); - } - - /** - * Adds an attribute. - * - * @param key the key - * @param value the value - * @return AttributesDocumentBuilder - */ - public AttributesDocumentBuilder attribute(final String key, final Boolean value) { - mainAttribute(key, value); - return attributeInternally(key, value); - } - - /** - * Returns the built document. - * - * @return the document - */ - public Document build() { - return tDocument; - } - - private AttributesDocumentBuilder attributeInternally(final String key, final Object value) { - // add attribute to flat representation - final List attributesList = ThingDocumentMapper.toList(tDocument, PersistenceConstants.FIELD_INTERNAL); - final Document doc = ThingDocumentMapper.newDocument(); - doc.append( - PersistenceConstants.FIELD_INTERNAL_KEY, PersistenceConstants.FIELD_ATTRIBUTE_PREFIX_WITH_ENDING_SLASH + key); - doc.append(PersistenceConstants.FIELD_INTERNAL_VALUE, value); - attributesList.add(doc); - - return this; - } - - private AttributesDocumentBuilder mainAttribute(final String key, final Object value) { - final Document doc = (Document) tDocument.get(PersistenceConstants.FIELD_ATTRIBUTES); - doc.append(KeyEscapeUtil.escape(key), value); - return this; - } - - private void addInternalAttributes(final String path, final JsonValue jsonValue) { - if (jsonValue == null || jsonValue.isNull()) { - attributeInternally(path, null); - } else if (jsonValue.isString()) { - attributeInternally(path, jsonValue.asString()); - } else if (jsonValue.isBoolean()) { - attributeInternally(path, jsonValue.asBoolean()); - } else if (jsonValue.isNumber()) { - addNumberAttribute(path, jsonValue); - } else if (jsonValue.isObject()) { - jsonValue.asObject().getKeys().forEach(key -> // - addInternalAttributes(path + PersistenceConstants.SLASH + key, jsonValue.asObject().getValue(key).orElse(null))); - } - } - - private void addNumberAttribute(final String path, final JsonValue jsonValue) { - if (jsonValue.isLong()) { - attributeInternally(path, jsonValue.asLong()); - } else { - attributeInternally(path, jsonValue.asDouble()); - } - } - -} diff --git a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/FeaturesDocumentBuilder.java b/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/FeaturesDocumentBuilder.java deleted file mode 100644 index 2a8fd883f5..0000000000 --- a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/FeaturesDocumentBuilder.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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.services.thingsearch.persistence.mapping; - -import java.util.ArrayList; -import java.util.List; - -import org.bson.Document; -import org.eclipse.ditto.json.JsonValue; -import org.eclipse.ditto.model.things.Features; -import org.eclipse.ditto.services.thingsearch.common.util.KeyEscapeUtil; -import org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants; - -/** - * Features document builder. - */ -final class FeaturesDocumentBuilder { - - private final Document tDocument; - - private FeaturesDocumentBuilder() { - tDocument = new Document(); - tDocument.append(PersistenceConstants.FIELD_INTERNAL, new ArrayList()); - tDocument.append(PersistenceConstants.FIELD_FEATURES, ThingDocumentMapper.newDocument()); - } - - /** - * Creates a new builder. - * - * @return the builder - */ - public static FeaturesDocumentBuilder create() { - return new FeaturesDocumentBuilder(); - } - - /** - * Adds features. - * - * @param features the attributes to add - * @return FeaturesDocumentBuilder - * @throws NullPointerException if {@code features} is {@code null}. - */ - public FeaturesDocumentBuilder features(final Features features) { - features.forEach(feature -> { - feature.getProperties().ifPresent(featureProperties -> featureProperties.forEach(field -> { - final Object value = ThingDocumentMapper.toValue(field.getValue()); - mainFeatureProperties(field.getKeyName(), value, feature.getId()); - addInternalFeatures(field.getKeyName(), field.getValue(), feature.getId()); - })); - addDefaultFeatureEntry(feature.getId()); - }); - - return this; - } - - /** - * Returns the built document. - * - * @return the document - */ - public Document build() { - return tDocument; - } - - private void addDefaultFeatureEntry(final String id) { - final List internalAttributes = ThingDocumentMapper.toList(tDocument, PersistenceConstants.FIELD_INTERNAL); - internalAttributes.add(new Document(PersistenceConstants.FIELD_INTERNAL_FEATURE_ID, id)); - } - - private FeaturesDocumentBuilder mainFeatureProperties(final String key, final Object value, - final String featureId) { - - final Document doc = (Document) tDocument.get(PersistenceConstants.FIELD_FEATURES); - final Document featurePropertiesDoc = getSubDocument(doc, featureId); - featurePropertiesDoc.append(KeyEscapeUtil.escape(key), value); - return this; - } - - private static Document getSubDocument(final Document doc, final String featureId) { - final String featureKey = KeyEscapeUtil.escape(featureId); - if (doc.get(featureId) == null) { - doc.put(featureKey, newFeaturePropertiesDocument()); - } - return (Document) ((Document) doc.get(featureKey)).get(PersistenceConstants.FIELD_PROPERTIES); - } - - private static Document newFeaturePropertiesDocument() { - return new Document(PersistenceConstants.FIELD_PROPERTIES, ThingDocumentMapper.newDocument()); - } - - private void addInternalFeatures(final String path, final JsonValue jsonValue, final String featureId) { - if ((jsonValue == null) || jsonValue.isNull()) { - featureInternally(path, null, featureId); - } else if (jsonValue.isString()) { - featureInternally(path, jsonValue.asString(), featureId); - } else if (jsonValue.isBoolean()) { - featureInternally(path, jsonValue.asBoolean(), featureId); - } else if (jsonValue.isNumber()) { - addNumberFeature(path, jsonValue, featureId); - } else if (jsonValue.isObject()) { - jsonValue.asObject().getKeys().forEach(name -> // - addInternalFeatures(path + "/" + name, jsonValue.asObject().getValue(name).orElse(null), - featureId)); - } - } - - private void addNumberFeature(final String path, final JsonValue jsonValue, final String featureId) { - if (jsonValue.isLong()) { - featureInternally(path, jsonValue.asLong(), featureId); - } else { - featureInternally(path, jsonValue.asDouble(), featureId); - } - } - - private void featureInternally(final String key, final Object value, final String featureId) { - // add attribute to flat representation - final List attributes1 = ThingDocumentMapper.toList(tDocument, PersistenceConstants.FIELD_INTERNAL); - final Document doc = ThingDocumentMapper.newDocument(); - doc.append(PersistenceConstants.FIELD_INTERNAL_KEY, - PersistenceConstants.FIELD_FEATURE_PROPERTIES_PREFIX + PersistenceConstants.SLASH + key); - doc.append(PersistenceConstants.FIELD_INTERNAL_VALUE, value); - doc.append(PersistenceConstants.FIELD_INTERNAL_FEATURE_ID, featureId); - attributes1.add(doc); - } - -} diff --git a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/ThingDocumentBuilder.java b/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/ThingDocumentBuilder.java deleted file mode 100644 index 74a650242c..0000000000 --- a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/ThingDocumentBuilder.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * 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.services.thingsearch.persistence.mapping; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.bson.Document; -import org.eclipse.ditto.model.base.auth.AuthorizationSubject; -import org.eclipse.ditto.model.things.AccessControlList; -import org.eclipse.ditto.model.things.AclEntry; -import org.eclipse.ditto.model.things.Attributes; -import org.eclipse.ditto.model.things.Features; -import org.eclipse.ditto.model.things.Permission; -import org.eclipse.ditto.services.thingsearch.persistence.PersistenceConstants; - - -/** - * Builder to create Thing {@link Document}s which are saved into the mongoDB search collection. - */ -final class ThingDocumentBuilder { - - private final Document tDocument; - private final AttributesDocumentBuilder attributesBuilder; - private final FeaturesDocumentBuilder featuresdocumentBuilder; - private final List aclEntries; - - private ThingDocumentBuilder(final String thingId, final String namespace, final String policyId) { - tDocument = new Document(); - tDocument.append(PersistenceConstants.FIELD_ID, thingId); - tDocument.append(PersistenceConstants.FIELD_NAMESPACE, namespace); - tDocument.append(PersistenceConstants.FIELD_POLICY_ID, policyId); - aclEntries = new ArrayList<>(); - attributesBuilder = AttributesDocumentBuilder.create(); - featuresdocumentBuilder = FeaturesDocumentBuilder.create(); - } - - /** - * Create a new ThingDocumentBuilder. - * - * @param thingId the ID of the thing. - * @return the same instance of this builder to allow method chaining. - */ - public static ThingDocumentBuilder create(final String thingId) { - String namespace = ""; - if (thingId.contains(":")) { - namespace = thingId.substring(0, thingId.indexOf(':')); - } - return new ThingDocumentBuilder(thingId, namespace, null); - } - - /** - * Create a new ThingDocumentBuilder. - * - * @param thingId the ID of the thing. - * @param policyId the policy ID of the thing. - * @return the same instance of this builder to allow method chaining. - */ - public static ThingDocumentBuilder create(final String thingId, final String policyId) { - String namespace = ""; - if (thingId.contains(":")) { - namespace = thingId.substring(0, thingId.indexOf(':')); - } - return new ThingDocumentBuilder(thingId, namespace, policyId); - } - - /** - * Adds a map of attributes. - * - * @param attributes the attributes to add. - * @return the same instance of this builder to allow method chaining. - * @throws NullPointerException if {@code attributes} is {@code null}. - */ - public ThingDocumentBuilder attributes(final Attributes attributes) { - attributesBuilder.attributes(attributes); - return this; - } - - /** - * Adds the given features. - * - * @param features the features to add. - * @return the same instance of this builder to allow method chaining. - * @throws NullPointerException if {@code features} is {@code null}. - */ - public ThingDocumentBuilder features(final Features features) { - featuresdocumentBuilder.features(features); - return this; - } - - /** - * Adds an attribute. - * - * @param key the key of the attribute to add. - * @param value the value of the attribute to add. - * @return the same instance of this builder to allow method chaining. - */ - public ThingDocumentBuilder attribute(final String key, final String value) { - attributesBuilder.attribute(key, value); - return this; - } - - /** - * Adds an attribute. - * - * @param key the key of the attribute to add. - * @param value the value of the attribute to add. - * @return the same instance of this builder to allow method chaining. - */ - public ThingDocumentBuilder attribute(final String key, final Number value) { - attributesBuilder.attribute(key, value); - return this; - } - - /** - * Adds an attribute. - * - * @param key the key of the attribute to add. - * @param value the value of the attribute to add. - * @return the same instance of this builder to allow method chaining. - */ - public ThingDocumentBuilder attribute(final String key, final Boolean value) { - attributesBuilder.attribute(key, value); - return this; - } - - /** - * Adds an ACL entry. - * - * @param sid the sid for the entry. - * @return the same instance of this builder to allow method chaining. - */ - public ThingDocumentBuilder aclReadEntry(final String sid) { - aclEntries.add(new Document(PersistenceConstants.FIELD_ACL, sid)); - return this; - } - - /** - * Adds all sids which do have READ permission. - * - * @param acl the whole access control list. - * @return the same instance of this builder to allow method chaining. - */ - public ThingDocumentBuilder acl(final AccessControlList acl) { - acl.getEntriesSet() - .stream() - .filter(entry -> entry.contains(Permission.READ)) - .map(AclEntry::getAuthorizationSubject) - .map(AuthorizationSubject::getId) - .forEach(this::aclReadEntry); - return this; - } - - /** - * Returns the built document. - * - * @return the document. - */ - @SuppressWarnings("unchecked") - public Document build() { - final Document attributes = attributesBuilder.build(); - final Document features = featuresdocumentBuilder.build(); - final Collection internal = (Collection) attributes.get(PersistenceConstants.FIELD_INTERNAL); - addAclEntries(internal); - addFeatureEntries(internal, (Collection) features.get(PersistenceConstants.FIELD_INTERNAL)); - tDocument.append(PersistenceConstants.FIELD_INTERNAL, internal); - tDocument.append(PersistenceConstants.FIELD_ATTRIBUTES, attributes.get(PersistenceConstants.FIELD_ATTRIBUTES)); - tDocument.append(PersistenceConstants.FIELD_FEATURES, features.get(PersistenceConstants.FIELD_FEATURES)); - return tDocument; - } - - private static void addFeatureEntries(final Collection internalList, - final Collection featureList) { - internalList.addAll(featureList); - } - - private void addAclEntries(final Collection internal) { - if (!aclEntries.isEmpty()) { - internal.addAll(aclEntries); - } - } - -} diff --git a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/ThingDocumentMapper.java b/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/ThingDocumentMapper.java deleted file mode 100644 index 4396e646ca..0000000000 --- a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/mapping/ThingDocumentMapper.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * 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.services.thingsearch.persistence.mapping; - -import java.util.ArrayList; -import java.util.List; - -import org.bson.Document; -import org.eclipse.ditto.json.JsonField; -import org.eclipse.ditto.json.JsonValue; -import org.eclipse.ditto.model.things.Thing; -import org.eclipse.ditto.services.thingsearch.common.util.KeyEscapeUtil; - -/** - * A mapper for {@link Document} instance to a {@link Thing} and vice versa. - */ -public final class ThingDocumentMapper { - - private ThingDocumentMapper() { - throw new AssertionError(); - } - - /** - * Returns a new {@code Document}. - * - * @return the Document. - */ - static Document newDocument() { - return new Document(); - } - - public static List toList(final Document document, final String name) { - @SuppressWarnings("unchecked") List entries = (List) document.get(name); - - if (entries == null) { - entries = new ArrayList<>(); - document.append(name, entries); - } - - return entries; - } - - /** - * Maps a {@link Thing} to a document. - * - * @param thing the thing to map - * @return the mapped document - */ - public static Document toDocument(final Thing thing) { - final String thingId = thing.getId().orElseThrow(() -> new NullPointerException("Thing has no ID!")); - final ThingDocumentBuilder builder = ThingDocumentBuilder.create(thingId, thing.getPolicyId() - .orElse(null)); - - thing.getAccessControlList().ifPresent(builder::acl); - thing.getAttributes().ifPresent(builder::attributes); - thing.getFeatures().ifPresent(builder::features); - - return builder.build(); - } - - /** - * Maps the given {@code jsonValue} to it's equivalent Java type. A {@code JsonObject} will be mapped to {@code - * Document}. - * - * @param jsonValue the JSON value. - * @return the value. - */ - public static Object toValue(final JsonValue jsonValue) { - final Object value; - - if (jsonValue.isNull()) { - value = null; - } else if (jsonValue.isString()) { - value = jsonValue.asString(); - } else if (jsonValue.isBoolean()) { - value = jsonValue.asBoolean(); - } else if (jsonValue.isNumber()) { - value = handleNumberAttribute(jsonValue); - } else if (jsonValue.isObject()) { - value = objectToDocument(jsonValue.asObject()); - } else { - value = null; - } - - return value; - } - - private static Document objectToDocument(final Iterable jsonObject) { - final Document subDocument = new Document(); - jsonObject.forEach(field -> { - final String key = KeyEscapeUtil.escape(field.getKeyName()); - final Object value = toValue(field.getValue()); - subDocument.append(key, value); - }); - return subDocument; - } - - private static Object handleNumberAttribute(final JsonValue jsonValue) { - final Number result; - - if (jsonValue.isInt()) { - result = jsonValue.asInt(); - } else if (jsonValue.isLong()) { - result = jsonValue.asLong(); - } else { - result = jsonValue.asDouble(); - } - - return result; - } - -} diff --git a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/query/AggregationParameterOptionVisitor.java b/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/query/AggregationParameterOptionVisitor.java deleted file mode 100644 index 7d85df5dbc..0000000000 --- a/services/thingsearch/persistence/src/main/java/org/eclipse/ditto/services/thingsearch/persistence/query/AggregationParameterOptionVisitor.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * 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.services.thingsearch.persistence.query; - -import static java.util.Objects.requireNonNull; -import static org.eclipse.ditto.model.base.common.ConditionChecker.checkNotNull; - -import java.util.List; -import java.util.stream.Collectors; - -import org.eclipse.ditto.model.query.SortDirection; -import org.eclipse.ditto.model.query.SortOption; -import org.eclipse.ditto.model.query.expression.FieldExpressionFactory; -import org.eclipse.ditto.model.query.expression.SortFieldExpression; -import org.eclipse.ditto.model.thingsearch.LimitOption; -import org.eclipse.ditto.model.thingsearch.Option; -import org.eclipse.ditto.model.thingsearch.OptionVisitor; -import org.eclipse.ditto.model.thingsearch.SortOptionEntry; -import org.eclipse.ditto.services.thingsearch.persistence.read.AggregationBuilder; -import org.eclipse.ditto.utils.jsr305.annotations.AllValuesAreNonnullByDefault; - -/** - * OptionVisitor for the parsed parameters. Goes through the list of option parameters and creates the persistence - * specific output out of them. - */ -@AllValuesAreNonnullByDefault -public final class AggregationParameterOptionVisitor implements OptionVisitor { - - private final AggregationBuilder aggregationBuilder; - private final FieldExpressionFactory fieldExpressionFactory; - - /** - * @param fieldExpressionFactory the FieldExpressionFactory. - * @param aggregationBuilder the query builder to be used. - */ - public AggregationParameterOptionVisitor(final FieldExpressionFactory fieldExpressionFactory, - final AggregationBuilder aggregationBuilder) { - this.fieldExpressionFactory = requireNonNull(fieldExpressionFactory); - this.aggregationBuilder = requireNonNull(aggregationBuilder); - } - - /** - * Given a list of options, calls the visit method on every option with this visitor instance. - * - * @param options the list of options. - * @return the visitor for chaining. - * @throws NullPointerException if {@code options} is {@code null}. - */ - public AggregationParameterOptionVisitor visitAll(final List