1e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck/* 2e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * Copyright (C) 2011 The Android Open Source Project 3e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * 4e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * Licensed under the Apache License, Version 2.0 (the "License"); 5e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * you may not use this file except in compliance with the License. 6e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * You may obtain a copy of the License at 7e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * 8e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * http://www.apache.org/licenses/LICENSE-2.0 9e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * 10e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * Unless required by applicable law or agreed to in writing, software 11e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * distributed under the License is distributed on an "AS IS" BASIS, 12e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * See the License for the specific language governing permissions and 14e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck * limitations under the License. 15e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck */ 16e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 17e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reckpackage com.android.browser.tests.utils; 18e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 19e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reckimport android.database.ContentObserver; 20e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reckimport android.net.Uri; 21e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 22e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reckimport java.util.ArrayList; 23e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 24e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reckpublic final class MockObserverNode { 25e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck private class MockObserverEntry { 26e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public final ContentObserver observer; 27e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public final boolean notifyForDescendents; 28e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 29e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public MockObserverEntry(ContentObserver o, boolean n) { 30e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck observer = o; 31e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck notifyForDescendents = n; 32e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 33e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 34e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 35e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public static final int INSERT_TYPE = 0; 36e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public static final int UPDATE_TYPE = 1; 37e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public static final int DELETE_TYPE = 2; 38e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 39e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck private String mName; 40e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck private ArrayList<MockObserverNode> mChildren = new ArrayList<MockObserverNode>(); 41e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck private ArrayList<MockObserverEntry> mObservers = new ArrayList<MockObserverEntry>(); 42e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 43e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public MockObserverNode(String name) { 44e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck mName = name; 45e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 46e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 47e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck private String getUriSegment(Uri uri, int index) { 48e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (uri != null) { 49e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (index == 0) { 50e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck return uri.getAuthority(); 51e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } else { 52e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck return uri.getPathSegments().get(index - 1); 53e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 54e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } else { 55e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck return null; 56e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 57e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 58e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 59e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck private int countUriSegments(Uri uri) { 60e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (uri == null) { 61e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck return 0; 62e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 63e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck return uri.getPathSegments().size() + 1; 64e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 65e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 66e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public void addObserver(Uri uri, ContentObserver observer, 67e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck boolean notifyForDescendents) { 68e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck addObserver(uri, 0, observer, notifyForDescendents); 69e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 70e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 71e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck private void addObserver(Uri uri, int index, ContentObserver observer, 72e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck boolean notifyForDescendents) { 73e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck // If this is the leaf node add the observer 74e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (index == countUriSegments(uri)) { 75e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck mObservers.add(new MockObserverEntry(observer, notifyForDescendents)); 76e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck return; 77e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 78e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 79e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck // Look to see if the proper child already exists 80e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck String segment = getUriSegment(uri, index); 81e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (segment == null) { 82e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck throw new IllegalArgumentException("Invalid Uri (" + uri + ") used for observer"); 83e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 84e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck int N = mChildren.size(); 85e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck for (int i = 0; i < N; i++) { 86e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck MockObserverNode node = mChildren.get(i); 87e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (node.mName.equals(segment)) { 88e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck node.addObserver(uri, index + 1, observer, notifyForDescendents); 89e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck return; 90e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 91e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 92e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 93e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck // No child found, create one 94e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck MockObserverNode node = new MockObserverNode(segment); 95e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck mChildren.add(node); 96e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck node.addObserver(uri, index + 1, observer, notifyForDescendents); 97e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 98e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 99e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public boolean removeObserver(ContentObserver observer) { 100e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck int size = mChildren.size(); 101e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck for (int i = 0; i < size; i++) { 102e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck boolean empty = mChildren.get(i).removeObserver(observer); 103e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (empty) { 104e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck mChildren.remove(i); 105e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck i--; 106e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck size--; 107e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 108e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 109e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 110e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck size = mObservers.size(); 111e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck for (int i = 0; i < size; i++) { 112e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck MockObserverEntry entry = mObservers.get(i); 113e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (entry.observer == observer) { 114e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck mObservers.remove(i); 115e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck break; 116e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 117e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 118e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 119e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (mChildren.size() == 0 && mObservers.size() == 0) { 120e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck return true; 121e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 122e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck return false; 123e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 124e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 125e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck private void notifyMyObservers(boolean leaf, ContentObserver observer, 126e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck boolean selfNotify) { 127e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck int N = mObservers.size(); 128e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck for (int i = 0; i < N; i++) { 129e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck MockObserverEntry entry = mObservers.get(i); 130e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 131e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck // Don't notify the observer if it sent the notification and isn't interesed 132e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck // in self notifications 133e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (entry.observer == observer && !selfNotify) { 134e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck continue; 135e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 136e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 137e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck // Make sure the observer is interested in the notification 138e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (leaf || (!leaf && entry.notifyForDescendents)) { 139e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck entry.observer.onChange(selfNotify); 140e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 141e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 142e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 143e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 144e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck public void notifyMyObservers(Uri uri, int index, ContentObserver observer, 145e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck boolean selfNotify) { 146e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck String segment = null; 147e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck int segmentCount = countUriSegments(uri); 148e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (index >= segmentCount) { 149e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck // This is the leaf node, notify all observers 150e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck notifyMyObservers(true, observer, selfNotify); 151e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } else if (index < segmentCount){ 152e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck segment = getUriSegment(uri, index); 153e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck // Notify any observers at this level who are interested in descendents 154e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck notifyMyObservers(false, observer, selfNotify); 155e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 156e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck 157e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck int N = mChildren.size(); 158e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck for (int i = 0; i < N; i++) { 159e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck MockObserverNode node = mChildren.get(i); 160e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (segment == null || node.mName.equals(segment)) { 161e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck // We found the child, 162e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck node.notifyMyObservers(uri, index + 1, observer, selfNotify); 163e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck if (segment != null) { 164e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck break; 165e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 166e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 167e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 168e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck } 169e6adaf57a9a4f05e88505e4a86c565b5f18a1d3bJohn Reck} 170