Skip to content

Commit

Permalink
openhab#16308 Commit to share
Browse files Browse the repository at this point in the history
  • Loading branch information
ulbi committed Jan 24, 2024
1 parent 73402f6 commit 2871b94
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 48 deletions.
23 changes: 20 additions & 3 deletions bundles/org.openhab.persistence.mongodb/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,28 @@
<name>openHAB Add-ons :: Bundles :: Persistence Service :: MongoDB</name>

<dependencies>
<!-- https://mvnrepository.com/artifact/org.mongodb/mongo-java-driver -->
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>2.13.1</version>
<artifactId>mongodb-driver-sync</artifactId>
<version>4.11.1</version>
</dependency>
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongodb-crypt</artifactId>
<version>1.8.0</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.11</version>
</dependency>
<!-- MongoDB In-memory Server -->
<dependency>
<groupId>de.bwaldvogel</groupId>
<artifactId>mongo-java-server</artifactId>
<version>1.44.0</version>
<scope>test</scope>
</dependency>

</dependencies>
</project>
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import java.util.Map;
import java.util.Set;

import org.bson.Document;
import org.bson.types.ObjectId;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
Expand Down Expand Up @@ -59,12 +60,10 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import com.mongodb.DBCursor;
import com.mongodb.DBObject;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientURI;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;

/**
* This is the implementation of the MongoDB {@link PersistenceService}.
Expand Down Expand Up @@ -176,7 +175,7 @@ public void store(Item item, @Nullable String alias) {
String collectionName = collectionPerItem ? realItemName : this.collection;

@Nullable
DBCollection collection = connectToCollection(collectionName);
MongoCollection<Document> collection = connectToCollection(collectionName);

if (collection == null) {
// Logging is done in connectToCollection()
Expand All @@ -186,13 +185,13 @@ public void store(Item item, @Nullable String alias) {
String name = (alias != null) ? alias : realItemName;
Object value = this.convertValue(item.getState());

DBObject obj = new BasicDBObject();
Document obj = new Document();
obj.put(FIELD_ID, new ObjectId());
obj.put(FIELD_ITEM, name);
obj.put(FIELD_REALNAME, realItemName);
obj.put(FIELD_TIMESTAMP, new Date());
obj.put(FIELD_VALUE, value);
collection.save(obj);
collection.insertOne(obj);

logger.debug("MongoDB save {}={}", name, value);
}
Expand Down Expand Up @@ -236,7 +235,7 @@ private synchronized boolean isConnected() {
// Network problems may cause failure sometimes,
// even if the connection object was successfully created before.
try {
cl.getAddress();
cl.listDatabaseNames().first();
return true;
} catch (Exception ex) {
return false;
Expand All @@ -257,11 +256,11 @@ private synchronized boolean tryConnectToDatabase() {
logger.debug("Connect MongoDB");
disconnectFromDatabase();

this.cl = new MongoClient(new MongoClientURI(this.url));
this.cl = MongoClients.create(this.url);

// The mongo always succeeds in creating the connection.
// The MongoDB driver always succeeds in creating the connection.
// We have to actually force it to test the connection to try to connect to the server.
cl.getAddress();
cl.listDatabaseNames().first();

logger.debug("Connect MongoDB ... done");
return true;
Expand All @@ -286,7 +285,7 @@ private synchronized boolean tryConnectToDatabase() {
*
* @return The collection object when collection creation was successful. Null otherwise.
*/
private @Nullable DBCollection connectToCollection(String collectionName) {
private @Nullable MongoCollection<Document> connectToCollection(String collectionName) {
try {
@Nullable
MongoClient db = getDatabase();
Expand All @@ -296,9 +295,9 @@ private synchronized boolean tryConnectToDatabase() {
return null;
}

DBCollection mongoCollection = db.getDB(this.db).getCollection(collectionName);
MongoCollection<Document> mongoCollection = db.getDatabase(this.db).getCollection(collectionName);

BasicDBObject idx = new BasicDBObject();
Document idx = new Document();
idx.append(FIELD_ITEM, 1).append(FIELD_TIMESTAMP, 1);
mongoCollection.createIndex(idx);

Expand Down Expand Up @@ -338,7 +337,7 @@ public Iterable<HistoricItem> query(FilterCriteria filter) {

String collectionName = collectionPerItem ? realItemName : this.collection;
@Nullable
DBCollection collection = connectToCollection(collectionName);
MongoCollection<Document> collection = connectToCollection(collectionName);

// If collection creation failed, return nothing.
if (collection == null) {
Expand All @@ -355,7 +354,7 @@ public Iterable<HistoricItem> query(FilterCriteria filter) {
}

List<HistoricItem> items = new ArrayList<>();
BasicDBObject query = new BasicDBObject();
Document query = new Document();
if (filter.getItemName() != null) {
query.put(FIELD_ITEM, filter.getItemName());
}
Expand All @@ -370,10 +369,10 @@ public Iterable<HistoricItem> query(FilterCriteria filter) {
}

Object value = convertValue(filterState);
query.put(FIELD_VALUE, new BasicDBObject(op, value));
query.put(FIELD_VALUE, new Document(op, value));
}

BasicDBObject dateQueries = new BasicDBObject();
Document dateQueries = new Document();
if (filter.getBeginDate() != null) {
dateQueries.put("$gte", Date.from(filter.getBeginDate().toInstant()));
}
Expand All @@ -387,32 +386,39 @@ public Iterable<HistoricItem> query(FilterCriteria filter) {
logger.debug("Query: {}", query);

Integer sortDir = (filter.getOrdering() == Ordering.ASCENDING) ? 1 : -1;
DBCursor cursor = collection.find(query).sort(new BasicDBObject(FIELD_TIMESTAMP, sortDir))
.skip(filter.getPageNumber() * filter.getPageSize()).limit(filter.getPageSize());

while (cursor.hasNext()) {
BasicDBObject obj = (BasicDBObject) cursor.next();

final State state;
if (item instanceof NumberItem) {
state = new DecimalType(obj.getDouble(FIELD_VALUE));
} else if (item instanceof DimmerItem) {
state = new PercentType(obj.getInt(FIELD_VALUE));
} else if (item instanceof SwitchItem) {
state = OnOffType.valueOf(obj.getString(FIELD_VALUE));
} else if (item instanceof ContactItem) {
state = OpenClosedType.valueOf(obj.getString(FIELD_VALUE));
} else if (item instanceof RollershutterItem) {
state = new PercentType(obj.getInt(FIELD_VALUE));
} else if (item instanceof DateTimeItem) {
state = new DateTimeType(
ZonedDateTime.ofInstant(obj.getDate(FIELD_VALUE).toInstant(), ZoneId.systemDefault()));
} else {
state = new StringType(obj.getString(FIELD_VALUE));
MongoCursor<Document> cursor = null;
try {
cursor = collection.find(query).sort(new Document(FIELD_TIMESTAMP, sortDir))
.skip(filter.getPageNumber() * filter.getPageSize()).limit(filter.getPageSize()).iterator();

while (cursor.hasNext()) {
Document obj = cursor.next();

final State state;
if (item instanceof NumberItem) {
state = new DecimalType(obj.getDouble(FIELD_VALUE));
} else if (item instanceof DimmerItem) {
state = new PercentType(obj.getInteger(FIELD_VALUE));
} else if (item instanceof SwitchItem) {
state = OnOffType.valueOf(obj.getString(FIELD_VALUE));
} else if (item instanceof ContactItem) {
state = OpenClosedType.valueOf(obj.getString(FIELD_VALUE));
} else if (item instanceof RollershutterItem) {
state = new PercentType(obj.getInteger(FIELD_VALUE));
} else if (item instanceof DateTimeItem) {
state = new DateTimeType(
ZonedDateTime.ofInstant(obj.getDate(FIELD_VALUE).toInstant(), ZoneId.systemDefault()));
} else {
state = new StringType(obj.getString(FIELD_VALUE));
}

items.add(new MongoDBItem(realItemName, state,
ZonedDateTime.ofInstant(obj.getDate(FIELD_TIMESTAMP).toInstant(), ZoneId.systemDefault())));
}
} finally {
if (cursor != null) {
cursor.close();
}

items.add(new MongoDBItem(realItemName, state,
ZonedDateTime.ofInstant(obj.getDate(FIELD_TIMESTAMP).toInstant(), ZoneId.systemDefault())));
}

return items;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/**
* Copyright (c) 2010-2024 Contributors to the openHAB project
*
* See the NOTICE file(s) distributed with this work for additional
* information.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*/
package org.openhab.persistence.mongodb.internal;

import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.*;

import java.net.InetSocketAddress;

import org.bson.Document;
import org.junit.jupiter.api.Test;

import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoDatabase;

import de.bwaldvogel.mongo.MongoServer;
import de.bwaldvogel.mongo.backend.memory.MemoryBackend;

/**
* This is the implementation of the test for MongoDB {@link PersistenceService}.
*
* @author René Ulbricht - Initial contribution
*/
public class MongoDBPersistenceServiceTest {

@Test
public void testMongoMemory() {
// Mock the MongoDB server
MongoServer server = new MongoServer(new MemoryBackend());
InetSocketAddress serverAddress = server.bind();

// Create a MongoClient connected to the mock server
MongoClient mongoClient = MongoClients
.create("mongodb://" + serverAddress.getHostName() + ":" + serverAddress.getPort());

// Create a database and collection
MongoDatabase database = mongoClient.getDatabase("testDatabase");
MongoCollection<Document> collection = database.getCollection("testCollection");

// Create a document to insert
Document document = new Document("key", "value");

// Insert the document into the collection
collection.insertOne(document);

// Query the data
Document result = collection.find().first();

// Verify the data
assertEquals(document, result);

// Clean up
collection.drop();
database.drop();
mongoClient.close();
server.shutdown();
}
}

0 comments on commit 2871b94

Please sign in to comment.