findSortedByQuery(String query, String sort, Object... params) {
+ return this.dataAccess.findSortedByQuery(query, sort, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
+ * rename or filter fields in the result elements. Instead of returning typed objects it returns objects of type
+ * as
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param projection the projection of fields to use
+ * @param as the target to convert result elements to
+ * @param params the parameters to replace # symbols
+ * @param the element type
+ * @return the list of elements found
+ */
+ protected final
List
findSortedByQuery(String query, String sort, String projection, Class
as, Object... params) {
+ return this.dataAccess.findSortedByQuery(query, sort, projection, as, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
+ * rename or filter fields in the result elements. Instead of returning typed objects it returns objects converted
+ * by the given {@link ResultHandler}
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param projection the projection of fields to use
+ * @param handler the handler to convert result elements with
+ * @param params the parameters to replace # symbols
+ * @param
the element type
+ * @return the list of elements found
+ */
+ protected final
List
findSortedByQuery(String query, String sort, String projection, ResultHandler
handler, Object... params) {
+ return this.dataAccess.findSortedByQuery(query, sort, projection, handler, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
+ * @param params the parameters to replace # symbols
+ * @return the list of elements found
+ */
+ protected final List findSortedByQuery(String query, String sort, Integer skip, Integer limit, Object... params) {
+ return this.dataAccess.findSortedByQuery(query, sort, skip, limit, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
+ * rename or filter fields in the result elements. Instead of returning typed objects it returns objects of type
+ * as
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
+ * @param projection the projection of fields to use
+ * @param as the target to convert result elements to
+ * @param params the parameters to replace # symbols
+ * @param the element type
+ * @return the list of elements found
+ */
+ protected final
List
findSortedByQuery(String query, String sort, Integer skip, Integer limit, String projection, Class
as, Object... params) {
+ return this.dataAccess.findSortedByQuery(query, sort, skip, limit, projection, as, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
+ * rename or filter fields in the result elements. Instead of returning typed objects it returns objects converted
+ * by the given {@link ResultHandler}
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
+ * @param projection the projection of fields to use
+ * @param handler the handler to convert result elements with
+ * @param params the parameters to replace # symbols
+ * @param
the element type
+ * @return the list of elements found
+ */
+ protected final
List
findSortedByQuery(String query, String sort, Integer skip, Integer limit, String projection, ResultHandler
handler, Object... params) {
+ return this.dataAccess.findSortedByQuery(query, sort, skip, limit, projection, handler, params);
+ }
+
+ /**
+ * finds all elements containing the given searchString in any text field and sorts them accordingly.
+ *
+ * @param searchString the searchString to search for
+ * @param sort the sort query to apply
+ * @return the list of elements found
+ */
+ protected final List searchSorted(String searchString, String sort) {
+ return this.dataAccess.searchSorted(searchString, sort);
+ }
+
+ /**
+ * queries with the given string, sorts the result and returns the first element. null
is returned if no element is found.
+ *
+ * @param query the query string
+ * @param sort the sort string
+ * @param params the parameters to replace # symbols
+ * @return the first element found or null
if none is found
+ */
+ protected final T findFirstByQuery(String query, String sort, Object... params) {
+ return this.dataAccess.findFirstByQuery(query, sort, params).orElse(null);
+ }
+
+ @Override
+ public final T findById(String id) {
+ return this.dataAccess.findByObjectId(id).orElse(null);
+ }
+
+ @Override
+ public final T save(T object) {
+ this.beforeSave(object);
+ T saved = this.dataAccess.save(object);
+ this.afterSave(saved);
+ return saved;
+ }
+
+ /**
+ * override this to do something after the object was saved
+ *
+ * @param object the saved object
+ */
+ @SuppressWarnings("unused")
+ protected void afterSave(T object) {
+ //
+ }
+
+ /**
+ * override this to do something before the object was saved
+ *
+ * @param object the object to be saved
+ */
+ @SuppressWarnings("unused")
+ protected void beforeSave(T object) {
+ //
+ }
+
+ @Override
+ public final void delete(T object) {
+ this.delete(object.getId());
+ }
+
+ @Override
+ public final void delete(String id) {
+ this.beforeDelete(id);
+ this.dataAccess.deleteByObjectId(id);
+ this.afterDelete(id);
+ }
+
+ @SuppressWarnings("unused")
+ protected void beforeDelete(String id) {
+ //
+ }
+
+ @SuppressWarnings("unused")
+ protected void afterDelete(String id) {
+ //
+ }
+
+ protected GridFSBucket getGridFSBucket(String bucket) {
+ return this.dataAccess.getGridFSBucket(bucket);
+ }
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ChangelogUtil.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ChangelogUtil.java
new file mode 100644
index 00000000..46abc789
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ChangelogUtil.java
@@ -0,0 +1,76 @@
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBCollection;
+
+/**
+ * Copyright 2015 Hoegernet
+ *
+ * Utils for changelog creation
+ *
+ * @author Thorsten Hoeger
+ */
+public final class ChangelogUtil {
+
+ private ChangelogUtil() {
+ // private utility class constructor
+ }
+
+ /**
+ * adds a TTL index to the given collection. The TTL must be a positive integer.
+ *
+ * @param collection the collection to use for the TTL index
+ * @param field the field to use for the TTL index
+ * @param ttl the TTL to set on the given field
+ * @throws IllegalArgumentException if the TTL is less or equal 0
+ */
+ public static void addTTLIndex(DBCollection collection, String field, int ttl) {
+ if (ttl <= 0) {
+ throw new IllegalArgumentException("TTL must be positive");
+ }
+ collection.createIndex(new BasicDBObject(field, 1), new BasicDBObject("expireAfterSeconds", ttl));
+ }
+
+ /**
+ * Add an index on the given collection and field
+ *
+ * @param collection the collection to use for the index
+ * @param field the field to use for the index
+ * @param asc the sorting direction. true
to sort ascending; false
to sort descending
+ * @param background iff true
the index is created in the background
+ */
+ public static void addIndex(DBCollection collection, String field, boolean asc, boolean background) {
+ int dir = (asc) ? 1 : -1;
+ collection.createIndex(new BasicDBObject(field, dir), new BasicDBObject("background", background));
+ }
+
+ /**
+ * Add a text index on the given collection
+ *
+ * @param collection the collection to use for the index
+ */
+ public static void addTextIndex(DBCollection collection) {
+ collection.createIndex(new BasicDBObject("$**", "text"));
+ }
+
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/ConverterIterable.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ConverterIterable.java
similarity index 100%
rename from mongodb/src/main/java/de/taimos/dvalin/mongo/ConverterIterable.java
rename to mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ConverterIterable.java
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ICrudAuditedDAO.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ICrudAuditedDAO.java
new file mode 100644
index 00000000..e54d264a
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ICrudAuditedDAO.java
@@ -0,0 +1,48 @@
+package de.taimos.dvalin.mongo;
+
+/*-
+ * #%L
+ * MongoDB support for dvalin
+ * %%
+ * Copyright (C) 2015 - 2017 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import java.util.List;
+
+/**
+ * Copyright 2015 Cinovo AG
+ *
+ *
+ * @author psigloch
+ *
+ * @param an {@link AEntity}
+ */
+public interface ICrudAuditedDAO extends ICrudDAO {
+
+ /**
+ * @param id the id of the document to get the history elements for
+ * @return the history elements for a document
+ */
+ public List findHistoryElements(String id);
+
+ /**
+ * @param id the id of the document to get the element for
+ * @param version the version of the document to get
+ * @return the correct version of a document
+ */
+ public E findVersion(String id, Integer version);
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ICrudDAO.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ICrudDAO.java
new file mode 100644
index 00000000..52f9b1d9
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/ICrudDAO.java
@@ -0,0 +1,80 @@
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import java.util.List;
+
+/**
+ * Copyright 2015 Hoegernet
+ *
+ * DAO with default CRUD operations
+ *
+ * @param type of the managed {@link AEntity}
+ * @author Thorsten Hoeger
+ */
+public interface ICrudDAO {
+
+ /**
+ * find the element with the given id
+ *
+ * @param id the id to find
+ * @return the obejct with the given id or null
if no element exists with this id
+ */
+ T findById(String id);
+
+ /**
+ * saves the given element
+ *
+ * @param object the element to save
+ * @return the saved element
+ */
+ T save(T object);
+
+ /**
+ * deletes the given object using its id.
+ *
+ * @param object the object to delete
+ */
+ void delete(T object);
+
+ /**
+ * deletes the given object using its id.
+ *
+ * @param id the id of the object to delete
+ */
+ void delete(String id);
+
+ /**
+ * @return a list of all elements in this collection
+ */
+ List findList();
+
+ /**
+ * @param sortProp the sort parameter
+ * @param sortDirection the sort direction
+ * @param limit the limit
+ * @param skip the number of documents to skip
+ * @return list of sorted stored contracts
+ */
+ List findList(String sortProp, Integer sortDirection, Integer limit, Integer skip);
+
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/IMappedSupertype.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/IMappedSupertype.java
new file mode 100644
index 00000000..b4547f1f
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/IMappedSupertype.java
@@ -0,0 +1,36 @@
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+/**
+ * Copyright 2015 Hoegernet
+ *
+ * denotes that the class is used as a superclass meant to be sub-classes. It advises Jongo to include type information into the JSON string
+ * into the field @class
to allow deserialization into the correct Java class
+ *
+ * @author Thorsten Hoeger
+ */
+@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY, property = "@class")
+public interface IMappedSupertype {
+ //
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/JodaMapping.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/JodaMapping.java
similarity index 100%
rename from mongodb/src/main/java/de/taimos/dvalin/mongo/JodaMapping.java
rename to mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/JodaMapping.java
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/JongoFactory.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/JongoFactory.java
similarity index 100%
rename from mongodb/src/main/java/de/taimos/dvalin/mongo/JongoFactory.java
rename to mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/JongoFactory.java
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/MapReduceResultHandler.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MapReduceResultHandler.java
similarity index 100%
rename from mongodb/src/main/java/de/taimos/dvalin/mongo/MapReduceResultHandler.java
rename to mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MapReduceResultHandler.java
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MongoClientOptionsFactory.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MongoClientOptionsFactory.java
new file mode 100644
index 00000000..eae4c0e1
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MongoClientOptionsFactory.java
@@ -0,0 +1,74 @@
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+
+import org.springframework.beans.factory.FactoryBean;
+
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoClientOptions.Builder;
+
+/**
+ * Copyright 2014 Hoegernet
+ *
+ * Special factory for MongoClientOptions which is setting timeouts
+ *
+ * @author Thorsten Hoeger
+ */
+public class MongoClientOptionsFactory implements FactoryBean {
+
+ private int socketTimeout;
+ private int connectTimeout;
+
+
+ @Override
+ public MongoClientOptions.Builder getObject() throws Exception {
+ Builder builder = MongoClientOptions.builder();
+ builder.socketTimeout(this.socketTimeout);
+ builder.connectTimeout(this.connectTimeout);
+ return builder;
+ }
+
+ @Override
+ public Class> getObjectType() {
+ return MongoClientOptions.Builder.class;
+ }
+
+ @Override
+ public boolean isSingleton() {
+ return false;
+ }
+
+ /**
+ * @param socketTimeout the socketTimeout to set
+ */
+ public void setSocketTimeout(int socketTimeout) {
+ this.socketTimeout = socketTimeout;
+ }
+
+ /**
+ * @param connectTimeout the connectTimeout to set
+ */
+ public void setConnectTimeout(int connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MongoDBDataAccess.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MongoDBDataAccess.java
new file mode 100644
index 00000000..9b2992d0
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MongoDBDataAccess.java
@@ -0,0 +1,382 @@
+package de.taimos.dvalin.mongo;
+
+/*-
+ * #%L
+ * MongoDB support for dvalin
+ * %%
+ * Copyright (C) 2015 - 2018 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+import org.bson.types.ObjectId;
+import org.jongo.Find;
+import org.jongo.Jongo;
+import org.jongo.MongoCollection;
+import org.jongo.ResultHandler;
+import org.jongo.Update;
+import org.springframework.beans.factory.InjectionPoint;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.config.ConfigurableBeanFactory;
+import org.springframework.context.annotation.Scope;
+import org.springframework.stereotype.Repository;
+import org.springframework.util.StreamUtils;
+
+import com.mongodb.DBObject;
+import com.mongodb.MapReduceCommand;
+import com.mongodb.MapReduceOutput;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.gridfs.GridFSBucket;
+import com.mongodb.client.gridfs.GridFSBuckets;
+
+import de.taimos.dvalin.daemon.spring.InjectionUtils;
+
+@Repository
+@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
+public class MongoDBDataAccess {
+
+ /**
+ * Query to perform a full text search
+ */
+ public static final String FULLTEXT_QUERY = "{\"$text\" : {\"$search\" : #}}";
+
+ private final MongoDatabase db;
+ private final Class entityClass;
+ private final MongoCollection collection;
+
+ @Autowired
+ public MongoDBDataAccess(Jongo jongo, MongoDatabase db, InjectionPoint ip) {
+ this.db = db;
+ this.entityClass = (Class) InjectionUtils.getGenericType(ip);
+ this.collection = jongo.getCollection(this.getCollectionName());
+ }
+
+ public String getCollectionName() {
+ return this.entityClass.getSimpleName();
+ }
+
+ public Class getEntityClass() {
+ return this.entityClass;
+ }
+
+ /**
+ * runs a map-reduce-job on the collection. same as {@link #mapReduce(String, DBObject, DBObject, Map, MapReduceResultHandler)
+ * mapReduce(name, null, null, null, conv)}
+ *
+ * @param the type of the result class
+ * @param name the name of the map-reduce functions
+ * @param conv the converter to convert the result
+ * @return an {@link Iterable} with the result entries
+ */
+ public final Iterable mapReduce(String name, final MapReduceResultHandler conv) {
+ return this.mapReduce(name, null, null, null, conv);
+ }
+
+ /**
+ * runs a map-reduce-job on the collection. The functions are read from the classpath in the folder mongodb. The systems reads them from
+ * files called <name>.map.js, <name>.reduce.js and optionally <name>.finalize.js. After this the result is converted
+ * using the given {@link MapReduceResultHandler}
+ *
+ * @param the type of the result class
+ * @param name the name of the map-reduce functions
+ * @param query the query to filter the elements used for the map-reduce
+ * @param sort sort query to sort elements before running map-reduce
+ * @param scope the global scope for the JavaScript run
+ * @param conv the converter to convert the result
+ * @return an {@link Iterable} with the result entries
+ * @throws RuntimeException if resources cannot be read
+ */
+ public final Iterable mapReduce(String name, DBObject query, DBObject sort, Map scope, final MapReduceResultHandler conv) {
+ String map = this.getMRFunction(name, "map");
+ String reduce = this.getMRFunction(name, "reduce");
+
+ MapReduceCommand mrc = new MapReduceCommand(this.collection.getDBCollection(), map, reduce, null, MapReduceCommand.OutputType.INLINE, query);
+ String finalizeFunction = this.getMRFunction(name, "finalize");
+ if(finalizeFunction != null) {
+ mrc.setFinalize(finalizeFunction);
+ }
+ if(sort != null) {
+ mrc.setSort(sort);
+ }
+ if(scope != null) {
+ mrc.setScope(scope);
+ }
+ MapReduceOutput mr = this.collection.getDBCollection().mapReduce(mrc);
+ return new ConverterIterable<>(mr.results().iterator(), conv);
+ }
+
+ private String getMRFunction(String name, String type) {
+ try {
+ InputStream stream = this.getClass().getResourceAsStream("/mongodb/" + name + "." + type + ".js");
+ if(stream != null) {
+ return StreamUtils.copyToString(stream, Charset.defaultCharset());
+ }
+ return null;
+ } catch(IOException e) {
+ throw new RuntimeException("Failed to read resource", e);
+ }
+ }
+
+ public final List findList() {
+ Iterable as = this.collection.find().sort("{_id:1}").as(this.entityClass);
+ return this.convertIterable(as);
+ }
+
+ public List findList(String sortProp, Integer sortDirection, Integer limit, Integer skip) {
+ return this.findSortedByQuery("{}", "{" + sortProp + ":" + sortDirection + "}", skip, limit);
+ }
+
+ /**
+ * converts the given {@link Iterable} to a {@link List}
+ *
+ * @param the element type
+ * @param as the {@link Iterable}
+ * @return the converted {@link List}
+ */
+ public final
List
convertIterable(Iterable
as) {
+ List
objects = new ArrayList<>();
+ for(P mp : as) {
+ objects.add(mp);
+ }
+ return objects;
+ }
+
+ /**
+ * finds all elements matching the given query
+ *
+ * @param query the query to search for
+ * @param params the parameters to replace # symbols
+ * @return the list of elements found
+ */
+ public final List findByQuery(String query, Object... params) {
+ return this.findSortedByQuery(query, null, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param params the parameters to replace # symbols
+ * @return the list of elements found
+ */
+ public final List findSortedByQuery(String query, String sort, Object... params) {
+ return this.findSortedByQuery(query, sort, null, (Integer) null, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
+ * rename or filter fields in the result elements. Instead of returning objects it returns objects of type
+ * as
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param projection the projection of fields to use
+ * @param as the target to convert result elements to
+ * @param params the parameters to replace # symbols
+ * @param the element type
+ * @return the list of elements found
+ */
+ public final
List
findSortedByQuery(String query, String sort, String projection, Class
as, Object... params) {
+ return this.findSortedByQuery(query, sort, null, null, projection, as, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
+ * rename or filter fields in the result elements. Instead of returning objects it returns objects converted
+ * by the given {@link ResultHandler}
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param projection the projection of fields to use
+ * @param handler the handler to convert result elements with
+ * @param params the parameters to replace # symbols
+ * @param
the element type
+ * @return the list of elements found
+ */
+ protected final
List
findSortedByQuery(String query, String sort, String projection, ResultHandler
handler, Object... params) {
+ return this.findSortedByQuery(query, sort, null, null, projection, handler, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
+ * @param params the parameters to replace # symbols
+ * @return the list of elements found
+ */
+ public final List findSortedByQuery(String query, String sort, Integer skip, Integer limit, Object... params) {
+ return this.findSortedByQuery(query, sort, skip, limit, null, this.entityClass, params);
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
+ * rename or filter fields in the result elements. Instead of returning objects it returns objects of type
+ * as
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
+ * @param projection the projection of fields to use
+ * @param as the target to convert result elements to
+ * @param params the parameters to replace # symbols
+ * @param the element type
+ * @return the list of elements found
+ */
+ public final
List
findSortedByQuery(String query, String sort, Integer skip, Integer limit, String projection, Class
as, Object... params) {
+ Find find = this.createFind(query, sort, skip, limit, projection, params);
+ return this.convertIterable(find.as(as));
+ }
+
+ /**
+ * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
+ * rename or filter fields in the result elements. Instead of returning objects it returns objects converted
+ * by the given {@link ResultHandler}
+ *
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
+ * @param projection the projection of fields to use
+ * @param handler the handler to convert result elements with
+ * @param params the parameters to replace # symbols
+ * @param
the element type
+ * @return the list of elements found
+ */
+ public final
List
findSortedByQuery(String query, String sort, Integer skip, Integer limit, String projection, ResultHandler
handler, Object... params) {
+ Find find = this.createFind(query, sort, skip, limit, projection, params);
+ return this.convertIterable(find.map(handler));
+ }
+
+ private Find createFind(String query, String sort, Integer skip, Integer limit, String projection, Object... params) {
+ Find find = this.collection.find(query, params);
+ if((sort != null) && !sort.isEmpty()) {
+ find.sort(sort);
+ }
+ if((projection != null) && !projection.isEmpty()) {
+ find.projection(projection);
+ }
+ if(skip != null) {
+ find.skip(skip);
+ }
+ if(limit != null) {
+ find.limit(limit);
+ }
+ return find;
+ }
+
+ /**
+ * finds all elements containing the given searchString in any text field and sorts them accordingly.
+ *
+ * @param searchString the searchString to search for
+ * @param sort the sort query to apply
+ * @return the list of elements found
+ */
+ public final List searchSorted(String searchString, String sort) {
+ return this.findSortedByQuery(MongoDBDataAccess.FULLTEXT_QUERY, sort, searchString);
+ }
+
+ /**
+ * queries with the given string, sorts the result and returns the first element. null
is returned if no element is found.
+ *
+ * @param query the query string
+ * @param sort the sort string
+ * @param params the parameters to replace # symbols
+ * @return the first element found or null
if none is found
+ */
+ public final Optional findFirstByQuery(String query, String sort, Object... params) {
+ Find find = this.collection.find(query, params);
+ if((sort != null) && !sort.isEmpty()) {
+ find.sort(sort);
+ }
+ Iterable as = find.limit(1).as(this.entityClass);
+ Iterator iterator = as.iterator();
+ if(iterator.hasNext()) {
+ return Optional.of(iterator.next());
+ }
+ return Optional.empty();
+ }
+
+ public final Optional findByObjectId(String id) {
+ return Optional.ofNullable(this.collection.findOne(new ObjectId(id)).as(this.entityClass));
+ }
+
+ public final Optional findByStringId(String id) {
+ return Optional.ofNullable(this.collection.findOne("{\"_id\":#}", id).as(this.entityClass));
+ }
+
+ /**
+ * @param query the query string
+ * @param parameter the parameters to replace # symbols
+ * @return the number of elements matching the query
+ */
+ public final long count(String query, Object... parameter) {
+ return this.collection.count(query, parameter);
+ }
+
+ public final T save(T object) {
+ this.collection.save(object);
+ return object;
+ }
+
+ public final void deleteByObjectId(String id) {
+ this.collection.remove(new ObjectId(id));
+ }
+
+ public final void deleteByStringId(String id) {
+ this.collection.remove("{\"_id\":#}", id);
+ }
+
+ public final void delete(String query, Object... parameter) {
+ this.collection.remove(query, parameter);
+ }
+
+ public final Update update(ObjectId id) {
+ return this.collection.update(id);
+ }
+
+ public final Update update(String query) {
+ return this.collection.update(query);
+ }
+
+ public final Update update(String query, Object... parameter) {
+ return this.collection.update(query, parameter);
+ }
+
+ @Deprecated
+ public MongoCollection getCollection() {
+ return this.collection;
+ }
+
+ public GridFSBucket getGridFSBucket(String bucket) {
+ if(bucket == null || bucket.isEmpty()) {
+ throw new IllegalArgumentException();
+ }
+ return GridFSBuckets.create(this.db, bucket);
+ }
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MongoDBInit.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MongoDBInit.java
new file mode 100644
index 00000000..4209af1e
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/MongoDBInit.java
@@ -0,0 +1,103 @@
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import java.io.IOException;
+import java.util.Scanner;
+
+import javax.annotation.PostConstruct;
+
+import com.mongodb.BasicDBObject;
+import com.mongodb.DBObject;
+import com.mongodb.MongoClient;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import de.taimos.daemon.spring.conditional.OnSystemProperty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * Copyright 2014 Taimos GmbH
+ *
+ *
+ * Initialized the database with data found in the classpath. It searches for files in the folder mongodb ending with .ndjson. The filename
+ * is used as name of the collection. The contents of this file has to be valid ND-JSON which means that it contains one JSON Object per
+ * line.
+ *
+ * @author Thorsten Hoeger
+ */
+@Component
+@OnSystemProperty(propertyName = "mongodb.demodata", propertyValue = "true")
+public class MongoDBInit {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MongoDBInit.class);
+
+ @Autowired
+ private MongoClient mongo;
+
+
+ /**
+ * init database with demo data
+ */
+ @PostConstruct
+ public void initDatabase() {
+ MongoDBInit.LOGGER.info("initializing MongoDB");
+ String dbName = System.getProperty("mongodb.name");
+ if (dbName == null) {
+ throw new RuntimeException("Missing database name; Set system property 'mongodb.name'");
+ }
+ MongoDatabase db = this.mongo.getDatabase(dbName);
+
+ try {
+ PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
+ Resource[] resources = resolver.getResources("classpath*:mongodb/*.ndjson");
+ MongoDBInit.LOGGER.info("Scanning for collection data");
+ for (Resource res : resources) {
+ String filename = res.getFilename();
+ if(filename != null) {
+ String collection = filename.substring(0, filename.length() - 7);
+ MongoDBInit.LOGGER.info("Found collection file: {}", collection);
+ MongoCollection dbCollection = db.getCollection(collection, DBObject.class);
+ try (Scanner scan = new Scanner(res.getInputStream(), "UTF-8")) {
+ int lines = 0;
+ while (scan.hasNextLine()) {
+ String json = scan.nextLine();
+ DBObject parse = BasicDBObject.parse(json);
+ dbCollection.insertOne(parse);
+ lines++;
+ }
+ MongoDBInit.LOGGER.info("Imported {} objects into collection {}", lines, collection);
+ }
+ } else {
+ MongoDBInit.LOGGER.error("Failure loading resource {}", res);
+ }
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Error importing objects", e);
+ }
+ }
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/config/FakeClientConfig.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/config/FakeClientConfig.java
new file mode 100644
index 00000000..05377059
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/config/FakeClientConfig.java
@@ -0,0 +1,54 @@
+package de.taimos.dvalin.mongo.config;
+
+/*-
+ * #%L
+ * MongoDB support for dvalin
+ * %%
+ * Copyright (C) 2015 - 2017 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import com.mongodb.MongoClient;
+import com.mongodb.ServerAddress;
+import com.mongodb.client.MongoClients;
+import de.bwaldvogel.mongo.MongoServer;
+import de.bwaldvogel.mongo.backend.memory.MemoryBackend;
+import de.taimos.daemon.spring.conditional.OnSystemProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+@OnSystemProperty(propertyName = "mongodb.type", propertyValue = "fake")
+@Configuration
+public class FakeClientConfig {
+
+
+ @Bean
+ public MongoServer mongoServer() {
+ return new MongoServer(new MemoryBackend());
+ }
+
+
+ @Bean
+ public MongoClient mongoClient(MongoServer mongoServer) {
+ return new MongoClient(new ServerAddress(mongoServer.bind()));
+ }
+
+ @Bean
+ public com.mongodb.client.MongoClient mongoClient2(MongoServer mongoServer) {
+ return MongoClients.create(mongoServer.bindAndGetConnectionString());
+ }
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/config/MongoDBConfig.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/config/MongoDBConfig.java
new file mode 100644
index 00000000..116b0eea
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/config/MongoDBConfig.java
@@ -0,0 +1,96 @@
+package de.taimos.dvalin.mongo.config;
+
+/*-
+ * #%L
+ * MongoDB support for dvalin
+ * %%
+ * Copyright (C) 2015 - 2017 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import java.util.concurrent.TimeUnit;
+
+import com.mongodb.DB;
+import com.mongodb.MongoClient;
+import com.mongodb.ReadConcern;
+import com.mongodb.ReadPreference;
+import com.mongodb.WriteConcern;
+import com.mongodb.client.MongoDatabase;
+import de.taimos.dvalin.mongo.JongoFactory;
+import io.mongock.api.config.LegacyMigration;
+import io.mongock.driver.mongodb.sync.v4.driver.MongoSync4Driver;
+import io.mongock.runner.standalone.MongockStandalone;
+import io.mongock.runner.standalone.RunnerStandaloneBuilder;
+import org.jongo.Jongo;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MongoDBConfig {
+
+ @Value("${mongock.enabled:false}")
+ private boolean mongockEnabled;
+
+ @Value("${mongock.legacyMigration.enabled:true}")
+ private boolean mongockLegacyMigrationEnabled;
+
+ @Value("${mongock.legacyMigration.table:dbchangelog}")
+ private String mongockLegacyTable;
+
+ @Value("${mongodb.name}")
+ private String dbName;
+
+ @Value("${mongock.basepackage:${mongock.basePackage:}}")
+ private String basePackage;
+
+ @Bean
+ public RunnerStandaloneBuilder mongockRunner(com.mongodb.client.MongoClient mongoClient, Jongo jongo, DB legacyDB) {
+
+ MongoSync4Driver driver = MongoSync4Driver.withDefaultLock(mongoClient, this.dbName);
+ driver.setWriteConcern(WriteConcern.MAJORITY.withJournal(true).withWTimeout(1000, TimeUnit.MILLISECONDS));
+ driver.setReadConcern(ReadConcern.MAJORITY);
+ driver.setReadPreference(ReadPreference.primary());
+ driver.disableTransaction();
+
+ RunnerStandaloneBuilder runnerStandaloneBuilder = MongockStandalone.builder().setDriver(driver).setTransactionEnabled(false);
+ if (this.basePackage == null || this.basePackage.isEmpty()){
+ throw new RuntimeException("LegacyMigration basePackage must be set!");
+ }
+ runnerStandaloneBuilder.addMigrationScanPackage(this.basePackage);
+ if(mongockLegacyMigrationEnabled) {
+ LegacyMigration legacyMigration = new LegacyMigration();
+ legacyMigration.setOrigin(this.mongockLegacyTable);
+ runnerStandaloneBuilder.setLegacyMigration(legacyMigration);
+ }
+ runnerStandaloneBuilder.addDependency(jongo).addDependency(legacyDB).buildRunner().execute();
+ return runnerStandaloneBuilder;
+ }
+
+ @Bean
+ public MongoDatabase mongoDatabase(MongoClient mongoClient) {
+ return mongoClient.getDatabase(this.dbName);
+ }
+
+ @Bean
+ public Jongo jongo(MongoClient mongoClient) {
+ return JongoFactory.createDefault(mongoClient.getDB(this.dbName));
+ }
+
+ @Bean
+ public DB mongoDB(MongoClient mongoClient){
+ return mongoClient.getDB(this.dbName);
+ }
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/config/RealClientConfig.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/config/RealClientConfig.java
new file mode 100644
index 00000000..207b228d
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/config/RealClientConfig.java
@@ -0,0 +1,66 @@
+package de.taimos.dvalin.mongo.config;
+
+/*-
+ * #%L
+ * MongoDB support for dvalin
+ * %%
+ * Copyright (C) 2015 - 2017 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import com.mongodb.MongoClient;
+import com.mongodb.MongoClientOptions;
+import com.mongodb.MongoClientURI;
+import com.mongodb.client.MongoClients;
+import de.taimos.daemon.spring.conditional.OnSystemProperty;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+@OnSystemProperty(propertyName = "mongodb.type", propertyValue = "real")
+@Configuration
+public class RealClientConfig {
+
+ @Value("${mongodb.uri:mongodb://${mongodb.host:localhost}:${mongodb.port:27017}}")
+ private String mongoURI;
+
+ @Value("${mongodb.sockettimeout:${mongodb.socketTimeout:10000}}")
+ private int socketTimeout;
+
+ @Value("${mongodb.connecttimeout:${mongodb.connectTimeout:10000}}")
+ private int connectTimeout;
+
+
+ @Bean
+ public MongoClient mongoClient() {
+ MongoClientOptions.Builder builder = MongoClientOptions.builder();
+ builder.socketTimeout(this.socketTimeout);
+ builder.connectTimeout(this.connectTimeout);
+
+ return new MongoClient(new MongoClientURI(this.mongoURI, builder));
+ }
+
+ @Bean
+ public com.mongodb.client.MongoClient mongoClient2() {
+ MongoClientOptions.Builder builder = MongoClientOptions.builder();
+ builder.socketTimeout(this.socketTimeout);
+ builder.connectTimeout(this.connectTimeout);
+ return MongoClients.create(new MongoClientURI(this.mongoURI, builder).getURI());
+ }
+
+
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/AReferenceableEntity.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/AReferenceableEntity.java
new file mode 100644
index 00000000..5ddb9bc3
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/AReferenceableEntity.java
@@ -0,0 +1,44 @@
+package de.taimos.dvalin.mongo.links;
+
+/*-
+ * #%L
+ * MongoDB support for dvalin
+ * %%
+ * Copyright (C) 2015 - 2018 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+
+/**
+ * referenceable via DocumentLink
+ *
+ * @param generic link to myself
+ * @author Thorsten Hoeger
+ */
+public interface AReferenceableEntity> {
+
+ @JsonIgnore
+ @SuppressWarnings("unchecked")
+ default DocumentLink asLink() {
+ return new DocumentLink<>((T) this);
+ }
+
+ @JsonIgnore
+ String getLabel();
+
+ String getId();
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/DLinkDAO.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/DLinkDAO.java
new file mode 100644
index 00000000..b9a44ee4
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/DLinkDAO.java
@@ -0,0 +1,68 @@
+package de.taimos.dvalin.mongo.links;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.bson.types.ObjectId;
+import org.jongo.Jongo;
+import org.jongo.MongoCollection;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+
+@Repository
+public class DLinkDAO implements IDLinkDAO {
+
+ private final Jongo jongo;
+
+ @Autowired
+ public DLinkDAO(Jongo jongo) {
+ this.jongo = jongo;
+ }
+
+ @Override
+ public > T resolve(DocumentLink link) {
+ MongoCollection collection = this.jongo.getCollection(link.getTargetClass().getSimpleName());
+ return collection.findOne(new ObjectId(link.getObjectId())).as(link.getTargetClass());
+ }
+
+ @Override
+ public > List resolve(List> links, Class targetClass) {
+ MongoCollection collection = this.jongo.getCollection(targetClass.getSimpleName());
+ List ids = new ArrayList<>();
+ for (DocumentLink link : links) {
+ if (!link.getTargetClass().equals(targetClass)) {
+ throw new IllegalArgumentException("Invalid link in collection");
+ }
+ ids.add(new ObjectId(link.getObjectId()));
+ }
+ Iterator it = collection.find("{\"_id\" : {\"$in\" : #}}", ids).as(targetClass).iterator();
+ List resolved = new ArrayList<>();
+ while (it.hasNext()) {
+ resolved.add(it.next());
+ }
+ return resolved;
+ }
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/DLinkQuery.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/DLinkQuery.java
new file mode 100644
index 00000000..ce063aa4
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/DLinkQuery.java
@@ -0,0 +1,80 @@
+package de.taimos.dvalin.mongo.links;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jongo.MongoCollection;
+
+import com.mongodb.DBObject;
+
+import de.taimos.dvalin.mongo.MongoDBDataAccess;
+
+/**
+ * QueryHelper to convert query result to a list of DLinks. It only queries the fields necessary to construct links.
+ *
+ * @param the {@link AReferenceableEntity} this link uses
+ * @author Thorsten Hoeger
+ */
+public class DLinkQuery> {
+
+ private final Class targetClass;
+
+ private final String labelField;
+
+
+ /**
+ * @param targetClass the links target class
+ * @param labelField the name of the label field
+ */
+ public DLinkQuery(Class targetClass, String labelField) {
+ this.targetClass = targetClass;
+ this.labelField = labelField;
+ }
+
+ public List> find(MongoDBDataAccess dataAccess, String query, Object... parameter) {
+ return dataAccess.findSortedByQuery(query, null, null, null, String.format("{%s:1}", this.labelField), this::convert, parameter);
+ }
+
+ @Deprecated
+ public List> find(MongoCollection collection, String query, Object... parameter) {
+ Iterator> it = collection.find(query, parameter).projection(String.format("{%s:1}", this.labelField)).map(this::convert).iterator();
+
+ List> objects = new ArrayList<>();
+ while (it.hasNext()) {
+ DocumentLink link = it.next();
+ objects.add(link);
+ }
+ return objects;
+ }
+
+ private DocumentLink convert(DBObject result) {
+ if (!result.containsField("_id") || !result.containsField(DLinkQuery.this.labelField)) {
+ throw new RuntimeException("Fields missing to construct DocumentLink");
+ }
+ String id = result.get("_id").toString();
+ String label = result.get(DLinkQuery.this.labelField).toString();
+ return new DocumentLink<>(DLinkQuery.this.targetClass, id, label);
+ }
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/DocumentLink.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/DocumentLink.java
new file mode 100644
index 00000000..591a0115
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/DocumentLink.java
@@ -0,0 +1,123 @@
+package de.taimos.dvalin.mongo.links;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import java.io.Serializable;
+
+/**
+ * Link to another document of a {@link AReferenceableEntity}
+ * It is stored as an object containing the target class, the objectId of the target and a label to avoid joining the document for display
+ * purpose.
+ *
+ * @param the target type
+ * @author Thorsten Hoeger
+ */
+public class DocumentLink> implements Serializable {
+
+ private Class targetClass;
+ private String objectId;
+ private String label;
+
+
+ public DocumentLink() {
+ //
+ }
+
+ @SuppressWarnings("unchecked")
+ public DocumentLink(T object) {
+ this((Class) object.getClass(), object.getId(), object.getLabel());
+ }
+
+ public DocumentLink(Class targetClass, String objectId, String label) {
+ this.targetClass = targetClass;
+ this.objectId = objectId;
+ this.label = label;
+ }
+
+ public Class getTargetClass() {
+ return this.targetClass;
+ }
+
+ public void setTargetClass(Class targetClass) {
+ this.targetClass = targetClass;
+ }
+
+ public String getObjectId() {
+ return this.objectId;
+ }
+
+ public void setObjectId(String objectId) {
+ this.objectId = objectId;
+ }
+
+ public String getLabel() {
+ return this.label;
+ }
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ @Override
+ public String toString() {
+ return String.format("%s [%s@%s]", this.label, this.objectId, this.targetClass.getSimpleName());
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = (prime * result) + ((this.objectId == null) ? 0 : this.objectId.hashCode());
+ result = (prime * result) + ((this.targetClass == null) ? 0 : this.targetClass.hashCode());
+ return result;
+ }
+
+ @Override
+ @SuppressWarnings("rawtypes")
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof DocumentLink)) {
+ return false;
+ }
+ DocumentLink other = (DocumentLink) obj;
+ if (this.objectId == null) {
+ if (other.objectId != null) {
+ return false;
+ }
+ } else if (!this.objectId.equals(other.objectId)) {
+ return false;
+ }
+ if (this.targetClass == null) {
+ if (other.targetClass != null) {
+ return false;
+ }
+ } else if (!this.targetClass.equals(other.targetClass)) {
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/IDLinkDAO.java b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/IDLinkDAO.java
new file mode 100644
index 00000000..bf02aef1
--- /dev/null
+++ b/mongodb-legacy/src/main/java/de/taimos/dvalin/mongo/links/IDLinkDAO.java
@@ -0,0 +1,34 @@
+package de.taimos.dvalin.mongo.links;
+
+import java.util.List;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+/**
+ * DAO to generically resolve DLinks
+ */
+public interface IDLinkDAO {
+
+ > T resolve(DocumentLink link);
+
+ > List resolve(List> links, Class targetClass);
+
+}
diff --git a/mongodb-legacy/src/main/resources/.gitkeep b/mongodb-legacy/src/main/resources/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/ABaseTest.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/ABaseTest.java
new file mode 100644
index 00000000..7aa7f075
--- /dev/null
+++ b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/ABaseTest.java
@@ -0,0 +1,79 @@
+/**
+ *
+ */
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * MongoDB support for dvalin
+ * %%
+ * Copyright (C) 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import java.math.BigDecimal;
+
+import com.mongodb.ConnectionString;
+import com.mongodb.DB;
+import com.mongodb.ServerAddress;
+import com.mongodb.client.MongoClient;
+import com.mongodb.client.MongoClients;
+import com.mongodb.client.MongoDatabase;
+import de.bwaldvogel.mongo.MongoServer;
+import de.bwaldvogel.mongo.ServerVersion;
+import de.bwaldvogel.mongo.backend.memory.MemoryBackend;
+import de.taimos.daemon.log4j.Log4jLoggingConfigurer;
+import org.jongo.Jongo;
+import org.junit.Assert;
+
+/**
+ * Copyright 2015 Taimos GmbH
+ *
+ *
+ * @author thoeger
+ */
+public class ABaseTest {
+
+ protected static final String dbName = "dvalin-mongo";
+ private static final ServerAddress serverAddress = new ServerAddress(new MongoServer(new MemoryBackend().version(ServerVersion.MONGO_3_6)).bind());
+
+ public static final MongoClient mongo = MongoClients.create(new ConnectionString(String.format("mongodb://%s:%d", ABaseTest.serverAddress.getHost(), ABaseTest.serverAddress.getPort())));
+ public static final com.mongodb.MongoClient oldMongo = new com.mongodb.MongoClient(new ServerAddress(new MongoServer(new MemoryBackend().version(ServerVersion.MONGO_3_6)).bind()));;
+
+ public static final DB oldDB = ABaseTest.oldMongo.getDB(ABaseTest.dbName);
+ public static final Jongo jongo = JongoFactory.createDefault(ABaseTest.oldMongo.getDB(ABaseTest.dbName));
+ public static final MongoDatabase database = ABaseTest.mongo.getDatabase(ABaseTest.dbName);
+
+ static {
+ try {
+ new Log4jLoggingConfigurer().simpleLogging();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+
+ protected static void assertEquals(BigDecimal bd1, BigDecimal bd2) {
+ Assert.assertEquals(bd1.doubleValue(), bd2.doubleValue(), 0);
+ }
+
+ /**
+ *
+ */
+ public ABaseTest() {
+ super();
+ }
+
+}
diff --git a/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkDAO.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkDAO.java
new file mode 100644
index 00000000..439b43d4
--- /dev/null
+++ b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkDAO.java
@@ -0,0 +1,29 @@
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+public class LinkDAO extends AbstractMongoDAO {
+
+ public LinkObject findByName(String name) {
+ return this.findFirstByQuery("{name:#}", null, name);
+ }
+
+}
diff --git a/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkObject.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkObject.java
similarity index 100%
rename from mongodb/src/test/java/de/taimos/dvalin/mongo/LinkObject.java
rename to mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkObject.java
diff --git a/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkTester.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkTester.java
similarity index 100%
rename from mongodb/src/test/java/de/taimos/dvalin/mongo/LinkTester.java
rename to mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkTester.java
diff --git a/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkedDAO.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkedDAO.java
new file mode 100644
index 00000000..a16a6bc8
--- /dev/null
+++ b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkedDAO.java
@@ -0,0 +1,26 @@
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+public class LinkedDAO extends AbstractMongoDAO {
+
+ //
+}
diff --git a/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkedObject.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkedObject.java
similarity index 100%
rename from mongodb/src/test/java/de/taimos/dvalin/mongo/LinkedObject.java
rename to mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/LinkedObject.java
diff --git a/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/TestDAO.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/TestDAO.java
new file mode 100644
index 00000000..ef1cd34a
--- /dev/null
+++ b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/TestDAO.java
@@ -0,0 +1,28 @@
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+public class TestDAO extends AbstractMongoDAO {
+
+ public TestObject findByName(String name) {
+ return this.findFirstByQuery("{name:#}", null, name);
+ }
+}
diff --git a/mongodb/src/test/java/de/taimos/dvalin/mongo/TestObject.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/TestObject.java
similarity index 100%
rename from mongodb/src/test/java/de/taimos/dvalin/mongo/TestObject.java
rename to mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/TestObject.java
diff --git a/mongodb/src/test/java/de/taimos/dvalin/mongo/Tester.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/Tester.java
similarity index 90%
rename from mongodb/src/test/java/de/taimos/dvalin/mongo/Tester.java
rename to mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/Tester.java
index 2f84a770..16ccdef8 100644
--- a/mongodb/src/test/java/de/taimos/dvalin/mongo/Tester.java
+++ b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/Tester.java
@@ -23,6 +23,7 @@
import java.lang.reflect.Field;
import java.math.BigDecimal;
+import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.SerializationFeature;
@@ -33,6 +34,7 @@
import io.mongock.driver.mongodb.sync.v4.driver.MongoSync4Driver;
import io.mongock.runner.standalone.MongockStandalone;
import org.bson.Document;
+import org.bson.types.ObjectId;
import org.joda.time.DateTime;
import org.jongo.Mapper;
import org.jongo.marshall.jackson.JacksonMapper;
@@ -40,6 +42,7 @@
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
+import org.junit.jupiter.api.Assertions;
public class Tester extends ABaseTest {
@@ -73,6 +76,20 @@ public static void init() {
}
}
+ @Test
+ public void testObjectId() throws JsonProcessingException {
+ TestObject to = new TestObject();
+ Tester.dao.dataAccess.save(to);
+
+ Document result = Tester.dao.dataAccess.getCollection().findOne().as(Document.class);
+
+ Assertions.assertNotNull(result);
+
+// TestObject mappedObject = mapper.readValue(result.toJson(), TestObject.class);
+ Object id = result.get("_id");
+ Assertions.assertEquals(new ObjectId(to.getId()), id);
+ }
+
@Test
public void testUpdate() {
TestObject o = new TestObject();
diff --git a/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/changelog/TestChangelog.java b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/changelog/TestChangelog.java
new file mode 100644
index 00000000..fbd5b541
--- /dev/null
+++ b/mongodb-legacy/src/test/java/de/taimos/dvalin/mongo/changelog/TestChangelog.java
@@ -0,0 +1,39 @@
+package de.taimos.dvalin.mongo.changelog;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 - 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import de.taimos.dvalin.mongo.ABaseTest;
+import de.taimos.dvalin.mongo.ChangelogUtil;
+import io.mongock.api.annotations.ChangeUnit;
+import io.mongock.api.annotations.Execution;
+import io.mongock.api.annotations.RollbackExecution;
+
+@ChangeUnit(order = "001", id = "index1", author = "thoeger", transactional = false)
+public class TestChangelog {
+
+ @Execution
+ public void index1() {
+ ChangelogUtil.addIndex(ABaseTest.oldDB.getCollection("TestObject"), "name", true, true);
+ }
+
+ @RollbackExecution
+ public void index1Rollback(){}
+}
diff --git a/mongodb-legacy/src/test/resources/.gitkeep b/mongodb-legacy/src/test/resources/.gitkeep
new file mode 100644
index 00000000..e69de29b
diff --git a/mongodb/pom.xml b/mongodb/pom.xml
index c7628211..26e0b9c3 100644
--- a/mongodb/pom.xml
+++ b/mongodb/pom.xml
@@ -1,15 +1,14 @@
-
- 4.0.0
-
- de.taimos
- dvalin-parent
- 1.36-SNAPSHOT
-
- dvalin-mongodb
- MongoDB support for dvalin
- 2015
-
-
+
+ 4.0.0
+
+ de.taimos
+ dvalin-parent
+ 1.36-SNAPSHOT
+
+ dvalin-mongodb
+ MongoDB support for dvalin
+ 2015
@@ -21,7 +20,7 @@
-
+
de.taimos
dvalin-daemon
@@ -29,56 +28,39 @@
- com.fasterxml.jackson.core
- jackson-databind
-
-
- com.fasterxml.jackson.jaxrs
- jackson-jaxrs-json-provider
-
-
- de.undercouch
- bson4jackson
- ${bson.version}
-
+ com.fasterxml.jackson.core
+ jackson-databind
+
+
+ com.fasterxml.jackson.datatype
+ jackson-datatype-joda
+
+
+ com.fasterxml.jackson.jaxrs
+ jackson-jaxrs-json-provider
+
+
+ de.undercouch
+ bson4jackson
+ ${bson.version}
+
+
+
+
+ org.springframework
+ spring-beans
+
+
+ org.springframework
+ spring-context
+
+
+ org.mongodb
+ mongodb-driver-sync
+ ${mongo.version}
+
-
-
- org.springframework
- spring-beans
-
-
- org.springframework
- spring-context
-
-
- org.mongodb
- mongodb-driver-legacy
-
-
- org.jongo
- jongo
- ${jongo.version}
-
-
- jackson-databind
- com.fasterxml.jackson.core
-
-
- jackson-core
- com.fasterxml.jackson.core
-
-
- bson4jackson
- de.undercouch
-
-
- jackson-annotations
- com.fasterxml.jackson.core
-
-
-
io.mongock
mongock-standalone
@@ -93,5 +75,5 @@
${mongo-java-server.version}
true
-
+
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/AEntity.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/AEntity.java
index 19df4ca0..a94680b1 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/AEntity.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/AEntity.java
@@ -9,9 +9,9 @@
* 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.
@@ -20,11 +20,14 @@
* #L%
*/
-import java.io.Serializable;
-
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import de.taimos.dvalin.mongo.id.IdEntity;
+import de.taimos.dvalin.mongo.mapper.ObjectIdMapping;
import org.bson.types.ObjectId;
-import org.jongo.marshall.jackson.oid.MongoId;
-import org.jongo.marshall.jackson.oid.MongoObjectId;
+
+import java.io.Serializable;
/**
* Copyright 2015 Hoegernet
@@ -34,18 +37,16 @@
*
* @author Thorsten Hoeger
*/
-public abstract class AEntity implements Serializable {
+public abstract class AEntity extends IdEntity implements Serializable {
private static final long serialVersionUID = 6328501276339927785L;
- @MongoId
- @MongoObjectId
+ @JsonProperty("_id")
+ @JsonSerialize(using = ObjectIdMapping.ObjectIdSerializer.class)
+ @JsonDeserialize(using = ObjectIdMapping.ObjectIdDeserializer.class)
protected String id = ObjectId.get().toString();
-
- /**
- * @return the unique id of the element
- */
+ @Override
public String getId() {
return this.id;
}
@@ -53,5 +54,4 @@ public String getId() {
public void setId(final String id) {
this.id = id;
}
-
}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/AbstractAuditedMongoDAO.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/AbstractAuditedMongoDAO.java
index fe0e9b53..214b8571 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/AbstractAuditedMongoDAO.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/AbstractAuditedMongoDAO.java
@@ -20,32 +20,39 @@
* #L%
*/
-import java.util.List;
-
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.model.Sorts;
+import org.bson.BsonDocument;
+import org.bson.BsonObjectId;
import org.bson.Document;
+import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import org.joda.time.DateTime;
-import org.jongo.Jongo;
-import org.jongo.Mapper;
-import org.jongo.MongoCollection;
-import org.jongo.MongoCursor;
-import org.jongo.bson.BsonDocument;
-import com.mongodb.BasicDBObject;
-import com.mongodb.client.MongoDatabase;
+import java.util.ArrayList;
+import java.util.List;
-public abstract class AbstractAuditedMongoDAO extends AbstractMongoDAO implements ICrudAuditedDAO {
+import static com.mongodb.client.model.Filters.and;
+import static com.mongodb.client.model.Filters.eq;
- protected MongoCollection jongoHistoryCollection;
- private com.mongodb.client.MongoCollection historyCollection;
- private Mapper jongoMapper;
+/**
+ * @param the entity this DAO is used for
+ * @author Thorsten Hoeger
+ */
+public abstract class AbstractAuditedMongoDAO extends AbstractMongoDAO
+ implements ICrudAuditedDAO {
+
+ private static final String HISTORY_OBJECT_ID = "originalId";
+
+ private MongoCollection historyCollection;
+ private ObjectMapper mapper;
@Override
- protected void customInit(MongoDatabase db, Jongo jongo) {
+ protected void customInit() {
+ this.mapper = this.dataAccess.getMapper();
String collectionName = this.dataAccess.getCollectionName() + "_history";
- this.jongoHistoryCollection = jongo.getCollection(collectionName);
- this.historyCollection = db.getCollection(collectionName);
- this.jongoMapper = jongo.getMapper();
+ this.historyCollection = this.dataAccess.getDb().getCollection(collectionName);
}
@Override
@@ -54,17 +61,22 @@ public T findVersion(String id, Integer version) {
return this.findById(id);
}
- MongoCursor as = this.jongoHistoryCollection.find("{originalId:#, version:#}", new ObjectId(id), version).as(this.dataAccess.getEntityClass());
- if (as.hasNext()) {
- return as.next();
- }
- return null;
+ return this.historyCollection.find(and(eq(AbstractAuditedMongoDAO.getIdFilter(id)), eq("version", version)))
+ .map(this::mapToEntity).first();
}
@Override
public List findHistoryElements(String id) {
- Iterable as = this.jongoHistoryCollection.find("{originalId : #}", new ObjectId(id)).sort("{version: -1}").as(this.dataAccess.getEntityClass());
- return this.dataAccess.convertIterable(as);
+ return this.historyCollection.find(AbstractAuditedMongoDAO.getIdFilter(id)).sort(Sorts.descending("version"))
+ .map(this::mapToEntity).into(new ArrayList<>());
+ }
+
+ private T mapToEntity(Document document) {
+ return this.dataAccess.mapToEntity(document);
+ }
+
+ private static Bson getIdFilter(String id) {
+ return eq(AbstractAuditedMongoDAO.HISTORY_OBJECT_ID, new ObjectId(id));
}
@Override
@@ -81,15 +93,17 @@ protected void beforeSave(T object) {
@Override
protected void afterSave(T object) {
try {
- BsonDocument bsonDocument = this.jongoMapper.getMarshaller().marshall(object);
- BasicDBObject dbObject = new BasicDBObject(bsonDocument.toDBObject().toMap());
- dbObject.removeField("_id");
- dbObject.put("originalId", new ObjectId(object.getId()));
- Document doc = Document.parse(dbObject.toString());
- this.historyCollection.insertOne(doc);
+ String json = this.mapper.writeValueAsString(object);
+ BsonDocument bsonDocument = BsonDocument.parse(json);
+ bsonDocument.remove(this.dataAccess.idField());
+ bsonDocument.append(AbstractAuditedMongoDAO.HISTORY_OBJECT_ID,
+ new BsonObjectId(new ObjectId(object.getId())));
+
+ this.historyCollection.insertOne(this.bsonToDocument(bsonDocument));
} catch (Exception e) {
String message = String.format("Unable to save object %s due to a marshalling error", object);
throw new IllegalArgumentException(message, e);
}
}
+
}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/AbstractMongoDAO.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/AbstractMongoDAO.java
index 547f707c..53c23022 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/AbstractMongoDAO.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/AbstractMongoDAO.java
@@ -20,20 +20,18 @@
* #L%
*/
-import java.util.List;
-import java.util.Map;
-
-import javax.annotation.PostConstruct;
-
-import org.jongo.Jongo;
-import org.jongo.MongoCollection;
-import org.jongo.ResultHandler;
+import com.mongodb.Function;
+import com.mongodb.client.gridfs.GridFSBucket;
+import org.bson.BsonDocument;
+import org.bson.BsonDocumentReader;
+import org.bson.Document;
+import org.bson.codecs.DecoderContext;
+import org.bson.codecs.DocumentCodec;
+import org.bson.conversions.Bson;
import org.springframework.beans.factory.annotation.Autowired;
-import com.mongodb.DBObject;
-import com.mongodb.MongoClient;
-import com.mongodb.client.MongoDatabase;
-import com.mongodb.client.gridfs.GridFSBucket;
+import javax.annotation.PostConstruct;
+import java.util.List;
/**
* Copyright 2015 Hoegernet
@@ -46,60 +44,26 @@
*/
public abstract class AbstractMongoDAO implements ICrudDAO {
- @Autowired
- @Deprecated
- protected MongoClient mongo;
-
- @Autowired
- private Jongo jongo;
- @Autowired
- private MongoDatabase db;
-
- @Deprecated
- protected MongoCollection collection;
+ protected DocumentCodec codec;
+ protected DecoderContext decoderContext;
@Autowired
protected MongoDBDataAccess dataAccess;
@PostConstruct
public final void init() {
- this.collection = this.dataAccess.getCollection();
- this.customInit(this.db, this.jongo);
- }
-
- protected void customInit(MongoDatabase db, Jongo jongo) {
- // implement if needed
+ this.customInit();
+ this.codecInit();
}
- /**
- * runs a map-reduce-job on the collection. same as {@link #mapReduce(String, DBObject, DBObject, Map, MapReduceResultHandler)
- * mapReduce(name, null, null, null, conv)}
- *
- * @param the type of the result class
- * @param name the name of the map-reduce functions
- * @param conv the converter to convert the result
- * @return an {@link Iterable} with the result entries
- */
- protected final Iterable mapReduce(String name, final MapReduceResultHandler conv) {
- return this.dataAccess.mapReduce(name, conv);
+ protected void codecInit() {
+ // override if needed
+ this.codec = new DocumentCodec();
+ this.decoderContext = DecoderContext.builder().build();
}
- /**
- * runs a map-reduce-job on the collection. The functions are read from the classpath in the folder mongodb. The systems reads them from
- * files called <name>.map.js, <name>.reduce.js and optionally <name>.finalize.js. After this the result is converted
- * using the given {@link MapReduceResultHandler}
- *
- * @param the type of the result class
- * @param name the name of the map-reduce functions
- * @param query the query to filter the elements used for the map-reduce
- * @param sort sort query to sort elements before running map-reduce
- * @param scope the global scope for the JavaScript run
- * @param conv the converter to convert the result
- * @return an {@link Iterable} with the result entries
- * @throws RuntimeException if resources cannot be read
- */
- protected final Iterable mapReduce(String name, DBObject query, DBObject sort, Map scope, final MapReduceResultHandler conv) {
- return this.dataAccess.mapReduce(name, query, sort, scope, conv);
+ protected void customInit() {
+ // implement if needed
}
@Override
@@ -115,24 +79,22 @@ public List findList(String sortProp, Integer sortDirection, Integer limit, I
/**
* finds all elements matching the given query
*
- * @param query the query to search for
- * @param params the parameters to replace # symbols
+ * @param query the query to search for
* @return the list of elements found
*/
- protected final List findByQuery(String query, Object... params) {
- return this.dataAccess.findByQuery(query, params);
+ protected final List findByQuery(Bson query) {
+ return this.dataAccess.findSortedByQuery(query, null, null, null, null);
}
/**
* finds all elements matching the given query and sorts them accordingly
*
- * @param query the query to search for
- * @param sort the sort query to apply
- * @param params the parameters to replace # symbols
+ * @param query the query to search for
+ * @param sort the sort query to apply
* @return the list of elements found
*/
- protected final List findSortedByQuery(String query, String sort, Object... params) {
- return this.dataAccess.findSortedByQuery(query, sort, params);
+ protected final List findSortedByQuery(Bson query, Bson sort) {
+ return this.dataAccess.findSortedByQuery(query, sort, null, null, null);
}
/**
@@ -143,44 +105,39 @@ protected final List findSortedByQuery(String query, String sort, Object... p
* @param query the query to search for
* @param sort the sort query to apply
* @param projection the projection of fields to use
- * @param as the target to convert result elements to
- * @param params the parameters to replace # symbols
- * @param the element type
* @return the list of elements found
*/
- protected final
List
findSortedByQuery(String query, String sort, String projection, Class
as, Object... params) {
- return this.dataAccess.findSortedByQuery(query, sort, projection, as, params);
+ protected final List findSortedByQuery(Bson query, Bson sort, Bson projection) {
+ return this.dataAccess.findSortedByQuery(query, sort, null, null, projection);
}
/**
* finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
* rename or filter fields in the result elements. Instead of returning typed objects it returns objects converted
- * by the given {@link ResultHandler}
+ * by the given {@link Function}
*
* @param query the query to search for
* @param sort the sort query to apply
* @param projection the projection of fields to use
* @param handler the handler to convert result elements with
- * @param params the parameters to replace # symbols
* @param the element type
* @return the list of elements found
*/
- protected final
List
findSortedByQuery(String query, String sort, String projection, ResultHandler
handler, Object... params) {
- return this.dataAccess.findSortedByQuery(query, sort, projection, handler, params);
+ protected final
List
findSortedByQuery(Bson query, Bson sort, Bson projection, Function handler) {
+ return this.dataAccess.findSortedByQuery(query, sort, null, null, projection, handler);
}
/**
* finds all elements matching the given query and sorts them accordingly
*
- * @param query the query to search for
- * @param sort the sort query to apply
- * @param skip the number of elements to skip
- * @param limit the number of elements to fetch
- * @param params the parameters to replace # symbols
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
* @return the list of elements found
*/
- protected final List findSortedByQuery(String query, String sort, Integer skip, Integer limit, Object... params) {
- return this.dataAccess.findSortedByQuery(query, sort, skip, limit, params);
+ protected final List findSortedByQuery(Bson query, Bson sort, Integer skip, Integer limit) {
+ return this.dataAccess.findSortedByQuery(query, sort, skip, limit, null);
}
/**
@@ -193,19 +150,16 @@ protected final List findSortedByQuery(String query, String sort, Integer ski
* @param skip the number of elements to skip
* @param limit the number of elements to fetch
* @param projection the projection of fields to use
- * @param as the target to convert result elements to
- * @param params the parameters to replace # symbols
- * @param the element type
* @return the list of elements found
*/
- protected final
List
findSortedByQuery(String query, String sort, Integer skip, Integer limit, String projection, Class
as, Object... params) {
- return this.dataAccess.findSortedByQuery(query, sort, skip, limit, projection, as, params);
+ protected final List findSortedByQuery(Bson query, Bson sort, Integer skip, Integer limit, Bson projection) {
+ return this.dataAccess.findSortedByQuery(query, sort, skip, limit, projection);
}
/**
* finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
* rename or filter fields in the result elements. Instead of returning typed objects it returns objects converted
- * by the given {@link ResultHandler}
+ * by the given {@link Function}
*
* @param query the query to search for
* @param sort the sort query to apply
@@ -213,40 +167,38 @@ protected final List
findSortedByQuery(String query, String sort, Integer
* @param limit the number of elements to fetch
* @param projection the projection of fields to use
* @param handler the handler to convert result elements with
- * @param params the parameters to replace # symbols
- * @param
the element type
+ * @param the element type
* @return the list of elements found
*/
- protected final List
findSortedByQuery(String query, String sort, Integer skip, Integer limit, String projection, ResultHandler
handler, Object... params) {
- return this.dataAccess.findSortedByQuery(query, sort, skip, limit, projection, handler, params);
+ protected final List findSortedByQuery(Bson query, Bson sort, Integer skip, Integer limit, Bson projection, Function handler) {
+ return this.dataAccess.findSortedByQuery(query, sort, skip, limit, projection, handler);
}
/**
* finds all elements containing the given searchString in any text field and sorts them accordingly.
*
- * @param searchString the searchString to search for
- * @param sort the sort query to apply
+ * @param searchString the searchString to search for
+ * @param sort the sort query to apply
* @return the list of elements found
*/
- protected final List searchSorted(String searchString, String sort) {
+ protected final List searchSorted(String searchString, Bson sort) {
return this.dataAccess.searchSorted(searchString, sort);
}
/**
* queries with the given string, sorts the result and returns the first element. null
is returned if no element is found.
*
- * @param query the query string
- * @param sort the sort string
- * @param params the parameters to replace # symbols
+ * @param query the query
+ * @param sort the sort
* @return the first element found or null
if none is found
*/
- protected final T findFirstByQuery(String query, String sort, Object... params) {
- return this.dataAccess.findFirstByQuery(query, sort, params).orElse(null);
+ protected final T findFirstByQuery(Bson query, Bson sort) {
+ return this.dataAccess.findFirstByQuery(query, sort).orElse(null);
}
@Override
public final T findById(String id) {
- return this.dataAccess.findByObjectId(id).orElse(null);
+ return this.dataAccess.findById(id).orElse(null);
}
@Override
@@ -285,7 +237,7 @@ public final void delete(T object) {
@Override
public final void delete(String id) {
this.beforeDelete(id);
- this.dataAccess.deleteByObjectId(id);
+ this.dataAccess.deleteById(id);
this.afterDelete(id);
}
@@ -303,4 +255,7 @@ protected GridFSBucket getGridFSBucket(String bucket) {
return this.dataAccess.getGridFSBucket(bucket);
}
+ protected Document bsonToDocument(BsonDocument bsonDocument) {
+ return this.codec.decode(new BsonDocumentReader(bsonDocument), this.decoderContext);
+ }
}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/ChangelogUtil.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/ChangelogUtil.java
index 46abc789..a5bda9e1 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/ChangelogUtil.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/ChangelogUtil.java
@@ -21,7 +21,10 @@
*/
import com.mongodb.BasicDBObject;
-import com.mongodb.DBCollection;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.model.IndexOptions;
+
+import java.util.concurrent.TimeUnit;
/**
* Copyright 2015 Hoegernet
@@ -44,11 +47,13 @@ private ChangelogUtil() {
* @param ttl the TTL to set on the given field
* @throws IllegalArgumentException if the TTL is less or equal 0
*/
- public static void addTTLIndex(DBCollection collection, String field, int ttl) {
+ public static void addTTLIndex(MongoCollection collection, String field, int ttl) {
if (ttl <= 0) {
throw new IllegalArgumentException("TTL must be positive");
}
- collection.createIndex(new BasicDBObject(field, 1), new BasicDBObject("expireAfterSeconds", ttl));
+ IndexOptions indexOptions = new IndexOptions();
+ indexOptions.expireAfter((long) ttl, TimeUnit.SECONDS);
+ collection.createIndex(new BasicDBObject(field, 1), indexOptions);
}
/**
@@ -59,9 +64,11 @@ public static void addTTLIndex(DBCollection collection, String field, int ttl) {
* @param asc the sorting direction. true
to sort ascending; false
to sort descending
* @param background iff true
the index is created in the background
*/
- public static void addIndex(DBCollection collection, String field, boolean asc, boolean background) {
+ public static void addIndex(MongoCollection collection, String field, boolean asc, boolean background) {
int dir = (asc) ? 1 : -1;
- collection.createIndex(new BasicDBObject(field, dir), new BasicDBObject("background", background));
+ IndexOptions indexOptions = new IndexOptions();
+ indexOptions.background(background);
+ collection.createIndex(new BasicDBObject(field, dir), indexOptions);
}
/**
@@ -69,8 +76,8 @@ public static void addIndex(DBCollection collection, String field, boolean asc,
*
* @param collection the collection to use for the index
*/
- public static void addTextIndex(DBCollection collection) {
- collection.createIndex(new BasicDBObject("$**", "text"));
+ public static void addTextIndex(MongoCollection collection) {
+ collection.createIndex(new BasicDBObject("$**", "text"));
}
}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/JodaCodec.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/JodaCodec.java
new file mode 100644
index 00000000..ad37de4d
--- /dev/null
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/JodaCodec.java
@@ -0,0 +1,33 @@
+package de.taimos.dvalin.mongo;
+
+import org.bson.BsonReader;
+import org.bson.BsonWriter;
+import org.bson.codecs.Codec;
+import org.bson.codecs.DecoderContext;
+import org.bson.codecs.EncoderContext;
+import org.joda.time.DateTime;
+
+/**
+ * Copyright 2024 Cinovo AG
+ *
+ *
+ * @author fzwirn
+ */
+public class JodaCodec implements Codec {
+ @Override
+ public DateTime decode(BsonReader reader, DecoderContext decoderContext) {
+ return new DateTime(reader.readDateTime());
+ }
+
+ @Override
+ public void encode(BsonWriter writer, DateTime value, EncoderContext encoderContext) {
+ if (value != null) {
+ writer.writeDateTime(value.getMillis());
+ }
+ }
+
+ @Override
+ public Class getEncoderClass() {
+ return DateTime.class;
+ }
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoClientOptionsFactory.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoClientOptionsFactory.java
index eae4c0e1..2a36e534 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoClientOptionsFactory.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoClientOptionsFactory.java
@@ -9,9 +9,9 @@
* 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.
@@ -21,10 +21,12 @@
*/
+import com.mongodb.MongoClientSettings;
+import com.mongodb.MongoClientSettings.Builder;
import org.springframework.beans.factory.FactoryBean;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoClientOptions.Builder;
+import java.util.concurrent.TimeUnit;
+
/**
* Copyright 2014 Hoegernet
@@ -33,23 +35,25 @@
*
* @author Thorsten Hoeger
*/
-public class MongoClientOptionsFactory implements FactoryBean {
+public class MongoClientOptionsFactory implements FactoryBean {
private int socketTimeout;
private int connectTimeout;
@Override
- public MongoClientOptions.Builder getObject() throws Exception {
- Builder builder = MongoClientOptions.builder();
- builder.socketTimeout(this.socketTimeout);
- builder.connectTimeout(this.connectTimeout);
- return builder;
+ public MongoClientSettings.Builder getObject() throws Exception {
+ Builder settingsBuilder = MongoClientSettings.builder();
+ settingsBuilder.applyToSocketSettings(builder -> {
+ builder.connectTimeout(MongoClientOptionsFactory.this.connectTimeout, TimeUnit.MILLISECONDS);
+ builder.readTimeout(MongoClientOptionsFactory.this.socketTimeout, TimeUnit.MILLISECONDS);
+ });
+ return settingsBuilder;
}
@Override
public Class> getObjectType() {
- return MongoClientOptions.Builder.class;
+ return MongoClientSettings.Builder.class;
}
@Override
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoDBDataAccess.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoDBDataAccess.java
index 9b2992d0..df618daa 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoDBDataAccess.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoDBDataAccess.java
@@ -20,360 +20,343 @@
* #L%
*/
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.mongodb.Function;
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.gridfs.GridFSBucket;
+import com.mongodb.client.gridfs.GridFSBuckets;
+import com.mongodb.client.model.ReplaceOptions;
+import com.mongodb.client.model.Sorts;
+import de.taimos.dvalin.daemon.spring.InjectionUtils;
+import de.taimos.dvalin.mongo.id.IdEntity;
+import de.taimos.dvalin.mongo.mapper.JacksonConfig;
+import org.bson.BsonDocument;
+import org.bson.Document;
+import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
-import org.jongo.Find;
-import org.jongo.Jongo;
-import org.jongo.MongoCollection;
-import org.jongo.ResultHandler;
-import org.jongo.Update;
import org.springframework.beans.factory.InjectionPoint;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Repository;
-import org.springframework.util.StreamUtils;
-import com.mongodb.DBObject;
-import com.mongodb.MapReduceCommand;
-import com.mongodb.MapReduceOutput;
-import com.mongodb.client.MongoDatabase;
-import com.mongodb.client.gridfs.GridFSBucket;
-import com.mongodb.client.gridfs.GridFSBuckets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
-import de.taimos.dvalin.daemon.spring.InjectionUtils;
+import static com.mongodb.client.model.Filters.eq;
+/**
+ * @param document class for which this will be the DB access
+ * @author hoegertn
+ * @author fzwirn
+ */
@Repository
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
-public class MongoDBDataAccess {
+@SuppressWarnings("unused")
+public class MongoDBDataAccess {
/**
* Query to perform a full text search
*/
public static final String FULLTEXT_QUERY = "{\"$text\" : {\"$search\" : #}}";
+ public static final String DEFAULT_ID = "_id";
private final MongoDatabase db;
private final Class entityClass;
- private final MongoCollection collection;
+ private final MongoCollection collection;
+ private ObjectMapper mapper;
+ /**
+ * @param db database
+ * @param ip injection point
+ */
@Autowired
- public MongoDBDataAccess(Jongo jongo, MongoDatabase db, InjectionPoint ip) {
+ public MongoDBDataAccess(MongoDatabase db, InjectionPoint ip) {
this.db = db;
+ //noinspection unchecked
this.entityClass = (Class) InjectionUtils.getGenericType(ip);
- this.collection = jongo.getCollection(this.getCollectionName());
+ this.collection = db.getCollection(this.getCollectionName());
+ this.initMapper();
}
- public String getCollectionName() {
- return this.entityClass.getSimpleName();
- }
-
- public Class getEntityClass() {
- return this.entityClass;
+ protected void initMapper() {
+ this.mapper = JacksonConfig.createObjectMapper();
}
/**
- * runs a map-reduce-job on the collection. same as {@link #mapReduce(String, DBObject, DBObject, Map, MapReduceResultHandler)
- * mapReduce(name, null, null, null, conv)}
- *
- * @param the type of the result class
- * @param name the name of the map-reduce functions
- * @param conv the converter to convert the result
- * @return an {@link Iterable} with the result entries
+ * @return the mapper
*/
- public final Iterable mapReduce(String name, final MapReduceResultHandler conv) {
- return this.mapReduce(name, null, null, null, conv);
+ public ObjectMapper getMapper() {
+ return this.mapper;
}
/**
- * runs a map-reduce-job on the collection. The functions are read from the classpath in the folder mongodb. The systems reads them from
- * files called <name>.map.js, <name>.reduce.js and optionally <name>.finalize.js. After this the result is converted
- * using the given {@link MapReduceResultHandler}
- *
- * @param the type of the result class
- * @param name the name of the map-reduce functions
- * @param query the query to filter the elements used for the map-reduce
- * @param sort sort query to sort elements before running map-reduce
- * @param scope the global scope for the JavaScript run
- * @param conv the converter to convert the result
- * @return an {@link Iterable} with the result entries
- * @throws RuntimeException if resources cannot be read
+ * @param mapper the mapper to set
*/
- public final Iterable mapReduce(String name, DBObject query, DBObject sort, Map scope, final MapReduceResultHandler conv) {
- String map = this.getMRFunction(name, "map");
- String reduce = this.getMRFunction(name, "reduce");
-
- MapReduceCommand mrc = new MapReduceCommand(this.collection.getDBCollection(), map, reduce, null, MapReduceCommand.OutputType.INLINE, query);
- String finalizeFunction = this.getMRFunction(name, "finalize");
- if(finalizeFunction != null) {
- mrc.setFinalize(finalizeFunction);
- }
- if(sort != null) {
- mrc.setSort(sort);
- }
- if(scope != null) {
- mrc.setScope(scope);
- }
- MapReduceOutput mr = this.collection.getDBCollection().mapReduce(mrc);
- return new ConverterIterable<>(mr.results().iterator(), conv);
- }
-
- private String getMRFunction(String name, String type) {
- try {
- InputStream stream = this.getClass().getResourceAsStream("/mongodb/" + name + "." + type + ".js");
- if(stream != null) {
- return StreamUtils.copyToString(stream, Charset.defaultCharset());
- }
- return null;
- } catch(IOException e) {
- throw new RuntimeException("Failed to read resource", e);
- }
+ public void setMapper(ObjectMapper mapper) {
+ this.mapper = mapper;
}
- public final List findList() {
- Iterable as = this.collection.find().sort("{_id:1}").as(this.entityClass);
- return this.convertIterable(as);
+ /**
+ * @return the id Field used by the entity
+ */
+ public String idField() {
+ return MongoDBDataAccess.DEFAULT_ID;
}
- public List findList(String sortProp, Integer sortDirection, Integer limit, Integer skip) {
- return this.findSortedByQuery("{}", "{" + sortProp + ":" + sortDirection + "}", skip, limit);
+ /**
+ * @return the name of the collection
+ */
+ public String getCollectionName() {
+ return this.entityClass.getSimpleName();
}
/**
- * converts the given {@link Iterable} to a {@link List}
- *
- * @param the element type
- * @param as the {@link Iterable}
- * @return the converted {@link List}
+ * @return the class of the entity
*/
- public final
List
convertIterable(Iterable
as) {
- List
objects = new ArrayList<>();
- for(P mp : as) {
- objects.add(mp);
- }
- return objects;
+ public Class getEntityClass() {
+ return this.entityClass;
}
/**
- * finds all elements matching the given query
- *
- * @param query the query to search for
- * @param params the parameters to replace # symbols
- * @return the list of elements found
+ * @return all elements sorted by id field
*/
- public final List findByQuery(String query, Object... params) {
- return this.findSortedByQuery(query, null, params);
+ public final List findList() {
+ return this.collection.find().sort(Sorts.ascending(this.idField())).map(this::mapToEntity)
+ .into(new ArrayList<>());
}
/**
- * finds all elements matching the given query and sorts them accordingly
- *
- * @param query the query to search for
- * @param sort the sort query to apply
- * @param params the parameters to replace # symbols
+ * @param sortProp property to sort by
+ * @param sortDirection direction to sort by
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
* @return the list of elements found
*/
- public final List findSortedByQuery(String query, String sort, Object... params) {
- return this.findSortedByQuery(query, sort, null, (Integer) null, params);
+ public List findList(String sortProp, Integer sortDirection, Integer limit, Integer skip) {
+ return this.collection.find().sort(sortDirection == -1 ? Sorts.descending(sortProp) : Sorts.ascending(sortProp))
+ .skip(skip).limit(limit).map(this::mapToEntity).into(new ArrayList<>());
}
/**
* finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
- * rename or filter fields in the result elements. Instead of returning objects it returns objects of type
- * as
+ * rename or filter fields in the result elements.
*
* @param query the query to search for
* @param sort the sort query to apply
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
* @param projection the projection of fields to use
- * @param as the target to convert result elements to
- * @param params the parameters to replace # symbols
- * @param the element type
* @return the list of elements found
*/
- public final
List
findSortedByQuery(String query, String sort, String projection, Class
as, Object... params) {
- return this.findSortedByQuery(query, sort, null, null, projection, as, params);
+ public final List findSortedByQuery(Bson query, Bson sort, Integer skip, Integer limit, Bson projection) {
+ return this.innerFindSortedByQuery(query, sort, skip, limit, projection).map(this::mapToEntity)
+ .into(new ArrayList<>());
+ }
+
+ private FindIterable innerFindSortedByQuery(Bson query, Bson sort, Integer skip, Integer limit, Bson projection) {
+ FindIterable result = this.collection.find(query).sort(sort).limit(limit != null ? limit : 0)
+ .projection(projection);
+ if (skip != null) {
+ result = result.skip(skip);
+ }
+ return result;
}
+
/**
* finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
* rename or filter fields in the result elements. Instead of returning objects it returns objects converted
- * by the given {@link ResultHandler}
+ * by the given {@link Function}
*
- * @param query the query to search for
- * @param sort the sort query to apply
- * @param projection the projection of fields to use
- * @param handler the handler to convert result elements with
- * @param params the parameters to replace # symbols
- * @param the element type
+ * @param query the query to search for
+ * @param sort the sort query to apply
+ * @param skip the number of elements to skip
+ * @param limit the number of elements to fetch
+ * @param projection the projection of fields to use
+ * @param mappingFunction the handler to convert result elements with
+ * @param the element type
* @return the list of elements found
*/
- protected final List
findSortedByQuery(String query, String sort, String projection, ResultHandler
handler, Object... params) {
- return this.findSortedByQuery(query, sort, null, null, projection, handler, params);
+ public final List findSortedByQuery(Bson query, Bson sort, Integer skip, Integer limit, Bson projection, Function mappingFunction) {
+ return this.innerFindSortedByQuery(query, sort, skip, limit, projection).map(this::mapToEntity)
+ .map(mappingFunction).into(new ArrayList<>());
}
/**
- * finds all elements matching the given query and sorts them accordingly
+ * finds all elements containing the given searchString in any text field and sorts them accordingly.
*
- * @param query the query to search for
- * @param sort the sort query to apply
- * @param skip the number of elements to skip
- * @param limit the number of elements to fetch
- * @param params the parameters to replace # symbols
+ * @param searchString the searchString to search for
+ * @param sort the sort query to apply
* @return the list of elements found
*/
- public final List findSortedByQuery(String query, String sort, Integer skip, Integer limit, Object... params) {
- return this.findSortedByQuery(query, sort, skip, limit, null, this.entityClass, params);
+ public final List searchSorted(String searchString, Bson sort) {
+ return this.findSortedByQuery(MongoDBDataAccess.createQuery(MongoDBDataAccess.FULLTEXT_QUERY, searchString),
+ sort, null, null, null);
}
+
/**
- * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
- * rename or filter fields in the result elements. Instead of returning objects it returns objects of type
- * as
+ * queries with the given query, sorts the result and returns the first element. Empty Optional is returned if no element is found.
*
- * @param query the query to search for
- * @param sort the sort query to apply
- * @param skip the number of elements to skip
- * @param limit the number of elements to fetch
- * @param projection the projection of fields to use
- * @param as the target to convert result elements to
- * @param params the parameters to replace # symbols
- * @param the element type
- * @return the list of elements found
+ * @param query the query
+ * @param sort the sort
+ * @return optional of the first element found or null
if none is found
*/
- public final
List
findSortedByQuery(String query, String sort, Integer skip, Integer limit, String projection, Class
as, Object... params) {
- Find find = this.createFind(query, sort, skip, limit, projection, params);
- return this.convertIterable(find.as(as));
+ public final Optional findFirstByQuery(Bson query, Bson sort) {
+ return Optional.ofNullable(this.collection.find(query).sort(sort).map(this::mapToEntity).first());
}
/**
- * finds all elements matching the given query and sorts them accordingly. With this method it is possible to specify a projection to
- * rename or filter fields in the result elements. Instead of returning objects it returns objects converted
- * by the given {@link ResultHandler}
- *
- * @param query the query to search for
- * @param sort the sort query to apply
- * @param skip the number of elements to skip
- * @param limit the number of elements to fetch
- * @param projection the projection of fields to use
- * @param handler the handler to convert result elements with
- * @param params the parameters to replace # symbols
- * @param the element type
- * @return the list of elements found
+ * @param id of the object
+ * @return optional with the object or empty optional
*/
- public final
List
findSortedByQuery(String query, String sort, Integer skip, Integer limit, String projection, ResultHandler
handler, Object... params) {
- Find find = this.createFind(query, sort, skip, limit, projection, params);
- return this.convertIterable(find.map(handler));
+ public final Optional findById(String id) {
+ return Optional.ofNullable(
+ this.collection.find(MongoDBDataAccess.getIdFilter(id)).map(this::mapToEntity).first());
}
- private Find createFind(String query, String sort, Integer skip, Integer limit, String projection, Object... params) {
- Find find = this.collection.find(query, params);
- if((sort != null) && !sort.isEmpty()) {
- find.sort(sort);
- }
- if((projection != null) && !projection.isEmpty()) {
- find.projection(projection);
- }
- if(skip != null) {
- find.skip(skip);
- }
- if(limit != null) {
- find.limit(limit);
- }
- return find;
+ private static Bson getIdFilter(String id) {
+ return eq(new ObjectId(id));
}
/**
- * finds all elements containing the given searchString in any text field and sorts them accordingly.
- *
- * @param searchString the searchString to search for
- * @param sort the sort query to apply
- * @return the list of elements found
+ * @param id the id
+ * @deprecated use findById - this one will be deleted with next version
*/
- public final List searchSorted(String searchString, String sort) {
- return this.findSortedByQuery(MongoDBDataAccess.FULLTEXT_QUERY, sort, searchString);
+ @Deprecated
+ public final Optional findByObjectId(String id) {
+ return this.findById(id);
}
/**
- * queries with the given string, sorts the result and returns the first element. null
is returned if no element is found.
- *
- * @param query the query string
- * @param sort the sort string
- * @param params the parameters to replace # symbols
- * @return the first element found or null
if none is found
+ * @param id the id
+ * @deprecated use findById - this one will be deleted with next version
*/
- public final Optional findFirstByQuery(String query, String sort, Object... params) {
- Find find = this.collection.find(query, params);
- if((sort != null) && !sort.isEmpty()) {
- find.sort(sort);
- }
- Iterable as = find.limit(1).as(this.entityClass);
- Iterator iterator = as.iterator();
- if(iterator.hasNext()) {
- return Optional.of(iterator.next());
- }
- return Optional.empty();
+ @Deprecated
+ public final Optional findByStringId(String id) {
+ return this.findById(id);
}
- public final Optional findByObjectId(String id) {
- return Optional.ofNullable(this.collection.findOne(new ObjectId(id)).as(this.entityClass));
+ /**
+ * @param query the query as Bson
+ * @return the number of elements matching the query
+ */
+ public final long count(Bson query) {
+ return this.collection.countDocuments(query);
}
- public final Optional findByStringId(String id) {
- return Optional.ofNullable(this.collection.findOne("{\"_id\":#}", id).as(this.entityClass));
+ private static Bson createQuery(String query, Object... params) {
+ String filledQuery = query;
+
+ for (Object param : params) {
+ if (filledQuery.indexOf('#') != -1) {
+ filledQuery = filledQuery.replaceFirst("#", "\\\"" + param.toString() + "\\\"");
+ }
+ }
+
+ return BsonDocument.parse(filledQuery);
+ }
+
+
+ protected T mapToEntity(Document document) {
+ try {
+ return this.mapper.readValue(document.toJson(), this.entityClass);
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
}
/**
- * @param query the query string
- * @param parameter the parameters to replace # symbols
- * @return the number of elements matching the query
+ * @param object to save
+ * @return saved object
*/
- public final long count(String query, Object... parameter) {
- return this.collection.count(query, parameter);
+ public final T save(T object) {
+ try {
+ Document document = Document.parse(this.mapper.writeValueAsString(object));
+ if (this.collection.countDocuments(MongoDBDataAccess.getIdFilter(object.getId())) == 0) {
+ this.collection.insertOne(document);
+ } else {
+ this.collection.replaceOne(MongoDBDataAccess.getIdFilter(object.getId()), document);
+ }
+ return object;
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException(e);
+ }
}
- public final T save(T object) {
- this.collection.save(object);
- return object;
+ /**
+ * @param id of the object, that will be deleted
+ */
+ public final void deleteById(String id) {
+ this.collection.deleteOne(MongoDBDataAccess.getIdFilter(id));
}
+ /**
+ * @param id the di
+ * @deprecated use deleteById - this one will be deleted with next version
+ */
+ @Deprecated
public final void deleteByObjectId(String id) {
- this.collection.remove(new ObjectId(id));
+ this.deleteById(id);
}
+ /**
+ * @param id the di
+ * @deprecated use deleteById - this one will be deleted with next version
+ */
+ @Deprecated
public final void deleteByStringId(String id) {
- this.collection.remove("{\"_id\":#}", id);
+ this.deleteById(id);
}
- public final void delete(String query, Object... parameter) {
- this.collection.remove(query, parameter);
+ /**
+ * @param query to select the objects that will be deleted
+ */
+ public final void delete(String query) {
+ this.collection.deleteOne(BsonDocument.parse(query));
}
- public final Update update(ObjectId id) {
- return this.collection.update(id);
+ /**
+ * @param id of the object
+ * @param update list of updates to perfom
+ */
+ public final void update(ObjectId id, List extends Bson> update) {
+ this.collection.updateOne(eq(id), update);
}
- public final Update update(String query) {
- return this.collection.update(query);
+ /**
+ * @param query to select the objects that will be updated
+ * @param update list of updates to perfom
+ */
+ public final void update(String query, List extends Bson> update) {
+ this.collection.updateOne(BsonDocument.parse(query), update);
}
- public final Update update(String query, Object... parameter) {
- return this.collection.update(query, parameter);
+ /**
+ * @return the MongoCollection
+ */
+ public MongoCollection getCollection() {
+ return this.collection;
}
- @Deprecated
- public MongoCollection getCollection() {
- return this.collection;
+ /**
+ * @return the db
+ */
+ public MongoDatabase getDb() {
+ return this.db;
}
+ /**
+ * @param bucket name of the bucket
+ * @return the GridFS bucket
+ */
public GridFSBucket getGridFSBucket(String bucket) {
- if(bucket == null || bucket.isEmpty()) {
+ if (bucket == null || bucket.isEmpty()) {
throw new IllegalArgumentException();
}
return GridFSBuckets.create(this.db, bucket);
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoDBInit.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoDBInit.java
index 4209af1e..b10ff39e 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoDBInit.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/MongoDBInit.java
@@ -20,14 +20,9 @@
* #L%
*/
-import java.io.IOException;
-import java.util.Scanner;
-
-import javax.annotation.PostConstruct;
-
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
-import com.mongodb.MongoClient;
+import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;
import de.taimos.daemon.spring.conditional.OnSystemProperty;
@@ -38,6 +33,10 @@
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.stereotype.Component;
+import javax.annotation.PostConstruct;
+import java.io.IOException;
+import java.util.Scanner;
+
/**
* Copyright 2014 Taimos GmbH
@@ -77,7 +76,7 @@ public void initDatabase() {
MongoDBInit.LOGGER.info("Scanning for collection data");
for (Resource res : resources) {
String filename = res.getFilename();
- if(filename != null) {
+ if (filename != null) {
String collection = filename.substring(0, filename.length() - 7);
MongoDBInit.LOGGER.info("Found collection file: {}", collection);
MongoCollection dbCollection = db.getCollection(collection, DBObject.class);
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/config/FakeClientConfig.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/config/FakeClientConfig.java
index ed1b14a2..657f8f55 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/config/FakeClientConfig.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/config/FakeClientConfig.java
@@ -20,9 +20,7 @@
* #L%
*/
-import com.mongodb.ConnectionString;
-import com.mongodb.MongoClient;
-import com.mongodb.ServerAddress;
+import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import de.bwaldvogel.mongo.MongoServer;
import de.bwaldvogel.mongo.backend.memory.MemoryBackend;
@@ -44,12 +42,8 @@ public MongoServer mongoServer() {
@Bean
public MongoClient mongoClient(MongoServer mongoServer) {
- return new MongoClient(new ServerAddress(mongoServer.bind()));
- }
-
- @Bean
- public com.mongodb.client.MongoClient mongoClient2(MongoServer mongoServer) {
return MongoClients.create(mongoServer.bindAndGetConnectionString());
}
+
}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/config/MongoDBConfig.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/config/MongoDBConfig.java
index 116b0eea..bebcc219 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/config/MongoDBConfig.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/config/MongoDBConfig.java
@@ -20,24 +20,28 @@
* #L%
*/
-import java.util.concurrent.TimeUnit;
-
-import com.mongodb.DB;
-import com.mongodb.MongoClient;
+import com.mongodb.MongoClientSettings;
import com.mongodb.ReadConcern;
import com.mongodb.ReadPreference;
import com.mongodb.WriteConcern;
+import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoDatabase;
-import de.taimos.dvalin.mongo.JongoFactory;
+import de.taimos.dvalin.mongo.JodaCodec;
import io.mongock.api.config.LegacyMigration;
import io.mongock.driver.mongodb.sync.v4.driver.MongoSync4Driver;
import io.mongock.runner.standalone.MongockStandalone;
import io.mongock.runner.standalone.RunnerStandaloneBuilder;
-import org.jongo.Jongo;
+import org.bson.codecs.configuration.CodecRegistries;
+import org.bson.codecs.configuration.CodecRegistry;
+import org.bson.codecs.pojo.PojoCodecProvider;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import java.util.concurrent.TimeUnit;
+
+import static org.bson.codecs.pojo.Conventions.DEFAULT_CONVENTIONS;
+
@Configuration
public class MongoDBConfig {
@@ -57,7 +61,7 @@ public class MongoDBConfig {
private String basePackage;
@Bean
- public RunnerStandaloneBuilder mongockRunner(com.mongodb.client.MongoClient mongoClient, Jongo jongo, DB legacyDB) {
+ public RunnerStandaloneBuilder mongockRunner(MongoClient mongoClient, MongoDatabase mongoDatabase) {
MongoSync4Driver driver = MongoSync4Driver.withDefaultLock(mongoClient, this.dbName);
driver.setWriteConcern(WriteConcern.MAJORITY.withJournal(true).withWTimeout(1000, TimeUnit.MILLISECONDS));
@@ -65,32 +69,30 @@ public RunnerStandaloneBuilder mongockRunner(com.mongodb.client.MongoClient mong
driver.setReadPreference(ReadPreference.primary());
driver.disableTransaction();
- RunnerStandaloneBuilder runnerStandaloneBuilder = MongockStandalone.builder().setDriver(driver).setTransactionEnabled(false);
- if (this.basePackage == null || this.basePackage.isEmpty()){
+ RunnerStandaloneBuilder runnerStandaloneBuilder = MongockStandalone.builder().setDriver(driver)
+ .setTransactionEnabled(false);
+ if (this.basePackage == null || this.basePackage.isEmpty()) {
throw new RuntimeException("LegacyMigration basePackage must be set!");
}
runnerStandaloneBuilder.addMigrationScanPackage(this.basePackage);
- if(mongockLegacyMigrationEnabled) {
+ if (mongockLegacyMigrationEnabled) {
LegacyMigration legacyMigration = new LegacyMigration();
legacyMigration.setOrigin(this.mongockLegacyTable);
runnerStandaloneBuilder.setLegacyMigration(legacyMigration);
}
- runnerStandaloneBuilder.addDependency(jongo).addDependency(legacyDB).buildRunner().execute();
+ runnerStandaloneBuilder.addDependency(mongoDatabase).buildRunner().execute();
return runnerStandaloneBuilder;
}
@Bean
public MongoDatabase mongoDatabase(MongoClient mongoClient) {
- return mongoClient.getDatabase(this.dbName);
- }
+ MongoDatabase database = mongoClient.getDatabase(this.dbName);
- @Bean
- public Jongo jongo(MongoClient mongoClient) {
- return JongoFactory.createDefault(mongoClient.getDB(this.dbName));
- }
+ CodecRegistry codecReg = CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
+ CodecRegistries.fromCodecs(new JodaCodec()), CodecRegistries.fromProviders(
+ PojoCodecProvider.builder().conventions(DEFAULT_CONVENTIONS).automatic(true).build()));
+ database.withCodecRegistry(codecReg);
- @Bean
- public DB mongoDB(MongoClient mongoClient){
- return mongoClient.getDB(this.dbName);
+ return database;
}
}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/config/RealClientConfig.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/config/RealClientConfig.java
index 207b228d..3673fc03 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/config/RealClientConfig.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/config/RealClientConfig.java
@@ -20,15 +20,18 @@
* #L%
*/
-import com.mongodb.MongoClient;
-import com.mongodb.MongoClientOptions;
-import com.mongodb.MongoClientURI;
+import com.mongodb.ConnectionString;
+import com.mongodb.MongoClientSettings;
+import com.mongodb.MongoClientSettings.Builder;
import com.mongodb.client.MongoClients;
import de.taimos.daemon.spring.conditional.OnSystemProperty;
+import de.taimos.dvalin.mongo.MongoClientOptionsFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
+import java.util.concurrent.TimeUnit;
+
@OnSystemProperty(propertyName = "mongodb.type", propertyValue = "real")
@Configuration
@@ -45,22 +48,15 @@ public class RealClientConfig {
@Bean
- public MongoClient mongoClient() {
- MongoClientOptions.Builder builder = MongoClientOptions.builder();
- builder.socketTimeout(this.socketTimeout);
- builder.connectTimeout(this.connectTimeout);
-
- return new MongoClient(new MongoClientURI(this.mongoURI, builder));
- }
-
- @Bean
- public com.mongodb.client.MongoClient mongoClient2() {
- MongoClientOptions.Builder builder = MongoClientOptions.builder();
- builder.socketTimeout(this.socketTimeout);
- builder.connectTimeout(this.connectTimeout);
- return MongoClients.create(new MongoClientURI(this.mongoURI, builder).getURI());
+ public com.mongodb.client.MongoClient mongoClient() {
+ Builder settingsBuilder = MongoClientSettings.builder();
+ settingsBuilder.applyConnectionString(new ConnectionString(this.mongoURI));
+ settingsBuilder.applyToSocketSettings(builder -> {
+ builder.connectTimeout(RealClientConfig.this.connectTimeout, TimeUnit.MILLISECONDS);
+ builder.readTimeout(RealClientConfig.this.socketTimeout, TimeUnit.MILLISECONDS);
+ });
+ return MongoClients.create(settingsBuilder.build());
}
-
}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/id/IdEntity.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/id/IdEntity.java
new file mode 100644
index 00000000..5af54ceb
--- /dev/null
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/id/IdEntity.java
@@ -0,0 +1,14 @@
+package de.taimos.dvalin.mongo.id;
+
+/**
+ * Copyright 2024 Cinovo AG
+ *
+ *
+ * @author fzwirn
+ */
+public abstract class IdEntity {
+ /**
+ * @return the unique id of the element
+ */
+ abstract public String getId();
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/id/MongoId.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/id/MongoId.java
new file mode 100644
index 00000000..6dbae176
--- /dev/null
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/id/MongoId.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 Benoît GUÉROUT and Yves AMSELLEM
+ *
+ * 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 de.taimos.dvalin.mongo.id;
+
+import java.lang.annotation.Retention;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Retention(RUNTIME)
+public @interface MongoId {
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/id/MongoObjectId.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/id/MongoObjectId.java
new file mode 100644
index 00000000..1361dfef
--- /dev/null
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/id/MongoObjectId.java
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2011 Benoît GUÉROUT and Yves AMSELLEM
+ *
+ * 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 de.taimos.dvalin.mongo.id;
+
+import java.lang.annotation.Retention;
+
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+@Retention(RUNTIME)
+public @interface MongoObjectId {
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/links/DLinkDAO.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/links/DLinkDAO.java
index b9a44ee4..1201f181 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/links/DLinkDAO.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/links/DLinkDAO.java
@@ -1,15 +1,17 @@
package de.taimos.dvalin.mongo.links;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
+import com.mongodb.client.FindIterable;
+import com.mongodb.client.MongoCollection;
+import com.mongodb.client.MongoDatabase;
+import com.mongodb.client.model.Filters;
+import org.bson.Document;
import org.bson.types.ObjectId;
-import org.jongo.Jongo;
-import org.jongo.MongoCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
+import java.util.ArrayList;
+import java.util.List;
+
/*
* #%L
* Spring DAO Mongo
@@ -34,22 +36,23 @@
@Repository
public class DLinkDAO implements IDLinkDAO {
- private final Jongo jongo;
+ private final MongoDatabase mongoDatabase;
@Autowired
- public DLinkDAO(Jongo jongo) {
- this.jongo = jongo;
+ public DLinkDAO(MongoDatabase mongoDatabase) {
+ this.mongoDatabase = mongoDatabase;
}
@Override
public > T resolve(DocumentLink link) {
- MongoCollection collection = this.jongo.getCollection(link.getTargetClass().getSimpleName());
- return collection.findOne(new ObjectId(link.getObjectId())).as(link.getTargetClass());
+ MongoCollection collection = this.mongoDatabase.getCollection(link.getTargetClass().getSimpleName(),
+ link.getTargetClass());
+ return (T) collection.find(new Document("_id", link.getObjectId()), link.getTargetClass()).first();
}
@Override
public > List resolve(List> links, Class targetClass) {
- MongoCollection collection = this.jongo.getCollection(targetClass.getSimpleName());
+ MongoCollection collection = this.mongoDatabase.getCollection(targetClass.getSimpleName(), targetClass);
List ids = new ArrayList<>();
for (DocumentLink link : links) {
if (!link.getTargetClass().equals(targetClass)) {
@@ -57,10 +60,10 @@ public > List resolve(List>
}
ids.add(new ObjectId(link.getObjectId()));
}
- Iterator it = collection.find("{\"_id\" : {\"$in\" : #}}", ids).as(targetClass).iterator();
+ FindIterable it = collection.find(Filters.in("_id", ids), targetClass);
List resolved = new ArrayList<>();
- while (it.hasNext()) {
- resolved.add(it.next());
+ for (T t : it) {
+ resolved.add(t);
}
return resolved;
}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/links/DLinkQuery.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/links/DLinkQuery.java
index ce063aa4..f766ca42 100644
--- a/mongodb/src/main/java/de/taimos/dvalin/mongo/links/DLinkQuery.java
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/links/DLinkQuery.java
@@ -20,15 +20,12 @@
* #L%
*/
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
-import org.jongo.MongoCollection;
-
import com.mongodb.DBObject;
-
+import com.mongodb.client.model.Projections;
import de.taimos.dvalin.mongo.MongoDBDataAccess;
+import org.bson.conversions.Bson;
+
+import java.util.List;
/**
* QueryHelper to convert query result to a list of DLinks. It only queries the fields necessary to construct links.
@@ -52,28 +49,20 @@ public DLinkQuery(Class targetClass, String labelField) {
this.labelField = labelField;
}
- public List> find(MongoDBDataAccess dataAccess, String query, Object... parameter) {
- return dataAccess.findSortedByQuery(query, null, null, null, String.format("{%s:1}", this.labelField), this::convert, parameter);
+ public List> find(MongoDBDataAccess> dataAccess, Bson query) {
+ return dataAccess.findSortedByQuery(query, null, null, null, Projections.include(this.labelField), this::convert);
}
- @Deprecated
- public List> find(MongoCollection collection, String query, Object... parameter) {
- Iterator> it = collection.find(query, parameter).projection(String.format("{%s:1}", this.labelField)).map(this::convert).iterator();
-
- List> objects = new ArrayList<>();
- while (it.hasNext()) {
- DocumentLink link = it.next();
- objects.add(link);
+ private DocumentLink convert(Object result) {
+ if (!(result instanceof DBObject)) {
+ throw new RuntimeException("Wront response for DocumentLink");
}
- return objects;
- }
-
- private DocumentLink convert(DBObject result) {
- if (!result.containsField("_id") || !result.containsField(DLinkQuery.this.labelField)) {
+ if (!((DBObject) result).containsField("_id") ||
+ !((DBObject) result).containsField(DLinkQuery.this.labelField)) {
throw new RuntimeException("Fields missing to construct DocumentLink");
}
- String id = result.get("_id").toString();
- String label = result.get(DLinkQuery.this.labelField).toString();
+ String id = ((DBObject) result).get("_id").toString();
+ String label = ((DBObject) result).get(DLinkQuery.this.labelField).toString();
return new DocumentLink<>(DLinkQuery.this.targetClass, id, label);
}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/DvalinJodaModule.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/DvalinJodaModule.java
new file mode 100644
index 00000000..fbc640d2
--- /dev/null
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/DvalinJodaModule.java
@@ -0,0 +1,22 @@
+package de.taimos.dvalin.mongo.mapper;
+
+import com.fasterxml.jackson.core.Version;
+import com.fasterxml.jackson.databind.module.SimpleModule;
+import org.joda.time.DateTime;
+
+/**
+ * Copyright 2024 Cinovo AG
+ *
+ *
+ * @author fzwirn
+ */
+public class DvalinJodaModule extends SimpleModule {
+
+ private static final long serialVersionUID = 232046413074427246L;
+
+ public DvalinJodaModule() {
+ super(new Version(1, 0, 0, null, "de.taimos.dvalin", "mongodb"));
+ this.addSerializer(DateTime.class, new JodaMapping.MongoDateTimeSerializer());
+ this.addDeserializer(DateTime.class, new JodaMapping.MongoDateTimeDeserializer());
+ }
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/IdSelector.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/IdSelector.java
new file mode 100644
index 00000000..96993af7
--- /dev/null
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/IdSelector.java
@@ -0,0 +1,12 @@
+package de.taimos.dvalin.mongo.mapper;
+
+/**
+ * Copyright 2024 Cinovo AG
+ *
+ *
+ * @author fzwirn
+ */
+public interface IdSelector {
+ boolean isId(T a);
+ boolean isObjectId(T a);
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/JacksonConfig.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/JacksonConfig.java
new file mode 100644
index 00000000..617b0442
--- /dev/null
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/JacksonConfig.java
@@ -0,0 +1,34 @@
+package de.taimos.dvalin.mongo.mapper;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.MapperFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.json.JsonMapper;
+
+/**
+ * Copyright 2024 Cinovo AG
+ *
+ *
+ * @author fzwirn
+ */
+public class JacksonConfig {
+ /**
+ * @return configured Jackson object mapper
+ */
+ public static ObjectMapper createObjectMapper() {
+ return JsonMapper.builder() //
+ .enable(MapperFeature.AUTO_DETECT_GETTERS) //
+ // enable SerializationFeatures
+ .enable(SerializationFeature.FAIL_ON_EMPTY_BEANS)//
+ // enable DeserializationFeature
+ .enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)//
+ // disable SerializationFeature
+ .disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)//
+ // disable DeserializationFeature
+ .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)//
+ .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)//
+ // modules
+ .addModule(new DvalinJodaModule()).build();
+ }
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/JodaMapping.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/JodaMapping.java
new file mode 100644
index 00000000..ed2bc9b7
--- /dev/null
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/JodaMapping.java
@@ -0,0 +1,65 @@
+package de.taimos.dvalin.mongo.mapper;
+
+/*
+ * #%L
+ * Spring DAO Mongo
+ * %%
+ * Copyright (C) 2013 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.format.ISODateTimeFormat;
+
+import java.io.IOException;
+
+/**
+ * Copyright 2015 Hoegernet
+ *
+ * (De-)Serializer for Jodatime
+ *
+ * @author Thorsten Hoeger
+ */
+public class JodaMapping {
+
+ public static class MongoDateTimeSerializer extends JsonSerializer {
+
+ @Override
+ public void serialize(DateTime value, JsonGenerator jgen, SerializerProvider provider) throws IOException {
+ jgen.writeStartObject();
+ jgen.writeStringField("$date", value.withZone(DateTimeZone.UTC).toString(ISODateTimeFormat.dateTime()));
+ jgen.writeEndObject();
+ }
+
+ }
+
+ public static class MongoDateTimeDeserializer extends JsonDeserializer {
+
+ @Override
+ public DateTime deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
+ JsonNode node = jp.getCodec().readTree(jp);
+ String date = node.get("$date").asText();
+ return ISODateTimeFormat.dateTimeParser().withZoneUTC().parseDateTime(date);
+ }
+ }
+}
diff --git a/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/ObjectIdMapping.java b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/ObjectIdMapping.java
new file mode 100644
index 00000000..b79ada08
--- /dev/null
+++ b/mongodb/src/main/java/de/taimos/dvalin/mongo/mapper/ObjectIdMapping.java
@@ -0,0 +1,40 @@
+package de.taimos.dvalin.mongo.mapper;
+
+import com.fasterxml.jackson.core.JacksonException;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.DeserializationContext;
+import com.fasterxml.jackson.databind.JsonDeserializer;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import java.io.IOException;
+
+/**
+ * Copyright 2024 Cinovo AG
+ *
+ *
+ * @author fzwirn
+ */
+public class ObjectIdMapping {
+ public static class ObjectIdSerializer extends JsonSerializer {
+
+ @Override
+ public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
+ gen.writeStartObject();
+ gen.writeFieldName("$oid");
+ gen.writeString(value);
+ gen.writeEndObject();
+ }
+ }
+
+ public static class ObjectIdDeserializer extends JsonDeserializer {
+ @Override
+ public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
+ JsonNode node = p.getCodec().readTree(p);
+ return node.get("$oid").textValue();
+ }
+
+ }
+}
diff --git a/mongodb/src/test/java/de/taimos/dvalin/mongo/ABaseTest.java b/mongodb/src/test/java/de/taimos/dvalin/mongo/ABaseTest.java
index 7aa7f075..1f30915c 100644
--- a/mongodb/src/test/java/de/taimos/dvalin/mongo/ABaseTest.java
+++ b/mongodb/src/test/java/de/taimos/dvalin/mongo/ABaseTest.java
@@ -23,10 +23,8 @@
* #L%
*/
-import java.math.BigDecimal;
-
import com.mongodb.ConnectionString;
-import com.mongodb.DB;
+import com.mongodb.MongoClientSettings;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
@@ -35,8 +33,14 @@
import de.bwaldvogel.mongo.ServerVersion;
import de.bwaldvogel.mongo.backend.memory.MemoryBackend;
import de.taimos.daemon.log4j.Log4jLoggingConfigurer;
-import org.jongo.Jongo;
-import org.junit.Assert;
+import org.bson.codecs.configuration.CodecRegistries;
+import org.bson.codecs.pojo.PojoCodecProvider;
+import org.junit.jupiter.api.Assertions;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+
+import static org.bson.codecs.pojo.Conventions.DEFAULT_CONVENTIONS;
/**
* Copyright 2015 Taimos GmbH
@@ -46,27 +50,31 @@
*/
public class ABaseTest {
- protected static final String dbName = "dvalin-mongo";
- private static final ServerAddress serverAddress = new ServerAddress(new MongoServer(new MemoryBackend().version(ServerVersion.MONGO_3_6)).bind());
+ public static final String dbName = "dvalin-mongo";
+
+ private static final ServerAddress serverAddress = new ServerAddress(
+ new MongoServer(new MemoryBackend().version(ServerVersion.MONGO_3_6)).bind());
- public static final MongoClient mongo = MongoClients.create(new ConnectionString(String.format("mongodb://%s:%d", ABaseTest.serverAddress.getHost(), ABaseTest.serverAddress.getPort())));
- public static final com.mongodb.MongoClient oldMongo = new com.mongodb.MongoClient(new ServerAddress(new MongoServer(new MemoryBackend().version(ServerVersion.MONGO_3_6)).bind()));;
+ public static final MongoClient mongo = MongoClients.create(new ConnectionString(
+ String.format("mongodb://%s:%d", ABaseTest.serverAddress.getHost(), ABaseTest.serverAddress.getPort())));
- public static final DB oldDB = ABaseTest.oldMongo.getDB(ABaseTest.dbName);
- public static final Jongo jongo = JongoFactory.createDefault(ABaseTest.oldMongo.getDB(ABaseTest.dbName));
- public static final MongoDatabase database = ABaseTest.mongo.getDatabase(ABaseTest.dbName);
+ public static final MongoDatabase database = ABaseTest.mongo.getDatabase(ABaseTest.dbName).withCodecRegistry(
+ CodecRegistries.fromRegistries(MongoClientSettings.getDefaultCodecRegistry(),
+ CodecRegistries.fromCodecs(new JodaCodec()),
+ CodecRegistries.fromProviders(
+ PojoCodecProvider.builder().conventions(DEFAULT_CONVENTIONS).automatic(true).build())));
static {
try {
new Log4jLoggingConfigurer().simpleLogging();
} catch (Exception e) {
- e.printStackTrace();
+ Assertions.fail(Arrays.toString(e.getStackTrace()));
}
}
protected static void assertEquals(BigDecimal bd1, BigDecimal bd2) {
- Assert.assertEquals(bd1.doubleValue(), bd2.doubleValue(), 0);
+ Assertions.assertEquals(bd1.doubleValue(), bd2.doubleValue(), 0);
}
/**
diff --git a/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkDAO.java b/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkDAO.java
index 439b43d4..5cbb6b16 100644
--- a/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkDAO.java
+++ b/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkDAO.java
@@ -20,10 +20,13 @@
* #L%
*/
+import com.mongodb.client.model.Filters;
+import de.taimos.dvalin.mongo.model.LinkObject;
+
public class LinkDAO extends AbstractMongoDAO {
public LinkObject findByName(String name) {
- return this.findFirstByQuery("{name:#}", null, name);
+ return this.findFirstByQuery(Filters.eq("name", name), null);
}
}
diff --git a/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkTest.java b/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkTest.java
new file mode 100644
index 00000000..ecc72844
--- /dev/null
+++ b/mongodb/src/test/java/de/taimos/dvalin/mongo/LinkTest.java
@@ -0,0 +1,97 @@
+/**
+ *
+ */
+package de.taimos.dvalin.mongo;
+
+/*
+ * #%L
+ * MongoDB support for dvalin
+ * %%
+ * Copyright (C) 2015 Taimos GmbH
+ * %%
+ * 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.
+ * #L%
+ */
+
+import java.lang.reflect.Field;
+import java.util.List;
+
+import de.taimos.dvalin.daemon.spring.InjectionUtils;
+import de.taimos.dvalin.mongo.links.DLinkDAO;
+import de.taimos.dvalin.mongo.model.LinkObject;
+import de.taimos.dvalin.mongo.model.LinkedObject;
+import de.taimos.dvalin.mongo.model.TestObject;
+import io.mongock.driver.mongodb.sync.v4.driver.MongoSync4Driver;
+import io.mongock.runner.standalone.MongockStandalone;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+/**
+ * Copyright 2015 Taimos GmbH
+ *
+ *
+ * @author thoeger
+ */
+public class LinkTest {
+
+ private static final LinkDAO dao = new LinkDAO();
+ private static final LinkedDAO ldao = new LinkedDAO();
+
+ private static final DLinkDAO dlinkDAO = new DLinkDAO(ABaseTest.mongo.getDatabase(ABaseTest.dbName));
+
+
+ @BeforeClass
+ public static void init() {
+ try {
+ System.setProperty("mongodb.name", ABaseTest.dbName);
+
+ Field dao2Field = AbstractMongoDAO.class.getDeclaredField("dataAccess");
+ dao2Field.setAccessible(true);
+ dao2Field.set(LinkTest.dao, new MongoDBDataAccess(ABaseTest.database, InjectionUtils.createDependencyDescriptor(dao2Field, LinkTest.dao)));
+ dao2Field.set(LinkTest.ldao, new MongoDBDataAccess(ABaseTest.database, InjectionUtils.createDependencyDescriptor(dao2Field, LinkTest.ldao)));
+
+
+ MongoSync4Driver driver = MongoSync4Driver.withDefaultLock(ABaseTest.mongo, ABaseTest.dbName);
+ driver.disableTransaction();
+ MongockStandalone.builder().setDriver(driver).addMigrationScanPackage("de.taimos.dvalin.mongo.changelog").setTransactionEnabled(false).setEnabled(true).buildRunner().execute();
+ LinkTest.dao.init();
+ LinkTest.ldao.init();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testLinks() {
+ LinkedObject lo1 = new LinkedObject();
+ lo1.setName("LinkedObject1");
+ lo1 = LinkTest.ldao.save(lo1);
+
+ LinkedObject lo2 = new LinkedObject();
+ lo2.setName("LinkedObject2");
+ lo2 = LinkTest.ldao.save(lo2);
+
+ LinkObject lo = new LinkObject();
+ lo.setName("LinkObject");
+ lo.getLinks().add(lo1.asLink());
+ lo.getLinks().add(lo2.asLink());
+ lo = LinkTest.dao.save(lo);
+
+ Assert.assertEquals(2, lo.getLinks().size());
+
+ List