diff options
author | desperateCoder <echotodevnull@gmail.com> | 2020-10-03 18:45:55 +0300 |
---|---|---|
committer | desperateCoder <echotodevnull@gmail.com> | 2020-10-03 18:45:55 +0300 |
commit | 8244469e782ffd391ea2ebc639108d253e1954d6 (patch) | |
tree | cd769bccfb8fd386a3b4139c291690347d4c3f7a /app/src/main/java/it/niedermann/nextcloud/deck/persistence | |
parent | 37d398fc200c5cea427c081e86d3f6d809233e16 (diff) | |
parent | 8f1e207120b9c596488c28ba7c1f43cddce29c86 (diff) |
Merge branch '608-clone-cards-when-cloning-boards'
Diffstat (limited to 'app/src/main/java/it/niedermann/nextcloud/deck/persistence')
13 files changed, 243 insertions, 82 deletions
diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java index e70ed48e3..c5b7b3367 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/SyncManager.java @@ -22,6 +22,7 @@ import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -555,11 +556,14 @@ public class SyncManager { /** * Creates a new {@link Board} and adds the same {@link Label} and {@link Stack} as in the origin {@link Board}. * Owner of the target {@link Board} will be the {@link User} with the {@link Account} of {@param targetAccountId}. + * @param cloneCards determines whether or not the cards in this {@link Board} shall be cloned or not * Does <strong>not</strong> clone any {@link Card} or {@link AccessControl} from the origin {@link Board}. + * + * TODO implement https://github.com/stefan-niedermann/nextcloud-deck/issues/608 */ @AnyThread - public WrappedLiveData<FullBoard> cloneBoard(long originAccountId, long originBoardLocalId, long targetAccountId, String targetBoardColor) { - WrappedLiveData<FullBoard> liveData = new WrappedLiveData<>(); + public WrappedLiveData<FullBoard> cloneBoard(long originAccountId, long originBoardLocalId, long targetAccountId, String targetBoardColor, boolean cloneCards) { + final WrappedLiveData<FullBoard> liveData = new WrappedLiveData<>(); doAsync(() -> { Account originAccount = dataBaseAdapter.getAccountByIdDirectly(originAccountId); @@ -591,6 +595,7 @@ public class SyncManager { } while (dataBaseAdapter.getBoardForAccountByNameDirectly(targetAccountId, newBoardTitle) != null); + originalBoard.setAccountId(targetAccountId); originalBoard.setId(null); originalBoard.setLocalId(null); @@ -602,24 +607,70 @@ public class SyncManager { long newBoardId = dataBaseAdapter.createBoardDirectly(originAccountId, originalBoard.getBoard()); originalBoard.setLocalId(newBoardId); - for (Stack stack : originalBoard.getStacks()) { - stack.setLocalId(null); - stack.setId(null); - stack.setStatusEnum(DBStatus.LOCAL_EDITED); - stack.setAccountId(targetAccountId); - stack.setBoardId(newBoardId); - dataBaseAdapter.createStack(targetAccountId, stack); + boolean isSameAccount = targetAccountId == originAccountId; + + if (isSameAccount) { + List<AccessControl> aclList = originalBoard.getParticipants(); + for (AccessControl acl : aclList) { + acl.setLocalId(null); + acl.setId(null); + acl.setBoardId(newBoardId); + dataBaseAdapter.createAccessControl(targetAccountId, acl); + } } - originalBoard.setStacks(null); + + Map<Long, Long> oldToNewLabelIdsDictionary = new HashMap<>(); + for (Label label : originalBoard.getLabels()) { + Long oldLocalId = label.getLocalId(); label.setLocalId(null); label.setId(null); label.setAccountId(targetAccountId); label.setStatusEnum(DBStatus.LOCAL_EDITED); label.setBoardId(newBoardId); - dataBaseAdapter.createLabel(targetAccountId, label); + long newLocalId = dataBaseAdapter.createLabelDirectly(targetAccountId, label); + oldToNewLabelIdsDictionary.put(oldLocalId, newLocalId); } - if (serverAdapter.hasInternetConnection()) { + + List<Stack> oldStacks = originalBoard.getStacks(); + for (Stack stack : oldStacks) { + Long oldStackId = stack.getLocalId(); + stack.setLocalId(null); + stack.setId(null); + stack.setStatusEnum(DBStatus.LOCAL_EDITED); + stack.setAccountId(targetAccountId); + stack.setBoardId(newBoardId); + long createdStackId = dataBaseAdapter.createStack(targetAccountId, stack); + if (cloneCards) { + List<FullCard> oldCards = dataBaseAdapter.getFullCardsForStackDirectly(originAccountId, oldStackId); + for (FullCard oldCard : oldCards) { + Card newCard = oldCard.getCard(); + newCard.setId(null); + newCard.setUserId(newOwner.getLocalId()); + newCard.setLocalId(null); + newCard.setStackId(createdStackId); + newCard.setAccountId(targetAccountId); + newCard.setStatusEnum(DBStatus.LOCAL_EDITED); + long createdCardId = dataBaseAdapter.createCardDirectly(targetAccountId, newCard); + if (oldCard.getLabels() != null) { + for (Label oldLabel : oldCard.getLabels()) { + Long newLabelId = oldToNewLabelIdsDictionary.get(oldLabel.getLocalId()); + if (newLabelId != null) { + dataBaseAdapter.createJoinCardWithLabel(newLabelId, createdCardId, DBStatus.LOCAL_EDITED); + } else DeckLog.error("ID of created Label is null! Skipping assignment of \"" + oldLabel.getTitle() + "\"..."); + } + } + if (isSameAccount && oldCard.getAssignedUsers() != null) { + for (User assignedUser : oldCard.getAssignedUsers()) { + dataBaseAdapter.createJoinCardWithUser(assignedUser.getLocalId(), createdCardId, DBStatus.LOCAL_EDITED); + } + } + } + } + } + // dont trigger concurrent syncs! + List<IResponseCallback<Boolean>> queuedSync = RUNNING_SYNCS.get(targetAccountId); + if ((queuedSync == null || queuedSync.isEmpty()) && serverAdapter.hasInternetConnection()) { Account targetAccount = dataBaseAdapter.getAccountByIdDirectly(targetAccountId); ServerAdapter serverAdapterToUse = this.serverAdapter; if (originAccountId != targetAccountId) { @@ -637,7 +688,7 @@ public class SyncManager { super.onError(throwable); liveData.postError(throwable); } - }).doUpSyncFor(new BoardWithStacksAndLabelsUpSyncDataProvider(originalBoard)); + }).doUpSyncFor(new BoardWithStacksAndLabelsUpSyncDataProvider(dataBaseAdapter.getFullBoardByLocalIdDirectly(targetAccountId, newBoardId))); } else { liveData.postValue(dataBaseAdapter.getFullBoardByLocalIdDirectly(targetAccountId, newBoardId)); } @@ -995,7 +1046,7 @@ public class SyncManager { card.getCard().setAccountId(accountId); card.getCard().setStatusEnum(DBStatus.LOCAL_EDITED); card.getCard().setOrder(dataBaseAdapter.getHighestCardOrderInStack(localStackId) + 1); - long localCardId = dataBaseAdapter.createCard(accountId, card.getCard()); + long localCardId = dataBaseAdapter.createCardDirectly(accountId, card.getCard()); card.getCard().setLocalId(localCardId); List<User> assignedUsers = card.getAssignedUsers(); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java index e13abf1b1..549e1a0ae 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/DataBaseAdapter.java @@ -266,17 +266,20 @@ public class DataBaseAdapter { return db.getUserDao().getUserByUidDirectly(accountId, uid); } + @WorkerThread public long createUser(long accountId, User user) { user.setAccountId(accountId); return db.getUserDao().insert(user); } + @WorkerThread public void updateUser(long accountId, User user, boolean setStatus) { markAsEditedIfNeeded(user, setStatus); user.setAccountId(accountId); db.getUserDao().update(user); } + @AnyThread public LiveData<Label> getLabelByRemoteId(long accountId, long remoteId) { return distinctUntilChanged(db.getLabelDao().getLabelByRemoteId(accountId, remoteId)); } @@ -286,7 +289,8 @@ public class DataBaseAdapter { return db.getLabelDao().getLabelByRemoteIdDirectly(accountId, remoteId); } - public long createLabel(long accountId, @NonNull Label label) { + @WorkerThread + public long createLabelDirectly(long accountId, @NonNull Label label) { label.setAccountId(accountId); return db.getLabelDao().insert(label); } @@ -545,7 +549,7 @@ public class DataBaseAdapter { } @WorkerThread - public long createCard(long accountId, Card card) { + public long createCardDirectly(long accountId, Card card) { card.setAccountId(accountId); long newCardId = db.getCardDao().insert(card); @@ -706,6 +710,11 @@ public class DataBaseAdapter { return db.getAttachmentDao().getLocallyChangedAttachmentsDirectly(accountId); } + @WorkerThread + public List<Attachment> getLocallyChangedAttachmentsForStackDirectly(long localStackId) { + return db.getAttachmentDao().getLocallyChangedAttachmentsForStackDirectly(localStackId); + } + public long createAttachment(long accountId, @NonNull Attachment attachment) { attachment.setAccountId(accountId); attachment.setCreatedAt(new Date()); @@ -808,16 +817,24 @@ public class DataBaseAdapter { return db.getJoinCardWithLabelDao().getAllDeletedJoinsWithRemoteIDs(); } - public List<JoinCardWithLabel> getAllChangedJoins() { + public List<JoinCardWithLabel> getAllChangedLabelJoins() { return db.getJoinCardWithLabelDao().getAllChangedJoins(); } - public JoinCardWithLabel getRemoteIdsForJoin(Long localCardId, Long localLabelId) { + public List<JoinCardWithLabel> getAllChangedLabelJoinsForStack(Long localStackId) { + return db.getJoinCardWithLabelDao().getAllChangedJoinsForStack(localStackId); + } + + public JoinCardWithLabel getAllChangedLabelJoinsWithRemoteIDs(Long localCardId, Long localLabelId) { return db.getJoinCardWithLabelDao().getRemoteIdsForJoin(localCardId, localLabelId); } - public List<JoinCardWithUser> getAllDeletedUserJoinsWithRemoteIDs() { - return db.getJoinCardWithUserDao().getDeletedJoinsWithRemoteIDs(); + public List<JoinCardWithUser> getAllChangedUserJoinsWithRemoteIDs() { + return db.getJoinCardWithUserDao().getChangedJoinsWithRemoteIDs(); + } + + public List<JoinCardWithUser> getAllChangedUserJoinsWithRemoteIDsForStack(Long localStackId) { + return db.getJoinCardWithUserDao().getChangedJoinsWithRemoteIDsForStack(localStackId); } public void deleteJoinedLabelForCardPhysicallyByRemoteIDs(Long accountId, Long remoteCardId, Long remoteLabelId) { @@ -925,11 +942,17 @@ public class DataBaseAdapter { return db.getCommentDao().getCommentByLocalCardIdDirectly(localCardId); } + @WorkerThread public List<Card> getCardsWithLocallyChangedCommentsDirectly(Long accountId) { return db.getCardDao().getCardsWithLocallyChangedCommentsDirectly(accountId); } @WorkerThread + public List<Card> getCardsWithLocallyChangedCommentsForStackDirectly(Long localStackId) { + return db.getCardDao().getCardsWithLocallyChangedCommentsForStackDirectly(localStackId); + } + + @WorkerThread public Long getLocalStackIdByRemoteStackIdDirectly(long accountId, Long stackId) { return db.getStackDao().getLocalStackIdByRemoteStackIdDirectly(accountId, stackId); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AttachmentDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AttachmentDao.java index 2d0887903..8f7ee1cba 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AttachmentDao.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/AttachmentDao.java @@ -25,6 +25,10 @@ public interface AttachmentDao extends GenericDao<Attachment> { @Query("SELECT * FROM attachment WHERE accountId = :accountId and (status<>1 or id is null or lastModified <> lastModifiedLocal)") List<Attachment> getLocallyChangedAttachmentsDirectly(long accountId); + @Query("SELECT a.* FROM attachment a inner join card c on c.localId = a.cardId " + + "WHERE c.stackId = :localStackId and (a.status<>1 or a.id is null or a.lastModified <> a.lastModifiedLocal)") + List<Attachment> getLocallyChangedAttachmentsForStackDirectly(long localStackId); + @Query("SELECT * FROM attachment WHERE accountId = :accountId and cardId = :localCardId") List<Attachment> getAttachmentsForLocalCardIdDirectly(long accountId, Long localCardId); }
\ No newline at end of file diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/CardDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/CardDao.java index 03c910ffc..d77a3b6b4 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/CardDao.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/CardDao.java @@ -70,6 +70,9 @@ public interface CardDao extends GenericDao<Card> { @Query("SELECT * FROM card c WHERE accountId = :accountId and exists ( select 1 from DeckComment dc where dc.objectId = c.localId and dc.status<>1)") List<Card> getCardsWithLocallyChangedCommentsDirectly(Long accountId); + @Query("SELECT * FROM card c WHERE stackId = :localStackId and exists ( select 1 from DeckComment dc where dc.objectId = c.localId and dc.status<>1)") + List<Card> getCardsWithLocallyChangedCommentsForStackDirectly(Long localStackId); + @Query("SELECT count(*) FROM card c WHERE accountId = :accountId and stackId = :localStackId and status <> 3") LiveData<Integer> countCardsInStack(long accountId, long localStackId); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/JoinCardWithLabelDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/JoinCardWithLabelDao.java index c96c64e7d..26e6c65a8 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/JoinCardWithLabelDao.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/JoinCardWithLabelDao.java @@ -40,6 +40,9 @@ public interface JoinCardWithLabelDao extends GenericDao<JoinCardWithLabel> { @Query("select * from joincardwithlabel WHERE status <> 1") // not UP_TO_DATE List<JoinCardWithLabel> getAllChangedJoins(); + @Query("select j.* from joincardwithlabel j inner join card c on j.cardId = c.localId WHERE c.stackId = :localStackId and j.status <> 1") // not UP_TO_DATE + List<JoinCardWithLabel> getAllChangedJoinsForStack(Long localStackId); + @Query("delete from joincardwithlabel " + "where cardId = (select c.localId from card c where c.accountId = :accountId and c.id = :remoteCardId) " + "and labelId = (select l.localId from label l where l.accountId = :accountId and l.id = :remoteLabelId)") diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/JoinCardWithUserDao.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/JoinCardWithUserDao.java index 46554685f..416d52eed 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/JoinCardWithUserDao.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/adapters/db/dao/JoinCardWithUserDao.java @@ -25,7 +25,14 @@ public interface JoinCardWithUserDao extends GenericDao<JoinCardWithUser> { "inner join card c on j.cardId = c.localId " + "inner join user u on j.userId = u.localId " + "WHERE j.status <> 1") // not UP_TO_DATE - List<JoinCardWithUser> getDeletedJoinsWithRemoteIDs(); + List<JoinCardWithUser> getChangedJoinsWithRemoteIDs(); + + @Query("select u.localId as userId, c.id as cardId, j.status from joincardwithuser j " + + "inner join card c on j.cardId = c.localId " + + "inner join user u on j.userId = u.localId " + + "WHERE c.stackId = :localStackId " + + "AND j.status <> 1") // not UP_TO_DATE + List<JoinCardWithUser> getChangedJoinsWithRemoteIDsForStack(Long localStackId); @Query("delete from joincardwithuser " + "where cardId = (select c.localId from card c where c.accountId = :accountId and c.id = :remoteCardId) " + diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/SyncHelper.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/SyncHelper.java index b8e757b65..6f7c0d9c0 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/SyncHelper.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/SyncHelper.java @@ -131,6 +131,7 @@ public class SyncHelper { public void onResponse(T response) { response.setAccountId(this.account.getId()); T update = applyUpdatesFromRemote(provider, entity, response, accountId); + update.setId(response.getId()); update.setStatus(DBStatus.UP_TO_DATE.getId()); provider.updateInDB(dataBaseAdapter, accountId, update, false); provider.goDeeperForUpSync(SyncHelper.this, serverAdapter, dataBaseAdapter, responseCallback); diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/AccessControlDataProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/AccessControlDataProvider.java index 36e5d9522..aab3aeb09 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/AccessControlDataProvider.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/AccessControlDataProvider.java @@ -14,6 +14,7 @@ import it.niedermann.nextcloud.deck.model.ocs.user.GroupMemberUIDs; import it.niedermann.nextcloud.deck.model.ocs.user.OcsUser; import it.niedermann.nextcloud.deck.persistence.sync.adapters.ServerAdapter; import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.DataBaseAdapter; +import it.niedermann.nextcloud.deck.persistence.sync.helpers.util.AsyncUtil; public class AccessControlDataProvider extends AbstractSyncDataProvider<AccessControl> { @@ -29,32 +30,29 @@ public class AccessControlDataProvider extends AbstractSyncDataProvider<AccessCo @Override public void getAllFromServer(ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, long accountId, IResponseCallback<List<AccessControl>> responder, Date lastSync) { - CountDownLatch latch = new CountDownLatch(acl.size()); - for (AccessControl accessControl : acl) { - if (accessControl.getType() == TYPE_GROUP) { - serverAdapter.searchGroupMembers(accessControl.getUser().getUid(), new IResponseCallback<GroupMemberUIDs>(responder.getAccount()) { - @Override - public void onResponse(GroupMemberUIDs response) { - accessControl.setGroupMemberUIDs(response); - if (response.getUids().size() > 0) { - ensureGroupMembersInDB(getAccount(), dataBaseAdapter, serverAdapter, response); + AsyncUtil.awaitAsyncWork(acl.size(), latch -> { + for (AccessControl accessControl : acl) { + if (accessControl.getType() == TYPE_GROUP) { + serverAdapter.searchGroupMembers(accessControl.getUser().getUid(), new IResponseCallback<GroupMemberUIDs>(responder.getAccount()) { + @Override + public void onResponse(GroupMemberUIDs response) { + accessControl.setGroupMemberUIDs(response); + if (response.getUids().size() > 0) { + ensureGroupMembersInDB(getAccount(), dataBaseAdapter, serverAdapter, response); + } + latch.countDown(); } - latch.countDown(); - } - @Override - public void onError(Throwable throwable) { - super.onError(throwable); - latch.countDown(); - } - }); - } else latch.countDown(); - } - try { - latch.await(); - } catch (InterruptedException e) { - DeckLog.logError(e); - } + @Override + public void onError(Throwable throwable) { + super.onError(throwable); + latch.countDown(); + } + }); + } else latch.countDown(); + } + }); + responder.onResponse(acl); } @@ -137,6 +135,7 @@ public class AccessControlDataProvider extends AbstractSyncDataProvider<AccessCo @Override public void updateInDB(DataBaseAdapter dataBaseAdapter, long accountId, AccessControl entity, boolean setStatus) { prepareUser(dataBaseAdapter, accountId, entity); + entity.setBoardId(board.getLocalId()); dataBaseAdapter.updateAccessControl(entity, setStatus); handleGroupMemberships(dataBaseAdapter, entity); } @@ -150,6 +149,9 @@ public class AccessControlDataProvider extends AbstractSyncDataProvider<AccessCo public void createOnServer(ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, long accountId, IResponseCallback<AccessControl> responder, AccessControl entity) { AccessControl acl = new AccessControl(entity); acl.setBoardId(board.getBoard().getId()); + if (acl.getUser() == null && acl.getUserId() != null) { + acl.setUser(dataBaseAdapter.getUserByLocalIdDirectly(acl.getUserId())); + } serverAdapter.createAccessControl(board.getBoard().getId(), acl, responder); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/BoardDataProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/BoardDataProvider.java index 2f5629474..45ea6cff6 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/BoardDataProvider.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/BoardDataProvider.java @@ -6,9 +6,7 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.concurrent.CountDownLatch; -import it.niedermann.nextcloud.deck.DeckLog; import it.niedermann.nextcloud.deck.api.IResponseCallback; import it.niedermann.nextcloud.deck.model.AccessControl; import it.niedermann.nextcloud.deck.model.Board; @@ -19,6 +17,7 @@ import it.niedermann.nextcloud.deck.model.full.FullStack; import it.niedermann.nextcloud.deck.persistence.sync.adapters.ServerAdapter; import it.niedermann.nextcloud.deck.persistence.sync.adapters.db.DataBaseAdapter; import it.niedermann.nextcloud.deck.persistence.sync.helpers.SyncHelper; +import it.niedermann.nextcloud.deck.persistence.sync.helpers.util.AsyncUtil; public class BoardDataProvider extends AbstractSyncDataProvider<FullBoard> { @@ -77,11 +76,29 @@ public class BoardDataProvider extends AbstractSyncDataProvider<FullBoard> { @Override public void updateInDB(DataBaseAdapter dataBaseAdapter, long accountId, FullBoard entity, boolean setStatus) { + handleDefaultLabels(dataBaseAdapter, entity); handleOwner(dataBaseAdapter, accountId, entity); dataBaseAdapter.updateBoard(entity.getBoard(), setStatus); handleUsers(dataBaseAdapter, accountId, entity); } + private void handleDefaultLabels(DataBaseAdapter dataBaseAdapter, FullBoard entity) { + // ## merge labels (created at board creation): + // the server creates four default labels. if a board is copied, they will also be copied. At sync, after creating the board, the labels are already there. + // this merges the created default ones with the ones i already have. + if (entity!= null && entity.getLabels() != null) { + for (Label label : entity.getLabels()) { + // does this label exist and unknown to server yet? + Label existing = dataBaseAdapter.getLabelByBoardIdAndTitleDirectly(entity.getLocalId(), label.getTitle()); + if (existing != null && existing.getId() == null) { + // take our label and lets say it IS the same as on server (but use the local color, no matter what the server says) + existing.setId(label.getId()); + dataBaseAdapter.updateLabel(existing, false); + } + } + } + } + @Override public void updateInDB(DataBaseAdapter dataBaseAdapter, long accountId, FullBoard entity) { updateInDB(dataBaseAdapter, accountId, entity, false); @@ -122,17 +139,13 @@ public class BoardDataProvider extends AbstractSyncDataProvider<FullBoard> { public void goDeeperForUpSync(SyncHelper syncHelper, ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, IResponseCallback<Boolean> callback) { Long accountId = callback.getAccount().getId(); List<Label> locallyChangedLabels = dataBaseAdapter.getLocallyChangedLabels(accountId); - CountDownLatch countDownLatch = new CountDownLatch(locallyChangedLabels.size()); - for (Label label : locallyChangedLabels) { - Board board = dataBaseAdapter.getBoardByLocalIdDirectly(label.getBoardId()); - label.setBoardId(board.getId()); - syncHelper.doUpSyncFor(new LabelDataProvider(this, board, Collections.singletonList(label)), countDownLatch); - } - try { - countDownLatch.await(); - } catch (InterruptedException e) { - DeckLog.logError(e); - } + AsyncUtil.awaitAsyncWork(locallyChangedLabels.size(), (countDownLatch) -> { + for (Label label : locallyChangedLabels) { + Board board = dataBaseAdapter.getBoardByLocalIdDirectly(label.getBoardId()); + label.setBoardId(board.getId()); + syncHelper.doUpSyncFor(new LabelDataProvider(this, board, Collections.singletonList(label)), countDownLatch); + } + }); List<Long> localBoardIDsWithChangedACL = dataBaseAdapter.getBoardIDsOfLocallyChangedAccessControl(accountId); for (Long boardId : localBoardIDsWithChangedACL) { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/CardDataProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/CardDataProvider.java index 9d7284fe7..00c2f8bd6 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/CardDataProvider.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/CardDataProvider.java @@ -70,7 +70,7 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { @Override public long createInDB(DataBaseAdapter dataBaseAdapter, long accountId, FullCard entity) { fixRelations(dataBaseAdapter, accountId, entity); - return dataBaseAdapter.createCard(accountId, entity.getCard()); + return dataBaseAdapter.createCardDirectly(accountId, entity.getCard()); } protected CardUpdate toCardUpdate(FullCard card) { @@ -150,7 +150,9 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { @Override public void createOnServer(ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, long accountId, IResponseCallback<FullCard> responder, FullCard entity) { entity.getCard().setStackId(stack.getId()); - serverAdapter.createCard(board.getId(), stack.getId(), entity.getCard(), responder); +// if (board != null && stack != null && board.getId() != null && stack.getId() != null) { + serverAdapter.createCard(board.getId(), stack.getId(), entity.getCard(), responder); +// } else DeckLog.error("Skipped card creation due to missing remote ID"); } @Override @@ -185,8 +187,13 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { public void goDeeperForUpSync(SyncHelper syncHelper, ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, IResponseCallback<Boolean> callback) { FullStack stack; Board board; + List<JoinCardWithLabel> changedLabels; + if (this.stack == null) { + changedLabels = dataBaseAdapter.getAllChangedLabelJoins(); + } else { + changedLabels = dataBaseAdapter.getAllChangedLabelJoinsForStack(this.stack.getLocalId()); + } - List<JoinCardWithLabel> changedLabels = dataBaseAdapter.getAllChangedJoins(); Account account = callback.getAccount(); for (JoinCardWithLabel changedLabelLocal : changedLabels) { Card card = dataBaseAdapter.getCardByLocalIdDirectly(account.getId(), changedLabelLocal.getCardId()); @@ -202,7 +209,7 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { board = this.board; } - JoinCardWithLabel changedLabel = dataBaseAdapter.getRemoteIdsForJoin(changedLabelLocal.getCardId(), changedLabelLocal.getLabelId()); + JoinCardWithLabel changedLabel = dataBaseAdapter.getAllChangedLabelJoinsWithRemoteIDs(changedLabelLocal.getCardId(), changedLabelLocal.getLabelId()); if (changedLabel.getStatusEnum() == DBStatus.LOCAL_DELETED) { if (changedLabel.getLabelId() == null || changedLabel.getCardId() == null) { dataBaseAdapter.deleteJoinedLabelForCardPhysicallyByRemoteIDs(account.getId(), changedLabel.getCardId(), changedLabel.getLabelId()); @@ -230,9 +237,20 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { } } - List<JoinCardWithUser> deletedUsers = dataBaseAdapter.getAllDeletedUserJoinsWithRemoteIDs(); - for (JoinCardWithUser deletedUser : deletedUsers) { - Card card = dataBaseAdapter.getCardByRemoteIdDirectly(account.getId(), deletedUser.getCardId()); + + List<JoinCardWithUser> changedUsers; + if (this.stack == null) { + changedUsers = dataBaseAdapter.getAllChangedUserJoinsWithRemoteIDs(); + } else { + changedUsers = dataBaseAdapter.getAllChangedUserJoinsWithRemoteIDsForStack(this.stack.getLocalId()); + } + for (JoinCardWithUser changedUser : changedUsers) { + // not already known to server? + if (changedUser.getCardId() == null) { + //skip for now + continue; + } + Card card = dataBaseAdapter.getCardByRemoteIdDirectly(account.getId(), changedUser.getCardId()); if (this.stack == null) { stack = dataBaseAdapter.getFullStackByLocalIdDirectly(card.getStackId()); } else { @@ -244,16 +262,16 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { } else { board = this.board; } - User user = dataBaseAdapter.getUserByLocalIdDirectly(deletedUser.getUserId()); - if (deletedUser.getStatusEnum() == DBStatus.LOCAL_DELETED) { - serverAdapter.unassignUserFromCard(board.getId(), stack.getId(), deletedUser.getCardId(), user.getUid(), new IResponseCallback<Void>(account) { + User user = dataBaseAdapter.getUserByLocalIdDirectly(changedUser.getUserId()); + if (changedUser.getStatusEnum() == DBStatus.LOCAL_DELETED) { + serverAdapter.unassignUserFromCard(board.getId(), stack.getId(), changedUser.getCardId(), user.getUid(), new IResponseCallback<Void>(account) { @Override public void onResponse(Void response) { - dataBaseAdapter.deleteJoinedUserForCardPhysicallyByRemoteIDs(account.getId(), deletedUser.getCardId(), user.getUid()); + dataBaseAdapter.deleteJoinedUserForCardPhysicallyByRemoteIDs(account.getId(), changedUser.getCardId(), user.getUid()); } }); - } else if (deletedUser.getStatusEnum() == DBStatus.LOCAL_EDITED) { - serverAdapter.assignUserToCard(board.getId(), stack.getId(), deletedUser.getCardId(), user.getUid(), new IResponseCallback<Void>(account) { + } else if (changedUser.getStatusEnum() == DBStatus.LOCAL_EDITED) { + serverAdapter.assignUserToCard(board.getId(), stack.getId(), changedUser.getCardId(), user.getUid(), new IResponseCallback<Void>(account) { @Override public void onResponse(Void response) { dataBaseAdapter.setStatusForJoinCardWithUser(card.getLocalId(), user.getLocalId(), DBStatus.UP_TO_DATE.getId()); @@ -262,7 +280,12 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { } } - List<Attachment> attachments = dataBaseAdapter.getLocallyChangedAttachmentsDirectly(account.getId()); + List<Attachment> attachments; + if (this.stack == null) { + attachments = dataBaseAdapter.getLocallyChangedAttachmentsDirectly(account.getId()); + } else { + attachments = dataBaseAdapter.getLocallyChangedAttachmentsForStackDirectly(this.stack.getLocalId()); + } for (Attachment attachment : attachments) { FullCard card = dataBaseAdapter.getFullCardByLocalIdDirectly(account.getId(), attachment.getCardId()); stack = dataBaseAdapter.getFullStackByLocalIdDirectly(card.getCard().getStackId()); @@ -270,7 +293,12 @@ public class CardDataProvider extends AbstractSyncDataProvider<FullCard> { syncHelper.doUpSyncFor(new AttachmentDataProvider(this, board, stack.getStack(), card, Collections.singletonList(attachment))); } - List<Card> cardsWithChangedComments = dataBaseAdapter.getCardsWithLocallyChangedCommentsDirectly(account.getId()); + List<Card> cardsWithChangedComments; + if (this.stack == null) { + cardsWithChangedComments = dataBaseAdapter.getCardsWithLocallyChangedCommentsDirectly(account.getId()); + } else { + cardsWithChangedComments = dataBaseAdapter.getCardsWithLocallyChangedCommentsForStackDirectly(this.stack.getLocalId()); + } for (Card card : cardsWithChangedComments) { syncHelper.doUpSyncFor(new DeckCommentsDataProvider(this, card)); } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/LabelDataProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/LabelDataProvider.java index 7510d9be3..90d633bce 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/LabelDataProvider.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/LabelDataProvider.java @@ -45,7 +45,7 @@ public class LabelDataProvider extends AbstractSyncDataProvider<Label> { updateInDB(dataBaseAdapter, accountId, entity, false); return entity.getLocalId(); } else { - return dataBaseAdapter.createLabel(accountId, entity); + return dataBaseAdapter.createLabelDirectly(accountId, entity); } } diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/StackDataProvider.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/StackDataProvider.java index a3c123afd..ba305dc0a 100644 --- a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/StackDataProvider.java +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/providers/StackDataProvider.java @@ -2,9 +2,9 @@ package it.niedermann.nextcloud.deck.persistence.sync.helpers.providers; import java.util.Collections; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.ConcurrentSkipListSet; import it.niedermann.nextcloud.deck.api.IResponseCallback; import it.niedermann.nextcloud.deck.model.Board; @@ -19,6 +19,8 @@ import it.niedermann.nextcloud.deck.persistence.sync.helpers.SyncHelper; public class StackDataProvider extends AbstractSyncDataProvider<FullStack> { private FullBoard board; + private Set<Long> syncedStacks = new ConcurrentSkipListSet<>(); + public StackDataProvider(AbstractSyncDataProvider<?> parent, FullBoard board) { super(parent); this.board = board; @@ -103,16 +105,19 @@ public class StackDataProvider extends AbstractSyncDataProvider<FullStack> { @Override public void goDeeperForUpSync(SyncHelper syncHelper, ServerAdapter serverAdapter, DataBaseAdapter dataBaseAdapter, IResponseCallback<Boolean> callback) { List<FullCard> changedCards = dataBaseAdapter.getLocallyChangedCardsDirectly(callback.getAccount().getId()); - Set<Long> syncedStacks = new HashSet<>(); - if (changedCards != null && changedCards.size() > 0){ + if (changedCards != null && !changedCards.isEmpty()){ for (FullCard changedCard : changedCards) { long stackId = changedCard.getCard().getStackId(); - boolean added = syncedStacks.add(stackId); - if (added) { + boolean alreadySynced = syncedStacks.contains(stackId); + if (!alreadySynced) { FullStack stack = dataBaseAdapter.getFullStackByLocalIdDirectly(stackId); - Board board = dataBaseAdapter.getBoardByLocalIdDirectly(stack.getStack().getBoardId()); - changedCard.getCard().setStackId(stack.getId()); - syncHelper.doUpSyncFor(new CardDataProvider(this, board, stack)); + // already synced and known to server? + if (stack.getStack().getId() != null) { + syncedStacks.add(stackId); + Board board = dataBaseAdapter.getBoardByLocalIdDirectly(stack.getStack().getBoardId()); + changedCard.getCard().setStackId(stack.getId()); + syncHelper.doUpSyncFor(new CardDataProvider(this, board, stack)); + } } } } else { diff --git a/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/util/AsyncUtil.java b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/util/AsyncUtil.java new file mode 100644 index 000000000..faabda163 --- /dev/null +++ b/app/src/main/java/it/niedermann/nextcloud/deck/persistence/sync/helpers/util/AsyncUtil.java @@ -0,0 +1,21 @@ +package it.niedermann.nextcloud.deck.persistence.sync.helpers.util; + +import java.util.concurrent.CountDownLatch; + +import it.niedermann.nextcloud.deck.DeckLog; + +public class AsyncUtil { + public interface LatchCallback { + void doWork(CountDownLatch latch); + } + + public static void awaitAsyncWork(int count, LatchCallback worker){ + CountDownLatch countDownLatch = new CountDownLatch(count); + worker.doWork(countDownLatch); + try { + countDownLatch.await(); + } catch (InterruptedException e) { + DeckLog.logError(e); + } + } +} |