Home | History | Annotate | Download | only in content
      1 /*
      2  * Copyright (C) 2008 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 android.content;
     18 
     19 import android.net.Uri;
     20 import android.util.Xml;
     21 
     22 import org.xml.sax.Attributes;
     23 import org.xml.sax.Locator;
     24 import org.xml.sax.SAXException;
     25 
     26 import java.io.IOException;
     27 import java.io.InputStream;
     28 import java.util.Stack;
     29 
     30 /**
     31  * Inserts default data from InputStream, should be in XML format.
     32  * If the provider syncs data to the server, the imported data will be synced to the server.
     33  * <p>Samples:</p>
     34  * <br/>
     35  *  Insert one row:
     36  * <pre>
     37  * &lt;row uri="content://contacts/people">
     38  *  &lt;Col column = "name" value = "foo feebe "/>
     39  *  &lt;Col column = "addr" value = "Tx"/>
     40  * &lt;/row></pre>
     41  * <br/>
     42  * Delete, it must be in order of uri, select, and arg:
     43  * <pre>
     44  * &lt;del uri="content://contacts/people" select="name=? and addr=?"
     45  *  arg1 = "foo feebe" arg2 ="Tx"/></pre>
     46  * <br/>
     47  *  Use first row's uri to insert into another table,
     48  *  content://contacts/people/1/phones:
     49  * <pre>
     50  * &lt;row uri="content://contacts/people">
     51  *  &lt;col column = "name" value = "foo feebe"/>
     52  *  &lt;col column = "addr" value = "Tx"/>
     53  *  &lt;row postfix="phones">
     54  *    &lt;col column="number" value="512-514-6535"/>
     55  *  &lt;/row>
     56  *  &lt;row postfix="phones">
     57  *    &lt;col column="cell" value="512-514-6535"/>
     58  *  &lt;/row>
     59  * &lt;/row></pre>
     60  * <br/>
     61  *  Insert multiple rows in to same table and same attributes:
     62  * <pre>
     63  * &lt;row uri="content://contacts/people" >
     64  *  &lt;row>
     65  *   &lt;col column= "name" value = "foo feebe"/>
     66  *   &lt;col column= "addr" value = "Tx"/>
     67  *  &lt;/row>
     68  *  &lt;row>
     69  *  &lt;/row>
     70  * &lt;/row></pre>
     71  *
     72  * @hide
     73  */
     74 public class DefaultDataHandler implements ContentInsertHandler {
     75     private final static String ROW = "row";
     76     private final static String COL = "col";
     77     private final static String URI_STR = "uri";
     78     private final static String POSTFIX = "postfix";
     79     private final static String DEL = "del";
     80     private final static String SELECT = "select";
     81     private final static String ARG = "arg";
     82 
     83     private Stack<Uri> mUris = new Stack<Uri>();
     84     private ContentValues mValues;
     85     private ContentResolver mContentResolver;
     86 
     87     public void insert(ContentResolver contentResolver, InputStream in)
     88             throws IOException, SAXException {
     89         mContentResolver = contentResolver;
     90         Xml.parse(in, Xml.Encoding.UTF_8, this);
     91     }
     92 
     93     public void insert(ContentResolver contentResolver, String in)
     94         throws SAXException {
     95         mContentResolver = contentResolver;
     96         Xml.parse(in, this);
     97     }
     98 
     99     private void parseRow(Attributes atts) throws SAXException {
    100         String uriStr = atts.getValue(URI_STR);
    101         Uri uri;
    102         if (uriStr != null) {
    103             // case 1
    104             uri = Uri.parse(uriStr);
    105             if (uri == null) {
    106                 throw new SAXException("attribute " +
    107                         atts.getValue(URI_STR) + " parsing failure");
    108             }
    109 
    110         } else if (mUris.size() > 0){
    111             // case 2
    112             String postfix = atts.getValue(POSTFIX);
    113             if (postfix != null) {
    114                 uri = Uri.withAppendedPath(mUris.lastElement(),
    115                         postfix);
    116             } else {
    117                 uri = mUris.lastElement();
    118             }
    119         } else {
    120             throw new SAXException("attribute parsing failure");
    121         }
    122 
    123         mUris.push(uri);
    124 
    125     }
    126 
    127     private Uri insertRow() {
    128         Uri u = mContentResolver.insert(mUris.lastElement(), mValues);
    129         mValues = null;
    130         return u;
    131     }
    132 
    133     public void startElement(String uri, String localName, String name,
    134             Attributes atts) throws SAXException {
    135         if (ROW.equals(localName)) {
    136             if (mValues != null) {
    137                 // case 2, <Col> before <Row> insert last uri
    138                 if (mUris.empty()) {
    139                     throw new SAXException("uri is empty");
    140                 }
    141                 Uri nextUri = insertRow();
    142                 if (nextUri == null) {
    143                     throw new SAXException("insert to uri " +
    144                             mUris.lastElement().toString() + " failure");
    145                 } else {
    146                     // make sure the stack lastElement save uri for more than one row
    147                     mUris.pop();
    148                     mUris.push(nextUri);
    149                     parseRow(atts);
    150                 }
    151             } else {
    152                 int attrLen = atts.getLength();
    153                 if (attrLen == 0) {
    154                     // case 3, share same uri as last level
    155                     mUris.push(mUris.lastElement());
    156                 } else {
    157                     parseRow(atts);
    158                 }
    159             }
    160         } else if (COL.equals(localName)) {
    161             int attrLen = atts.getLength();
    162             if (attrLen != 2) {
    163                 throw new SAXException("illegal attributes number " + attrLen);
    164             }
    165             String key = atts.getValue(0);
    166             String value = atts.getValue(1);
    167             if (key != null && key.length() > 0 && value != null && value.length() > 0) {
    168                 if (mValues == null) {
    169                     mValues = new ContentValues();
    170                 }
    171                 mValues.put(key, value);
    172             } else {
    173                 throw new SAXException("illegal attributes value");
    174             }
    175         } else if (DEL.equals(localName)){
    176             Uri u = Uri.parse(atts.getValue(URI_STR));
    177             if (u == null) {
    178                 throw new SAXException("attribute " +
    179                         atts.getValue(URI_STR) + " parsing failure");
    180             }
    181             int attrLen = atts.getLength() - 2;
    182             if (attrLen > 0) {
    183                 String[] selectionArgs = new String[attrLen];
    184                 for (int i = 0; i < attrLen; i++) {
    185                     selectionArgs[i] = atts.getValue(i+2);
    186                 }
    187                 mContentResolver.delete(u, atts.getValue(1), selectionArgs);
    188             } else if (attrLen == 0){
    189                 mContentResolver.delete(u, atts.getValue(1), null);
    190             } else {
    191                 mContentResolver.delete(u, null, null);
    192             }
    193 
    194         } else {
    195             throw new SAXException("unknown element: " + localName);
    196         }
    197     }
    198 
    199     public void endElement(String uri, String localName, String name)
    200             throws SAXException {
    201         if (ROW.equals(localName)) {
    202             if (mUris.empty()) {
    203                 throw new SAXException("uri mismatch");
    204             }
    205             if (mValues != null) {
    206                 insertRow();
    207             }
    208             mUris.pop();
    209         }
    210     }
    211 
    212 
    213     public void characters(char[] ch, int start, int length)
    214             throws SAXException {
    215         // TODO Auto-generated method stub
    216 
    217     }
    218 
    219     public void endDocument() throws SAXException {
    220         // TODO Auto-generated method stub
    221 
    222     }
    223 
    224     public void endPrefixMapping(String prefix) throws SAXException {
    225         // TODO Auto-generated method stub
    226 
    227     }
    228 
    229     public void ignorableWhitespace(char[] ch, int start, int length)
    230             throws SAXException {
    231         // TODO Auto-generated method stub
    232 
    233     }
    234 
    235     public void processingInstruction(String target, String data)
    236             throws SAXException {
    237         // TODO Auto-generated method stub
    238 
    239     }
    240 
    241     public void setDocumentLocator(Locator locator) {
    242         // TODO Auto-generated method stub
    243 
    244     }
    245 
    246     public void skippedEntity(String name) throws SAXException {
    247         // TODO Auto-generated method stub
    248 
    249     }
    250 
    251     public void startDocument() throws SAXException {
    252         // TODO Auto-generated method stub
    253 
    254     }
    255 
    256     public void startPrefixMapping(String prefix, String uri)
    257             throws SAXException {
    258         // TODO Auto-generated method stub
    259 
    260     }
    261 
    262 }
    263