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