Home | History | Annotate | Download | only in utils
      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 
     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 
     43     public MockObserverNode(String name) {
     44         mName = name;
     45     }
     46 
     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 
     59     private int countUriSegments(Uri uri) {
     60         if (uri == null) {
     61             return 0;
     62         }
     63         return uri.getPathSegments().size() + 1;
     64     }
     65 
     66     public void addObserver(Uri uri, ContentObserver observer,
     67             boolean notifyForDescendents) {
     68         addObserver(uri, 0, observer, notifyForDescendents);
     69     }
     70 
     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 
     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 
    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 
    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