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

com.helger.phoss.smp.backend.mongodb.mgr.SMPBusinessCardManagerMongoDB Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (C) 2019-2024 Philip Helger and contributors
 * philip[at]helger[dot]com
 *
 * 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 com.helger.phoss.smp.backend.mongodb.mgr;

import java.time.LocalDate;
import java.util.Collection;
import java.util.Date;
import java.util.List;

import javax.annotation.Nonnegative;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;

import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.helger.commons.ValueEnforcer;
import com.helger.commons.annotation.ELockType;
import com.helger.commons.annotation.IsLocked;
import com.helger.commons.annotation.ReturnsMutableCopy;
import com.helger.commons.annotation.ReturnsMutableObject;
import com.helger.commons.callback.CallbackList;
import com.helger.commons.collection.impl.CommonsArrayList;
import com.helger.commons.collection.impl.CommonsHashSet;
import com.helger.commons.collection.impl.ICommonsList;
import com.helger.commons.collection.impl.ICommonsSet;
import com.helger.commons.state.EChange;
import com.helger.commons.typeconvert.TypeConverter;
import com.helger.peppolid.IParticipantIdentifier;
import com.helger.peppolid.factory.IIdentifierFactory;
import com.helger.phoss.smp.domain.businesscard.ISMPBusinessCard;
import com.helger.phoss.smp.domain.businesscard.ISMPBusinessCardCallback;
import com.helger.phoss.smp.domain.businesscard.ISMPBusinessCardManager;
import com.helger.phoss.smp.domain.businesscard.SMPBusinessCard;
import com.helger.phoss.smp.domain.businesscard.SMPBusinessCardContact;
import com.helger.phoss.smp.domain.businesscard.SMPBusinessCardEntity;
import com.helger.phoss.smp.domain.businesscard.SMPBusinessCardIdentifier;
import com.helger.phoss.smp.domain.businesscard.SMPBusinessCardName;
import com.helger.photon.audit.AuditHelper;
import com.mongodb.client.model.Indexes;
import com.mongodb.client.result.DeleteResult;

/**
 * Manager for all {@link SMPBusinessCard} objects.
 *
 * @author Philip Helger
 */
public final class SMPBusinessCardManagerMongoDB extends AbstractManagerMongoDB implements ISMPBusinessCardManager
{
  private static final Logger LOGGER = LoggerFactory.getLogger (SMPBusinessCardManagerMongoDB.class);

  private static final String BSON_ID = "id";
  private static final String BSON_SERVICE_GROUP_ID = "sgid";
  private static final String BSON_ENTITIES = "entities";
  private static final String BSON_NAMES = "names";
  private static final String BSON_COUNTRYCODE = "countrycode";
  private static final String BSON_GEOINFO = "geoinfo";
  private static final String BSON_IDS = "ids";
  private static final String BSON_WEBSITES = "websites";
  private static final String BSON_CONTACTS = "contacts";
  private static final String BSON_ADDITIONAL = "additional";
  private static final String BSON_REGDATE = "regdate";
  private static final String BSON_TYPE = "type";
  private static final String BSON_NAME = "name";
  private static final String BSON_PHONE = "phone";
  private static final String BSON_EMAIL = "email";
  private static final String BSON_SCHEME = "scheme";
  private static final String BSON_VALUE = "value";
  private static final String BSON_LANGUAGE = "language";

  private final IIdentifierFactory m_aIdentifierFactory;
  private final CallbackList  m_aCBs = new CallbackList <> ();

  public SMPBusinessCardManagerMongoDB (@Nonnull final IIdentifierFactory aIdentifierFactory)
  {
    super ("smp-businesscard");
    m_aIdentifierFactory = aIdentifierFactory;
    getCollection ().createIndex (Indexes.ascending (BSON_ID));
  }

  @Nonnull
  @ReturnsMutableObject
  public CallbackList  bcCallbacks ()
  {
    return m_aCBs;
  }

  @Nonnull
  @ReturnsMutableCopy
  public static Document toBson (@Nonnull final SMPBusinessCardName aValue)
  {
    final Document ret = new Document ().append (BSON_NAME, aValue.getName ());
    if (aValue.hasLanguageCode ())
      ret.append (BSON_LANGUAGE, aValue.getLanguageCode ());
    return ret;
  }

  @Nonnull
  @ReturnsMutableCopy
  public static SMPBusinessCardName toBCName (@Nonnull final Document aDoc)
  {
    return new SMPBusinessCardName (aDoc.getString (BSON_NAME), aDoc.getString (BSON_LANGUAGE));
  }

  @Nonnull
  @ReturnsMutableCopy
  public static Document toBson (@Nonnull final SMPBusinessCardIdentifier aValue)
  {
    return new Document ().append (BSON_ID, aValue.getID ())
                          .append (BSON_SCHEME, aValue.getScheme ())
                          .append (BSON_VALUE, aValue.getValue ());
  }

  @Nonnull
  @ReturnsMutableCopy
  public static SMPBusinessCardIdentifier toBCIdentifier (@Nonnull final Document aDoc)
  {
    return new SMPBusinessCardIdentifier (aDoc.getString (BSON_ID),
                                          aDoc.getString (BSON_SCHEME),
                                          aDoc.getString (BSON_VALUE));
  }

  @Nonnull
  @ReturnsMutableCopy
  public static Document toBson (@Nonnull final SMPBusinessCardContact aValue)
  {
    final Document ret = new Document ().append (BSON_ID, aValue.getID ());
    if (aValue.hasType ())
      ret.append (BSON_TYPE, aValue.getType ());
    if (aValue.hasName ())
      ret.append (BSON_NAME, aValue.getName ());
    if (aValue.hasPhoneNumber ())
      ret.append (BSON_PHONE, aValue.getPhoneNumber ());
    if (aValue.hasEmail ())
      ret.append (BSON_EMAIL, aValue.getEmail ());
    return ret;
  }

  @Nonnull
  @ReturnsMutableCopy
  public static SMPBusinessCardContact toBCContact (@Nonnull final Document aDoc)
  {
    return new SMPBusinessCardContact (aDoc.getString (BSON_ID),
                                       aDoc.getString (BSON_TYPE),
                                       aDoc.getString (BSON_NAME),
                                       aDoc.getString (BSON_PHONE),
                                       aDoc.getString (BSON_EMAIL));
  }

  @Nonnull
  @ReturnsMutableCopy
  public static Document toBson (@Nonnull final SMPBusinessCardEntity aValue)
  {
    final Document ret = new Document ().append (BSON_ID, aValue.getID ());
    // Mandatory fields
    {
      final ICommonsList  aNames = new CommonsArrayList <> ();
      for (final SMPBusinessCardName aName : aValue.names ())
        aNames.add (toBson (aName));
      ret.append (BSON_NAMES, aNames);
    }
    ret.append (BSON_COUNTRYCODE, aValue.getCountryCode ());

    // Optional fields
    if (aValue.hasGeographicalInformation ())
      ret.append (BSON_GEOINFO, aValue.getGeographicalInformation ());
    {
      final ICommonsList  aIDs = new CommonsArrayList <> ();
      for (final SMPBusinessCardIdentifier aID : aValue.identifiers ())
        aIDs.add (toBson (aID));
      if (aIDs.isNotEmpty ())
        ret.append (BSON_IDS, aIDs);
    }
    if (aValue.websiteURIs ().isNotEmpty ())
      ret.append (BSON_WEBSITES, aValue.websiteURIs ());
    {
      final ICommonsList  aContacts = new CommonsArrayList <> ();
      for (final SMPBusinessCardContact aContact : aValue.contacts ())
        aContacts.add (toBson (aContact));
      if (aContacts.isNotEmpty ())
        ret.append (BSON_CONTACTS, aContacts);
    }
    if (aValue.hasAdditionalInformation ())
      ret.append (BSON_ADDITIONAL, aValue.getAdditionalInformation ());
    if (aValue.hasRegistrationDate ())
      ret.append (BSON_REGDATE, TypeConverter.convert (aValue.getRegistrationDate (), Date.class));

    return ret;
  }

  @Nonnull
  @ReturnsMutableCopy
  public static SMPBusinessCardEntity toBCEntity (@Nonnull final Document aDoc)
  {
    final SMPBusinessCardEntity ret = new SMPBusinessCardEntity (aDoc.getString (BSON_ID));
    final List  aNames = aDoc.getList (BSON_NAMES, Document.class);
    if (aNames != null)
      for (final Document aItemDoc : aNames)
        ret.names ().add (toBCName (aItemDoc));
    ret.setCountryCode (aDoc.getString (BSON_COUNTRYCODE));
    ret.setGeographicalInformation (aDoc.getString (BSON_GEOINFO));
    final List  aIDList = aDoc.getList (BSON_IDS, Document.class);
    if (aIDList != null)
      for (final Document aItemDoc : aIDList)
        ret.identifiers ().add (toBCIdentifier (aItemDoc));
    final List  aWebsiteList = aDoc.getList (BSON_WEBSITES, String.class);
    if (aWebsiteList != null)
      for (final String sItem : aWebsiteList)
        ret.websiteURIs ().add (sItem);
    final List  aContactList = aDoc.getList (BSON_CONTACTS, Document.class);
    if (aContactList != null)
      for (final Document aItemDoc : aContactList)
        ret.contacts ().add (toBCContact (aItemDoc));
    ret.setAdditionalInformation (aDoc.getString (BSON_ADDITIONAL));
    ret.setRegistrationDate (TypeConverter.convert (aDoc.get (BSON_REGDATE, Date.class), LocalDate.class));
    return ret;
  }

  @Nonnull
  @ReturnsMutableCopy
  public static Document toBson (@Nonnull final ISMPBusinessCard aValue)
  {
    final Document ret = new Document ().append (BSON_ID, aValue.getID ())
                                        .append (BSON_SERVICE_GROUP_ID, aValue.getID ());
    final ICommonsList  aEntities = new CommonsArrayList <> ();
    for (final SMPBusinessCardEntity aEntity : aValue.getAllEntities ())
      aEntities.add (toBson (aEntity));
    if (aEntities.isNotEmpty ())
      ret.append (BSON_ENTITIES, aEntities);
    return ret;
  }

  @Nonnull
  @ReturnsMutableCopy
  public SMPBusinessCard toDomain (@Nonnull final Document aDoc)
  {
    final IParticipantIdentifier aParticipantID = m_aIdentifierFactory.parseParticipantIdentifier (aDoc.getString (BSON_SERVICE_GROUP_ID));
    final ICommonsList  aEntities = new CommonsArrayList <> ();
    final List  aEntityList = aDoc.getList (BSON_ENTITIES, Document.class);
    if (aEntityList != null)
      for (final Document aItemDoc : aEntityList)
        aEntities.add (toBCEntity (aItemDoc));
    return new SMPBusinessCard (aParticipantID, aEntities);
  }

  @Nonnull
  @IsLocked (ELockType.WRITE)
  private ISMPBusinessCard _createSMPBusinessCard (@Nonnull final SMPBusinessCard aSMPBusinessCard)
  {
    if (!getCollection ().insertOne (toBson (aSMPBusinessCard)).wasAcknowledged ())
      throw new IllegalStateException ("Failed to insert into MongoDB Collection");

    AuditHelper.onAuditCreateSuccess (SMPBusinessCard.OT,
                                      aSMPBusinessCard.getID (),
                                      Integer.valueOf (aSMPBusinessCard.getEntityCount ()));
    return aSMPBusinessCard;
  }

  @Nonnull
  @IsLocked (ELockType.WRITE)
  private ISMPBusinessCard _updateSMPBusinessCard (@Nonnull final SMPBusinessCard aSMPBusinessCard)
  {
    final Document aOldDoc = getCollection ().findOneAndReplace (new Document (BSON_ID, aSMPBusinessCard.getID ()),
                                                                 toBson (aSMPBusinessCard));
    if (aOldDoc != null)
      AuditHelper.onAuditModifySuccess (SMPBusinessCard.OT,
                                        "set-all",
                                        aSMPBusinessCard.getID (),
                                        Integer.valueOf (aSMPBusinessCard.getEntityCount ()));
    return aSMPBusinessCard;
  }

  @Nonnull
  public ISMPBusinessCard createOrUpdateSMPBusinessCard (@Nonnull final IParticipantIdentifier aParticipantID,
                                                         @Nonnull final Collection  aEntities)
  {
    ValueEnforcer.notNull (aParticipantID, "ParticipantID");
    ValueEnforcer.notNull (aEntities, "Entities");

    if (LOGGER.isDebugEnabled ())
      LOGGER.debug ("createOrUpdateSMPBusinessCard (" +
                    aParticipantID.getURIEncoded () +
                    ", " +
                    aEntities.size () +
                    " entities)");

    final ISMPBusinessCard aOldBusinessCard = getSMPBusinessCardOfID (aParticipantID);
    final SMPBusinessCard aNewBusinessCard = new SMPBusinessCard (aParticipantID, aEntities);
    if (aOldBusinessCard != null)
    {
      // Reuse old ID
      _updateSMPBusinessCard (aNewBusinessCard);

      if (LOGGER.isDebugEnabled ())
        LOGGER.debug ("createOrUpdateSMPBusinessCard update successful");
    }
    else
    {
      // Create new ID
      _createSMPBusinessCard (aNewBusinessCard);

      if (LOGGER.isDebugEnabled ())
        LOGGER.debug ("createOrUpdateSMPBusinessCard create successful");
    }

    // Invoke generic callbacks
    m_aCBs.forEach (x -> x.onSMPBusinessCardCreatedOrUpdated (aNewBusinessCard));

    return aNewBusinessCard;
  }

  @Nonnull
  public EChange deleteSMPBusinessCard (@Nullable final ISMPBusinessCard aSMPBusinessCard)
  {
    if (aSMPBusinessCard == null)
      return EChange.UNCHANGED;

    if (LOGGER.isDebugEnabled ())
      LOGGER.debug ("deleteSMPBusinessCard (" + aSMPBusinessCard.getID () + ")");

    final DeleteResult aDR = getCollection ().deleteOne (new Document (BSON_ID, aSMPBusinessCard.getID ()));
    if (!aDR.wasAcknowledged () || aDR.getDeletedCount () == 0)
    {
      AuditHelper.onAuditDeleteFailure (SMPBusinessCard.OT, aSMPBusinessCard.getID (), "no-such-id");
      return EChange.UNCHANGED;
    }

    // Invoke generic callbacks
    m_aCBs.forEach (x -> x.onSMPBusinessCardDeleted (aSMPBusinessCard));

    AuditHelper.onAuditDeleteSuccess (SMPBusinessCard.OT,
                                      aSMPBusinessCard.getID (),
                                      Integer.valueOf (aSMPBusinessCard.getEntityCount ()));

    if (LOGGER.isDebugEnabled ())
      LOGGER.debug ("deleteSMPBusinessCard successful");

    return EChange.CHANGED;
  }

  @Nonnull
  @ReturnsMutableCopy
  public ICommonsList  getAllSMPBusinessCards ()
  {
    final ICommonsList  ret = new CommonsArrayList <> ();
    getCollection ().find ().forEach (x -> ret.add (toDomain (x)));
    return ret;
  }

  @Nonnull
  @ReturnsMutableCopy
  public ICommonsSet  getAllSMPBusinessCardIDs ()
  {
    final ICommonsSet  ret = new CommonsHashSet <> ();
    getCollection ().find ().forEach (x -> ret.add (x.getString (BSON_SERVICE_GROUP_ID)));
    return ret;
  }

  public boolean containsSMPBusinessCardOfID (@Nullable final IParticipantIdentifier aID)
  {
    if (aID == null)
      return false;

    return getCollection ().find (new Document (BSON_ID, aID.getURIEncoded ())).first () != null;
  }

  @Nullable
  public ISMPBusinessCard getSMPBusinessCardOfID (@Nullable final IParticipantIdentifier aID)
  {
    if (aID == null)
      return null;

    return getCollection ().find (new Document (BSON_ID, aID.getURIEncoded ())).map (this::toDomain).first ();
  }

  @Nonnegative
  public long getSMPBusinessCardCount ()
  {
    return getCollection ().countDocuments ();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy