X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/e2a7138e0e6480b8566cda186b3f740210fcc518..5b54915209ce26d977d9dabb97001ac06b24441a:/src/com/owncloud/android/files/services/IndexedForest.java diff --git a/src/com/owncloud/android/files/services/IndexedForest.java b/src/com/owncloud/android/files/services/IndexedForest.java new file mode 100644 index 00000000..daf46a56 --- /dev/null +++ b/src/com/owncloud/android/files/services/IndexedForest.java @@ -0,0 +1,179 @@ +/* ownCloud Android client application + * Copyright (C) 2015 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * 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 . + * + */ + +package com.owncloud.android.files.services; + +import android.accounts.Account; + +import com.owncloud.android.datamodel.OCFile; + +import java.io.File; +import java.util.HashSet; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +/** + * Helper structure to keep the trees of folders containing any file downloading or synchronizing. + * + * A map provides the indexation based in hashing. + * + * A tree is created per account. + * + * @author David A. Velasco + */ +public class IndexedForest { + + private ConcurrentMap> mMap = new ConcurrentHashMap>(); + + private class Node { + String mKey = null; + Node mParent = null; + Set> mChildren = new HashSet>(); // TODO be careful with hash() + V mPayload = null; + + // payload is optional + public Node(String key, V payload) { + if (key == null) { + throw new IllegalArgumentException("Argument key MUST NOT be null"); + } + mKey = key; + mPayload = payload; + } + + public Node getParent() { + return mParent; + }; + + public Set> getChildren() { + return mChildren; + } + + public String getKey() { + return mKey; + } + + public V getPayload() { + return mPayload; + } + + public void addChild(Node child) { + mChildren.add(child); + child.setParent(this); + } + + private void setParent(Node parent) { + mParent = parent; + } + + public boolean hasChildren() { + return mChildren.size() > 0; + } + + public void removeChild(Node removed) { + mChildren.remove(removed); + } + } + + + public /* synchronized */ String putIfAbsent(Account account, String remotePath, V value) { + String targetKey = buildKey(account, remotePath); + Node valuedNode = new Node(targetKey, value); + mMap.putIfAbsent( + targetKey, + valuedNode + ); + + String currentPath = remotePath, parentPath = null, parentKey = null; + Node currentNode = valuedNode, parentNode = null; + boolean linked = false; + while (!OCFile.ROOT_PATH.equals(currentPath) && !linked) { + parentPath = new File(currentPath).getParent(); + if (!parentPath.endsWith(OCFile.PATH_SEPARATOR)) { + parentPath += OCFile.PATH_SEPARATOR; + } + parentKey = buildKey(account, parentPath); + parentNode = mMap.get(parentKey); + if (parentNode == null) { + parentNode = new Node(parentKey, null); + parentNode.addChild(currentNode); + mMap.put(parentKey, parentNode); + } else { + parentNode.addChild(currentNode); + linked = true; + } + currentPath = parentPath; + currentNode = parentNode; + } + + return targetKey; + }; + + public /* synchronized */ V remove(Account account, String remotePath) { + String targetKey = buildKey(account, remotePath); + Node firstRemoved = mMap.remove(targetKey); + + if (firstRemoved != null) { + Node removed = firstRemoved; + Node parent = removed.getParent(); + while (parent != null) { + parent.removeChild(removed); + if (!parent.hasChildren()) { + removed = mMap.remove(parent.getKey()); + parent = removed.getParent(); + } else { + parent = null; + } + } + } + + if (firstRemoved != null) { + return firstRemoved.getPayload(); + } else { + return null; + } + + } + + public boolean contains(Account account, String remotePath) { + String targetKey = buildKey(account, remotePath); + return mMap.containsKey(targetKey); + } + + public /* synchronized */ V get(String key) { + Node node = mMap.get(key); + if (node != null) { + return node.getPayload(); + } else { + return null; + } + } + + + /** + * Builds a key to index files + * + * @param account Account where the file to download is stored + * @param remotePath Path of the file in the server + */ + private String buildKey(Account account, String remotePath) { + return account.name + remotePath; + } + + + +}