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 17package com.android.inputmethod.dictionarypack; 18 19import android.content.Context; 20import android.database.Cursor; 21 22import java.io.IOException; 23import java.io.InputStreamReader; 24import java.util.Collections; 25import java.util.ArrayList; 26import java.util.List; 27 28/** 29 * Helper class to easy up manipulation of dictionary pack metadata. 30 */ 31public class MetadataHandler { 32 @SuppressWarnings("unused") 33 private static final String TAG = "DictionaryProvider:" + MetadataHandler.class.getSimpleName(); 34 35 // The canonical file name for metadata. This is not the name of a real file on the 36 // device, but a symbolic name used in the database and in metadata handling. It is never 37 // tested against, only used for human-readability as the file name for the metadata. 38 public final static String METADATA_FILENAME = "metadata.json"; 39 40 /** 41 * Reads the data from the cursor and store it in metadata objects. 42 * @param results the cursor to read data from. 43 * @return the constructed list of wordlist metadata. 44 */ 45 private static List<WordListMetadata> makeMetadataObject(final Cursor results) { 46 final ArrayList<WordListMetadata> buildingMetadata = new ArrayList<WordListMetadata>(); 47 48 if (results.moveToFirst()) { 49 final int localeColumn = results.getColumnIndex(MetadataDbHelper.LOCALE_COLUMN); 50 final int typeColumn = results.getColumnIndex(MetadataDbHelper.TYPE_COLUMN); 51 final int descriptionColumn = 52 results.getColumnIndex(MetadataDbHelper.DESCRIPTION_COLUMN); 53 final int idIndex = results.getColumnIndex(MetadataDbHelper.WORDLISTID_COLUMN); 54 final int updateIndex = results.getColumnIndex(MetadataDbHelper.DATE_COLUMN); 55 final int fileSizeIndex = results.getColumnIndex(MetadataDbHelper.FILESIZE_COLUMN); 56 final int checksumIndex = results.getColumnIndex(MetadataDbHelper.CHECKSUM_COLUMN); 57 final int localFilenameIndex = 58 results.getColumnIndex(MetadataDbHelper.LOCAL_FILENAME_COLUMN); 59 final int remoteFilenameIndex = 60 results.getColumnIndex(MetadataDbHelper.REMOTE_FILENAME_COLUMN); 61 final int versionIndex = results.getColumnIndex(MetadataDbHelper.VERSION_COLUMN); 62 final int formatVersionIndex = 63 results.getColumnIndex(MetadataDbHelper.FORMATVERSION_COLUMN); 64 65 do { 66 buildingMetadata.add(new WordListMetadata(results.getString(idIndex), 67 results.getInt(typeColumn), 68 results.getString(descriptionColumn), 69 results.getLong(updateIndex), 70 results.getLong(fileSizeIndex), 71 results.getString(checksumIndex), 72 results.getString(localFilenameIndex), 73 results.getString(remoteFilenameIndex), 74 results.getInt(versionIndex), 75 results.getInt(formatVersionIndex), 76 0, results.getString(localeColumn))); 77 } while (results.moveToNext()); 78 79 results.close(); 80 } 81 return Collections.unmodifiableList(buildingMetadata); 82 } 83 84 /** 85 * Gets the whole metadata, for installed and not installed dictionaries. 86 * @param context The context to open files over. 87 * @param clientId the client id for retrieving the database. null for default (deprecated) 88 * @return The current metadata. 89 */ 90 public static List<WordListMetadata> getCurrentMetadata(final Context context, 91 final String clientId) { 92 // If clientId is null, we get a cursor on the default database (see 93 // MetadataDbHelper#getInstance() for more on this) 94 final Cursor results = MetadataDbHelper.queryCurrentMetadata(context, clientId); 95 final List<WordListMetadata> resultList = makeMetadataObject(results); 96 results.close(); 97 return resultList; 98 } 99 100 /** 101 * Read metadata from a stream. 102 * @param input The stream to read from. 103 * @return The read metadata. 104 * @throws IOException if the input stream cannot be read 105 * @throws BadFormatException if the stream is not in a known format 106 */ 107 public static List<WordListMetadata> readMetadata(final InputStreamReader input) 108 throws IOException, BadFormatException { 109 return MetadataParser.parseMetadata(input); 110 } 111 112 /** 113 * Finds a single WordListMetadata inside a whole metadata chunk. 114 * 115 * Searches through the whole passed metadata for the first WordListMetadata associated 116 * with the passed ID. If several metadata chunks with the same id are found, it will 117 * always return the one with the bigger FormatVersion that is less or equal than the 118 * maximum supported format version (as listed in UpdateHandler). 119 * This will NEVER return the metadata with a FormatVersion bigger than what is supported, 120 * even if it is the only word list with this ID. 121 * 122 * @param metadata the metadata to search into. 123 * @param id the word list ID of the metadata to find. 124 * @return the associated metadata, or null if not found. 125 */ 126 public static WordListMetadata findWordListById(final List<WordListMetadata> metadata, 127 final String id) { 128 WordListMetadata bestWordList = null; 129 int bestFormatVersion = Integer.MIN_VALUE; // To be sure we can't be inadvertently smaller 130 for (WordListMetadata wordList : metadata) { 131 if (id.equals(wordList.mId) 132 && wordList.mFormatVersion <= UpdateHandler.MAXIMUM_SUPPORTED_FORMAT_VERSION 133 && wordList.mFormatVersion > bestFormatVersion) { 134 bestWordList = wordList; 135 bestFormatVersion = wordList.mFormatVersion; 136 } 137 } 138 // If we didn't find any match we'll return null. 139 return bestWordList; 140 } 141} 142