android的UriMatcher类

package fkshl.activity.contentProvider;

/* Copyright (C) 2006 The Android Open Source Project  

 *  

 * Licensed under the Apache License, Version 2.0 (the "License");  

 * you may not use this file except in compliance with the License.  

 * You may obtain a copy of the License at  

 *  

 *      http://www.apache.org/licenses/LICENSE-2.0  

 *  

 * Unless required by applicable law or agreed to in writing, software  

 * distributed under the License is distributed on an "AS IS" BASIS,  

 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  

 * See the License for the specific language governing permissions and  

 * limitations under the License.  

 */

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

import android.net.Uri;

public class UriMatcher

{

    public static final int NO_MATCH = -1;

    /***
     * 
     * Creates the root node of the URI tree.
     * 
     * 
     * 
     * @param code
     *            the code to match for the root URI
     */

    public UriMatcher(int code){
        mCode = code;
        mWhich = -1;
        mChildren = new ArrayList<UriMatcher>();
        mText = null;
    }

    private UriMatcher(){
        mCode = NO_MATCH;
        mWhich = -1;
        mChildren = new ArrayList<UriMatcher>();
        mText = null;

    }

    /***
     * 
     * Add a URI to match, and the code to return when this URI is
     * 
     * matched. URI nodes may be exact match string, the token "*"
     * 
     * that matches any text, or the token "#" that matches only
     * 
     * numbers.
     * 
     * 
     * 
     * @param authority
     *            the authority to match
     * 
     * @param path
     *            the path to match. * may be used as a wild card for
     * 
     *            any text, and # may be used as a wild card for numbers.
     * 
     * @param code
     *            the code that is returned when a URI is matched
     * 
     *            against the given components. Must be positive.
     */

    public void addURI(String authority, String path, int code){

        if (code < 0) {
            throw new IllegalArgumentException("code " + code
                    + " is invalid: it must be positive");

        }
        //以"/"分隔path
        String[] tokens = path != null ? PATH_SPLIT_PATTERN.split(path) : null;
        //判断分隔后的数组长度.并取其值
        int numTokens = tokens != null ? tokens.length : 0;
        //当前对象
        UriMatcher node = this;
        
        for (int i = -1; i < numTokens; i++) {
            //当前循环变量小于0就取authority,否则就获取分隔后的数组的字符,并赋值给token
            String token = i < 0 ? authority : tokens[i];
            //把当前对象的集合赋值给children
            ArrayList<UriMatcher> children = node.mChildren;
            //获取其长度
            int numChildren = children.size();    
                  UriMatcher child;
            int j;    
            for (j = 0; j < numChildren; j++) {
                //获取children对象的孩子
                child = children.get(j);
                //判断当前的token和child对象中的mText是否相等
                if (token.equals(child.mText)) {
                    //把child 赋值给 node;
                    node = child;
                    break;
                }
            }
            //获取循环变量j并判断是否等于children对应的大小.也就是判断是否是最后一个
            if (j == numChildren) {
                // Child not found, create it
                //没有发现孩子,并创建
                child = new UriMatcher();
                ///判断当前的token是否等于"#"
                if (token.equals("#")) {
                    //mWhich=1
                    child.mWhich = NUMBER;
                } else if (token.equals("*")) {
                    //mWhich=2
                    child.mWhich = TEXT;
                } else {
                    //mWhich=0
                    child.mWhich = EXACT;
                }
                //mText=当前的token
                child.mText = token;
                //添加到mChildren集合中
                node.mChildren.add(child);
                //node = child;
                node = child;
            }
        }
        //node.mCode = code;
        node.mCode = code;
    }

    static final Pattern PATH_SPLIT_PATTERN = Pattern.compile("/");

    /***
     * 
     * Try to match against the path in a url.
     * 
     * 
     * 
     * @param uri
     *            The url whose path we will match against.
     * 
     * 
     * 
     * @return The code for the matched node (added using addURI),
     * 
     *         or -1 if there is no matched node.
     */

    public int match(Uri uri){

        final List<String> pathSegments = uri.getPathSegments();
        final int li = pathSegments.size();
        UriMatcher node = this;
        if (li == 0 && uri.getAuthority() == null) {
            return this.mCode;
        }
        for (int i = -1; i < li; i++) {
            String u = i < 0 ? uri.getAuthority() : pathSegments.get(i);
            ArrayList<UriMatcher> list = node.mChildren;
            if (list == null) {
                break;

            }
            node = null;
            int lj = list.size();
            for (int j = 0; j < lj; j++) {
                UriMatcher n = list.get(j);
                which_switch:
                switch (n.mWhich) {
                case EXACT:
                    if (n.mText.equals(u)) {
                        node = n;
                    }
                        break;
                case NUMBER:
                    int lk = u.length();
                    for (int k = 0; k < lk; k++) {
                        char c = u.charAt(k);
                                 if (c < '0' || c > '9') {
                            break which_switch;
                        }
                    }
                    node = n;
                    break;
                case TEXT:
                    node = n;
                    break;
                }
                if (node != null) {
                     break;
                }
            }
            if (node == null) {
                return NO_MATCH;
            }
        }
        return node.mCode;
    }
    private static final int EXACT = 0;
    private static final int NUMBER = 1;
    private static final int TEXT = 2;
    private int mCode;
    private int mWhich;
    private String mText;
    private final ArrayList<UriMatcher> mChildren;

}
这是android源码.
由于不懂所以就把它粘贴的项目中.所以包自然就改成自己项目的了..
package fkshl.activity.contentProvider;

import java.util.HashMap;
import java.util.Map;

import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import fkshl.activity.contentProviderMetaData.ContentProviderMetaData;
import fkshl.activity.contentProviderMetaData.ContentProviderMetaData.UserTableMetaData;
import fkshl.activity.dataBase.DBHelper;

public class FkshlContentProvider extends ContentProvider {

    public static final UriMatcher URI_MATCHER;
    public static final int FKSHL_TABLE = 1;
    public static final int FKSHL_TABLE_COLUMN = 2;
    public static final Map<String, String> COLUM_MAPPIGN;

    public DBHelper dbHelper;

    static {
        /**
         * uri验证
         */
        URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
        URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "users", 1);
        URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "users/#", 2);

        /**
         * 列的映射
         */
        COLUM_MAPPIGN = new HashMap<String, String>();
        COLUM_MAPPIGN.put(UserTableMetaData._ID, UserTableMetaData._ID);
        COLUM_MAPPIGN.put(UserTableMetaData.COLUMN_NAME, UserTableMetaData.COLUMN_NAME);
    }

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        // TODO Auto-generated method stub
        return 0;
    }

    @Override
    public String getType(Uri uri) {
        // TODO Auto-generated method stub
        switch (URI_MATCHER.match(uri)) {
        case FKSHL_TABLE:
            return UserTableMetaData.CONTENT_TYPE;
        case FKSHL_TABLE_COLUMN:
            return UserTableMetaData.CONTENT_TYPE_ITEM;
        default:
            throw new IllegalArgumentException("Unknown URI!!!!!" + uri);
        }
    }

    @Override
    public Uri insert(Uri uri, ContentValues values) {
        // TODO Auto-generated method stub
        SQLiteDatabase database = dbHelper.getWritableDatabase();
        Long rowId = database.insert(ContentProviderMetaData.TABLE_NAME, null, values);
        if (rowId > 0) {
            Uri empuri = ContentUris.withAppendedId(UserTableMetaData.CONTENT_URI, rowId);
            getContext().getContentResolver().notifyChange(empuri, null);
            System.out.println("insert success!!!");
        }
        return null;
    }

    @Override
    public boolean onCreate() {
        // TODO Auto-generated method stub
        dbHelper = new DBHelper(getContext(), ContentProviderMetaData.DATABASE_NAME);
        dbHelper.getReadableDatabase();
        System.out.println("create database success!!");
        return true;
    }

    @Override
    public Cursor query(Uri uri, String[] projection, String selection,
            String[] selectionArgs, String sortOrder) {
        SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
        // TODO Auto-generated method stub
        switch (URI_MATCHER.match(uri)) {
        case FKSHL_TABLE:
            builder.setTables(UserTableMetaData.TABLE_NAME);
            builder.setProjectionMap(COLUM_MAPPIGN);
            break;
        case FKSHL_TABLE_COLUMN:
            builder.setTables(UserTableMetaData.TABLE_NAME);
            builder.setProjectionMap(COLUM_MAPPIGN);
            builder.appendWhere(UserTableMetaData.COLUMN_NAME + "="
                    + uri.getPathSegments().get(1));
            break;

        default:
            throw new IllegalArgumentException("uri error !!!!" + uri);
        }
        String orderBy;
        if (TextUtils.isEmpty(sortOrder)) {
            orderBy = UserTableMetaData.ORDER_BY + " Desc";
        } else {
            orderBy = sortOrder;
        }
        SQLiteDatabase database = dbHelper.getReadableDatabase();
        Cursor c =    builder.query(database, projection, selection, selectionArgs, null, null, orderBy);
        c.setNotificationUri(getContext().getContentResolver(), uri);
        System.out.println("seach end!!!!");
        return c;
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection,
            String[] selectionArgs) {
        // TODO Auto-generated method stub
        return 0;
    }

}
做的时间发现一个问题.
这是之前发现在按官方提示做的.
    URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "/users", 1);
        URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "/users/#", 2);
可是在getType中怎么都走default.都是抛异常.
05-22 09:39:23.449: ERROR/AndroidRuntime(581): java.lang.IllegalArgumentException: uri error !!!!content://fkshl.activity.contentProvider.FkshlContentProvider/users
最后看了源码,改成了.
    URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "users", 1);
        URI_MATCHER.addURI(ContentProviderMetaData.AUTHORIY, "users/#", 2);
这样就好.
原因是在add方法中它会以"/"分隔users/#,然后把分隔后的字符串像树型的一级一级保存在mChildren中.如果在users/#前面加"/",哪么就导致在"/"之前有一个空字符(content://fkshl.activity.contentProvider.FkshlContentProvider//users),而在我的项目中调用getType方法传过来时的uir中没有这样的一个空字符(content://fkshl.activity.contentProvider.FkshlContentProvider/users)
没有.

转  http://fkshl.iteye.com/blog/1054518

posted @ 2012-11-09 01:49  编程小爬虫  阅读(355)  评论(0编辑  收藏  举报