package org.sigmah.offline.dao; /* * #%L * Sigmah * %% * Copyright (C) 2010 - 2016 URD * %% * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program. If not, see * <http://www.gnu.org/licenses/gpl-3.0.html>. * #L% */ import com.google.gwt.user.client.rpc.AsyncCallback; import java.util.Collection; import org.sigmah.offline.indexeddb.Transaction; import org.sigmah.offline.indexeddb.CountRequest; import org.sigmah.offline.indexeddb.Cursor; import org.sigmah.offline.indexeddb.IDBKeyRange; import org.sigmah.offline.indexeddb.ObjectStore; import org.sigmah.offline.indexeddb.OpenCursorRequest; import org.sigmah.offline.indexeddb.Order; import org.sigmah.offline.indexeddb.Request; import org.sigmah.offline.js.HasId; import org.sigmah.shared.command.result.VoidResult; import org.sigmah.offline.indexeddb.Schema; /** * Implements basic CRUD operations for objects using an int as key. * * @author Raphaƫl Calabro (rcalabro@ideia.fr) * @param <T> Type of the objects handled by this DAO. * @param <S> Schema where to save objects. */ public abstract class AbstractAsyncDAO<T, S extends Enum<S> & Schema> extends BaseAsyncDAO<S> implements AsyncDAO<T, S> { /** * Open a transaction and save the given object. * * @param t Object to save. */ @Override public void saveOrUpdate(T t) { saveOrUpdate(t, null); } /** * Open a transaction and save the given object, the given callback will be * called when done (if not null). * * @param t Object to save. * @param callback Callback to call (may be null). */ public void saveOrUpdate(final T t, final AsyncCallback<T> callback) { openTransaction(Transaction.Mode.READ_WRITE, new OpenTransactionHandler<S>() { @Override public void onTransaction(Transaction<S> transaction) { saveOrUpdate(t, callback, transaction); } }); } /** * Open a transaction and save every objects in the given collection, the * given callback will be called when done (if not null). * * @param ts Objects to save. * @param callback Callback to call (may be null). */ public void saveAll(final Collection<T> ts, final AsyncCallback<Void> callback) { openTransaction(Transaction.Mode.READ_WRITE, new OpenTransactionHandler<S>() { @Override public void onTransaction(Transaction<S> transaction) { saveAll(ts, callback, transaction); } }); } /** * Saves the given objects in the given transaction. * Override this method to save of most complexe objects. * * @param ts Objects to save. * @param callback Callback to call (may be null). * @param transaction Transaction to use. */ public void saveAll(Collection<T> ts, AsyncCallback<Void> callback, Transaction<S> transaction) { final RequestManager<Void> requestManager = new RequestManager<Void>(null, callback); for(final T t : ts) { saveOrUpdate(t, new RequestManagerCallback<Void, T>(requestManager) { @Override public void onRequestSuccess(T result) { // Success. } }, transaction); } requestManager.ready(); } /** * Open a transaction and retrieve the object identified by the given id. * * @param id Identifier. * @param callback Callback to call when the object is loaded. */ @Override public void get(final int id, final AsyncCallback<T> callback) { openTransaction(Transaction.Mode.READ_ONLY, new OpenTransactionHandler<S>() { @Override public void onTransaction(Transaction<S> transaction) { get(id, callback, transaction); } }); } /** * Open a new transaction and removes the object identified by <code>id</code>. * * @param id Identifier of the object to remove. */ public void remove(final int id) { remove(id, null); } /** * Open a new transaction and removes the object identified by <code>id</code>. * * @param id Identifier of the object to remove. * @param callback Called when the removal is done. */ public void remove(final int id, final AsyncCallback<VoidResult> callback) { openTransaction(Transaction.Mode.READ_WRITE, new OpenTransactionHandler<S>() { @Override public void onTransaction(Transaction<S> transaction) { remove(id, callback, transaction); } }); } /** * Removes the object identified by <code>id</code>. * Override this method to implements the removal of most complexe objects. * * @param id Identifier of the object to remove. * @param callback Called when the removal is done. * @param transaction Transaction to use. */ public void remove(int id, final AsyncCallback<VoidResult> callback, Transaction<S> transaction) { final ObjectStore commandObjectStore = transaction.getObjectStore(getRequiredStore()); commandObjectStore.delete(id).addCallback(new AsyncCallback<Request>() { @Override public void onFailure(Throwable caught) { if(callback != null) { callback.onFailure(caught); } } @Override public void onSuccess(Request result) { if(callback != null) { callback.onSuccess(null); } } }); } /** * Remove every entry matching the given identifiers. * * @param ids Collection of identifier to remove. */ public void removeAll(final Collection<Integer> ids) { removeAll(ids, null); } /** * Remove every entry matching the given identifiers. * * @param ids Collection of identifier to remove. * @param callback Called when the removal is done. */ public void removeAll(final Collection<Integer> ids, final AsyncCallback<VoidResult> callback) { final RequestManager<VoidResult> requestManager = new RequestManager<VoidResult>(null, callback); openTransaction(Transaction.Mode.READ_WRITE, new OpenTransactionHandler<S>() { @Override public void onTransaction(Transaction<S> transaction) { for(final Integer id : ids) { // Remove the current object remove(id, new RequestManagerCallback<VoidResult, VoidResult>(requestManager) { @Override public void onRequestSuccess(VoidResult result) { // Success } }, transaction); } requestManager.ready(); } }); } public void count(final AsyncCallback<Integer> callback) { openTransaction(Transaction.Mode.READ_ONLY, new OpenTransactionHandler<S>() { @Override public void onTransaction(Transaction<S> transaction) { final ObjectStore objectStore = transaction.getObjectStore(getRequiredStore()); final CountRequest countRequest = objectStore.count(); countRequest.addCallback(new AsyncCallback<Request>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); } @Override public void onSuccess(Request request) { callback.onSuccess(countRequest.getCount()); } }); } }); } /** * Open a new transaction and generates a negative identifier. * * @param callback Called when the identifier is generated. */ public void generateNegativeId(final AsyncCallback<Integer> callback) { openTransaction(Transaction.Mode.READ_ONLY, new OpenTransactionHandler<S>() { @Override public void onTransaction(Transaction<S> transaction) { generateNegativeId(callback, transaction); } }); } /** * Generates a negative identifier within the given transaction. * * @param callback Called when the identifier is generated. * @param transaction Transaction to use. */ protected void generateNegativeId(final AsyncCallback<Integer> callback, Transaction<S> transaction) { final ObjectStore objectStore = transaction.getObjectStore(getRequiredStore()); final OpenCursorRequest request = objectStore.openCursor(IDBKeyRange.upperBound(0, false), Order.ASCENDING); request.addCallback(new AsyncCallback<Request>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); } @Override public void onSuccess(Request result) { final Cursor cursor = request.getResult(); if(cursor != null) { final HasId hasId = cursor.getValue(); callback.onSuccess(hasId.getId() - 1); } else { callback.onSuccess(-1); } } }); } /** * Removes every objets whose id is a negative integer. * * @param callback Called when the removal is done. */ public void removeTemporaryObjects(final AsyncCallback<VoidResult> callback) { openTransaction(Transaction.Mode.READ_WRITE, new OpenTransactionHandler<S>() { @Override public void onTransaction(final Transaction<S> transaction) { final ObjectStore objectStore = transaction.getObjectStore(getRequiredStore()); final OpenCursorRequest request = objectStore.openCursor(IDBKeyRange.upperBound(0, false), Order.ASCENDING); request.addCallback(new AsyncCallback<Request>() { @Override public void onFailure(Throwable caught) { callback.onFailure(caught); } @Override public void onSuccess(Request result) { final Cursor cursor = request.getResult(); if(cursor != null) { final HasId hasId = cursor.getValue(); remove(hasId.getId(), callback, transaction); cursor.next(); } else { callback.onSuccess(null); } } }); } }); } }