-
-
Save NiPfi/f00dc0f8178ef907202ed1046ced2746 to your computer and use it in GitHub Desktop.
| package ch.jojoni.jamplan.model.repository; | |
| import android.support.annotation.NonNull; | |
| import android.util.Log; | |
| import com.google.android.gms.tasks.Continuation; | |
| import com.google.android.gms.tasks.OnFailureListener; | |
| import com.google.android.gms.tasks.Task; | |
| import com.google.firebase.firestore.CollectionReference; | |
| import com.google.firebase.firestore.DocumentReference; | |
| import com.google.firebase.firestore.DocumentSnapshot; | |
| import com.google.firebase.firestore.FirebaseFirestore; | |
| import ch.jojoni.jamplan.model.Identifiable; | |
| /** | |
| * Manages data access for Firebase | |
| */ | |
| public class FirestoreRepository<TEntity extends Identifiable<String>> implements Repository<TEntity, String> { | |
| private static final String TAG = "FirestoreRepository"; | |
| private final Class<TEntity> entityClass; | |
| private final CollectionReference collectionReference; | |
| private final String collectionName; | |
| /** | |
| * Initializes the repository storing the data in the given collection. Should be from {@link FirestoreCollections}. | |
| */ | |
| public FirestoreRepository(Class<TEntity> entityClass, String collectionName) { | |
| this.collectionName = collectionName; | |
| this.entityClass = entityClass; | |
| FirebaseFirestore db = FirebaseFirestore.getInstance(); | |
| this.collectionReference = db.collection(this.collectionName); | |
| } | |
| @Override | |
| public Task<Boolean> exists(final String documentName) { | |
| DocumentReference documentReference = collectionReference.document(documentName); | |
| Log.i(TAG, "Checking existence of '" + documentName + "' in '" + collectionName + "'."); | |
| return documentReference.get().continueWith(new Continuation<DocumentSnapshot, Boolean>() { | |
| @Override | |
| public Boolean then(@NonNull Task<DocumentSnapshot> task) { | |
| Log.d(TAG,"Checking if '" + documentName + "' exists in '" + collectionName +"'."); | |
| return task.getResult().exists(); | |
| } | |
| }); | |
| } | |
| @Override | |
| public Task<TEntity> get(String id) { | |
| final String documentName = id; | |
| DocumentReference documentReference = collectionReference.document(documentName); | |
| Log.i(TAG, "Getting '" + documentName + "' in '" + collectionName + "'."); | |
| return documentReference.get().continueWith(new Continuation<DocumentSnapshot, TEntity>() { | |
| @Override | |
| public TEntity then(@NonNull Task<DocumentSnapshot> task) throws Exception { | |
| DocumentSnapshot documentSnapshot = task.getResult(); | |
| if (documentSnapshot.exists()) { | |
| return documentSnapshot.toObject(entityClass); | |
| } else { | |
| Log.d(TAG, "Document '" + documentName + "' does not exist in '" + collectionName + "'."); | |
| return entityClass.newInstance(); | |
| } | |
| } | |
| }); | |
| } | |
| @Override | |
| public Task<Void> create(TEntity entity) { | |
| final String documentName = entity.getEntityKey(); | |
| DocumentReference documentReference = collectionReference.document(documentName); | |
| Log.i(TAG, "Creating '" + documentName + "' in '" + collectionName + "'."); | |
| return documentReference.set(entity).addOnFailureListener(new OnFailureListener() { | |
| @Override | |
| public void onFailure(@NonNull Exception e) { | |
| Log.d(TAG, "There was an error creating '" + documentName + "' in '" + collectionName + "'!", e); | |
| } | |
| }); | |
| } | |
| @Override | |
| public Task<Void> update(TEntity entity) { | |
| final String documentName = entity.getEntityKey(); | |
| DocumentReference documentReference = collectionReference.document(documentName); | |
| Log.i(TAG, "Updating '" + documentName + "' in '" + collectionName + "'."); | |
| return documentReference.set(entity).addOnFailureListener(new OnFailureListener() { | |
| @Override | |
| public void onFailure(@NonNull Exception e) { | |
| Log.d(TAG, "There was an error updating '" + documentName + "' in '" + collectionName + "'.", e); | |
| } | |
| }); | |
| } | |
| @Override | |
| public Task<Void> delete(final String documentName) { | |
| DocumentReference documentReference = collectionReference.document(documentName); | |
| Log.i(TAG, "Deleting '" + documentName + "' in '" + collectionName + "'."); | |
| return documentReference.delete().addOnFailureListener(new OnFailureListener() { | |
| @Override | |
| public void onFailure(@NonNull Exception e) { | |
| Log.d(TAG, "There was an error deleting '" + documentName + "' in '" + collectionName + "'.", e); | |
| } | |
| }); | |
| } | |
| } |
| package ch.jojoni.jamplan.model; | |
| import com.google.firebase.firestore.Exclude; | |
| /** | |
| * Represents an object that can be uniquely identified among other objects of the same type | |
| * by using an UID. | |
| * | |
| * @param <TKey> type of the unique key (UID) this object is uniquely identified by. The type needs | |
| * a correct implementation of its equals() method or the behaviour of code using this | |
| * interface will be undefined. | |
| */ | |
| public interface Identifiable<TKey> { | |
| @Exclude | |
| TKey getEntityKey(); | |
| } |
| package ch.jojoni.jamplan.model.repository; | |
| import com.google.android.gms.tasks.Task; | |
| import ch.jojoni.jamplan.model.Identifiable; | |
| /** | |
| * Manages data access for POJOs that are uniquely identifiable by a key, such as POJOs implementing {@link Identifiable}. | |
| */ | |
| public interface Repository<TEntity extends Identifiable<TKey>, TKey> { | |
| /** | |
| * Checks the repository for a given id and returns a boolean representing its existence. | |
| * @param id the unique id of an entity. | |
| * @return A {@link Task} for a boolean which is 'true' if the entity for the given id exists, 'false' otherwise. | |
| */ | |
| Task<Boolean> exists(TKey id); | |
| /** | |
| * Queries the repository for an uniquely identified entity and returns it. If the entity does | |
| * not exist in the repository, a new instance is returned. | |
| * @param id the unique id of an entity. | |
| * @return A {@link Task} for an entity implementing {@link Identifiable}. | |
| */ | |
| Task<TEntity> get(TKey id); | |
| /** | |
| * Stores an entity in the repository so it is accessible via its unique id. | |
| * @param entity the entity implementing {@link Identifiable} to be stored. | |
| * @return An {@link Task} to be notified of failures. | |
| */ | |
| Task<Void> create(TEntity entity); | |
| /** | |
| * Updates an entity in the repository | |
| * @param entity the new entity to be stored. | |
| * @return A {@link Task} to be notified of failures. | |
| */ | |
| Task<Void> update(TEntity entity); | |
| /** | |
| * Deletes an entity from the repository. | |
| * @param id uniquely identifying the entity. | |
| * @return A {@link Task} to be notified of failures. | |
| */ | |
| Task<Void> delete(TKey id); | |
| } |
Eusse.... If you're still dealing with the problem....
I had the same issue. Found out why. When you implement the identifiable interface, you need to also write the @exclude above @OverRide. If you don't, it tries to deal with that in the upload to firestore somehow, which apparently is not possible.
This is excellent !! Thanks :)
@NiPfi This is great!! One question though, how can I query by adding whereEqualTo and orderBy on get method?
Is there a reason these codes are written in Java instead of Kotlin?
@wonsuc There's a few but it basically boils down to this code being created for a school project during one semester and the school primarily teaching programming using Java. Also, when I wrote this code 2 years ago, Google was still in the process of making Kotlin the primary language for Android and since I don't program for Android professionally now, it didn't make sense to learn Kotlin for the purpose of a single semester.
@NiPfi Thanks for the answer, I just wondered if I can't use Repository pattern with Kotlin for Firestore.
Can you post an example of the usage?
I created a data class that extends interface "Identifiable" and i get this error:
Found conflicting getters for name getEntityKey on class Model