1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16 
17 package com.android.inputmethod.dictionarypack;
18 
19 import android.text.TextUtils;
20 import android.util.JsonReader;
21 
22 import java.io.IOException;
23 import java.io.InputStreamReader;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.List;
27 import java.util.TreeMap;
28 
29 /**
30  * Helper class containing functions to parse the dictionary metadata.
31  */
32 public class MetadataParser {
33 
34     // Name of the fields in the JSON-formatted file.
35     private static final String ID_FIELD_NAME = MetadataDbHelper.WORDLISTID_COLUMN;
36     private static final String LOCALE_FIELD_NAME = "locale";
37     private static final String DESCRIPTION_FIELD_NAME = MetadataDbHelper.DESCRIPTION_COLUMN;
38     private static final String UPDATE_FIELD_NAME = "update";
39     private static final String FILESIZE_FIELD_NAME = MetadataDbHelper.FILESIZE_COLUMN;
40     private static final String RAW_CHECKSUM_FIELD_NAME = MetadataDbHelper.RAW_CHECKSUM_COLUMN;
41     private static final String CHECKSUM_FIELD_NAME = MetadataDbHelper.CHECKSUM_COLUMN;
42     private static final String REMOTE_FILENAME_FIELD_NAME =
43             MetadataDbHelper.REMOTE_FILENAME_COLUMN;
44     private static final String VERSION_FIELD_NAME = MetadataDbHelper.VERSION_COLUMN;
45     private static final String FORMATVERSION_FIELD_NAME = MetadataDbHelper.FORMATVERSION_COLUMN;
46 
47     /**
48      * Parse one JSON-formatted word list metadata.
49      * @param reader the reader containing the data.
50      * @return a WordListMetadata object from the parsed data.
51      * @throws IOException if the underlying reader throws IOException during reading.
52      */
parseOneWordList(final JsonReader reader)53     private static WordListMetadata parseOneWordList(final JsonReader reader)
54             throws IOException, BadFormatException {
55         final TreeMap<String, String> arguments = new TreeMap<>();
56         reader.beginObject();
57         while (reader.hasNext()) {
58             final String name = reader.nextName();
59             if (!TextUtils.isEmpty(name)) {
60                 arguments.put(name, reader.nextString());
61             }
62         }
63         reader.endObject();
64         if (TextUtils.isEmpty(arguments.get(ID_FIELD_NAME))
65                 || TextUtils.isEmpty(arguments.get(LOCALE_FIELD_NAME))
66                 || TextUtils.isEmpty(arguments.get(DESCRIPTION_FIELD_NAME))
67                 || TextUtils.isEmpty(arguments.get(UPDATE_FIELD_NAME))
68                 || TextUtils.isEmpty(arguments.get(FILESIZE_FIELD_NAME))
69                 || TextUtils.isEmpty(arguments.get(CHECKSUM_FIELD_NAME))
70                 || TextUtils.isEmpty(arguments.get(REMOTE_FILENAME_FIELD_NAME))
71                 || TextUtils.isEmpty(arguments.get(VERSION_FIELD_NAME))
72                 || TextUtils.isEmpty(arguments.get(FORMATVERSION_FIELD_NAME))) {
73             throw new BadFormatException(arguments.toString());
74         }
75         // TODO: need to find out whether it's bulk or update
76         // The null argument is the local file name, which is not known at this time and will
77         // be decided later.
78         return new WordListMetadata(
79                 arguments.get(ID_FIELD_NAME),
80                 MetadataDbHelper.TYPE_BULK,
81                 arguments.get(DESCRIPTION_FIELD_NAME),
82                 Long.parseLong(arguments.get(UPDATE_FIELD_NAME)),
83                 Long.parseLong(arguments.get(FILESIZE_FIELD_NAME)),
84                 arguments.get(RAW_CHECKSUM_FIELD_NAME),
85                 arguments.get(CHECKSUM_FIELD_NAME),
86                 MetadataDbHelper.DICTIONARY_RETRY_THRESHOLD /* retryCount */,
87                 null,
88                 arguments.get(REMOTE_FILENAME_FIELD_NAME),
89                 Integer.parseInt(arguments.get(VERSION_FIELD_NAME)),
90                 Integer.parseInt(arguments.get(FORMATVERSION_FIELD_NAME)),
91                 0, arguments.get(LOCALE_FIELD_NAME));
92     }
93 
94     /**
95      * Parses metadata in the JSON format.
96      * @param input a stream reader expected to contain JSON formatted metadata.
97      * @return dictionary metadata, as an array of WordListMetadata objects.
98      * @throws IOException if the underlying reader throws IOException during reading.
99      * @throws BadFormatException if the data was not in the expected format.
100      */
parseMetadata(final InputStreamReader input)101     public static List<WordListMetadata> parseMetadata(final InputStreamReader input)
102             throws IOException, BadFormatException {
103         JsonReader reader = new JsonReader(input);
104         final ArrayList<WordListMetadata> readInfo = new ArrayList<>();
105         reader.beginArray();
106         while (reader.hasNext()) {
107             final WordListMetadata thisMetadata = parseOneWordList(reader);
108             if (!TextUtils.isEmpty(thisMetadata.mLocale))
109                 readInfo.add(thisMetadata);
110         }
111         return Collections.unmodifiableList(readInfo);
112     }
113 
114 }
115