OPENNLP-1880: Lexical knowledge base seam with WN-LMF and WNDB readers and a Morphy lemmatizer#1155
Draft
krickert wants to merge 12 commits into
Draft
OPENNLP-1880: Lexical knowledge base seam with WN-LMF and WNDB readers and a Morphy lemmatizer#1155krickert wants to merge 12 commits into
krickert wants to merge 12 commits into
Conversation
…edgeBase Renames the public seam interface so consumers describe what they are injecting (a lexical knowledge base) rather than naming the WordNet brand in a public API type. Concrete implementations that genuinely are WordNet-format readers (InMemoryWordNetLexicon, WnLmfReader, WndbReader) keep the WordNet name, since they describe the data format they read, not the contract itself.
…declarations Completes the LexicalKnowledgeBase rename in this file, and switches DOCTYPE handling from outright rejection to the OWASP-documented alternative for formats that require DOCTYPE support: the DOCTYPE event is skipped rather than resolved, while SUPPORT_DTD stays off (so no custom entity, internal or external, is ever declared), IS_SUPPORTING_EXTERNAL_ENTITIES and ACCESS_EXTERNAL_DTD stay off, and the XMLResolver still throws on any resolution attempt. This closes the same attack surface as outright rejection while letting the reader parse Open English WordNet releases unmodified, since real OEWN files ship a DOCTYPE line referencing the schema DTD. Test changes: testRejectsDoctype becomes testSkipsDoctypeDeclaration and now asserts a DOCTYPE-bearing document parses correctly instead of throwing. Added testInternalSubsetEntityIsNeverExpanded, which proves a classic XXE payload (a DOCTYPE-declared internal-subset entity pointing at a local file) still fails loud rather than expanding into the parsed output.
Contributor
Author
|
There's a minor windows-specific build issue due to line endings and Windoze. Will flip back to review once I find my windows machine and test. Code is the same though. |
a22e00d to
d01ddff
Compare
WNDB data lines embed their own byte offset, which WndbReader validates against the actual position. The repo's default `* text=auto` lets Git normalize these fixtures to CRLF on Windows checkout, inserting a CR before every LF and shifting every offset after the first line; every WndbReaderTest case failed on Windows CI as a result. Scoping -text to the fixture directory keeps the checkout byte-identical everywhere.
Contributor
|
Hi @krickert - as mentioned on Slack I currently dont have the time for a manual review but I just let Fable do a comprehensive review on this PR. Here is the result:
Human review will follow. |
…iring, fail-loud coverage The three loading entry points (WndbReader.read, WnLmfReader.read, MorphyExceptions.load) now follow the codebase's loader convention: they declare IOException, malformed content raises InvalidFormatException, and null or argument problems stay IllegalArgumentException. Every internal content-error throw site, the javadocs, and all affected test assertions moved with the contract, and a failing-stream test pins that an I/O error surfaces as itself rather than as a malformed-document report. The public enum WordNetPos is renamed to WordNetPOS to match POSTagger and POSModel before the name freezes at release. Several reader gaps close: SynsetRelation elements with relType "other" are now skipped like their SenseRelation counterparts instead of rejected, duplicate LexicalEntry and Sense ids fail loud like duplicate synset ids, and relation resolution in both readers now stores the synset table's canonical id instance per target so a full lexicon keeps one copy of each id regardless of pointer count. Dangling WNDB pointer errors name the pointer's own line through the previously unread RawPointer component, and posFromTag accepts the WordNet letter codes a and s only as one-letter tags, so AUX, ADP, SCONJ, and SYM map to the unknown-word result instead of adjective lookups. The duplicated lemma fold and space-split logic collapse into a package-private LemmaFolding helper shared by the exception lists, the sense index, and the WN-LMF parser. The module is now wired into the root pom's dependencyManagement, the binary distribution's dependencies, and the aggregated apidocs assembly, mirroring the other extension modules. New coverage pins the verb-group mapping in both readers (a WN-LMF document with similar on verb synsets, and a constructed WNDB directory with computed byte offsets exercising the dollar pointer), the InMemoryWordNetLexicon constructor validation, the LemmaFolding behavior, and every documented WN-LMF structural fail-loud path.
Contributor
Author
|
Thanks, every finding is addressed in 69ead68. Point by point:
Module tests go from 86 to 112; reactor verify is clean. |
Applies the review conventions from the OPENNLP-1869 review: philosophy prose shrinks to interface contracts, nested types carry javadoc instead of comments, inline rationale becomes single contract sentences, and the internal folding helpers guard their documented null contracts.
…m commentary Aligns null-argument validation with the project convention and removes remaining rationale commentary, keeping javadoc terse.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds the format-agnostic lexical knowledge base seam to opennlp-api (
opennlp.tools.wordnet:LexicalKnowledgeBase,Synset,WordNetPos,WordNetRelation), and a newopennlp-extensions/opennlp-wordnetmodule with two clean-room readers behind it:WnLmfReader: a StAX reader for WN-LMF XML, Open English WordNet's interchange format. XXE-hardened per the OWASP posture for DOCTYPE-bearing formats: the DOCTYPE line real OEWN releases ship is tokenized and skipped while external entities and the external DTD subset stay fully disabled, so an unmodified download parses directly; a dedicated test proves a DOCTYPE-declared internal-subset entity payload fails loud rather than expanding.WndbReader: a reader for legacy Princeton WNDB directories, validating the format's documented offset contract.Both produce equivalent immutable, thread-safe lexicon views, pinned by a structural equivalence test over matching miniature fixtures. On top of the seam,
MorphyLemmatizerimplements the existingLemmatizerinterface with the documented Morphy algorithm: exception-list lookup first, then per-POS detachment rules with every candidate validated against the lexicon.Naming: the seam interface is
LexicalKnowledgeBaserather than a WordNet-branded name; the contract is generic and only the format-specific readers carry the WordNet name.The module ships code only; users point it at a WordNet database they downloaded. Verified against Princeton 3.0 (117,659 synsets) and OEWN 2024 (120,630 synsets). No third-party WordNet library is used or referenced.
Verification: api 303/0 (+17), opennlp-wordnet 86/0, full reactor verify green.
Small upstream note found along the way:
DictionaryLemmatizerjavadoc says unknown = "0" but the code returns the letter "O"; Morphy matches the code. Filed separately.https://issues.apache.org/jira/browse/OPENNLP-1880