1 // Copyright 2010-2018, Google Inc.
2 // All rights reserved.
3 //
4 // Redistribution and use in source and binary forms, with or without
5 // modification, are permitted provided that the following conditions are
6 // met:
7 //
8 //     * Redistributions of source code must retain the above copyright
9 // notice, this list of conditions and the following disclaimer.
10 //     * Redistributions in binary form must reproduce the above
11 // copyright notice, this list of conditions and the following disclaimer
12 // in the documentation and/or other materials provided with the
13 // distribution.
14 //     * Neither the name of Google Inc. nor the names of its
15 // contributors may be used to endorse or promote products derived from
16 // this software without specific prior written permission.
17 //
18 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 
30 // UserDicStorageInterface provides interface for accessing data
31 // storage of the user dictionary. Subclasses determine how to save
32 // dictionary data on a disk.
33 
34 // The followings are not responsibility of UserDicStorageInterface
35 // and supposed to be performed by its client.
36 //
37 // (1) Validation of input values.
38 //   Subclasses that implement the interface of
39 //   UserDicStorageInterface are supposed to perform only minimal
40 //   validation of input value, for example a subclass that saves
41 //   dictionary data in a tab-separated text file usually doesn't
42 //   accept input with a tab or new line character and should check
43 //   input for them. However, UserDicStorageInterface and its
44 //   subclasses don't care about any more complicated
45 //   application-level validity of data like an acceptable POS set,
46 //   character encoding and so on. The class takes input value as it
47 //   is.
48 //
49 // (2) Duplicate entry elimination.
50 //   UserDicStorageInterface treats an entry in it with a unique
51 //   integer key. This means it doesn't take into account any actual
52 //   attribute of the entry when distinguishing it from another. If
53 //   any kind of duplicate elimination is necessary, it should be done
54 //   before the value is passed to the class.
55 //
56 // (3) Importing a dictionary file of Mozc or third party IMEs.
57 //   UserDicStorageInterface provides CreateDictionary() and
58 //   AddEntry(). Clients of the class can import an external
59 //   dictionary file using the two member functions.
60 
61 #ifndef MOZC_DICTIONARY_USER_DICTIONARY_STORAGE_H_
62 #define MOZC_DICTIONARY_USER_DICTIONARY_STORAGE_H_
63 
64 #include <memory>
65 #include <string>
66 
67 #include "base/port.h"
68 #include "protocol/user_dictionary_storage.pb.h"
69 
70 namespace mozc {
71 
72 class Mutex;
73 class ProcessMutex;
74 
75 class UserDictionaryStorage {
76  public:
77   typedef user_dictionary::UserDictionary UserDictionary;
78   typedef user_dictionary::UserDictionary::Entry UserDictionaryEntry;
79 
80   // Instance of base class generated by Protocol Buffers compiler.
81   // Regular inheritance strongly discouraged.
82   user_dictionary::UserDictionaryStorage user_dictionary_storage_base;
83 
84   enum UserDictionaryStorageErrorType {
85     USER_DICTIONARY_STORAGE_NO_ERROR = 0,  // default
86     FILE_NOT_EXISTS,
87     BROKEN_FILE,
88     SYNC_FAILURE,
89     TOO_BIG_FILE_BYTES,
90     INVALID_DICTIONARY_ID,
91     INVALID_CHARACTERS_IN_DICTIONARY_NAME,
92     EMPTY_DICTIONARY_NAME,
93     DUPLICATED_DICTIONARY_NAME,
94     TOO_LONG_DICTIONARY_NAME,
95     TOO_MANY_DICTIONARIES,
96     TOO_MANY_ENTRIES,
97     EXPORT_FAILURE,
98     UNKNOWN_ERROR,
99     ERROR_TYPE_SIZE
100   };
101 
102   explicit UserDictionaryStorage(const string &filename);
103   virtual ~UserDictionaryStorage();
104 
105   // return the filename of user dictionary
106   const string &filename() const;
107 
108   // Return true if data tied with this object already
109   // exists. Otherwise, it means that the space for the data is used
110   // for the first time.
111   bool Exists() const;
112 
113   // Load user dictionary from the file.
114   // NOTE: If the file is not existent, nothing is updated.
115   //       Therefore if the file is deleted after first load(),
116   //       second load() does nothing so the content loaded by first load()
117   //       is kept as is.
118   bool Load();
119 
120   // Serialzie user dictionary to local file.
121   // Need to call Lock() the dictionary before calling Save().
122   bool Save();
123 
124   // Lock the dictionary so that other processes/threads cannot
125   // execute mutable operations on this dictionary.
126   bool Lock();
127 
128   // release the lock
129   bool UnLock();
130 
131   // Export a dictionary to a file in TSV format.
132   bool ExportDictionary(uint64 dic_id, const string &file_name);
133 
134   // Create a new dictionary with a specified name. Returns the id of
135   // the new instance via new_dic_id.
136 
137   bool CreateDictionary(const string &dic_name, uint64 *new_dic_id);
138 
139   // Delete a dictionary.
140   bool DeleteDictionary(uint64 dic_id);
141 
142   // Rename a dictionary.
143   bool RenameDictionary(uint64 dic_id, const string &dic_name);
144 
145   // return the index of "dic_id"
146   // return -1 if no dictionary is found.
147   int GetUserDictionaryIndex(uint64 dic_id) const;
148 
149   // return mutable UserDictionary corresponding to dic_id
150   UserDictionary *GetUserDictionary(uint64 dic_id);
151 
152   // Searches a dictionary from a dictionary name, and the dictionary id is
153   // stored in "dic_id".
154   // Returns false if the name is not found.
155   bool GetUserDictionaryId(const string &dic_name, uint64 *dic_id);
156 
157   // return last error type.
158   // You can obtain the reason of the error of dictionary operation.
159   UserDictionaryStorageErrorType GetLastError() const;
160 
161   // Add new entry to the auto registered dictionary.
162   bool AddToAutoRegisteredDictionary(const string &key,
163                                      const string &value,
164                                      UserDictionary::PosType pos);
165 
166   // Converts syncable dictionaries to unsyncable dictionaries.
167   // The name of default sync dictionary is renamed to locale-independent name
168   // like other unsyncable dictionaries.
169   // This method deletes syncable dictionaries which are marked as removed or
170   // don't have any dictionary entries.
171   // Returns true if this method converts some dictionaries.
172   bool ConvertSyncDictionariesToNormalDictionaries();
173 
174   // return the number of dictionaries with "synclbe" being true.
175   static int CountSyncableDictionaries(
176       const user_dictionary::UserDictionaryStorage &storage);
177 
178   // maxium number of dictionaries this storage can hold
179   static size_t max_dictionary_size();
180 
181   // maximum number of entries one dictionary can hold
182   static size_t max_entry_size();
183 
184   static string default_sync_dictionary_name();
185 
186  private:
187   // Return true if this object can accept the given dictionary name.
188   // This changes the internal state.
189   bool IsValidDictionaryName(const string &name);
190 
191   // Load the data from file_name actually.
192   bool LoadInternal();
193 
194   string file_name_;
195   bool locked_;
196   UserDictionaryStorageErrorType last_error_type_;
197   std::unique_ptr<Mutex> local_mutex_;
198   std::unique_ptr<ProcessMutex> process_mutex_;
199 };
200 
201 }  // namespace mozc
202 
203 #endif  // MOZC_DICTIONARY_USER_DICTIONARY_STORAGE_H_
204