Home | History | Annotate | Download | only in session
      1 /*
      2  * Copyright (C) 2012 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 #ifndef LATINIME_DIC_TRAVERSE_SESSION_H
     18 #define LATINIME_DIC_TRAVERSE_SESSION_H
     19 
     20 #include <stdint.h>
     21 #include <vector>
     22 
     23 #include "defines.h"
     24 #include "jni.h"
     25 #include "suggest/core/dicnode/dic_nodes_cache.h"
     26 #include "suggest/core/dictionary/multi_bigram_map.h"
     27 #include "suggest/core/layout/proximity_info_state.h"
     28 
     29 namespace latinime {
     30 
     31 class Dictionary;
     32 class DictionaryStructureWithBufferPolicy;
     33 class ProximityInfo;
     34 class SuggestOptions;
     35 
     36 class DicTraverseSession {
     37  public:
     38 
     39     // A factory method for DicTraverseSession
     40     static AK_FORCE_INLINE void *getSessionInstance(JNIEnv *env, jstring localeStr,
     41             jlong dictSize) {
     42         // To deal with the trade-off between accuracy and memory space, large cache is used for
     43         // dictionaries larger that the threshold
     44         return new DicTraverseSession(env, localeStr,
     45                 dictSize >= DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION);
     46     }
     47 
     48     static AK_FORCE_INLINE void initSessionInstance(DicTraverseSession *traverseSession,
     49             const Dictionary *const dictionary, const int *prevWord, const int prevWordLength,
     50             const SuggestOptions *const suggestOptions) {
     51         if (traverseSession) {
     52             DicTraverseSession *tSession = static_cast<DicTraverseSession *>(traverseSession);
     53             tSession->init(dictionary, prevWord, prevWordLength, suggestOptions);
     54         }
     55     }
     56 
     57     static AK_FORCE_INLINE void releaseSessionInstance(DicTraverseSession *traverseSession) {
     58         delete traverseSession;
     59     }
     60 
     61     AK_FORCE_INLINE DicTraverseSession(JNIEnv *env, jstring localeStr, bool usesLargeCache)
     62             : mPrevWordPos(NOT_A_DICT_POS), mProximityInfo(0),
     63               mDictionary(0), mSuggestOptions(0), mDicNodesCache(usesLargeCache),
     64               mMultiBigramMap(), mInputSize(0), mPartiallyCommited(false), mMaxPointerCount(1),
     65               mMultiWordCostMultiplier(1.0f) {
     66         // NOTE: mProximityInfoStates is an array of instances.
     67         // No need to initialize it explicitly here.
     68     }
     69 
     70     // Non virtual inline destructor -- never inherit this class
     71     AK_FORCE_INLINE ~DicTraverseSession() {}
     72 
     73     void init(const Dictionary *dictionary, const int *prevWord, int prevWordLength,
     74             const SuggestOptions *const suggestOptions);
     75     // TODO: Remove and merge into init
     76     void setupForGetSuggestions(const ProximityInfo *pInfo, const int *inputCodePoints,
     77             const int inputSize, const int *const inputXs, const int *const inputYs,
     78             const int *const times, const int *const pointerIds, const float maxSpatialDistance,
     79             const int maxPointerCount);
     80     void resetCache(const int thresholdForNextActiveDicNodes, const int maxWords);
     81 
     82     const DictionaryStructureWithBufferPolicy *getDictionaryStructurePolicy() const;
     83 
     84     //--------------------
     85     // getters and setters
     86     //--------------------
     87     const ProximityInfo *getProximityInfo() const { return mProximityInfo; }
     88     const SuggestOptions *getSuggestOptions() const { return mSuggestOptions; }
     89     int getPrevWordPos() const { return mPrevWordPos; }
     90     // TODO: REMOVE
     91     void setPrevWordPos(int pos) { mPrevWordPos = pos; }
     92     // TODO: Use proper parameter when changed
     93     int getDicRootPos() const { return 0; }
     94     DicNodesCache *getDicTraverseCache() { return &mDicNodesCache; }
     95     MultiBigramMap *getMultiBigramMap() { return &mMultiBigramMap; }
     96     const ProximityInfoState *getProximityInfoState(int id) const {
     97         return &mProximityInfoStates[id];
     98     }
     99     int getInputSize() const { return mInputSize; }
    100     void setPartiallyCommited() { mPartiallyCommited = true; }
    101     bool isPartiallyCommited() const { return mPartiallyCommited; }
    102 
    103     bool isOnlyOnePointerUsed(int *pointerId) const {
    104         // Not in the dictionary word
    105         int usedPointerCount = 0;
    106         int usedPointerId = 0;
    107         for (int i = 0; i < mMaxPointerCount; ++i) {
    108             if (mProximityInfoStates[i].isUsed()) {
    109                 ++usedPointerCount;
    110                 usedPointerId = i;
    111             }
    112         }
    113         if (usedPointerCount != 1) {
    114             return false;
    115         }
    116         if (pointerId) {
    117             *pointerId = usedPointerId;
    118         }
    119         return true;
    120     }
    121 
    122     void getSearchKeys(const DicNode *node, std::vector<int> *const outputSearchKeyVector) const {
    123         for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
    124             if (!mProximityInfoStates[i].isUsed()) {
    125                 continue;
    126             }
    127             const int pointerId = node->getInputIndex(i);
    128             const std::vector<int> *const searchKeyVector =
    129                     mProximityInfoStates[i].getSearchKeyVector(pointerId);
    130             outputSearchKeyVector->insert(outputSearchKeyVector->end(), searchKeyVector->begin(),
    131                     searchKeyVector->end());
    132         }
    133     }
    134 
    135     ProximityType getProximityTypeG(const DicNode *const node, const int childCodePoint) const {
    136         ProximityType proximityType = UNRELATED_CHAR;
    137         for (int i = 0; i < MAX_POINTER_COUNT_G; ++i) {
    138             if (!mProximityInfoStates[i].isUsed()) {
    139                 continue;
    140             }
    141             const int pointerId = node->getInputIndex(i);
    142             proximityType = mProximityInfoStates[i].getProximityTypeG(pointerId, childCodePoint);
    143             ASSERT(proximityType == UNRELATED_CHAR || proximityType == MATCH_CHAR);
    144             // TODO: Make this more generic
    145             // Currently we assume there are only two types here -- UNRELATED_CHAR
    146             // and MATCH_CHAR
    147             if (proximityType != UNRELATED_CHAR) {
    148                 return proximityType;
    149             }
    150         }
    151         return proximityType;
    152     }
    153 
    154     AK_FORCE_INLINE bool isCacheBorderForTyping(const int inputSize) const {
    155         return mDicNodesCache.isCacheBorderForTyping(inputSize);
    156     }
    157 
    158     /**
    159      * Returns whether or not it is possible to continue suggestion from the previous search.
    160      */
    161     // TODO: Remove. No need to check once the session is fully implemented.
    162     bool isContinuousSuggestionPossible() const {
    163         if (!mDicNodesCache.hasCachedDicNodesForContinuousSuggestion()) {
    164             return false;
    165         }
    166         ASSERT(mMaxPointerCount <= MAX_POINTER_COUNT_G);
    167         for (int i = 0; i < mMaxPointerCount; ++i) {
    168             const ProximityInfoState *const pInfoState = getProximityInfoState(i);
    169             // If a proximity info state is not continuous suggestion possible,
    170             // do not continue searching.
    171             if (pInfoState->isUsed() && !pInfoState->isContinuousSuggestionPossible()) {
    172                 return false;
    173             }
    174         }
    175         return true;
    176     }
    177 
    178     bool isTouchPositionCorrectionEnabled() const {
    179         return mProximityInfoStates[0].touchPositionCorrectionEnabled();
    180     }
    181 
    182     float getMultiWordCostMultiplier() const {
    183         return mMultiWordCostMultiplier;
    184     }
    185 
    186  private:
    187     DISALLOW_IMPLICIT_CONSTRUCTORS(DicTraverseSession);
    188     // threshold to start caching
    189     static const int CACHE_START_INPUT_LENGTH_THRESHOLD;
    190     static const int DICTIONARY_SIZE_THRESHOLD_TO_USE_LARGE_CACHE_FOR_SUGGESTION;
    191     void initializeProximityInfoStates(const int *const inputCodePoints, const int *const inputXs,
    192             const int *const inputYs, const int *const times, const int *const pointerIds,
    193             const int inputSize, const float maxSpatialDistance, const int maxPointerCount);
    194 
    195     int mPrevWordPos;
    196     const ProximityInfo *mProximityInfo;
    197     const Dictionary *mDictionary;
    198     const SuggestOptions *mSuggestOptions;
    199 
    200     DicNodesCache mDicNodesCache;
    201     // Temporary cache for bigram frequencies
    202     MultiBigramMap mMultiBigramMap;
    203     ProximityInfoState mProximityInfoStates[MAX_POINTER_COUNT_G];
    204 
    205     int mInputSize;
    206     bool mPartiallyCommited;
    207     int mMaxPointerCount;
    208 
    209     /////////////////////////////////
    210     // Configuration per dictionary
    211     float mMultiWordCostMultiplier;
    212 
    213 };
    214 } // namespace latinime
    215 #endif // LATINIME_DIC_TRAVERSE_SESSION_H
    216