T getValue() {
return (T) value;
}
+
+ /**
+ * Returns whether the current keyword indicates a {@literal $jsonSchema} object.
+ *
+ * @return {@literal true} if {@code key} equals {@literal $jsonSchema}.
+ * @since 2.1
+ */
+ public boolean isJsonSchema() {
+ return "$jsonSchema".equalsIgnoreCase(key);
+ }
}
/**
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java
index 650d185025..df83362859 100644
--- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java
@@ -24,6 +24,7 @@
import java.util.List;
import java.util.Map.Entry;
import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import org.bson.BSON;
import org.bson.BsonRegularExpression;
@@ -35,6 +36,9 @@
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
import org.springframework.data.mongodb.core.geo.GeoJson;
import org.springframework.data.mongodb.core.geo.Sphere;
+import org.springframework.data.mongodb.core.schema.JsonSchemaObject.Type;
+import org.springframework.data.mongodb.core.schema.JsonSchemaProperty;
+import org.springframework.data.mongodb.core.schema.MongoJsonSchema;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
@@ -115,6 +119,20 @@ public static Criteria byExample(Example> example) {
return new Criteria().alike(example);
}
+ /**
+ * Static factory method to create a {@link Criteria} matching documents against a given structure defined by the
+ * {@link MongoJsonSchema} using ({@code $jsonSchema}) operator.
+ *
+ * @param schema must not be {@literal null}.
+ * @return this
+ * @since 2.1
+ * @see MongoDB Query operator:
+ * $jsonSchema
+ */
+ public static Criteria matchingDocumentStructure(MongoJsonSchema schema) {
+ return new Criteria().andDocumentStructureMatches(schema);
+ }
+
/**
* Static factory method to create a Criteria using the provided key
*
@@ -335,6 +353,23 @@ public Criteria type(int t) {
return this;
}
+ /**
+ * Creates a criterion using the {@literal $type} operator.
+ *
+ * @param type must not be {@literal null}.
+ * @return this
+ * @since 2.1
+ * @see MongoDB Query operator: $type
+ */
+ public Criteria type(Type... types) {
+
+ Assert.notNull(types, "Types must not be null!");
+ Assert.noNullElements(types, "Types must not contain null.");
+
+ criteria.put("$type", Arrays.asList(types).stream().map(Type::value).collect(Collectors.toList()));
+ return this;
+ }
+
/**
* Creates a criterion using the {@literal $not} meta operator which affects the clause directly following
*
@@ -563,6 +598,30 @@ public Criteria alike(Example> sample) {
return this;
}
+ /**
+ * Creates a criterion ({@code $jsonSchema}) matching documents against a given structure defined by the
+ * {@link MongoJsonSchema}.
+ * NOTE: {@code $jsonSchema} cannot be used on field/property level but defines the whole document
+ * structure. Please use
+ * {@link org.springframework.data.mongodb.core.schema.MongoJsonSchema.MongoJsonSchemaBuilder#properties(JsonSchemaProperty...)}
+ * to specify nested fields or query them using the {@link #type(Type...) $type} operator.
+ *
+ * @param schema must not be {@literal null}.
+ * @return this
+ * @since 2.1
+ * @see MongoDB Query operator:
+ * $jsonSchema
+ */
+ public Criteria andDocumentStructureMatches(MongoJsonSchema schema) {
+
+ Assert.notNull(schema, "Schema must not be null!");
+
+ Criteria schemaCriteria = new Criteria();
+ schemaCriteria.criteria.putAll(schema.toDocument());
+
+ return registerCriteriaChainElement(schemaCriteria);
+ }
+
/**
* Creates an 'or' criteria using the $or operator for all of the provided criteria
*
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java
new file mode 100644
index 0000000000..07aed09173
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DefaultMongoJsonSchema.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mongodb.core.schema;
+
+import lombok.AllArgsConstructor;
+import lombok.NonNull;
+
+import org.bson.Document;
+
+/**
+ * Value object representing a MongoDB-specific JSON schema which is the default {@link MongoJsonSchema} implementation.
+ *
+ * @author Christoph Strobl
+ * @author Mark Paluch
+ * @since 2.1
+ */
+@AllArgsConstructor
+class DefaultMongoJsonSchema implements MongoJsonSchema {
+
+ private final @NonNull JsonSchemaObject root;
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.mongodb.core.schema.MongoJsonSchema#toDocument()
+ */
+ @Override
+ public Document toDocument() {
+ return new Document("$jsonSchema", root.toDocument());
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java
new file mode 100644
index 0000000000..ee1299543e
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/DocumentJsonSchema.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mongodb.core.schema;
+
+import lombok.AllArgsConstructor;
+import lombok.NonNull;
+
+import org.bson.Document;
+
+/**
+ * JSON schema backed by a {@link org.bson.Document} object.
+ *
+ * @author Mark Paluch
+ * @since 2.1
+ */
+@AllArgsConstructor
+class DocumentJsonSchema implements MongoJsonSchema {
+
+ private final @NonNull Document document;
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.mongodb.core.schema.MongoJsonSchema#toDocument()
+ */
+ @Override
+ public Document toDocument() {
+ return new Document("$jsonSchema", new Document(document));
+ }
+}
diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java
new file mode 100644
index 0000000000..0fc95ee098
--- /dev/null
+++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/schema/IdentifiableJsonSchemaProperty.java
@@ -0,0 +1,930 @@
+/*
+ * Copyright 2018 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springframework.data.mongodb.core.schema;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.bson.Document;
+import org.springframework.data.domain.Range;
+import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.ArrayJsonSchemaObject;
+import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.BooleanJsonSchemaObject;
+import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.NullJsonSchemaObject;
+import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.NumericJsonSchemaObject;
+import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.ObjectJsonSchemaObject;
+import org.springframework.data.mongodb.core.schema.TypedJsonSchemaObject.StringJsonSchemaObject;
+import org.springframework.util.Assert;
+
+/**
+ * {@link JsonSchemaProperty} implementation.
+ *
+ * @author Christoph Strobl
+ * @author Mark Paluch
+ * @since 2.1
+ */
+public class IdentifiableJsonSchemaProperty implements JsonSchemaProperty {
+
+ protected final String identifier;
+ protected final T jsonSchemaObjectDelegate;
+
+ /**
+ * Creates a new {@link IdentifiableJsonSchemaProperty} for {@code identifier} and {@code jsonSchemaObject}.
+ *
+ * @param identifier must not be {@literal null}.
+ * @param jsonSchemaObject must not be {@literal null}.
+ */
+ IdentifiableJsonSchemaProperty(String identifier, T jsonSchemaObject) {
+
+ Assert.notNull(identifier, "Identifier must not be null!");
+ Assert.notNull(jsonSchemaObject, "JsonSchemaObject must not be null!");
+
+ this.identifier = identifier;
+ this.jsonSchemaObjectDelegate = jsonSchemaObject;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.mongodb.core.schema.JsonSchemaProperty#getIdentifier()
+ */
+ @Override
+ public String getIdentifier() {
+ return identifier;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.mongodb.core.schema.JsonSchemaObject#toDocument()
+ */
+ @Override
+ public Document toDocument() {
+ return new Document(identifier, jsonSchemaObjectDelegate.toDocument());
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.springframework.data.mongodb.core.schema.JsonSchemaObject#getTypes()
+ */
+ @Override
+ public Set getTypes() {
+ return jsonSchemaObjectDelegate.getTypes();
+ }
+
+ /**
+ * Convenience {@link JsonSchemaProperty} implementation without a {@code type} property.
+ *
+ * @author Christoph Strobl
+ * @since 2.1
+ */
+ public static class UntypedJsonSchemaProperty extends IdentifiableJsonSchemaProperty {
+
+ UntypedJsonSchemaProperty(String identifier, UntypedJsonSchemaObject jsonSchemaObject) {
+ super(identifier, jsonSchemaObject);
+ }
+
+ /**
+ * @param possibleValues must not be {@literal null}.
+ * @return new instance of {@link StringJsonSchemaProperty}.
+ * @see StringJsonSchemaObject#possibleValues(Collection)
+ */
+ public UntypedJsonSchemaProperty possibleValues(Object... possibleValues) {
+ return possibleValues(Arrays.asList(possibleValues));
+ }
+
+ /**
+ * @param allOf must not be {@literal null}.
+ * @return new instance of {@link StringJsonSchemaProperty}.
+ * @see StringJsonSchemaObject#allOf(Collection)
+ */
+ public UntypedJsonSchemaProperty allOf(JsonSchemaObject... allOf) {
+ return allOf(new LinkedHashSet<>(Arrays.asList(allOf)));
+ }
+
+ /**
+ * @param anyOf must not be {@literal null}.
+ * @return new instance of {@link StringJsonSchemaProperty}.
+ * @see StringJsonSchemaObject#anyOf(Collection)
+ */
+ public UntypedJsonSchemaProperty anyOf(JsonSchemaObject... anyOf) {
+ return anyOf(new LinkedHashSet<>(Arrays.asList(anyOf)));
+ }
+
+ /**
+ * @param oneOf must not be {@literal null}.
+ * @return new instance of {@link StringJsonSchemaProperty}.
+ * @see StringJsonSchemaObject#oneOf(Collection)
+ */
+ public UntypedJsonSchemaProperty oneOf(JsonSchemaObject... oneOf) {
+ return oneOf(new LinkedHashSet<>(Arrays.asList(oneOf)));
+ }
+
+ /**
+ * @param possibleValues must not be {@literal null}.
+ * @return new instance of {@link StringJsonSchemaProperty}.
+ * @see StringJsonSchemaObject#possibleValues(Collection)
+ */
+ public UntypedJsonSchemaProperty possibleValues(Collection