RedPenを使って技術文書を手軽に校正しよう

第5回 RedPenの内部

この記事を読むのに必要な時間:およそ 4 分

本連載を執筆している伊藤@takahi_iです。今回はRedPenの内部について解説します。RedPenが提供する文書検査は,それほど複雑なタスクではありません。そのためRedPenはいくつかのコンポーネントからなる小規模なプロジェクトとなっています。

今回の主な目的は,ユーザがRedPenに機能を追加する,もしくは修正する際の手がかりを提供することです。はじめにRedPenのコンポーネント群について簡単に紹介します。その後,各コンポーネントについて詳しい解説を行います。

RedPen のコンポーネント

RedPenは次のコンポーネントで構成されています。

  • RedPen:コンポーネント群を使って文書校正処理を実行します。
  • DocumentParser:入力文書をDocumentモデルという文書を表すデータ構造に変換します。文書フォーマット毎に実装が存在します。
  • Documentモデル:DocumentParserによって生成される文書を表現するデータ構造です。内部にParagraph(パラグラフ)やSentence(文)など,文書の部品を保持しています。
  • Validator群:Documentモデル内の部分にたいして検査を行います。各Validatorは"文長検査"など,ひとつの検査項目に対応します。
  • そのほか(Formatter,Configuration,Tokenizer):RedPenが校正処理を行うのに利用されるコンポーネント群です。

RedPenを拡張する際に必要なコンポーネントはDocumentモデルとValidator群です。Documentモデルは文書を表すデータの構造です。Validator群は入力Documentの一部(各文等)にたいして定義された検査を実行します。

以下,各コンポーネントについて詳しく解説します。

Documentモデル

Documentモデルは文書フォーマットに依存しない抽象的な文書を表します。次の図はDocumentモデルを表します。次節で紹介する機能追加がフォーマットに非依存で記述できるのは,多様な文書を共通のDocumentモデルに抽象化したおかげでです。

Documentモデル

画像

図中の四角形はDocumentモデル内のブロックを表します。各ブロックの解説は以下のとおりです。

  • Document:文書を表します。ひとつのファイルに相当します。
  • FileName:ファイル名を保持します。
  • Header:節のヘッダを表します。文集合も保持します。
  • Section:節に相当します。節は入れ子関係があります。たとえば節1は節1.1を保持します。
  • Paragraph:節内に存在するパラグラフをあらわします。図内には表示されていませんがParagraphは文(Sentence)の集合を保持します。
  • ListBlock:文内のリストを保持します。図内には表示されていませんがリスト要素は文(Sentence)を保持します。

ブロックは入れ子構造になっています。たとえばDocumentはFileNameを持つことがわかります。ブロックを表す四角形の後ろに付いている"…"という記載は,リスト(配列)を表します。リストとして表現されたブロックはひとつ以上の要素を持てます。たとえば,Documentはひとつ以上のSectionブロックを保持できます。

Sentence

先の図には登場しませんが,HeaderやParagraphは内部にSentenceの集合を保持します。Sentenceは文書内の一文を表します。Sentenceは切りだされた文の内容以外に,いくつかの付加情報を提供します。

  • lineNum:
  • links:リンク集合
  • isFirstSentence:パラグラフの開始文であればtrueそうでなければfalse
  • tokens:文内の単語集合。単語はTokenizerによって分割されます。利用されるTokenizerは設定言語によって異なります。日本語(ja)を指定した場合にはKuromojiが入力文を単語に分割します。

Sentenceは次節で述べるValidatorの入力として使用されます。

DocumentParserを追加する

DocumentParserは入力文書からDocumentを生成します。DocumentParser自体はインターフェースで,入力データフォーマット毎に実装を追加する必要があります。

現在までにPlainTextParser,MarkdownParser,およびWikiParserが実装されています。DocumentParserの追加にはかなりのコストがかかります。とはいえ,先稿で述べたようにLaTeXパーサ等リクエストの多いフォーマットへのDocumentParserを追加していきたいと考えています。

Validator

ValidatorはRedPenプロジェクトに存在する抽象クラスです。RedPenが提供する機能はValidatorを継承したクラスによって実装されています。たとえばSentenceLength機能はSentenceLengthValidatorというクラスで実装されています。

Validatorを継承するクラスを作るにはいくつか(最小ではひとつ)のメソッドを実装する必要があります。かならず実装しないといけないメソッドがvalidateです。そのほかinit,preValidateは必要に応じて実装します。後ほど解説しますが,Validatorを継承したクラスを作成して機能を追加するにはクラス名の語尾がValidatorである必要があります。

validateメソッド

機能を追加するにはValidatorを継承するクラスを作り,validateメソッドを実装します。validateメソッドはDocumentモデル内のブロックを入力としてうけとります。validateメソッドは入力文内のブロックすべてにたいして自動で適用されます。

現状Validatorは二種類のvalidateメソッドを提供しています。ひとつは文(Sentence)を引数にとり,もうひとつはSectionを引数にとります。次のコードが各validateメソッドのインターフェースとなります。

public void validate(List<ValidationError> errors, Sentence sentence)
public void validate(List<ValidationError> errorList, Document document)

文内の情報だけで検査ができるものはSentenceを引数にとるもので十分です。しかし検査に節の情報が必要な場合にはSectionを引数にとるvalidateを実装します。Sectionを引数にとるValidatorの実装としては,ParagraphNumberなどがあります。

入力ブロックにエラーがみつかった場合には,ValidatorはValidationError(のリスト)を返します。現在入力として対応しているDocumentブロックはSentenceとSectionです。

例:validateメソッド

SentenceLengthValidatorのvalidateメソッドです。パラメータは発見されたエラーを保持するerrorsと入力のSentenceです。文内に不正な表現が存在するとにerrorsにValidationErrorが追加されます。次の例でもcreateValidationErrorメソッドで生成されたエラーがerrorsに追加され,呼び出し元に返されていますのがわかります。

@Override
public void validate(List<ValidationError> errors, Sentence sentence) {
  if (sentence.getContent().length() > maxLength) {
    errors.add(createValidationError(sentence, sentence.getContent().length(), maxLength));
  }
}

ここでcreateValidationErrorはValidatorクラスが提供するメソッドで,ValidationErrorを生成するために使用されます。createValidationErrorメソッドに渡す第2引数以降は,後で解説するエラー文テンプレートに対するパラメータとして使用されます。

著者プロフィール

伊藤敬彦(いとうたかひこ)

ソフトウェアエンジニア。専門はデータマイニングと情報検索だが,他にも色々やってみたいと感じている。

コメント

コメントの記入