1/*
2 * Copyright (C) 2009, 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#define LOG_TAG "LatinIME: dictionary.cpp"
18
19#include "suggest/core/dictionary/dictionary.h"
20
21#include <stdint.h>
22
23#include "defines.h"
24#include "suggest/core/dictionary/bigram_dictionary.h"
25#include "suggest/core/policy/dictionary_header_structure_policy.h"
26#include "suggest/core/policy/dictionary_structure_with_buffer_policy.h"
27#include "suggest/core/session/dic_traverse_session.h"
28#include "suggest/core/suggest.h"
29#include "suggest/core/suggest_options.h"
30#include "suggest/policyimpl/gesture/gesture_suggest_policy_factory.h"
31#include "suggest/policyimpl/typing/typing_suggest_policy_factory.h"
32#include "utils/log_utils.h"
33
34namespace latinime {
35
36const int Dictionary::HEADER_ATTRIBUTE_BUFFER_SIZE = 32;
37
38Dictionary::Dictionary(JNIEnv *env,
39        DictionaryStructureWithBufferPolicy *const dictionaryStructureWithBufferPolicy)
40        : mDictionaryStructureWithBufferPolicy(dictionaryStructureWithBufferPolicy),
41          mBigramDictionary(new BigramDictionary(mDictionaryStructureWithBufferPolicy)),
42          mGestureSuggest(new Suggest(GestureSuggestPolicyFactory::getGestureSuggestPolicy())),
43          mTypingSuggest(new Suggest(TypingSuggestPolicyFactory::getTypingSuggestPolicy())) {
44    logDictionaryInfo(env);
45}
46
47Dictionary::~Dictionary() {
48    delete mBigramDictionary;
49    delete mGestureSuggest;
50    delete mTypingSuggest;
51    delete mDictionaryStructureWithBufferPolicy;
52}
53
54int Dictionary::getSuggestions(ProximityInfo *proximityInfo, DicTraverseSession *traverseSession,
55        int *xcoordinates, int *ycoordinates, int *times, int *pointerIds, int *inputCodePoints,
56        int inputSize, int *prevWordCodePoints, int prevWordLength, int commitPoint,
57        const SuggestOptions *const suggestOptions, int *outWords, int *frequencies,
58        int *spaceIndices, int *outputTypes, int *outputAutoCommitFirstWordConfidence) const {
59    int result = 0;
60    if (suggestOptions->isGesture()) {
61        DicTraverseSession::initSessionInstance(
62                traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
63        result = mGestureSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
64                ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint, outWords,
65                frequencies, spaceIndices, outputTypes, outputAutoCommitFirstWordConfidence);
66        if (DEBUG_DICT) {
67            DUMP_RESULT(outWords, frequencies);
68        }
69        return result;
70    } else {
71        DicTraverseSession::initSessionInstance(
72                traverseSession, this, prevWordCodePoints, prevWordLength, suggestOptions);
73        result = mTypingSuggest->getSuggestions(proximityInfo, traverseSession, xcoordinates,
74                ycoordinates, times, pointerIds, inputCodePoints, inputSize, commitPoint,
75                outWords, frequencies, spaceIndices, outputTypes,
76                outputAutoCommitFirstWordConfidence);
77        if (DEBUG_DICT) {
78            DUMP_RESULT(outWords, frequencies);
79        }
80        return result;
81    }
82}
83
84int Dictionary::getBigrams(const int *word, int length, int *outWords, int *frequencies,
85        int *outputTypes) const {
86    if (length <= 0) return 0;
87    return mBigramDictionary->getPredictions(word, length, outWords, frequencies, outputTypes);
88}
89
90int Dictionary::getProbability(const int *word, int length) const {
91    int pos = getDictionaryStructurePolicy()->getTerminalNodePositionOfWord(word, length,
92            false /* forceLowerCaseSearch */);
93    if (NOT_A_DICT_POS == pos) {
94        return NOT_A_PROBABILITY;
95    }
96    return getDictionaryStructurePolicy()->getUnigramProbabilityOfPtNode(pos);
97}
98
99int Dictionary::getBigramProbability(const int *word0, int length0, const int *word1,
100        int length1) const {
101    return mBigramDictionary->getBigramProbability(word0, length0, word1, length1);
102}
103
104void Dictionary::addUnigramWord(const int *const word, const int length, const int probability) {
105    mDictionaryStructureWithBufferPolicy->addUnigramWord(word, length, probability);
106}
107
108void Dictionary::addBigramWords(const int *const word0, const int length0, const int *const word1,
109        const int length1, const int probability) {
110    mDictionaryStructureWithBufferPolicy->addBigramWords(word0, length0, word1, length1,
111            probability);
112}
113
114void Dictionary::removeBigramWords(const int *const word0, const int length0,
115        const int *const word1, const int length1) {
116    mDictionaryStructureWithBufferPolicy->removeBigramWords(word0, length0, word1, length1);
117}
118
119void Dictionary::flush(const char *const filePath) {
120    mDictionaryStructureWithBufferPolicy->flush(filePath);
121}
122
123void Dictionary::flushWithGC(const char *const filePath) {
124    mDictionaryStructureWithBufferPolicy->flushWithGC(filePath);
125}
126
127bool Dictionary::needsToRunGC(const bool mindsBlockByGC) {
128    return mDictionaryStructureWithBufferPolicy->needsToRunGC(mindsBlockByGC);
129}
130
131void Dictionary::getProperty(const char *const query, char *const outResult,
132        const int maxResultLength) {
133    return mDictionaryStructureWithBufferPolicy->getProperty(query, outResult, maxResultLength);
134}
135
136void Dictionary::logDictionaryInfo(JNIEnv *const env) const {
137    int dictionaryIdCodePointBuffer[HEADER_ATTRIBUTE_BUFFER_SIZE];
138    int versionStringCodePointBuffer[HEADER_ATTRIBUTE_BUFFER_SIZE];
139    int dateStringCodePointBuffer[HEADER_ATTRIBUTE_BUFFER_SIZE];
140    const DictionaryHeaderStructurePolicy *const headerPolicy =
141            getDictionaryStructurePolicy()->getHeaderStructurePolicy();
142    headerPolicy->readHeaderValueOrQuestionMark("dictionary", dictionaryIdCodePointBuffer,
143            HEADER_ATTRIBUTE_BUFFER_SIZE);
144    headerPolicy->readHeaderValueOrQuestionMark("version", versionStringCodePointBuffer,
145            HEADER_ATTRIBUTE_BUFFER_SIZE);
146    headerPolicy->readHeaderValueOrQuestionMark("date", dateStringCodePointBuffer,
147            HEADER_ATTRIBUTE_BUFFER_SIZE);
148
149    char dictionaryIdCharBuffer[HEADER_ATTRIBUTE_BUFFER_SIZE];
150    char versionStringCharBuffer[HEADER_ATTRIBUTE_BUFFER_SIZE];
151    char dateStringCharBuffer[HEADER_ATTRIBUTE_BUFFER_SIZE];
152    intArrayToCharArray(dictionaryIdCodePointBuffer, HEADER_ATTRIBUTE_BUFFER_SIZE,
153            dictionaryIdCharBuffer, HEADER_ATTRIBUTE_BUFFER_SIZE);
154    intArrayToCharArray(versionStringCodePointBuffer, HEADER_ATTRIBUTE_BUFFER_SIZE,
155            versionStringCharBuffer, HEADER_ATTRIBUTE_BUFFER_SIZE);
156    intArrayToCharArray(dateStringCodePointBuffer, HEADER_ATTRIBUTE_BUFFER_SIZE,
157            dateStringCharBuffer, HEADER_ATTRIBUTE_BUFFER_SIZE);
158
159    LogUtils::logToJava(env,
160            "Dictionary info: dictionary = %s ; version = %s ; date = %s",
161            dictionaryIdCharBuffer, versionStringCharBuffer, dateStringCharBuffer);
162}
163
164} // namespace latinime
165