You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by rm...@apache.org on 2012/01/12 21:10:52 UTC
svn commit: r1230748 [4/5] - in /lucene/dev/trunk: dev-tools/eclipse/
lucene/contrib/ modules/analysis/
modules/analysis/common/src/java/org/apache/lucene/analysis/util/
modules/analysis/common/src/test/org/apache/lucene/analysis/util/
modules/analysis...
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/resources/org/apache/lucene/analysis/kuromoji/stoptags.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/resources/org/apache/lucene/analysis/kuromoji/stoptags.txt?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/resources/org/apache/lucene/analysis/kuromoji/stoptags.txt (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/resources/org/apache/lucene/analysis/kuromoji/stoptags.txt Thu Jan 12 20:10:48 2012
@@ -0,0 +1,410 @@
+# set of default stop tags:
+# uncomment a part of speech to treat those words as stopwords.
+# the entire tagset is provided here for convenience.
+#
+#####
+# noun: unclassified nouns
+#åè©
+#
+# noun-common: Common nouns or nouns where the sub-classification is undefined
+#åè©-ä¸è¬
+#
+# noun-proper: Proper nouns where the sub-classification is undefined
+#åè©-åºæåè©
+#
+# noun-proper-misc: miscellaneous proper nouns
+#åè©-åºæåè©-ä¸è¬
+#
+# noun-proper-person: Personal names where the sub-classification is undefined
+#åè©-åºæåè©-人å
+#
+# noun-proper-person-misc: names that cannot be divided into surname and
+# given name; foreign names; names where the surname or given name is unknown.
+# e.g. ãå¸ã®æ¹
+#åè©-åºæåè©-人å-ä¸è¬
+#
+# noun-proper-person-surname: Mainly Japanese surnames.
+# e.g. å±±ç°
+#åè©-åºæåè©-人å-å§
+#
+# noun-proper-person-given_name: Mainly Japanese given names.
+# e.g. 太é
+#åè©-åºæåè©-人å-å
+#
+# noun-proper-organization: Names representing organizations.
+# e.g. éç£ç, NHK
+#åè©-åºæåè©-çµç¹
+#
+# noun-proper-place: Place names where the sub-classification is undefined
+#åè©-åºæåè©-å°å
+#
+# noun-proper-place-misc: Place names excluding countries.
+# e.g. ã¢ã¸ã¢, ãã«ã»ãã, 京é½
+#åè©-åºæåè©-å°å-ä¸è¬
+#
+# noun-proper-place-country: Country names.
+# e.g. æ¥æ¬, ãªã¼ã¹ãã©ãªã¢
+#åè©-åºæåè©-å°å-å½
+#
+# noun-pronoun: Pronouns where the sub-classification is undefined
+#åè©-代åè©
+#
+# noun-pronoun-misc: miscellaneous pronouns:
+# e.g. ãã, ãã, ããã¤, ããªã, ãã¡ãã¡, ããã¤, ã©ãã, ãªã«, ã¿ãªãã, ã¿ããª, ãããã, ãããã
+#åè©-代åè©-ä¸è¬
+#
+# noun-pronoun-contraction: Spoken language contraction made by combining a
+# pronoun and the particle 'wa'.
+# e.g. ããã, ããã, ãããã, ããã, ãããã
+#åè©-代åè©-縮ç´
+#
+# noun-adverbial: Temporal nouns such as names of days or months that behave
+# like adverbs. Nouns that represent amount or ratios and can be used adverbially,
+# e.g. éæ, 䏿, åå¾, å°é
+#åè©-å¯è©å¯è½
+#
+# noun-verbal: Nouns that take arguments with case and can appear followed by
+# 'suru' and related verbs (ãã, ã§ãã, ãªãã, ãã ãã)
+# e.g. ã¤ã³ããã, æç, æªå, æªæ¦è¦é, ä¸å®å¿, ä¸åã
+#åè©-ãµå¤æ¥ç¶
+#
+# noun-adjective-base: The base form of adjectives, words that appear before 㪠("na")
+# e.g. å¥åº·, 宿, é§ç®, ã ã
+#åè©-形容åè©èªå¹¹
+#
+# noun-numeric: Arabic numbers, Chinese numerals, and counters like ä½ (å), æ°.
+# e.g. 0, 1, 2, ä½, æ°, å¹¾
+#åè©-æ°
+#
+# noun-affix: noun affixes where the sub-classification is undefined
+#åè©-éèªç«
+#
+# noun-affix-misc: Of adnominalizers, the case-marker ã® ("no"), and words that
+# attach to the base form of inflectional words, words that cannot be classified
+# into any of the other categories below. This category includes indefinite nouns.
+# e.g. ããã¤ã, æ, ãã, ç²æ, æ°, ããã, å«ã, ãã, ç, ãã¨, äº, ãã¨, æ¯, ãã ã, 次第,
+# é , ãã, æçº, ã¤ãã§, åºã§, ã¤ãã, ç©ãã, ç¹, ã©ãã, ã®, ã¯ã, ç, ã¯ãã¿, å¼¾ã¿,
+# æå, ãµã, ãµã, æ¯ã, ã»ã, æ¹, æ¨, ãã®, ç©, è
, ãã, æ
, ããã, æä»¥, ãã, 訳,
+# ãã, å²ã, å², ã-å£èª/, ãã-å£èª/
+#åè©-éèªç«-ä¸è¬
+#
+# noun-affix-adverbial: noun affixes that that can behave as adverbs.
+# e.g. ããã , é, ããã, æãå¥, ãã¨, å¾, ä½ã, 以å¤, 以é, 以å¾, 以ä¸, 以å, 䏿¹, ãã,
+# ä¸, ãã¡, å
, ãã, æã, ããã, éã, ãã, ã£ãã, çµæ, ãã, é , ãã, é, æä¸, ããªã,
+# æä¸, ããã, èªä½, ãã³, 度, ãã, çº, ã¤ã©, é½åº¦, ã¨ãã, éã, ã¨ã, æ, ã¨ãã, æ,
+# ã¨ãã, é端, ãªã, ä¸, ã®ã¡, å¾, ã°ãã, å ´å, æ¥, ã¶ã, å, ã»ã, ä», ã¾ã, å, ã¾ã¾,
+# å, ä¾, ã¿ãã, ç¢å
+#åè©-éèªç«-å¯è©å¯è½
+#
+# noun-affix-aux: noun affixes treated as å©åè© ("auxiliary verb") in school grammars
+# with the stem ãã(ã ) ("you(da)").
+# e.g. ãã, ãã, æ§ (ãã)
+#åè©-éèªç«-å©åè©èªå¹¹
+#
+# noun-affix-adjective-base: noun affixes that can connect to the indeclinable
+# connection form 㪠(aux "da").
+# e.g. ã¿ãã, ãµã
+#åè©-éèªç«-形容åè©èªå¹¹
+#
+# noun-special: special nouns where the sub-classification is undefined.
+#åè©-ç¹æ®
+#
+# noun-special-aux: The ããã ("souda") stem form that is used for reporting news, is
+# treated as å©åè© ("auxiliary verb") in school grammars, and attach to the base
+# form of inflectional words.
+# e.g. ãã
+#åè©-ç¹æ®-å©åè©èªå¹¹
+#
+# noun-suffix: noun suffixes where the sub-classification is undefined.
+#åè©-æ¥å°¾
+#
+# noun-suffix-misc: Of the nouns or stem forms of other parts of speech that connect
+# to ã¬ã« or ã¿ã¤ and can combine into compound nouns, words that cannot be classified into
+# any of the other categories below. In general, this category is more inclusive than
+# æ¥å°¾èª ("suffix") and is usually the last element in a compound noun.
+# e.g. ãã, ãã, æ¹, ç²æ (ãã), ããã, ãã¿, æ°å³, ããã¿, (ï½ãã) ã, 次第, æ¸ (ã) ã¿,
+# ãã, (ã§ã)ã£ã, æ, 観, æ§, å¦, é¡, é¢, ç¨
+#åè©-æ¥å°¾-ä¸è¬
+#
+# noun-suffix-person: Suffixes that form nouns and attach to person names more often
+# than other nouns.
+# e.g. å, æ§, è
+#åè©-æ¥å°¾-人å
+#
+# noun-suffix-place: Suffixes that form nouns and attach to place names more often
+# than other nouns.
+# e.g. çº, å¸, ç
+#åè©-æ¥å°¾-å°å
+#
+# noun-suffix-verbal: Of the suffixes that attach to nouns and form nouns, those that
+# can appear before ã¹ã« ("suru").
+# e.g. å, è¦, åã, å
¥ã, è½ã¡, è²·ã
+#åè©-æ¥å°¾-ãµå¤æ¥ç¶
+#
+# noun-suffix-aux: The stem form of ããã (æ§æ
) that is used to indicate conditions,
+# is treated as å©åè© ("auxiliary verb") in school grammars, and attach to the
+# conjunctive form of inflectional words.
+# e.g. ãã
+#åè©-æ¥å°¾-å©åè©èªå¹¹
+#
+# noun-suffix-adjective-base: Suffixes that attach to other nouns or the conjunctive
+# form of inflectional words and appear before the copula ã ("da").
+# e.g. ç, ã, ãã¡
+#åè©-æ¥å°¾-形容åè©èªå¹¹
+#
+# noun-suffix-adverbial: Suffixes that attach to other nouns and can behave as adverbs.
+# e.g. å¾ (ã), 以å¾, 以é, 以å, åå¾, ä¸, æ«, ä¸, æ (ã)
+#åè©-æ¥å°¾-å¯è©å¯è½
+#
+# noun-suffix-classifier: Suffixes that attach to numbers and form nouns. This category
+# is more inclusive than 婿°è© ("classifier") and includes common nouns that attach
+# to numbers.
+# e.g. å, ã¤, æ¬, å, ãã¼ã»ã³ã, cm, kg, ã«æ, ãå½, åºç», æé, æå
+#åè©-æ¥å°¾-婿°è©
+#
+# noun-suffix-special: Special suffixes that mainly attach to inflecting words.
+# e.g. (楽ã) ã, (èã) æ¹
+#åè©-æ¥å°¾-ç¹æ®
+#
+# noun-suffix-conjunctive: Nouns that behave like conjunctions and join two words
+# together.
+# e.g. (æ¥æ¬) 対 (ã¢ã¡ãªã«), 対 (ã¢ã¡ãªã«), (3) 対 (5), (女åª) å
¼ (主婦)
+#åè©-æ¥ç¶è©ç
+#
+# noun-verbal_aux: Nouns that attach to the conjunctive particle 㦠("te") and are
+# semantically verb-like.
+# e.g. ããã, ã覧, 御覧, é æ´
+#åè©-åè©éèªç«ç
+#
+# noun-quotation: text that cannot be segmented into words, proverbs, Chinese poetry,
+# dialects, English, etc. Currently, the only entry for åè© å¼ç¨æåå ("noun quotation")
+# is ããã ("iwaku").
+#åè©-å¼ç¨æåå
+#
+# noun-nai_adjective: Words that appear before the auxiliary verb ãªã ("nai") and
+# behave like an adjective.
+# e.g. ç³ã訳, 仿¹, ã¨ãã§ã, éã
+#åè©-ãã¤å½¢å®¹è©èªå¹¹
+#
+#####
+# prefix: unclassified prefixes
+æ¥é è©
+#
+# prefix-nominal: Prefixes that attach to nouns (including adjective stem forms)
+# excluding numerical expressions.
+# e.g. ã (æ°´), æ (æ°), å (社), æ
(ï½æ°), é« (å質), ã (è¦äº), ã (ç«æ´¾)
+æ¥é è©-åè©æ¥ç¶
+#
+# prefix-verbal: Prefixes that attach to the imperative form of a verb or a verb
+# in conjunctive form followed by ãªã/ãªãã/ãã ãã.
+# e.g. ã (èªã¿ãªãã), ã (座ã)
+æ¥é è©-åè©æ¥ç¶
+#
+# prefix-adjectival: Prefixes that attach to adjectives.
+# e.g. ã (å¯ãã§ããã), ãã« (ã§ãã)
+æ¥é è©-å½¢å®¹è©æ¥ç¶
+#
+# prefix-numerical: Prefixes that attach to numerical expressions.
+# e.g. ç´, ããã, æ¯æ
+æ¥é è©-æ°æ¥ç¶
+#
+#####
+# verb: unclassified verbs
+#åè©
+#
+# verb-main:
+#åè©-èªç«
+#
+# verb-auxiliary:
+åè©-éèªç«
+#
+# verb-suffix:
+#åè©-æ¥å°¾
+#
+#####
+# adjective: unclassified adjectives
+#形容è©
+#
+# adjective-main:
+#形容è©-èªç«
+#
+# adjective-auxiliary:
+#形容è©-éèªç«
+#
+# adjective-suffix:
+#形容è©-æ¥å°¾
+#
+#####
+# adverb: unclassified adverbs
+#å¯è©
+#
+# adverb-misc: Words that can be segmented into one unit and where adnominal
+# modification is not possible.
+# e.g. ãããããã, å¤å
+#å¯è©-ä¸è¬
+#
+# adverb-particle_conjunction: Adverbs that can be followed by ã®, ã¯, ã«,
+# ãª, ãã, ã , etc.
+# e.g. ãããªã«, ãããªã«, ãããªã«, ãªã«ã, ãªãã§ã
+#å¯è©-å©è©é¡æ¥ç¶
+#
+#####
+# adnominal: Words that only have noun-modifying forms.
+# e.g. ãã®, ãã®, ãã®, ã©ã®, ãããã, ãªãããã®, ä½ããã®, ããããª, ãããã, ãããã, ãããã,
+# ã©ããã, ãããª, ãããª, ãããª, ã©ããª, 大ããª, å°ããª, ããããª, ã»ãã®, ãããã,
+# ã(, ã) ãã (ãã¨ãªãã)ã, å¾®ã
ãã, å ã
ãã, åãªã, ãããªã, æãããåã, 亡ã
+#é£ä½è©
+#
+#####
+# conjunction: Conjunctions that can occur independently.
+# e.g. ã, ããã©ã, ããã¦, ããã, ããã©ããã
+æ¥ç¶è©
+#
+#####
+# particle: unclassified particles.
+å©è©
+#
+# particle-case: case particles where the subclassification is undefined.
+å©è©-æ ¼å©è©
+#
+# particle-case-misc: Case particles.
+# e.g. ãã, ã, ã§, ã¨, ã«, ã¸, ãã, ã, ã®, ã«ã¦
+å©è©-æ ¼å©è©-ä¸è¬
+#
+# particle-case-quote: the "to" that appears after nouns, a personâs speech,
+# quotation marks, expressions of decisions from a meeting, reasons, judgements,
+# conjectures, etc.
+# e.g. ( ã ) 㨠(è¿°ã¹ã.), ( ã§ãã) 㨠(ãã¦å·è¡ç¶äº...)
+å©è©-æ ¼å©è©-å¼ç¨
+#
+# particle-case-compound: Compounds of particles and verbs that mainly behave
+# like case particles.
+# e.g. ã¨ãã, ã¨ãã£ã, ã¨ããã, ã¨ãã¦, ã¨ã¨ãã«, ã¨å
±ã«, ã§ãã£ã¦, ã«ããã£ã¦, ã«å½ãã£ã¦, ã«å½ã£ã¦,
+# ã«ããã, ã«å½ãã, ã«å½ã, ã«å½ãã, ã«ããã, ã«ããã¦, ã«æ¼ãã¦,ã«æ¼ã¦, ã«ããã, ã«æ¼ãã,
+# ã«ãã, ã«ããã¦, ã«ããã, ã«é¢ã, ã«ãããã¦, ã«é¢ãã¦, ã«ãããã, ã«é¢ãã, ã«éã,
+# ã«éãã¦, ã«ãããã, ã«å¾ã, ã«å¾ã, ã«ãããã£ã¦, ã«å¾ã£ã¦, ã«ããã, ã«å¯¾ã, ã«ãããã¦,
+# ã«å¯¾ãã¦, ã«ãããã, ã«å¯¾ãã, ã«ã¤ãã¦, ã«ã¤ã, ã«ã¤ã, ã«ã¤ãã¦, ã«ã¤ã, ã«ã¤ãã¦, ã«ã¨ã£ã¦,
+# ã«ã¨ã, ã«ã¾ã¤ãã, ã«ãã£ã¦, ã«ä¾ã£ã¦, ã«å ã£ã¦, ã«ãã, ã«ä¾ã, ã«å ã, ã«ãã, ã«ä¾ã, ã«å ã,
+# ã«ããã£ã¦, ã«ããã, ããã£ã¦, ã以ã£ã¦, ãéã, ãéãã¦, ãéãã¦, ãããã£ã¦, ãããã, ãããã,
+# ã£ã¦-å£èª/, ã¡ã
ã-é¢è¥¿å¼ãã¨ããã/, (ä½) ã¦ãã (人)-å£èª/, ã£ã¦ãã-å£èª/, ã¨ããµ, ã¨ãããµ
+å©è©-æ ¼å©è©-é£èª
+#
+# particle-conjunctive:
+# e.g. ãã, ããã«ã¯, ã, ããã©, ããã©ã, ãã©, ã, ã¤ã¤, ã¦, ã§, ã¨, ã¨ããã, ã©ããã, ã¨ã, ã©ã,
+# ãªãã, ãªã, ã®ã§, ã®ã«, ã°, ãã®ã®, ã ( ãã), ãããªã, (ããã) ãã(ãããªã)-å£èª/,
+# (è¡ã£) ã¡ã(ãããªã)-å£èª/, (è¨ã£) ãã£ã¦ (ãããããªã)-å£èª/, (ããããªã)ã£ãã£ã¦ (å¹³æ°)-å£èª/
+å©è©-æ¥ç¶å©è©
+#
+# particle-dependency:
+# e.g. ãã, ãã, ãã, ãã, ã¯, ã, ã
+å©è©-ä¿å©è©
+#
+# particle-adverbial:
+# e.g. ãã¦ã, ãã, ããã, ä½, ããã, ãã, (妿 ¡) ãã(ãããæµè¡ã£ã¦ãã)-å£èª/,
+# (ãã)ããã (ãããªã)-å£èª/, ãã¤, (ç§) ãªã, ãªã©, (ç§) ãªã (ã«), (å
ç) ãªãã (大å«ã)-å£èª/,
+# (ç§) ãªãã, (å
ç) ãªã㦠(大å«ã)-å£èª/, ã®ã¿, ã ã, (ç§) ã ã£ã¦-å£èª/, ã ã«,
+# (å½¼)ã£ãã-å£èª/, (ãè¶) ã§ã (ããã), ç (ã¨ã), (ä»å¾) ã¨ã, ã°ãã, ã°ã£ã-å£èª/, ã°ã£ãã-å£èª/,
+# ã»ã©, ç¨, ã¾ã§, è¿, (誰) ã (ã)([å©è©-æ ¼å©è©] ããã³ [å©è©-ä¿å©è©] ã®åã«ä½ç½®ããããã)
+å©è©-å¯å©è©
+#
+# particle-interjective: particles with interjective grammatical roles.
+# e.g. (æ¾å³¶) ã
+å©è©-éæå©è©
+#
+# particle-coordinate:
+# e.g. ã¨, ãã, ã ã®, ã ã, ã¨ã, ãªã, ã, ãã
+å©è©-並ç«å©è©
+#
+# particle-final:
+# e.g. ãã, ããã, ã, ã, (ã )ã£ã-å£èª/, (ã¨ã¾ã£ã¦ã) ã§-æ¹è¨/, ãª, ã, ãªã-å£èª/, ã, ã, ã,
+# ãã-å£èª/, ãã-å£èª/, ãã-æ¹è¨/, ã®, ã®ã-å£èª/, ã, ã, ã¨, ãã-å£èª/, ã, ãã-å£èª/
+å©è©-çµå©è©
+#
+# particle-adverbial/conjunctive/final: The particle "ka" when unknown whether it is
+# adverbial, conjunctive, or sentence final. For example:
+# (a) ãA ã B ãã. Ex:ã(å½å
ã§éç¨ãã) ã,(æµ·å¤ã§éç¨ãã) ã (.)ã
+# (b) Inside an adverb phrase. Ex:ã(幸ãã¨ãã) ã (, æ»è
ã¯ããªãã£ã.)ã
+# ã(ç¥ããå±ãããã) ã (, 試é¨ã«åæ ¼ãã.)ã
+# (c) ããã®ããã«ã. Ex:ã(ä½ããªãã£ã) ã (ã®ããã«æ¯ãèã£ã.)ã
+# e.g. ã
+å©è©-å¯å©è©ï¼ä¸¦ç«å©è©ï¼çµå©è©
+#
+# particle-adnominalizer: The "no" that attaches to nouns and modifies
+# non-inflectional words.
+å©è©-é£ä½å
+#
+# particle-adnominalizer: The "ni" and "to" that appear following nouns and adverbs
+# that are giongo, giseigo, or gitaigo.
+# e.g. ã«, ã¨
+å©è©-å¯è©å
+#
+# particle-special: A particle that does not fit into one of the above classifications.
+# This includes particles that are used in Tanka, Haiku, and other poetry.
+# e.g. ããª, ãã, ( ããã ãã) ã«, (ããã) ã«ã(ãããã), (俺) ã (å®¶)
+å©è©-ç¹æ®
+#
+#####
+# auxiliary-verb:
+å©åè©
+#
+#####
+# interjection: Greetings and other exclamations.
+# e.g. ãã¯ãã, ãã¯ãããããã¾ã, ããã«ã¡ã¯, ããã°ãã¯, ãããã¨ã, ã©ãããããã¨ã, ãããã¨ããããã¾ã,
+# ããã ãã¾ã, ãã¡ãããã¾, ãããªã, ããããªã, ã¯ã, ããã, ããã, ããããªãã
+æåè©
+#
+#####
+# symbol: unclassified Symbols.
+#è¨å·
+#
+# symbol-misc: A general symbol not in one of the categories below.
+# e.g. [ââ@$ãâ+]
+è¨å·-ä¸è¬
+#
+# symbol-comma: Commas
+# e.g. [,ã]
+è¨å·-èªç¹
+#
+# symbol-period: Periods and full stops.
+# e.g. [.ï¼ã]
+è¨å·-å¥ç¹
+#
+# symbol-space: Full-width whitespace.
+è¨å·-空ç½
+#
+# symbol-open_bracket:
+# e.g. [({ââãã]
+è¨å·-æ¬å¼§é
+#
+# symbol-close_bracket:
+# e.g. [)}ââããã]
+è¨å·-æ¬å¼§é
+#
+# symbol-alphabetic:
+#è¨å·-ã¢ã«ãã¡ããã
+#
+#####
+# other: unclassified other
+#ãã®ä»
+#
+# other-interjection: Words that are hard to classify as noun-suffixes or
+# sentence-final particles.
+# e.g. (ã )ã¡
+ãã®ä»-éæ
+#
+#####
+# filler: Aizuchi that occurs during a conversation or sounds inserted as filler.
+# e.g. ãã®, ããã¨, ãã¨
+ãã£ã©ã¼
+#
+#####
+# non-verbal: non-verbal sound.
+éè¨èªé³
+#
+#####
+# fragment:
+#èªæç
+#
+#####
+# unknown: unknown part of speech.
+#æªç¥èª
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/resources/org/apache/lucene/analysis/kuromoji/stopwords.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/resources/org/apache/lucene/analysis/kuromoji/stopwords.txt?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/resources/org/apache/lucene/analysis/kuromoji/stopwords.txt (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/resources/org/apache/lucene/analysis/kuromoji/stopwords.txt Thu Jan 12 20:10:48 2012
@@ -0,0 +1,13 @@
+# short set of japanese stopwords
+ãã
+ãã
+人ç©
+ãã¾
+ãããã¨
+ãã
+ãã®
+ããã¦
+ãªã
+ã§ãã
+ãã
+ãã
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/SegmenterTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/SegmenterTest.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/SegmenterTest.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/SegmenterTest.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,231 @@
+package org.apache.lucene.analysis.kuromoji;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.util.List;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class SegmenterTest extends LuceneTestCase {
+
+ private static Segmenter segmenter;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ segmenter = new Segmenter();
+ }
+
+ @AfterClass
+ public static void afterClass() throws Exception {
+ segmenter = null;
+ }
+
+ @Test
+ public void testSegmentation() {
+ // Skip tests for Michelle Kwan -- UniDic segments Kwan as 㯠ã¯ã³
+ // String input = "ãã·ã§ã«ã»ã¯ã¯ã³ãåªåãã¾ãããã¹ãã¼ã¹ã¹ãã¼ã·ã§ã³ã«è¡ãã¾ããããããããã";
+ // String[] surfaceForms = {
+ // "ãã·ã§ã«", "ã»", "ã¯ã¯ã³", "ã", "åªå", "ã", "ã¾ã", "ã", "ã",
+ // "ã¹ãã¼ã¹", "ã¹ãã¼ã·ã§ã³", "ã«", "è¡ã", "ã¾ã", "ã",
+ // "ãããããã", "ã"
+ // };
+ String input = "ã¹ãã¼ã¹ã¹ãã¼ã·ã§ã³ã«è¡ãã¾ããããããããã";
+ String[] surfaceForms = {
+ "ã¹ãã¼ã¹", "ã¹ãã¼ã·ã§ã³", "ã«", "è¡ã", "ã¾ã", "ã",
+ "ãããããã", "ã"
+ };
+ List<Token> tokens = segmenter.tokenize(input);
+ assertTrue(tokens.size() == surfaceForms.length);
+ for (int i = 0; i < tokens.size(); i++) {
+ assertEquals(surfaceForms[i], tokens.get(i).getSurfaceFormString());
+ }
+ }
+
+ @Test
+ public void testReadings() {
+ List<Token> tokens = segmenter.tokenize("寿å¸ãé£ã¹ããã§ãã");
+ assertEquals(6, tokens.size());
+ assertEquals("ã¹ã·", tokens.get(0).getReading());
+ assertEquals("ã¬", tokens.get(1).getReading());
+ assertEquals("ã¿ã", tokens.get(2).getReading());
+ assertEquals("ã¿ã¤", tokens.get(3).getReading());
+ assertEquals("ãã¹", tokens.get(4).getReading());
+ assertEquals("ã", tokens.get(5).getReading());
+ }
+
+ @Test
+ public void testReadings2() {
+ List<Token> tokens = segmenter.tokenize("å¤ãã®å¦çã試é¨ã«è½ã¡ãã");
+ assertEquals(9, tokens.size());
+ assertEquals("ãªãªã¯", tokens.get(0).getReading());
+ assertEquals("ã", tokens.get(1).getReading());
+ assertEquals("ã¬ã¯ã»ã¤", tokens.get(2).getReading());
+ assertEquals("ã¬", tokens.get(3).getReading());
+ assertEquals("ã·ã±ã³", tokens.get(4).getReading());
+ assertEquals("ã", tokens.get(5).getReading());
+ assertEquals("ãªã", tokens.get(6).getReading());
+ assertEquals("ã¿", tokens.get(7).getReading());
+ assertEquals("ã", tokens.get(8).getReading());
+ }
+
+ @Test
+ public void testPronunciations() {
+ List<Token> tokens = segmenter.tokenize("寿å¸ãé£ã¹ããã§ãã");
+ assertEquals(6, tokens.size());
+ assertEquals("ã¹ã·", tokens.get(0).getPronunciation());
+ assertEquals("ã¬", tokens.get(1).getPronunciation());
+ assertEquals("ã¿ã", tokens.get(2).getPronunciation());
+ assertEquals("ã¿ã¤", tokens.get(3).getPronunciation());
+ assertEquals("ãã¹", tokens.get(4).getPronunciation());
+ assertEquals("ã", tokens.get(5).getPronunciation());
+ }
+
+ @Test
+ public void testPronunciations2() {
+ List<Token> tokens = segmenter.tokenize("å¤ãã®å¦çã試é¨ã«è½ã¡ãã");
+ assertEquals(9, tokens.size());
+ // pronunciation differs from reading here
+ assertEquals("ãªã¼ã¯", tokens.get(0).getPronunciation());
+ assertEquals("ã", tokens.get(1).getPronunciation());
+ assertEquals("ã¬ã¯ã»ã¤", tokens.get(2).getPronunciation());
+ assertEquals("ã¬", tokens.get(3).getPronunciation());
+ assertEquals("ã·ã±ã³", tokens.get(4).getPronunciation());
+ assertEquals("ã", tokens.get(5).getPronunciation());
+ assertEquals("ãªã", tokens.get(6).getPronunciation());
+ assertEquals("ã¿", tokens.get(7).getPronunciation());
+ assertEquals("ã", tokens.get(8).getPronunciation());
+ }
+
+ @Test
+ public void testBasicForms() {
+ List<Token> tokens = segmenter.tokenize("ããã¯ã¾ã å®é¨æ®µéã«ããã¾ãã");
+ assertEquals(9, tokens.size());
+ assertNull(tokens.get(0).getBaseForm());
+ assertNull(tokens.get(1).getBaseForm());
+ assertNull(tokens.get(2).getBaseForm());
+ assertNull(tokens.get(3).getBaseForm());
+ assertNull(tokens.get(4).getBaseForm());
+ assertNull(tokens.get(5).getBaseForm());
+ assertEquals(tokens.get(6).getBaseForm(), "ãã");
+ assertNull(tokens.get(7).getBaseForm());
+ assertNull(tokens.get(8).getBaseForm());
+ }
+
+ @Test
+ public void testInflectionTypes() {
+ List<Token> tokens = segmenter.tokenize("ããã¯ã¾ã å®é¨æ®µéã«ããã¾ãã");
+ assertEquals(9, tokens.size());
+ assertNull(tokens.get(0).getInflectionType());
+ assertNull(tokens.get(1).getInflectionType());
+ assertNull(tokens.get(2).getInflectionType());
+ assertNull(tokens.get(3).getInflectionType());
+ assertNull(tokens.get(4).getInflectionType());
+ assertNull(tokens.get(5).getInflectionType());
+ assertEquals("äºæ®µã»ã©è¡", tokens.get(6).getInflectionType());
+ assertEquals("ç¹æ®ã»ãã¹", tokens.get(7).getInflectionType());
+ assertNull(tokens.get(8).getInflectionType());
+ }
+
+ @Test
+ public void testInflectionForms() {
+ List<Token> tokens = segmenter.tokenize("ããã¯ã¾ã å®é¨æ®µéã«ããã¾ãã");
+ assertEquals(9, tokens.size());
+ assertNull(tokens.get(0).getInflectionForm());
+ assertNull(tokens.get(1).getInflectionForm());
+ assertNull(tokens.get(2).getInflectionForm());
+ assertNull(tokens.get(3).getInflectionForm());
+ assertNull(tokens.get(4).getInflectionForm());
+ assertNull(tokens.get(5).getInflectionForm());
+ assertEquals("é£ç¨å½¢", tokens.get(6).getInflectionForm());
+ assertEquals("åºæ¬å½¢", tokens.get(7).getInflectionForm());
+ assertNull(tokens.get(8).getInflectionForm());
+ }
+
+ @Test
+ public void testPartOfSpeech() {
+ List<Token> tokens = segmenter.tokenize("ããã¯ã¾ã å®é¨æ®µéã«ããã¾ãã");
+ assertEquals(9, tokens.size());
+ assertEquals("åè©-代åè©-ä¸è¬", tokens.get(0).getPartOfSpeech());
+ assertEquals("å©è©-ä¿å©è©", tokens.get(1).getPartOfSpeech());
+ assertEquals("å¯è©-å©è©é¡æ¥ç¶", tokens.get(2).getPartOfSpeech());
+ assertEquals("åè©-ãµå¤æ¥ç¶", tokens.get(3).getPartOfSpeech());
+ assertEquals("åè©-ä¸è¬", tokens.get(4).getPartOfSpeech());
+ assertEquals("å©è©-æ ¼å©è©-ä¸è¬", tokens.get(5).getPartOfSpeech());
+ assertEquals("åè©-èªç«", tokens.get(6).getPartOfSpeech());
+ assertEquals("å©åè©", tokens.get(7).getPartOfSpeech());
+ assertEquals("è¨å·-å¥ç¹", tokens.get(8).getPartOfSpeech());
+ }
+
+ // TODO: the next 2 tests are no longer using the first/last word ids, maybe lookup the words and fix?
+ // do we have a possibility to actually lookup the first and last word from dictionary?
+ public void testYabottai() {
+ List<Token> tokens = segmenter.tokenize("ãã¼ã£ãã");
+ assertEquals(1, tokens.size());
+ assertEquals("ãã¼ã£ãã", tokens.get(0).getSurfaceFormString());
+ }
+
+ public void testTsukitosha() {
+ List<Token> tokens = segmenter.tokenize("çªãéãã");
+ assertEquals(1, tokens.size());
+ assertEquals("çªãéãã", tokens.get(0).getSurfaceFormString());
+ }
+
+ public void testBocchan() throws Exception {
+ doTestBocchan(1);
+ }
+
+ @Test @Nightly
+ public void testBocchanBig() throws Exception {
+ doTestBocchan(100);
+ }
+
+ private void doTestBocchan(int numIterations) throws Exception {
+ LineNumberReader reader = new LineNumberReader(new InputStreamReader(
+ this.getClass().getResourceAsStream("bocchan.utf-8")));
+
+ String line = reader.readLine();
+ reader.close();
+
+ if (VERBOSE) {
+ System.out.println("Test for Bocchan without pre-splitting sentences");
+ }
+ long totalStart = System.currentTimeMillis();
+ for (int i = 0; i < numIterations; i++){
+ segmenter.tokenize(line);
+ }
+ if (VERBOSE) {
+ System.out.println("Total time : " + (System.currentTimeMillis() - totalStart));
+ System.out.println("Test for Bocchan with pre-splitting sentences");
+ }
+ String[] sentences = line.split("ã|ã");
+ totalStart = System.currentTimeMillis();
+ for (int i = 0; i < numIterations; i++) {
+ for (String sentence: sentences) {
+ segmenter.tokenize(sentence);
+ }
+ }
+ if (VERBOSE) {
+ System.out.println("Total time : " + (System.currentTimeMillis() - totalStart));
+ }
+ }
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestExtendedMode.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestExtendedMode.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestExtendedMode.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestExtendedMode.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,63 @@
+package org.apache.lucene.analysis.kuromoji;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.BaseTokenStreamTestCase;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.Tokenizer;
+import org.apache.lucene.analysis.kuromoji.Segmenter.Mode;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.util.UnicodeUtil;
+import org.apache.lucene.util._TestUtil;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class TestExtendedMode extends BaseTokenStreamTestCase {
+ private final Segmenter segmenter = new Segmenter(Mode.EXTENDED);
+ private final Analyzer analyzer = new Analyzer() {
+
+ @Override
+ protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
+ Tokenizer tokenizer = new KuromojiTokenizer(segmenter, reader);
+ return new TokenStreamComponents(tokenizer, tokenizer);
+ }
+ };
+
+ /** simple test for supplementary characters */
+ public void testSurrogates() throws IOException {
+ assertAnalyzesTo(analyzer, "ð©¬
è±é乿¯ç",
+ new String[] { "ð©¬
", "è±", "é", "ä¹", "æ¯", "ç" });
+ }
+
+ /** random test ensuring we don't ever split supplementaries */
+ public void testSurrogates2() throws IOException {
+ int numIterations = atLeast(10000);
+ for (int i = 0; i < numIterations; i++) {
+ String s = _TestUtil.randomUnicodeString(random, 100);
+ TokenStream ts = analyzer.tokenStream("foo", new StringReader(s));
+ CharTermAttribute termAtt = ts.addAttribute(CharTermAttribute.class);
+ ts.reset();
+ while (ts.incrementToken()) {
+ assertTrue(UnicodeUtil.validUTF16String(termAtt));
+ }
+ }
+ }
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiAnalyzer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiAnalyzer.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiAnalyzer.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiAnalyzer.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,51 @@
+package org.apache.lucene.analysis.kuromoji;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+
+import org.apache.lucene.analysis.BaseTokenStreamTestCase;
+
+public class TestKuromojiAnalyzer extends BaseTokenStreamTestCase {
+ /** This test fails with NPE when the
+ * stopwords file is missing in classpath */
+ public void testResourcesAvailable() {
+ new KuromojiAnalyzer(TEST_VERSION_CURRENT);
+ }
+
+ /**
+ * An example sentence, test removal of particles, etc by POS,
+ * lemmatization with the basic form, and that position increments
+ * and offsets are correct.
+ */
+ public void testBasics() throws IOException {
+ assertAnalyzesTo(new KuromojiAnalyzer(TEST_VERSION_CURRENT), "å¤ãã®å¦çã試é¨ã«è½ã¡ãã",
+ new String[] { "å¤ã", "å¦ç", "試é¨", "è½ã¡ã" },
+ new int[] { 0, 3, 6, 9 },
+ new int[] { 2, 5, 8, 11 },
+ new int[] { 1, 2, 2, 2 }
+ );
+ }
+
+ /**
+ * blast random strings against the analyzer
+ */
+ public void testRandom() throws IOException {
+ checkRandomData(random, new KuromojiAnalyzer(TEST_VERSION_CURRENT), atLeast(10000));
+ }
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiBaseFormFilter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiBaseFormFilter.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiBaseFormFilter.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiBaseFormFilter.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,50 @@
+package org.apache.lucene.analysis.kuromoji;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.Reader;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.BaseTokenStreamTestCase;
+import org.apache.lucene.analysis.Tokenizer;
+
+public class TestKuromojiBaseFormFilter extends BaseTokenStreamTestCase {
+ private Analyzer analyzer = new Analyzer() {
+ @Override
+ protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
+ Tokenizer tokenizer = new KuromojiTokenizer(reader);
+ return new TokenStreamComponents(tokenizer, new KuromojiBaseFormFilter(tokenizer));
+ }
+ };
+
+ public void testBasics() throws IOException {
+ assertAnalyzesTo(analyzer, "ããã¯ã¾ã å®é¨æ®µéã«ããã¾ã",
+ new String[] { "ãã", "ã¯", "ã¾ã ", "å®é¨", "段é", "ã«", "ãã", "ã¾ã" }
+ );
+ }
+
+ public void testEnglish() throws IOException {
+ assertAnalyzesTo(analyzer, "this atest",
+ new String[] { "this", "atest" });
+ }
+
+ public void testRandomStrings() throws IOException {
+ checkRandomData(random, analyzer, atLeast(10000));
+ }
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiTokenizer.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiTokenizer.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiTokenizer.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/TestKuromojiTokenizer.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,150 @@
+package org.apache.lucene.analysis.kuromoji;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+
+import org.apache.lucene.analysis.Analyzer;
+import org.apache.lucene.analysis.BaseTokenStreamTestCase;
+import org.apache.lucene.analysis.TokenStream;
+import org.apache.lucene.analysis.Tokenizer;
+import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
+import org.apache.lucene.util.UnicodeUtil;
+import org.apache.lucene.util._TestUtil;
+
+public class TestKuromojiTokenizer extends BaseTokenStreamTestCase {
+ private Analyzer analyzer = new Analyzer() {
+ @Override
+ protected TokenStreamComponents createComponents(String fieldName, Reader reader) {
+ Tokenizer tokenizer = new KuromojiTokenizer(reader);
+ return new TokenStreamComponents(tokenizer, tokenizer);
+ }
+ };
+
+ public void testDecomposition1() throws Exception {
+ assertAnalyzesTo(analyzer, "æ¬æ¥ã¯ãè²§å°å±¤ã®å¥³æ§ãåä¾ã«å»çä¿è·ãæä¾ããããã«åµè¨ãããå¶åº¦ã§ããã" +
+ "ã¢ã¡ãªã«ä½æå¾è
å»çæ´å©å¶åº¦ãã仿¥ã§ã¯ããã®äºç®ã®ç´ï¼åã®ï¼ãè人ã«è²»ããã¦ããã",
+ new String[] { "æ¬æ¥", "ã¯", "è²§å°", "層", "ã®", "女æ§", "ã", "åä¾", "ã«", "å»ç", "ä¿è·", "ã",
+ "æä¾", "ãã", "ãã", "ã«", "åµè¨", "ã", "ã", "ã", "å¶åº¦", "ã§", "ãã", "ã¢ã¡ãªã«",
+ "ä½", "æå¾", "è
", "å»ç", "æ´å©", "å¶åº¦", "ã", "仿¥", "ã§", "ã¯", "ãã®",
+ "äºç®", "ã®", "ç´", "ï¼", "åã®", "ï¼", "ã", "è人", "ã«", "è²»ãã", "ã¦", "ãã" },
+ new int[] { 0, 2, 4, 6, 7, 8, 10, 11, 13, 14, 16, 18, 19, 21, 23, 25, 26, 28, 29, 30,
+ 31, 33, 34, 37, 41, 42, 44, 45, 47, 49, 51, 53, 55, 56, 58, 60,
+ 62, 63, 64, 65, 67, 68, 69, 71, 72, 75, 76 },
+ new int[] { 2, 3, 6, 7, 8, 10, 11, 13, 14, 16, 18, 19, 21, 23, 25, 26, 28, 29, 30, 31,
+ 33, 34, 36, 41, 42, 44, 45, 47, 49, 51, 52, 55, 56, 57, 60, 62,
+ 63, 64, 65, 67, 68, 69, 71, 72, 75, 76, 78 }
+ );
+ }
+
+ public void testDecomposition2() throws Exception {
+ assertAnalyzesTo(analyzer, "麻è¬ã®å¯å£²ã¯æ ¹ãããçµ¶ãããªããã°ãªããªã",
+ new String[] { "麻è¬", "ã®", "å¯å£²", "ã¯", "æ ¹ããã", "çµ¶ãã", "ãªãã", "ã°", "ãªã", "ãªã" },
+ new int[] { 0, 2, 3, 5, 6, 10, 13, 16, 17, 19 },
+ new int[] { 2, 3, 5, 6, 10, 13, 16, 17, 19, 21 }
+ );
+ }
+
+ public void testDecomposition3() throws Exception {
+ assertAnalyzesTo(analyzer, "é女ç©å¤§å°ãã·ã¥ã¼ã»ãããã³ã¹ã",
+ new String[] { "é女", "ç©", "大å°", "ãã·ã¥ã¼", "ãããã³ã¹" },
+ new int[] { 0, 2, 3, 5, 10 },
+ new int[] { 2, 3, 5, 9, 15 }
+ );
+ }
+
+ public void testDecomposition4() throws Exception {
+ assertAnalyzesTo(analyzer, "ããã¯æ¬ã§ã¯ãªã",
+ new String[] { "ãã", "ã¯", "æ¬", "ã§", "ã¯", "ãªã" },
+ new int[] { 0, 2, 3, 4, 5, 6 },
+ new int[] { 2, 3, 4, 5, 6, 8 }
+ );
+ }
+
+ public void testDecomposition5() throws Exception {
+ assertAnalyzesTo(analyzer, "ãããããããããããããããããããããããããããããããããããããããã",
+ new String[] { "ãããã", "ãããã", "ãããã", "ãããã", "ãããã", "ãããã", "ãããã", "ãããã", "ãããã", "ãããã" },
+ new int[] { 0, 4, 8, 12, 16, 20, 24, 28, 32, 36},
+ new int[] { 4, 8, 12, 16, 20, 24, 28, 32, 36, 40 }
+ );
+ }
+
+ /** Tests that sentence offset is incorporated into the resulting offsets */
+ public void testTwoSentences() throws Exception {
+ assertAnalyzesTo(analyzer, "é女ç©å¤§å°ãã·ã¥ã¼ã»ãããã³ã¹ã é女ç©å¤§å°ãã·ã¥ã¼ã»ãããã³ã¹ã",
+ new String[] { "é女", "ç©", "大å°", "ãã·ã¥ã¼", "ãããã³ã¹", "é女", "ç©", "大å°", "ãã·ã¥ã¼", "ãããã³ã¹" },
+ new int[] { 0, 2, 3, 5, 10, 17, 19, 20, 22, 27 },
+ new int[] { 2, 3, 5, 9, 15, 19, 20, 22, 26, 32 }
+ );
+ }
+
+ /** blast some random strings through the analyzer */
+ public void testRandomStrings() throws Exception {
+ checkRandomData(random, analyzer, 10000*RANDOM_MULTIPLIER);
+ }
+
+ public void testLargeDocReliability() throws Exception {
+ for (int i = 0; i < 100; i++) {
+ String s = _TestUtil.randomUnicodeString(random, 10000);
+ TokenStream ts = analyzer.tokenStream("foo", new StringReader(s));
+ ts.reset();
+ while (ts.incrementToken()) {
+ }
+ }
+ }
+
+ /** simple test for supplementary characters */
+ public void testSurrogates() throws IOException {
+ assertAnalyzesTo(analyzer, "ð©¬
è±é乿¯ç",
+ new String[] { "ð©¬
", "è±", "é", "ä¹", "æ¯", "ç" });
+ }
+
+ /** random test ensuring we don't ever split supplementaries */
+ public void testSurrogates2() throws IOException {
+ int numIterations = atLeast(10000);
+ for (int i = 0; i < numIterations; i++) {
+ String s = _TestUtil.randomUnicodeString(random, 100);
+ TokenStream ts = analyzer.tokenStream("foo", new StringReader(s));
+ CharTermAttribute termAtt = ts.addAttribute(CharTermAttribute.class);
+ ts.reset();
+ while (ts.incrementToken()) {
+ assertTrue(UnicodeUtil.validUTF16String(termAtt));
+ }
+ }
+ }
+
+ // note: test is kinda silly since kuromoji emits punctuation tokens.
+ // but, when/if we filter these out it will be useful.
+ public void testEnd() throws Exception {
+ assertTokenStreamContents(analyzer.tokenStream("foo", new StringReader("ããã¯æ¬ã§ã¯ãªã")),
+ new String[] { "ãã", "ã¯", "æ¬", "ã§", "ã¯", "ãªã" },
+ new int[] { 0, 2, 3, 4, 5, 6 },
+ new int[] { 2, 3, 4, 5, 6, 8 },
+ new Integer(8)
+ );
+
+ assertTokenStreamContents(analyzer.tokenStream("foo", new StringReader("ããã¯æ¬ã§ã¯ãªã ")),
+ new String[] { "ãã", "ã¯", "æ¬", "ã§", "ã¯", "ãªã" },
+ new int[] { 0, 2, 3, 4, 5, 6, 8 },
+ new int[] { 2, 3, 4, 5, 6, 8, 9 },
+ new Integer(12)
+ );
+ }
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/bocchan.utf-8
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/bocchan.utf-8?rev=1230748&view=auto
==============================================================================
Binary file - no diff available.
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/dict/TestTokenInfoDictionary.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/dict/TestTokenInfoDictionary.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/dict/TestTokenInfoDictionary.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/dict/TestTokenInfoDictionary.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,107 @@
+package org.apache.lucene.analysis.kuromoji.dict;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.analysis.kuromoji.util.ToStringUtil;
+import org.apache.lucene.util.IntsRef;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.UnicodeUtil;
+import org.apache.lucene.util.fst.FST;
+import org.apache.lucene.util.fst.IntsRefFSTEnum;
+import org.apache.lucene.util.fst.IntsRefFSTEnum.InputOutput;
+
+public class TestTokenInfoDictionary extends LuceneTestCase {
+
+ /** enumerates the entire FST/lookup data and just does basic sanity checks */
+ public void testEnumerateAll() throws Exception {
+ // just for debugging
+ int numTerms = 0;
+ int numWords = 0;
+ int lastWordId = -1;
+ int lastSourceId = -1;
+ TokenInfoDictionary tid = TokenInfoDictionary.getInstance();
+ ConnectionCosts matrix = ConnectionCosts.getInstance();
+ FST<Long> fst = tid.getFST().getInternalFST();
+ IntsRefFSTEnum<Long> fstEnum = new IntsRefFSTEnum<Long>(fst);
+ InputOutput<Long> mapping;
+ IntsRef scratch = new IntsRef();
+ while ((mapping = fstEnum.next()) != null) {
+ numTerms++;
+ IntsRef input = mapping.input;
+ char chars[] = new char[input.length];
+ for (int i = 0; i < chars.length; i++) {
+ chars[i] = (char)input.ints[input.offset+i];
+ }
+ assertTrue(UnicodeUtil.validUTF16String(new String(chars)));
+
+ Long output = mapping.output;
+ int sourceId = output.intValue();
+ // we walk in order, terms, sourceIds, and wordIds should always be increasing
+ assertTrue(sourceId > lastSourceId);
+ lastSourceId = sourceId;
+ tid.lookupWordIds(sourceId, scratch);
+ for (int i = 0; i < scratch.length; i++) {
+ numWords++;
+ int wordId = scratch.ints[scratch.offset+i];
+ assertTrue(wordId > lastWordId);
+ lastWordId = wordId;
+
+ String baseForm = tid.getBaseForm(wordId);
+ assertTrue(baseForm == null || UnicodeUtil.validUTF16String(baseForm));
+
+ String inflectionForm = tid.getInflectionForm(wordId);
+ assertTrue(inflectionForm == null || UnicodeUtil.validUTF16String(inflectionForm));
+ if (inflectionForm != null) {
+ // check that its actually an ipadic inflection form
+ assertNotNull(ToStringUtil.getInflectedFormTranslation(inflectionForm));
+ }
+
+ String inflectionType = tid.getInflectionType(wordId);
+ assertTrue(inflectionType == null || UnicodeUtil.validUTF16String(inflectionType));
+ if (inflectionType != null) {
+ // check that its actually an ipadic inflection type
+ assertNotNull(ToStringUtil.getInflectionTypeTranslation(inflectionType));
+ }
+
+ int leftId = tid.getLeftId(wordId);
+ int rightId = tid.getRightId(wordId);
+
+ matrix.get(rightId, leftId);
+
+ tid.getWordCost(wordId);
+
+ String pos = tid.getPartOfSpeech(wordId);
+ assertNotNull(pos);
+ assertTrue(UnicodeUtil.validUTF16String(pos));
+ // check that its actually an ipadic pos tag
+ assertNotNull(ToStringUtil.getPOSTranslation(pos));
+
+ String pronunciation = tid.getPronunciation(wordId);
+ assertNotNull(pronunciation);
+ assertTrue(UnicodeUtil.validUTF16String(pronunciation));
+
+ String reading = tid.getReading(wordId);
+ assertNotNull(reading);
+ assertTrue(UnicodeUtil.validUTF16String(reading));
+ }
+ }
+ if (VERBOSE) {
+ System.out.println("checked " + numTerms + " terms, " + numWords + " words.");
+ }
+ }
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/dict/UserDictionaryTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/dict/UserDictionaryTest.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/dict/UserDictionaryTest.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/dict/UserDictionaryTest.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,98 @@
+package org.apache.lucene.analysis.kuromoji.dict;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.IOException;
+
+import org.apache.lucene.analysis.kuromoji.SegmenterTest;
+import org.apache.lucene.analysis.kuromoji.dict.UserDictionary;
+import org.apache.lucene.util.IOUtils;
+import org.apache.lucene.util.LuceneTestCase;
+import org.junit.Test;
+
+public class UserDictionaryTest extends LuceneTestCase {
+
+ private UserDictionary readDict() throws IOException {
+ InputStream is = SegmenterTest.class.getResourceAsStream("userdict.txt");
+ if (is == null)
+ throw new FileNotFoundException("Cannot find userdict.txt in test classpath!");
+ try {
+ Reader reader = new InputStreamReader(is, IOUtils.CHARSET_UTF_8);
+ return new UserDictionary(reader);
+ } finally {
+ is.close();
+ }
+ }
+
+ @Test
+ public void testLookup() throws IOException {
+ UserDictionary dictionary = readDict();
+ String s = "é¢è¥¿å½é空港ã«è¡ã£ã";
+ int[][] dictionaryEntryResult = dictionary.lookup(s.toCharArray(), 0, s.length());
+ // Length should be three é¢è¥¿, å½é, 空港
+ assertEquals(3, dictionaryEntryResult.length);
+
+ // Test positions
+ assertEquals(0, dictionaryEntryResult[0][1]); // index of é¢è¥¿
+ assertEquals(2, dictionaryEntryResult[1][1]); // index of å½é
+ assertEquals(4, dictionaryEntryResult[2][1]); // index of 空港
+
+ // Test lengths
+ assertEquals(2, dictionaryEntryResult[0][2]); // length of é¢è¥¿
+ assertEquals(2, dictionaryEntryResult[1][2]); // length of å½é
+ assertEquals(2, dictionaryEntryResult[2][2]); // length of 空港
+
+ s = "é¢è¥¿å½é空港ã¨é¢è¥¿å½é空港ã«è¡ã£ã";
+ int[][] dictionaryEntryResult2 = dictionary.lookup(s.toCharArray(), 0, s.length());
+ // Length should be six
+ assertEquals(6, dictionaryEntryResult2.length);
+ }
+
+ @Test
+ public void testReadings() throws IOException {
+ UserDictionary dictionary = readDict();
+ int[][] result = dictionary.lookup("æ¥æ¬çµæ¸æ°è".toCharArray(), 0, 6);
+ assertEquals(3, result.length);
+ int wordIdNihon = result[0][0]; // wordId of æ¥æ¬ in æ¥æ¬çµæ¸æ°è
+ assertEquals("ããã³", dictionary.getReading(wordIdNihon));
+
+ result = dictionary.lookup("æéé¾".toCharArray(), 0, 3);
+ assertEquals(1, result.length);
+ int wordIdAsashoryu = result[0][0]; // wordId for æéé¾
+ assertEquals("ã¢ãµã·ã§ã¦ãªã¥ã¦", dictionary.getReading(wordIdAsashoryu));
+ }
+
+ @Test
+ public void testPartOfSpeech() throws IOException {
+ UserDictionary dictionary = readDict();
+ int[][] result = dictionary.lookup("æ¥æ¬çµæ¸æ°è".toCharArray(), 0, 6);
+ assertEquals(3, result.length);
+ int wordIdKeizai = result[1][0]; // wordId of çµæ¸ in æ¥æ¬çµæ¸æ°è
+ assertEquals("ã«ã¹ã¿ã åè©", dictionary.getPartOfSpeech(wordIdKeizai));
+ }
+
+ @Test
+ public void testRead() throws IOException {
+ UserDictionary dictionary = readDict();
+ assertNotNull(dictionary);
+ }
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/userdict.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/userdict.txt?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/userdict.txt (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/userdict.txt Thu Jan 12 20:10:48 2012
@@ -0,0 +1,6 @@
+# Custom segmentation for long entries
+æ¥æ¬çµæ¸æ°è,æ¥æ¬ çµæ¸ æ°è,ããã³ ã±ã¤ã¶ã¤ ã·ã³ãã³,ã«ã¹ã¿ã åè©
+é¢è¥¿å½é空港,é¢è¥¿ å½é 空港,ã«ã³ãµã¤ ã³ã¯ãµã¤ ã¯ã¦ã³ã¦,ãã¹ãåè©
+
+# Custom reading for sumo wrestler
+æéé¾,æéé¾,ã¢ãµã·ã§ã¦ãªã¥ã¦,ã«ã¹ã¿ã 人å
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/util/TestToStringUtil.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/util/TestToStringUtil.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/util/TestToStringUtil.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/test/org/apache/lucene/analysis/kuromoji/util/TestToStringUtil.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,34 @@
+package org.apache.lucene.analysis.kuromoji.util;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.lucene.util.LuceneTestCase;
+
+public class TestToStringUtil extends LuceneTestCase {
+ public void testPOS() {
+ assertEquals("noun-suffix-verbal", ToStringUtil.getPOSTranslation("åè©-æ¥å°¾-ãµå¤æ¥ç¶"));
+ }
+
+ public void testHepburn() {
+ assertEquals("majan", ToStringUtil.getRomanization("ãã¼ã¸ã£ã³"));
+ assertEquals("uroncha", ToStringUtil.getRomanization("ã¦ã¼ãã³ãã£"));
+ assertEquals("chahan", ToStringUtil.getRomanization("ãã£ã¼ãã³"));
+ assertEquals("chashu", ToStringUtil.getRomanization("ãã£ã¼ã·ã¥ã¼"));
+ assertEquals("shumai", ToStringUtil.getRomanization("ã·ã¥ã¼ãã¤"));
+ }
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/BinaryDictionaryWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/BinaryDictionaryWriter.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/BinaryDictionaryWriter.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/BinaryDictionaryWriter.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,371 @@
+package org.apache.lucene.analysis.kuromoji.util;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.nio.channels.Channels;
+import java.nio.channels.WritableByteChannel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.lucene.store.DataOutput;
+import org.apache.lucene.store.OutputStreamDataOutput;
+import org.apache.lucene.util.ArrayUtil;
+import org.apache.lucene.util.CodecUtil;
+
+import org.apache.lucene.analysis.kuromoji.dict.BinaryDictionary;
+
+public abstract class BinaryDictionaryWriter {
+ protected final Class<? extends BinaryDictionary> implClazz;
+ protected ByteBuffer buffer;
+ private int targetMapEndOffset = 0, lastWordId = -1, lastSourceId = -1;
+ private int[] targetMap = new int[8192];
+ private int[] targetMapOffsets = new int[8192];
+ private final List<String> posDict = new ArrayList<String>();
+ private final Map<String,Integer> posDictLookup = new HashMap<String,Integer>();
+
+ private final List<String> inflDict = new ArrayList<String>();
+ private final Map<String,Integer> inflDictLookup = new HashMap<String,Integer>();
+
+ public BinaryDictionaryWriter(Class<? extends BinaryDictionary> implClazz, int size) {
+ this.implClazz = implClazz;
+ buffer = ByteBuffer.allocate(size);
+ }
+
+ /**
+ * put the entry in map
+ * @return current position of buffer, which will be wordId of next entry
+ */
+ public int put(String[] entry) {
+ short leftId = Short.parseShort(entry[1]);
+ short rightId = Short.parseShort(entry[2]);
+ short wordCost = Short.parseShort(entry[3]);
+
+ StringBuilder sb = new StringBuilder();
+
+ // build up the POS string
+ for (int i = 4; i < 8; i++) {
+ String part = entry[i];
+ assert part.length() > 0;
+ if (!"*".equals(part)) {
+ if (sb.length() > 0) {
+ sb.append('-');
+ }
+ sb.append(part);
+ }
+ }
+ String pos = sb.toString();
+ Integer posIndex = posDictLookup.get(pos);
+ if (posIndex == null) {
+ posIndex = posDict.size();
+ posDict.add(pos);
+ posDictLookup.put(pos, posIndex);
+ assert posDict.size() == posDictLookup.size();
+ }
+
+ sb.setLength(0);
+ sb.append(CSVUtil.quoteEscape(entry[8]));
+ sb.append(',');
+ sb.append(CSVUtil.quoteEscape(entry[9]));
+ String inflData = sb.toString();
+
+ Integer inflIndex = Integer.MAX_VALUE;
+ int hasInflData;
+ if ("*,*".equals(inflData)) {
+ hasInflData = 0; // no inflection data
+ } else {
+ hasInflData = 1;
+ inflIndex = inflDictLookup.get(inflData);
+ if (inflIndex == null) {
+ inflIndex = inflDict.size();
+ inflDict.add(inflData);
+ inflDictLookup.put(inflData, inflIndex);
+ assert inflDict.size() == inflDictLookup.size();
+ }
+ }
+
+ String baseForm = entry[10];
+ String reading = entry[11];
+ String pronunciation = entry[12];
+
+ // extend buffer if necessary
+ int left = buffer.remaining();
+ // worst case: three short, 4 bytes, one vint and features (all as utf-16)
+ int worstCase = 6 + 4 + 2 + 2*(baseForm.length() + reading.length() + pronunciation.length());
+ if (worstCase > left) {
+ ByteBuffer newBuffer = ByteBuffer.allocate(ArrayUtil.oversize(buffer.limit() + worstCase - left, 1));
+ buffer.flip();
+ newBuffer.put(buffer);
+ buffer = newBuffer;
+ }
+
+ buffer.putShort(leftId);
+ buffer.putShort(rightId);
+ buffer.putShort(wordCost);
+ assert posIndex.intValue() < 128;
+ buffer.put((byte) (posIndex.intValue() << 1 | hasInflData));
+
+ int pronunciationIsReading = pronunciation.equals(reading) ? 1 : 0;
+
+ if ("*".equals(baseForm) || baseForm.equals(entry[0])) {
+ buffer.put((byte)pronunciationIsReading); // base form is the same as surface form
+ } else {
+ assert baseForm.length() < 128;
+ buffer.put((byte)(baseForm.length() << 1 | pronunciationIsReading));
+ for (int i = 0; i < baseForm.length(); i++) {
+ buffer.putChar(baseForm.charAt(i));
+ }
+ }
+
+ if (isKatakana(reading)) {
+ buffer.put((byte) (reading.length() << 1 | 1));
+ writeKatakana(reading);
+ } else {
+ buffer.put((byte) (reading.length() << 1));
+ for (int i = 0; i < reading.length(); i++) {
+ buffer.putChar(reading.charAt(i));
+ }
+ }
+
+ if (pronunciationIsReading == 0) {
+ if (isKatakana(pronunciation)) {
+ buffer.put((byte) (pronunciation.length() << 1 | 1));
+ writeKatakana(pronunciation);
+ } else {
+ buffer.put((byte) (pronunciation.length() << 1));
+ for (int i = 0; i < pronunciation.length(); i++) {
+ buffer.putChar(pronunciation.charAt(i));
+ }
+ }
+ }
+
+ if (hasInflData > 0) {
+ int key = inflIndex.intValue();
+ assert key < 32768; // note there are really like 300 of these...
+ if (key < 128) {
+ buffer.put((byte) key);
+ } else {
+ buffer.put((byte) ((key & 0x7f) | 0x80));
+ buffer.put((byte) (key >>> 7));
+ }
+ }
+
+ return buffer.position();
+ }
+
+ private boolean isKatakana(String s) {
+ for (int i = 0; i < s.length(); i++) {
+ char ch = s.charAt(i);
+ if (ch < 0x30A0 || ch > 0x30FF) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ private void writeKatakana(String s) {
+ for (int i = 0; i < s.length(); i++) {
+ buffer.put((byte) (s.charAt(i) - 0x30A0));
+ }
+ }
+
+ public void addMapping(int sourceId, int wordId) {
+ assert wordId > lastWordId : "words out of order: " + wordId + " vs lastID: " + lastWordId;
+
+ if (sourceId > lastSourceId) {
+ assert sourceId > lastSourceId : "source ids out of order: lastSourceId=" + lastSourceId + " vs sourceId=" + sourceId;
+ targetMapOffsets = ArrayUtil.grow(targetMapOffsets, sourceId + 1);
+ for (int i = lastSourceId + 1; i <= sourceId; i++) {
+ targetMapOffsets[i] = targetMapEndOffset;
+ }
+ } else {
+ assert sourceId == lastSourceId;
+ }
+
+ targetMap = ArrayUtil.grow(targetMap, targetMapEndOffset + 1);
+ targetMap[targetMapEndOffset] = wordId;
+ targetMapEndOffset++;
+
+ lastSourceId = sourceId;
+ lastWordId = wordId;
+ }
+
+ protected final String getBaseFileName(String baseDir) throws IOException {
+ return baseDir + File.separator + implClazz.getName().replace('.', File.separatorChar);
+ }
+
+ /**
+ * Write dictionary in file
+ * Dictionary format is:
+ * [Size of dictionary(int)], [entry:{left id(short)}{right id(short)}{word cost(short)}{length of pos info(short)}{pos info(char)}], [entry...], [entry...].....
+ * @throws IOException
+ */
+ public void write(String baseDir) throws IOException {
+ final String baseName = getBaseFileName(baseDir);
+ writeDictionary(baseName + BinaryDictionary.DICT_FILENAME_SUFFIX);
+ writeTargetMap(baseName + BinaryDictionary.TARGETMAP_FILENAME_SUFFIX);
+ writePosDict(baseName + BinaryDictionary.POSDICT_FILENAME_SUFFIX);
+ writeInflDict(baseName + BinaryDictionary.INFLDICT_FILENAME_SUFFIX);
+ }
+
+ // TODO: maybe this int[] should instead be the output to the FST...
+ protected void writeTargetMap(String filename) throws IOException {
+ new File(filename).getParentFile().mkdirs();
+ OutputStream os = new FileOutputStream(filename);
+ try {
+ os = new BufferedOutputStream(os);
+ final DataOutput out = new OutputStreamDataOutput(os);
+ CodecUtil.writeHeader(out, BinaryDictionary.TARGETMAP_HEADER, BinaryDictionary.VERSION);
+
+ final int numSourceIds = lastSourceId + 1;
+ out.writeVInt(targetMapEndOffset); // <-- size of main array
+ out.writeVInt(numSourceIds + 1); // <-- size of offset array (+ 1 more entry)
+ int prev = 0, sourceId = 0;
+ for (int ofs = 0; ofs < targetMapEndOffset; ofs++) {
+ final int val = targetMap[ofs], delta = val - prev;
+ assert delta >= 0;
+ if (ofs == targetMapOffsets[sourceId]) {
+ out.writeVInt((delta << 1) | 0x01);
+ sourceId++;
+ } else {
+ out.writeVInt((delta << 1));
+ }
+ prev += delta;
+ }
+ assert sourceId == numSourceIds : "sourceId:"+sourceId+" != numSourceIds:"+numSourceIds;
+ } finally {
+ os.close();
+ }
+ }
+
+ protected void writePosDict(String filename) throws IOException {
+ new File(filename).getParentFile().mkdirs();
+ OutputStream os = new FileOutputStream(filename);
+ try {
+ os = new BufferedOutputStream(os);
+ final DataOutput out = new OutputStreamDataOutput(os);
+ CodecUtil.writeHeader(out, BinaryDictionary.POSDICT_HEADER, BinaryDictionary.VERSION);
+ out.writeVInt(posDict.size());
+ for (String s : posDict) {
+ out.writeString(s);
+ }
+ } finally {
+ os.close();
+ }
+ }
+
+ protected void writeInflDict(String filename) throws IOException {
+ new File(filename).getParentFile().mkdirs();
+ OutputStream os = new FileOutputStream(filename);
+ try {
+ os = new BufferedOutputStream(os);
+ final DataOutput out = new OutputStreamDataOutput(os);
+ CodecUtil.writeHeader(out, BinaryDictionary.INFLDICT_HEADER, BinaryDictionary.VERSION);
+ out.writeVInt(inflDict.size());
+ for (String s : inflDict) {
+ String data[] = CSVUtil.parse(s);
+ assert data.length == 2 : "malformed inflection: " + s;
+ out.writeString(data[0]);
+ out.writeString(data[1]);
+ }
+ } finally {
+ os.close();
+ }
+ }
+
+ protected void writeDictionary(String filename) throws IOException {
+ new File(filename).getParentFile().mkdirs();
+ final FileOutputStream os = new FileOutputStream(filename);
+ try {
+ final DataOutput out = new OutputStreamDataOutput(os);
+ CodecUtil.writeHeader(out, BinaryDictionary.DICT_HEADER, BinaryDictionary.VERSION);
+ out.writeVInt(buffer.position());
+ final WritableByteChannel channel = Channels.newChannel(os);
+ // Write Buffer
+ buffer.flip(); // set position to 0, set limit to current position
+ channel.write(buffer);
+ assert buffer.remaining() == 0L;
+ } finally {
+ os.close();
+ }
+ }
+
+ // TODO: the below is messy, but makes the dictionary smaller.
+ // we track frequencies of inflections so the highest-freq ones have smaller indexes.
+
+ /** optional: notes inflection seen in the data up front */
+ public void noteInflection(String entry[]) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(CSVUtil.quoteEscape(entry[8]));
+ sb.append(',');
+ sb.append(CSVUtil.quoteEscape(entry[9]));
+ String s = sb.toString();
+ if ("*,*".equals(s)) {
+ return; // no inflection data
+ }
+ Integer freq = notedInflections.get(s);
+ if (freq == null) {
+ freq = 0;
+ }
+ notedInflections.put(s, freq+1);
+ }
+
+ /** prepopulates inflection mapping by frequency */
+ public void finalizeInflections() {
+ InflectionAndFreq freqs[] = new InflectionAndFreq[notedInflections.size()];
+ int upto = 0;
+ for (Map.Entry<String,Integer> e : notedInflections.entrySet()) {
+ freqs[upto++] = new InflectionAndFreq(e.getKey(), e.getValue());
+ }
+ Arrays.sort(freqs, Collections.reverseOrder());
+ for (int i = 0; i < upto; i++) {
+ inflDict.add(freqs[i].inflection);
+ inflDictLookup.put(freqs[i].inflection, i);
+ }
+ }
+
+ static class InflectionAndFreq implements Comparable<InflectionAndFreq> {
+ String inflection;
+ int freq;
+
+ InflectionAndFreq(String s, int i) {
+ this.inflection = s;
+ this.freq = i;
+ }
+
+ public int compareTo(InflectionAndFreq other) {
+ int cmp = freq - other.freq;
+ if (cmp == 0) {
+ return inflection.compareTo(other.inflection);
+ } else {
+ return cmp;
+ }
+ }
+ }
+
+ private HashMap<String,Integer> notedInflections = new HashMap<String,Integer>();
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/CharacterDefinitionWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/CharacterDefinitionWriter.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/CharacterDefinitionWriter.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/CharacterDefinitionWriter.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,95 @@
+package org.apache.lucene.analysis.kuromoji.util;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.BufferedOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Arrays;
+
+import org.apache.lucene.analysis.kuromoji.dict.CharacterDefinition;
+
+import org.apache.lucene.store.DataOutput;
+import org.apache.lucene.store.OutputStreamDataOutput;
+import org.apache.lucene.util.CodecUtil;
+
+public final class CharacterDefinitionWriter {
+
+ private final byte[] characterCategoryMap = new byte[0x10000];
+
+ private final boolean[] invokeMap = new boolean[CharacterDefinition.CLASS_COUNT];
+ private final boolean[] groupMap = new boolean[CharacterDefinition.CLASS_COUNT];
+
+ /**
+ * Constructor for building. TODO: remove write access
+ */
+ public CharacterDefinitionWriter() {
+ Arrays.fill(characterCategoryMap, CharacterDefinition.DEFAULT);
+ }
+
+ /**
+ * Put mapping from unicode code point to character class.
+ *
+ * @param codePoint
+ * code point
+ * @param characterClassName character class name
+ */
+ public void putCharacterCategory(int codePoint, String characterClassName) {
+ characterClassName = characterClassName.split(" ")[0]; // use first
+ // category
+ // class
+
+ // Override Nakaguro
+ if (codePoint == 0x30FB) {
+ characterClassName = "SYMBOL";
+ }
+ characterCategoryMap[codePoint] = CharacterDefinition.lookupCharacterClass(characterClassName);
+ }
+
+ public void putInvokeDefinition(String characterClassName, int invoke, int group, int length) {
+ final byte characterClass = CharacterDefinition.lookupCharacterClass(characterClassName);
+ invokeMap[characterClass] = invoke == 1;
+ groupMap[characterClass] = group == 1;
+ // TODO: length def ignored
+ }
+
+ public void write(String baseDir) throws IOException {
+ String filename = baseDir + File.separator +
+ CharacterDefinition.class.getName().replace('.', File.separatorChar) + CharacterDefinition.FILENAME_SUFFIX;
+ new File(filename).getParentFile().mkdirs();
+ OutputStream os = new FileOutputStream(filename);
+ try {
+ os = new BufferedOutputStream(os);
+ final DataOutput out = new OutputStreamDataOutput(os);
+ CodecUtil.writeHeader(out, CharacterDefinition.HEADER, CharacterDefinition.VERSION);
+ out.writeBytes(characterCategoryMap, 0, characterCategoryMap.length);
+ for (int i = 0; i < CharacterDefinition.CLASS_COUNT; i++) {
+ final byte b = (byte) (
+ (invokeMap[i] ? 0x01 : 0x00) |
+ (groupMap[i] ? 0x02 : 0x00)
+ );
+ out.writeByte(b);
+ }
+ } finally {
+ os.close();
+ }
+ }
+
+}
Added: lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/ConnectionCostsBuilder.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/ConnectionCostsBuilder.java?rev=1230748&view=auto
==============================================================================
--- lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/ConnectionCostsBuilder.java (added)
+++ lucene/dev/trunk/modules/analysis/kuromoji/src/tools/java/org/apache/lucene/analysis/kuromoji/util/ConnectionCostsBuilder.java Thu Jan 12 20:10:48 2012
@@ -0,0 +1,67 @@
+package org.apache.lucene.analysis.kuromoji.util;
+
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+import java.nio.charset.CodingErrorAction;
+
+public class ConnectionCostsBuilder {
+
+ private ConnectionCostsBuilder() {
+ }
+
+ public static ConnectionCostsWriter build(String filename) throws IOException {
+ FileInputStream inputStream = new FileInputStream(filename);
+ Charset cs = Charset.forName("US-ASCII");
+ CharsetDecoder decoder = cs.newDecoder()
+ .onMalformedInput(CodingErrorAction.REPORT)
+ .onUnmappableCharacter(CodingErrorAction.REPORT);
+ InputStreamReader streamReader = new InputStreamReader(inputStream, decoder);
+ LineNumberReader lineReader = new LineNumberReader(streamReader);
+
+ String line = lineReader.readLine();
+ String[] dimensions = line.split("\\s+");
+
+ assert dimensions.length == 2;
+
+ int forwardSize = Integer.parseInt(dimensions[0]);
+ int backwardSize = Integer.parseInt(dimensions[1]);
+
+ assert forwardSize > 0 && backwardSize > 0;
+
+ ConnectionCostsWriter costs = new ConnectionCostsWriter(forwardSize, backwardSize);
+
+ while ((line = lineReader.readLine()) != null) {
+ String[] fields = line.split("\\s+");
+
+ assert fields.length == 3;
+
+ int forwardId = Integer.parseInt(fields[0]);
+ int backwardId = Integer.parseInt(fields[1]);
+ int cost = Integer.parseInt(fields[2]);
+
+ costs.add(forwardId, backwardId, cost);
+ }
+ return costs;
+ }
+}