OSDN Git Service

0a1867af24b0cbfae0c0ea08ffe30c7faf0defcc
[wordring-tm/wordring-tm.git] / proxy / tmtext.h
1 #ifndef TMTEXT_H
2 #define TMTEXT_H
3
4 #include "text.h"
5 #include "html.h"
6
7 #include <QString>
8 #include <QUrl>
9 #include <QList>
10 #include <QMap>
11 #include <QSet>
12
13 #include <QJsonDocument>
14 #include <QJsonObject>
15 #include <QJsonArray>
16
17 #include <memory>
18
19 namespace TM
20 {
21
22 class Service;
23 class SocketConnection;
24 class TextSegment;
25 class TextSegmentList;
26
27 /*!
28  * \brief データベースとの通信に使うデータ構造です。
29  */
30 class sentence_data_type
31 {
32 public:
33         sentence_data_type();
34
35         // サイトデータベース用
36         QString site;
37         quint32 scode;
38         quint32 tcode;
39
40         // センテンスデータベース用。
41         quint32 sentence_id; /*!< DBによって自動的に付与される文ID */
42         quint32 source_id;   /*!< 原文は0固定、訳文は原文のsentence_id */
43         QString sentence;    /*!< 文本体の文字列 */
44         QByteArray json;     /*!< 原文は空、訳文はリンク情報のJSON */
45         quint32 crc;         /*!< 検索に使う文のCRC */
46         quint32 previous_crc;/*!< 原文は文脈一致に使う前方文のCRC、訳文は0固定 */
47         quint32 next_crc;    /*!< 原文は文脈一致に使う後方文のCRC、訳文は0固定 */
48         quint32 user_id;     /*!< レコードを更新したユーザーのID */
49         quint64 time;        /*!< 更新時刻 */
50
51         // 索引データベース用。
52         /*!
53          * データベース登録時に、sentenceの単語を示すリスト。
54          * 原文にのみ必要。
55          */
56         QSet<QString> words;
57 };
58
59 /*!
60  * \brief 候補文のためのデータ構造です。
61  */
62 class candidate_data_type
63 {
64 public:
65         int edit_distance;
66         sentence_data_type source;
67         sentence_data_type target;
68 };
69
70 /*!
71  * \brief 単語間のリンクを表現するクラスです。
72  *
73  * 原単語と訳単語の多対多のリンクを表現します。
74  */
75 class WordLink
76 {
77 public:
78         typedef std::shared_ptr<WordLink> pointer;
79         typedef QList<Text::pointer> storage_type;
80
81 public:
82         enum : int { Source, Target, };
83
84 private:
85         WordLink();
86
87 public:
88         void clear();
89         void append(int place, Text::pointer word);
90         void remove(int place, Text::pointer word);
91
92         bool is_valid() const;
93         bool is_empty() const;
94         bool contains(int place, Text::pointer word);
95         int size(int place) const;
96
97         storage_type* sources();
98         storage_type* targets();
99
100         QJsonArray to_json_array() const;
101
102         QString debug_dump() const;
103
104         static pointer create();
105
106 private:
107         storage_type m_sources;
108         storage_type m_targets;
109 };
110
111 /*!
112  * \brief 単語間のリンクを作成・保持するクラスです。
113  *
114  * 複数の単語間リンクを保持するコンテナとしての機能を持ちます。
115  * 現在編集中の単語間リンクを明示する機能があります。
116  *
117  * ある特定の単語間リンクを編集するには、start()を呼び出し編集を開始し、
118  * append()呼び出しによってリンクへ単語を追加し、
119  * commit()呼び出しによって編集を終了します。
120  */
121 class WordLinker
122 {
123 public:
124         typedef QList<WordLink::pointer> storage_type;
125         typedef storage_type::iterator iterator;
126         typedef storage_type::const_iterator const_iterator;
127
128 public:
129         void clear();
130
131         void start();
132         void commit();
133         void append(int place, Text::pointer word);
134         void remove(int place, Text::pointer word);
135         void toggle(int place, Text::pointer word);
136
137         WordLink::pointer current();
138
139         WordLink::pointer find(Text::pointer word);
140         WordLink::pointer find(int place, Text::pointer word);
141
142         int index_of(WordLink::pointer link) const;
143
144         iterator begin();
145         iterator end();
146
147         QJsonArray to_json_array() const;
148
149         QString debug_dump() const;
150
151 private:
152         WordLink::pointer m_current_link;
153         storage_type m_links;
154 };
155
156 /*!
157  * \brief エディタで編集される対訳構造のためのクラスです。
158  *
159  * SocketConnection内でTextSegmentに内蔵されて保持されます。
160  */
161 class TextSentence
162 {
163 public:
164         typedef std::shared_ptr<TextSentence> pointer;
165         typedef std::weak_ptr<TextSentence> weak_pointer;
166
167         typedef std::shared_ptr<TextSegment> parent_pointer;
168         typedef std::weak_ptr<TextSegment> parent_weak_pointer;
169
170         typedef std::shared_ptr<TextSegmentList> segment_list_pointer;
171
172 private:
173         TextSentence(int index, Text::pointer ssentence, parent_pointer parent);
174 public:
175         Text::pointer ssentence();
176         Text::pointer tsentence();
177         void set_tsentence(Text::pointer tsentence);
178         void set_tsentence(QString tsentence, QByteArray json = QByteArray());
179         void set_tsentence(quint32 previous_crc_, quint32 next_crc_,
180                                            QString tstring, QByteArray json = QByteArray());
181         sentence_data_type ssentence_data();
182         sentence_data_type tsentence_data();
183
184         WordLinker* linker();
185         QByteArray to_json();
186         void set_json(QByteArray json);
187 private:
188         void set_json_links(QJsonObject const &jobject);
189         void set_json_link(QJsonArray const &link_array);
190         QList<QPair<int, int> > stuff_json_link(QJsonArray const &ranges);
191
192         QList<Text::pointer> find_words_by_range(Text::pointer sentence, int first, int tail);
193 public:
194         QString host();
195         int scode();
196         int tcode();
197
198         int segment_id();
199         int index() const;
200
201         segment_list_pointer segment_list();
202
203         parent_pointer parent();
204         pointer previous();
205         pointer next();
206
207         quint32 source_id() const;
208         void set_source_id(quint32 source_id);
209         quint32 target_id() const;
210         void set_target_id(quint32 source_id);
211
212         quint32 crc();
213         quint32 previous_crc();
214         quint32 next_crc();
215
216         quint32 user_id() { return 0; }
217
218         bool append_candidate(candidate_data_type const &candidate);
219         QList<candidate_data_type> const & candidates() const;
220         void clear_candidates();
221
222         bool is_loaded() const;
223         //void set_loaded(bool loaded);
224
225         QString debug_dump() const;
226
227         static pointer create(int index, Text::pointer ssentence, parent_pointer parent);
228
229 private:
230         Text::pointer m_source_sentence; // 原文
231         Text::pointer m_target_sentence; // 訳文
232         WordLinker m_linker; // 単語間のリンク
233
234         quint32 m_source_id; /*!< 原文のID */
235         quint32 m_target_id; /*!< 訳文のID */
236
237         int m_quality; /*!< 訳文の品質 */
238
239         QList<candidate_data_type> m_candidates; /*!< 訳文候補 */
240
241         parent_weak_pointer m_parent;
242         int m_index; /*!< セグメント内における位置 */
243
244         weak_pointer m_self;
245 };
246
247 /*!
248  * \brief セグメントとHTMLを対応付けるためのデータ構造です。
249  */
250 class HtmlData : public RangeData
251 {
252 public:
253         typedef std::shared_ptr<HtmlData> pointer;
254
255         enum : int { Type = UserData::User + 1, };
256
257 private:
258         HtmlData(HtmlNode node_, int begin_, int tail_);
259
260 public:
261         int type() const;
262         HtmlNode node();
263         UserData::pointer clone();
264
265         QString debug_dump() const;
266
267         static pointer create(HtmlNode node_, int begin_, int tail_);
268
269 private:
270         HtmlNode m_node;
271 };
272
273 /*!
274  * \brief 一つのパラグラフを保持するクラスです。
275  *
276  * 一つのパラグラフには複数の文があります。
277  */
278 class TextSegment
279 {
280 public:
281         typedef std::shared_ptr<TextSegment> pointer;
282         typedef std::weak_ptr<TextSegment> weak_pointer;
283
284         typedef QList<TextSentence::pointer> storage_type;
285         typedef storage_type::iterator iterator;
286
287         typedef std::shared_ptr<TextSegmentList> parent_pointer;
288         typedef std::weak_ptr<TextSegmentList> parent_weak_pointer;
289
290 private:
291         TextSegment(int segment_id, parent_weak_pointer parent);
292 public:
293
294         parent_pointer parent();
295         int segment_id() const;
296
297         int size() const;
298         TextSentence::pointer at(int index);
299         iterator begin();
300         iterator end();
301
302         void set_html(QString html);
303         QString to_html();
304         QString to_html_from_source(TextSentence::pointer sentence);
305         QString to_html_from_target(TextSentence::pointer sentence);
306
307         HtmlNode::pointer find_html_node_by_offset(int offset);
308
309         static pointer create(int segment_id, QString html, parent_weak_pointer parent);
310
311 private:
312         // リスト用
313         int m_segment_id; /*!< data-wordring-segmentの値によるセグメントのID。 */
314
315         // HTMLページとの対応用
316         HtmlDocument m_document; /*!< セグメントのHtmlDocument。 */
317         Text::pointer m_text; /*!< セグメントのHtmlData付テキスト。 */
318
319         // 編集用
320         QList<TextSentence::pointer> m_sentences; /*!< 編集用センテンスのリスト。 */
321
322         // 親子。
323         parent_weak_pointer m_parent;
324         weak_pointer m_self;
325 };
326
327 /*!
328  * \brief 一つのHTMLページを表現するクラスです。
329  *
330  * オーナーはSocketConnectionです。
331  * 編集スレッド内では、このデータ構造を参照します。
332  */
333 class TextSegmentList
334 {
335 public:
336         typedef std::shared_ptr<TextSegmentList> pointer;
337         typedef std::weak_ptr<TextSegmentList> weak_pointer;
338
339 private:
340         TextSegmentList(Service *service, SocketConnection *connection);
341
342 public:
343         // セグメント・リスト。
344         bool contains(int segment_id);
345         TextSegment::pointer at(int segment_id);
346         TextSegment::pointer append(int segment_id, QString html_source);
347         int size() const;
348
349         // 検索。
350         QList<TextSentence::pointer> find_sentences(QString ssentence);
351
352         // 編集。
353         TextSegment::pointer current_segment();
354         bool set_current_segment(TextSegment::pointer segment);
355         TextSentence::pointer current_sentence();
356         void set_current_sentence(TextSentence::pointer sentence);
357
358         SocketConnection* connection();
359
360         // 言語コード。
361         int scode() const;
362         int tcode() const;
363         void set_scode(int code);
364         void set_tcode(int code);
365
366         // URL
367         QUrl url() const;
368         void set_url(QUrl url);
369         QString host() const;
370
371         // 親子。
372         Service* service();
373
374         static pointer create(Service *service, SocketConnection *connection);
375
376 private:
377         Service *m_service;
378
379         SocketConnection *m_connection; /*!< このリストのオーナーとなるコネクション */
380         int m_scode; /*!< 原文言語コード。*/
381         int m_tcode; /*!< 訳文言語コード。 */
382         QUrl m_url;
383
384         QMap<int, TextSegment::pointer> m_segments; /*!< HTML内のdata-wordring-segmentの値とセグメントのマップ */
385         TextSegment::pointer m_current_segment; /*!< 編集中のセグメントを表す。(ブラウザから変更)*/
386         TextSentence::pointer m_current_sentence; /*!< 編集中のセンテンスを表す。(エディタから変更) */
387
388         /*! 正規化原文と編集文のマルチ・マップ。 */
389         QMap<QString, TextSentence::pointer> m_source_map;
390
391         weak_pointer m_self;
392 };
393
394 } // namespace TM
395
396 #endif // TMTEXT_H