All Downloads are FREE. Search and download functionalities are using the official Maven repository.

clients.mongodb.DBMongoClient Maven / Gradle / Ivy

The newest version!
package clients.mongodb;

import clients.mongodb.codec.DocumentCodecProvider;
import com.github.simondan.definition.*;
import com.github.simondan.definition.database.*;
import com.github.simondan.definition.fields.IDField;
import com.mongodb.MongoClient;
import com.mongodb.client.*;
import com.mongodb.client.model.UpdateOptions;
import config.InternalConfig;
import org.bson.Document;
import org.bson.codecs.configuration.*;
import org.bson.types.ObjectId;
import util.DatabaseUtil;

import java.util.*;

/**
 * Klasse für den Mongo-Datenbank-Zugriff.
 * Kann nicht direkt initialisiert werden, eine Instanz wird über die Methode "getInstance" geliefert.
 * Bei der Erzeugung wird eine Verbindung zu der in der Config festgelegten Datenbank erzeugt.
 * Diese Klasse bietet alle nötigen Methoden zu Datenbank-Abfragen und Manipulationen
 *
 * @author Simon Danner, 03.08.2015.
 */
public class DBMongoClient implements IDatabaseClient
{
  private MongoDatabase database;

  @Override
  public boolean providesEmbedded()
  {
    return true;
  }

  @Override
  public IEmbeddedDB startEmbedded()
  {
    MongoDBEmbedded embedded = new MongoDBEmbedded();
    embedded.startUp();
    return embedded;
  }

  @Override
  public boolean connect()
  {
    MongoClient mongoClient = new MongoClient(InternalConfig.DATABASE_HOST, InternalConfig.DATABASE_PORT);
    database = mongoClient.getDatabase(InternalConfig.DATABASE_NAME);
    return true;
  }

  @Override
  public  T findOne(ObjectBox pBox, SearchCondition... pConditions)
  {
    return _getCollection(pBox).find(_conditionsToDocument(pConditions)).first();
  }

  @Override
  public  List find(ObjectBox pBox, SearchCondition... pConditions)
  {
    return _iterableToList(_getCollection(pBox).find(_conditionsToDocument(pConditions)));
  }

  @Override
  public  void insert(ObjectBox pBox, T pObject)
  {
    _getCollection(pBox).insertOne(pObject);
    _checkNewObjectID(pBox, pObject);
  }

  @Override
  public  void insert(ObjectBox pBox, Collection pObjects)
  {
    _getCollection(pBox).insertMany(new ArrayList<>(pObjects));
    _checkNewObjectID(pBox, pObjects);
  }

  @Override
  public  void update(ObjectBox pBox, T pObject, boolean pUpsert,
                                                        SearchCondition... pConditions)
  {
    Document filter = _conditionsToDocument(pObject, pConditions);
    _getCollection(pBox).replaceOne(filter, pObject, new UpdateOptions().upsert(true));
    _checkNewObjectID(pBox, pObject);
  }

  @Override
  public  void remove(ObjectBox pBox, T pObject)
  {
    remove(pBox, DatabaseUtil.storableObjectToConditions(pObject));
  }

  @Override
  public  void remove(ObjectBox pBox, SearchCondition... pConditions)
  {
    _getCollection(pBox).deleteMany(_conditionsToDocument(pConditions));
  }

  @Override
  public  int count(ObjectBox pBox, SearchCondition... pConditions)
  {
    return (int) _getCollection(pBox).count(_conditionsToDocument(pConditions));
  }

  @Override
  public  int size(ObjectBox pBox)
  {
    return (int) _getCollection(pBox).count();
  }

  @Override
  public  List getBoxAsList(ObjectBox pBox)
  {
    List list = new ArrayList<>();
    for (T object : _getCollection(pBox).find())
      list.add(object);
    return list;
  }

  @Override
  public  List getSingleFieldValues(ObjectBox pBox,
                                                                              AbstractFieldDescription pDescription)
  {
    List values = new ArrayList<>();
    for (T object : getBoxAsList(pBox))
      values.add(object.getValue(pDescription));
    return values;
  }

  /**
   * Gibt eine Datenbank-Collection anhand eines ObjectBox-Typen zurück.
   * Dabei wird auch die Object-Class der annotations.Collection gesetzt.
   *
   * @param pBox die ObjectBox
   * @return die bestimmte Mongo-handling.DB-annotations.Collection der aktuellen handling.DB-Verbindung
   */
  private  MongoCollection _getCollection(ObjectBox pBox)
  {
    MongoCollection collection = database.getCollection(pBox.getName(), pBox.getObjectClass());
    return collection.withCodecRegistry(_getCodecRegistry(pBox.getObjectClass()));
  }

  /**
   * Liefert eine CodecRegistry, um Collections abzufragen, die Objekte von eigenen Erweiterungen von Document
   * zurückgeben können (Object-Class von MongoDB-Collections)
   *
   * @param pObjectClass die Klasse, die von der annotations.Collection abgefragt werden soll
   * @return eine CodecRegistry mit einem eigenen DocumentCodec (siehe. Klasse: CustomDocumentCodec)
   */
  private CodecRegistry _getCodecRegistry(Class pObjectClass)
  {
    CodecRegistry defaultCodec = MongoClient.getDefaultCodecRegistry();
    CodecRegistry documentCodec = CodecRegistries.fromProviders(new DocumentCodecProvider<>(pObjectClass));
    return CodecRegistries.fromRegistries(defaultCodec, documentCodec);
  }

  private Document _conditionsToDocument(SearchCondition... pConditions)
  {
    Document document = new Document();
    for (SearchCondition condition : pConditions)
    {
      boolean isID = condition.getFieldDescription() instanceof IDField;
      Object condValue = condition.getValue();
      String key = isID ? InternalConfig.OBJECT_ID : condition.getKey();
      Object value = isID ? condValue != null ? new ObjectId(condValue.toString()) : new ObjectId() : condValue;
      document.put(key, value);
    }

    return document;
  }

  private Document _conditionsToDocument(AbstractStorableObject pObject, SearchCondition... pConditions)
  {
    Document filter = _conditionsToDocument(pConditions);
    if (pObject instanceof AbstractUniqueStorableObject && ((AbstractUniqueStorableObject) pObject).getID() == null)
      ((AbstractUniqueStorableObject) pObject).setID(filter.get(InternalConfig.OBJECT_ID).toString());
    return filter;
  }


  /**
   * Wandelt ein Find-Iterable in eine Liste um
   */
  private  List _iterableToList(FindIterable pIterable)
  {
    List list = new ArrayList<>();
    for (T object : pIterable)
      list.add(object);

    return list;
  }

  private  void _checkNewObjectID(ObjectBox pBox, Collection pObjects)
  {
    for (T object : pObjects)
      _checkNewObjectID(pBox, object);
  }

  private  void _checkNewObjectID(ObjectBox pBox, T pObject)
  {
    if (pObject instanceof AbstractUniqueStorableObject && ((AbstractUniqueStorableObject) pObject).getID() == null)
    {
      T latest = _getCollection(pBox).find().sort(new Document("id", -1)).limit(1).first(); //TODO besser
      String latestID = ((AbstractUniqueStorableObject) latest).getID();
      ((AbstractUniqueStorableObject) pObject).setID(latestID);
    }
  }

  /**
   * Setzt für ein Objekt aus der Datenbank für alle Fremdschlüssel-Referenzen die richtigen Werte ein
   *
   * @param pObject     das Dokument, welches untersucht werden soll
   * @param pCollection die betreffende annotations.Collection
   */
  @SuppressWarnings("unchecked")
  private  void _fillForeignKeys(T pObject, ObjectBox pCollection)
  {
    /*for (AbstractFieldDescription description : pObject.getFieldDescriptions())
    {
      Reference foreignKey = metadata.getForeignKey();
      if (foreignKey != null)
      {
        Object replacement = null;

        //Sonderfall: Bei Maps können die Keys auch Referenzen sein
        if (metadata.getTypeInfo().getType().equals(TypeInfo.ColumnType.MAP))
        {
          Map oldMap = (Map) pDocument.get(key);
          Map newMap = new LinkedHashMap<>();

          for (Object objectID : oldMap.keySet())
          {
            String listColumn = foreignKey.getRelatedColumn().split("\\.")[0];
            String queryKey = listColumn + "." + InternalConfig.OBJECT_ID;
            Document query = new Document(queryKey, new ObjectId(objectID.toString()));
            Document match = new Document("$match", query);
            Document unwind = new Document("$unwind", "$" + listColumn);
            List list = Arrays.asList(match, unwind, match);
            Document result = getCollection(foreignKey.getCollection()).aggregate(list).first();
            Document innerResult = (Document) result.get(listColumn);
            newMap.put(innerResult.get(foreignKey.getRelatedColumn().split("\\.")[1]), oldMap.get(objectID));
          }

          replacement = newMap;
        }
        else
        {
          Object ref = pDocument.get(key);
          Document refTarget = _findDocumentByID(_getDocumentCollection(foreignKey.getCollection()), ref.toString());
          if (refTarget != null)
            replacement = refTarget.get(key);
        }

        if (replacement != null)
          pDocument.put(key, replacement);
      }
    }*/
  }

  /**
   * Fügt die Referenz-IDs (Object-IDs) für Fremdschlüssel-Spalten ein
   *
   * @param pMetadata   die Metadaten der Spalte
   * @param pForeignKey die Informationen zum Fremdschlüssel
   * @param pData       der neue Wert (echte Wert)
   * @return der neue Referenz-Wert
   */
  /*
  private Object _fillObjectIDs(ObjectMetadata pMetadata, Reference pForeignKey, Object pData)
  {
    if (pData == null || pData.equals(""))
      return pData; //Wenn das Ziel der Ref gelöscht wurde, wird dieser Wert zurückgesetzt und kann nicht gefüllt werden

    if (pMetadata.getTypeInfo().getType() == TypeInfo.ColumnType.MAP)
    {
      Map oldMap = (LinkedHashMap) pData;
      Map newMap = new LinkedHashMap<>();

      for (Object realKey : oldMap.keySet())
      {
        String listColumn = pForeignKey.getRelatedColumn().split("\\.")[0];
        Document query = new Document(pForeignKey.getRelatedColumn(), realKey);
        Document match = new Document("$match", query);
        Document unwind = new Document("$unwind", "$" + listColumn);
        List list = Arrays.asList(match, unwind, match);
        Document result = getCollection(pForeignKey.getCollection()).aggregate(list).first();
        Document innerResult = (Document) result.get(listColumn);
        newMap.put(innerResult.get(InternalConfig.OBJECT_ID).toString(), oldMap.get(realKey));
      }
      return newMap;
    }
    else
    {
      Document query = new Document(pForeignKey.getRelatedColumn(), pData);
      Document relatingRow = getCollection(pForeignKey.getCollection()).find(query).first();
      return relatingRow.get(InternalConfig.OBJECT_ID);
    }
  }*/
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy