10cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard/*
20cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Copyright (C) 2011 The Android Open Source Project
30cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard *
40cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Licensed under the Apache License, Version 2.0 (the "License"); you may not
50cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * use this file except in compliance with the License. You may obtain a copy of
60cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * the License at
70cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard *
80cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * http://www.apache.org/licenses/LICENSE-2.0
90cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard *
100cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Unless required by applicable law or agreed to in writing, software
110cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
120cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
130cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * License for the specific language governing permissions and limitations under
140cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * the License.
150cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard */
160cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard
170cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardpackage com.android.inputmethod.dictionarypack;
180cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard
190cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport android.text.TextUtils;
200cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport android.util.JsonReader;
210cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard
220cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport java.io.IOException;
230cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport java.io.InputStreamReader;
240cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport java.util.ArrayList;
250cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport java.util.Collections;
260cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport java.util.List;
270cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardimport java.util.TreeMap;
280cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard
290cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard/**
300cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard * Helper class containing functions to parse the dictionary metadata.
310cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard */
320cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalardpublic class MetadataParser {
330cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard
340cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    // Name of the fields in the JSON-formatted file.
350cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static final String ID_FIELD_NAME = MetadataDbHelper.WORDLISTID_COLUMN;
360cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static final String LOCALE_FIELD_NAME = "locale";
370cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static final String DESCRIPTION_FIELD_NAME = MetadataDbHelper.DESCRIPTION_COLUMN;
380cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static final String UPDATE_FIELD_NAME = "update";
390cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static final String FILESIZE_FIELD_NAME = MetadataDbHelper.FILESIZE_COLUMN;
40e077c014616f7b4e28dbbfab622ba36c8e922268Jean Chalard    private static final String RAW_CHECKSUM_FIELD_NAME = MetadataDbHelper.RAW_CHECKSUM_COLUMN;
410cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static final String CHECKSUM_FIELD_NAME = MetadataDbHelper.CHECKSUM_COLUMN;
420cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static final String REMOTE_FILENAME_FIELD_NAME =
430cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard            MetadataDbHelper.REMOTE_FILENAME_COLUMN;
440cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static final String VERSION_FIELD_NAME = MetadataDbHelper.VERSION_COLUMN;
450cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static final String FORMATVERSION_FIELD_NAME = MetadataDbHelper.FORMATVERSION_COLUMN;
460cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard
470cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    /**
480cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     * Parse one JSON-formatted word list metadata.
490cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     * @param reader the reader containing the data.
500cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     * @return a WordListMetadata object from the parsed data.
510cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     * @throws IOException if the underlying reader throws IOException during reading.
520cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     */
530cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    private static WordListMetadata parseOneWordList(final JsonReader reader)
540cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard            throws IOException, BadFormatException {
55a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka        final TreeMap<String, String> arguments = new TreeMap<>();
560cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        reader.beginObject();
570cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        while (reader.hasNext()) {
580cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard            final String name = reader.nextName();
590cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard            if (!TextUtils.isEmpty(name)) {
600cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                arguments.put(name, reader.nextString());
610cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard            }
620cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        }
630cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        reader.endObject();
640cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        if (TextUtils.isEmpty(arguments.get(ID_FIELD_NAME))
650cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                || TextUtils.isEmpty(arguments.get(LOCALE_FIELD_NAME))
660cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                || TextUtils.isEmpty(arguments.get(DESCRIPTION_FIELD_NAME))
670cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                || TextUtils.isEmpty(arguments.get(UPDATE_FIELD_NAME))
680cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                || TextUtils.isEmpty(arguments.get(FILESIZE_FIELD_NAME))
690cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                || TextUtils.isEmpty(arguments.get(CHECKSUM_FIELD_NAME))
700cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                || TextUtils.isEmpty(arguments.get(REMOTE_FILENAME_FIELD_NAME))
710cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                || TextUtils.isEmpty(arguments.get(VERSION_FIELD_NAME))
720cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                || TextUtils.isEmpty(arguments.get(FORMATVERSION_FIELD_NAME))) {
730cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard            throw new BadFormatException(arguments.toString());
740cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        }
750cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        // TODO: need to find out whether it's bulk or update
760cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        // The null argument is the local file name, which is not known at this time and will
770cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        // be decided later.
780cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        return new WordListMetadata(
790cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                arguments.get(ID_FIELD_NAME),
800cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                MetadataDbHelper.TYPE_BULK,
810cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                arguments.get(DESCRIPTION_FIELD_NAME),
820cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                Long.parseLong(arguments.get(UPDATE_FIELD_NAME)),
830cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                Long.parseLong(arguments.get(FILESIZE_FIELD_NAME)),
84e077c014616f7b4e28dbbfab622ba36c8e922268Jean Chalard                arguments.get(RAW_CHECKSUM_FIELD_NAME),
850cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                arguments.get(CHECKSUM_FIELD_NAME),
86256b1b2a1e054773987a0672b4ac3c867a4dbd27Jatin Matani                MetadataDbHelper.DICTIONARY_RETRY_THRESHOLD /* retryCount */,
870cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                null,
880cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                arguments.get(REMOTE_FILENAME_FIELD_NAME),
890cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                Integer.parseInt(arguments.get(VERSION_FIELD_NAME)),
900cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                Integer.parseInt(arguments.get(FORMATVERSION_FIELD_NAME)),
910cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                0, arguments.get(LOCALE_FIELD_NAME));
920cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    }
930cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard
940cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    /**
950cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     * Parses metadata in the JSON format.
960cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     * @param input a stream reader expected to contain JSON formatted metadata.
970cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     * @return dictionary metadata, as an array of WordListMetadata objects.
980cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     * @throws IOException if the underlying reader throws IOException during reading.
990cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     * @throws BadFormatException if the data was not in the expected format.
1000cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard     */
1010cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    public static List<WordListMetadata> parseMetadata(final InputStreamReader input)
1020cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard            throws IOException, BadFormatException {
1030cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        JsonReader reader = new JsonReader(input);
104a91561aa58db1c43092c1caecc051a11fa5391c7Tadashi G. Takaoka        final ArrayList<WordListMetadata> readInfo = new ArrayList<>();
1050cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        reader.beginArray();
1060cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        while (reader.hasNext()) {
1070cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard            final WordListMetadata thisMetadata = parseOneWordList(reader);
1080cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard            if (!TextUtils.isEmpty(thisMetadata.mLocale))
1090cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard                readInfo.add(thisMetadata);
1100cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        }
1110cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard        return Collections.unmodifiableList(readInfo);
1120cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard    }
1130cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard
1140cc0544a2995c7eb54a830ae54db60af89d4073dJean Chalard}
115