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