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