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

in.kuros.jfirebase.provider.firebase.PersistenceServiceImpl Maven / Gradle / Ivy

package in.kuros.jfirebase.provider.firebase;


import com.google.api.core.ApiFuture;
import com.google.cloud.firestore.CollectionReference;
import com.google.cloud.firestore.DocumentReference;
import com.google.cloud.firestore.DocumentSnapshot;
import com.google.cloud.firestore.FieldPath;
import com.google.cloud.firestore.FieldValue;
import com.google.cloud.firestore.Firestore;
import com.google.cloud.firestore.QueryDocumentSnapshot;
import com.google.cloud.firestore.QuerySnapshot;
import com.google.cloud.firestore.SetOptions;
import com.google.common.collect.Lists;
import in.kuros.jfirebase.PersistenceService;
import in.kuros.jfirebase.exception.PersistenceException;
import in.kuros.jfirebase.metadata.Attribute;
import in.kuros.jfirebase.metadata.AttributeValue;
import in.kuros.jfirebase.metadata.RemoveAttribute;
import in.kuros.jfirebase.metadata.SetAttribute;
import in.kuros.jfirebase.metadata.SetAttribute.Helper;
import in.kuros.jfirebase.metadata.UpdateAttribute;
import in.kuros.jfirebase.metadata.ValuePath;
import in.kuros.jfirebase.provider.firebase.query.QueryBuilder;
import in.kuros.jfirebase.query.Query;
import in.kuros.jfirebase.transaction.Transaction;
import in.kuros.jfirebase.transaction.WriteBatch;
import in.kuros.jfirebase.util.BeanMapper;
import in.kuros.jfirebase.util.ClassMapper;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

class PersistenceServiceImpl implements PersistenceService {

    private final Firestore firestore;
    private final EntityHelper entityHelper;
    private final AttributeValueHelper attributeValueHelper;

    PersistenceServiceImpl(final Firestore firestore) {
        this.firestore = firestore;
        this.entityHelper = EntityHelper.INSTANCE;
        this.attributeValueHelper = new AttributeValueHelper();
    }

    @Override
    public  T create(final T entity) {

        try {
            final CollectionReference collectionReference = getCollectionReference(entity);
            final String id = entityHelper.getId(entity);
            final DocumentReference documentReference = id == null ? collectionReference.document() : collectionReference.document(id);
            entityHelper.setCreateTime(entity);

            final BeanMapper beanMapper = ClassMapper.getBeanMapper(getClass(entity));
            documentReference.create(beanMapper.serialize(entity)).get();
            entityHelper.setId(entity, documentReference.getId());
            return entity;
        } catch (InterruptedException | ExecutionException e) {
            throw new PersistenceException(e);
        }
    }

    @SafeVarargs
    @Override
    public final  void set(final T... entities) {
        final com.google.cloud.firestore.WriteBatch batch = firestore.batch();

        for (T entity : entities) {
            final DocumentReference documentReference = getDocumentReference(entity);
            final BeanMapper beanMapper = ClassMapper.getBeanMapper(getClass(entity));
            batch.set(documentReference, beanMapper.serialize(entity), SetOptions.merge());
        }

        try {
            batch.commit().get();
        } catch (InterruptedException | ExecutionException e) {
            throw new PersistenceException(e);
        }
    }

    @Override
    public  void set(final T entity, final Attribute attribute) {
        final DocumentReference documentReference = getDocumentReference(entity);
        final List fields = Lists.newArrayList(attribute.getName());

        final BeanMapper beanMapper = ClassMapper.getBeanMapper(getClass(entity));
        try {
            documentReference.set(beanMapper.serialize(entity), SetOptions.mergeFields(fields)).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new PersistenceException(e);
        }
    }

    @Override
    public  void set(final SetAttribute setAttribute) {
        try {
            final Class declaringClass = Helper.getDeclaringClass(setAttribute);
            final List> keyAttributes = SetAttribute.Helper.getKeys(setAttribute);
            final List> updateValues = SetAttribute.Helper.getAttributeValues(setAttribute);
            final List> valuePaths = SetAttribute.Helper.getValuePaths(setAttribute);

            final Map updateMap = attributeValueHelper.convertToObjectMap(updateValues);
            final List fieldPaths = attributeValueHelper.getFieldPaths(updateValues);

            attributeValueHelper.addValuePaths(updateMap, valuePaths);
            final List valueFieldPaths = attributeValueHelper.convertValuePathToFieldPaths(valuePaths);
            fieldPaths.addAll(valueFieldPaths);

            final Optional updateTimeField = entityHelper.getUpdateTimeFieldName(declaringClass);
            updateTimeField.ifPresent(name -> {
                updateMap.put(name, FieldValue.serverTimestamp());
                fieldPaths.add(FieldPath.of(name));
            });

            final String documentPath = entityHelper.getDocumentPath(keyAttributes);
            final DocumentReference documentReference = firestore.document(documentPath);
            documentReference.set(updateMap, SetOptions.mergeFieldPaths(fieldPaths)).get();

        } catch (final Exception e) {
            throw new PersistenceException(e);
        }
    }

    @Override
    public  void remove(final RemoveAttribute removeAttribute) {
        try {
            final List> attributeValues = RemoveAttribute.Helper.getAttributeValues(removeAttribute, FieldValue::delete);
            final List> valuePaths = RemoveAttribute.Helper.getValuePaths(removeAttribute);
            final Map valueMap = attributeValueHelper.convertToObjectMap(attributeValues);
            final List fieldPaths = attributeValueHelper.getFieldPaths(attributeValues);
            attributeValueHelper.addValuePaths(valueMap, valuePaths);
            final List valueFieldPaths = attributeValueHelper.convertValuePathToFieldPaths(valuePaths);
            fieldPaths.addAll(valueFieldPaths);
            final String documentPath = entityHelper.getDocumentPath(RemoveAttribute.Helper.getKeys(removeAttribute));
            final DocumentReference documentReference = firestore.document(documentPath);
            documentReference.set(valueMap, SetOptions.mergeFieldPaths(fieldPaths)).get();
        } catch (final Exception e) {
            throw new PersistenceException(e);
        }
    }

    public  void update(final UpdateAttribute updateAttribute) {
        try {
            final Map valueMap = attributeValueHelper.convertToObjectMap(UpdateAttribute.Helper.getAttributeValues(updateAttribute));
            attributeValueHelper.addValuePaths(valueMap, UpdateAttribute.Helper.getValuePaths(updateAttribute));
            final Optional updateTimeField = entityHelper.getUpdateTimeFieldName(UpdateAttribute.Helper.getDeclaringClass(updateAttribute));
            updateTimeField.ifPresent(name -> valueMap.put(name, FieldValue.serverTimestamp()));

            final String documentPath = entityHelper.getDocumentPath(UpdateAttribute.Helper.getKeys(updateAttribute));
            final DocumentReference documentReference = firestore.document(documentPath);
            documentReference.update(valueMap).get();
        } catch (final Exception e) {
            throw new PersistenceException(e);
        }
    }

    @Override
    public void updateFields(final String path, final String field, final Object value) {
        try {
            firestore.document(path).update(field, value).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new PersistenceException(e);
        }
    }

    @Override
    @SafeVarargs
    public final  void delete(final T... entities) {

        final com.google.cloud.firestore.WriteBatch batch = firestore.batch();

        for (T entity : entities) {
            final DocumentReference documentReference = getDocumentReference(entity);
            batch.delete(documentReference);
        }

        try {
            batch.commit().get();
        } catch (InterruptedException | ExecutionException e) {
            throw new PersistenceException(e);
        }
    }

    @Override
    public  List find(final Query query) {
        try {

            final ApiFuture querySnapshot = QueryAdapter.toFirebaseQuery(firestore, query).get();
            final List documents = querySnapshot.get().getDocuments();

            return documents
                    .stream()
                    .map(document -> {
                        final T object = document.toObject(query.getResultType());
                        entityHelper.setId(object, document.getId());
                        return object;
                    })
                    .collect(Collectors.toList());
        } catch (final Exception e) {
            throw new PersistenceException(e);
        }
    }

    @Override
    public  Optional findById(final Query query) {
        try {
            final QueryBuilder queryBuilder = (QueryBuilder) query;
            final DocumentReference document = firestore.document(queryBuilder.getPath());
            final DocumentSnapshot documentSnapshot = document.get().get();
            final T object = documentSnapshot.toObject(queryBuilder.getResultType());
            return Optional.ofNullable(object)
                    .map(e -> {
                        entityHelper.setId(e, documentSnapshot.getId());
                        return e;
                    });
        } catch (final Exception e) {
            throw new PersistenceException(e);
        }
    }

    @Override
    public  T runTransaction(final Function transactionConsumer) {
        try {
            return firestore
                    .runTransaction(transaction ->
                            transactionConsumer.apply(new TransactionImpl(firestore, transaction))).get();
        } catch (final Exception e) {
            throw new PersistenceException(e);
        }
    }

    @Override
    public void writeInBatch(final Consumer batchConsumer) {
        try {
            final com.google.cloud.firestore.WriteBatch batch = firestore.batch();
            final WriteBatchImpl writeBatch = new WriteBatchImpl(firestore, batch);
            batchConsumer.accept(writeBatch);
            batch.commit().get();
        } catch (final Exception e) {
            throw new PersistenceException(e);
        }
    }

    @SuppressWarnings("unchecked")
    private  Class getClass(final T entity) {
        return (Class) entity.getClass();
    }

    private  DocumentReference getDocumentReference(final T entity) {
        final String documentPath = entityHelper.getDocumentPath(entity);
        return firestore.document(documentPath);
    }

    private  CollectionReference getCollectionReference(final T entity) {
        final String documentPath = entityHelper.getCollectionPath(entity);
        return firestore.collection(documentPath);
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy