Parametrization-for-Z-Axis-Solution.java Subtyping-for-Z-Axis-Solution.java
1import java.util.List;1import java.util.List;
2import java.util.Locale;2import java.util.Locale;
3import java.util.stream.Stream;3import java.util.stream.Stream;
44
5/* ****************************************5/* ****************************************
6 * 1) CORE LANGUAGE-SPECIFIC TYPES (AXIS Z)6 * 1) CORE LANGUAGE-SPECIFIC TYPES (AXIS Z)
7 ******************************************/7 ******************************************/
88
9/*9/*
10 * 1.A) PART OF SPEECH10 * 1.A) PART OF SPEECH
11 * https://en.wikipedia.org/wiki/Part_of_speech11 * https://en.wikipedia.org/wiki/Part_of_speech
12 */12 */
1313
14//14//
15// 1.A.I) ENGLISH PART OF SPEECH15// 1.A.I) ENGLISH PART OF SPEECH
16//16//
1717
18/**18/**
19 * Implementing classes consist of one or more part-of-speech tags (each tag provided by a different tagger).19 * Implementing classes consist of one or more part-of-speech tags (each tag provided by a different tagger).
20 */20 */
21interface PartOfSpeech {21interface PartOfSpeech {
22}22}
2323
24class EnglishPartOfSpeech implements PartOfSpeech {24class EnglishPartOfSpeech implements PartOfSpeech {
25    private final Type1EnglishTag type1Tag = Type1EnglishTag.TO; // SIMPLIFICATION25    private final Type1EnglishTag type1Tag = Type1EnglishTag.TO; // SIMPLIFICATION
26    private final Type2EnglishTag type2Tag = Type2EnglishTag.GENERAL_PREPOSITION; // SIMPLIFICATION26    private final Type2EnglishTag type2Tag = Type2EnglishTag.GENERAL_PREPOSITION; // SIMPLIFICATION
2727
28    boolean isInfinitiveMarker() {28    boolean isInfinitiveMarker() {
29        return type1Tag == Type1EnglishTag.TO && type2Tag == Type2EnglishTag.INFINITIVE_MARKER;29        return type1Tag == Type1EnglishTag.TO && type2Tag == Type2EnglishTag.INFINITIVE_MARKER;
30    }30    }
31}31}
3232
33enum Type1EnglishTag {33enum Type1EnglishTag {
34    // SIMPLIFICATION (partial content)34    // SIMPLIFICATION (partial content)
35    TO // "to" as a preposition or an infinitive marker35    TO // "to" as a preposition or an infinitive marker
36}36}
3737
38enum Type2EnglishTag {38enum Type2EnglishTag {
39    // SIMPLIFICATION (partial content)39    // SIMPLIFICATION (partial content)
40    GENERAL_PREPOSITION, // e.g. "to" in "I said to him that..."40    GENERAL_PREPOSITION, // e.g. "to" in "I said to him that..."
41    INFINITIVE_MARKER // "to", e.g. in "I want to ask."41    INFINITIVE_MARKER // "to", e.g. in "I want to ask."
42}42}
4343
44//44//
45// 1.A.II) GERMAN PART OF SPEECH45// 1.A.II) GERMAN PART OF SPEECH
46//46//
4747
48class GermanPartOfSpeech implements PartOfSpeech {48class GermanPartOfSpeech implements PartOfSpeech {
49    private final Type1GermanTag type1Tag = Type1GermanTag.POSTPOSITION; // SIMPLIFICATION49    private final Type1GermanTag type1Tag = Type1GermanTag.POSTPOSITION; // SIMPLIFICATION
5050
51    boolean isPostposition() {51    boolean isPostposition() {
52        return type1Tag == Type1GermanTag.POSTPOSITION;52        return type1Tag == Type1GermanTag.POSTPOSITION;
53    }53    }
54}54}
5555
56enum Type1GermanTag {56enum Type1GermanTag {
57    // SIMPLIFICATION (partial content)57    // SIMPLIFICATION (partial content)
58    POSTPOSITION, // e.g. "zufolge"58    POSTPOSITION, // e.g. "zufolge"
59}59}
6060
61/*61/*
62 * 1.B) CONSTITUENT62 * 1.B) CONSTITUENT
63 * https://en.wikipedia.org/wiki/Phrase_structure_grammar63 * https://en.wikipedia.org/wiki/Phrase_structure_grammar
64 */64 */
65interface ConstituentType {65interface ConstituentType {
66}66}
6767
68enum EnglishConstituentType implements ConstituentType {68enum EnglishConstituentType implements ConstituentType {
69    // SIMPLIFICATION (partial content)69    // SIMPLIFICATION (partial content)
70    VERB_PHRASE, // e.g. "is doing nice"70    VERB_PHRASE, // e.g. "is doing nice"
71    WH_WORD_NOUN_PHRASE // e.g. "whose daughter"71    WH_WORD_NOUN_PHRASE // e.g. "whose daughter"
72}72}
7373
74// enum GermanConstituentType missing as of yet74// enum GermanConstituentType missing as of yet
7575
76/*76/*
77 * 1.C) DEPENDENCY77 * 1.C) DEPENDENCY
78 * https://en.wikipedia.org/wiki/Dependency_grammar78 * https://en.wikipedia.org/wiki/Dependency_grammar
79 */79 */
80interface DependencyType {80interface DependencyType {
81}81}
8282
83enum EnglishDependencyType implements DependencyType {83enum EnglishDependencyType implements DependencyType {
84    // SIMPLIFICATION (partial content)84    // SIMPLIFICATION (partial content)
85    NOMINAL_SUBJECT, // e.g. "he" <- "walks" in "He walks."85    NOMINAL_SUBJECT, // e.g. "he" <- "walks" in "He walks."
86    PHRASAL_VERB_PARTICLE // e.g. "shut" -> "down" in "It was shut down."86    PHRASAL_VERB_PARTICLE // e.g. "shut" -> "down" in "It was shut down."
87}87}
8888
89// enum GermanDependencyType missing as of yet89// enum GermanDependencyType missing as of yet
9090
91/* ***************91/* ***************
92 * 2) HELPER TYPES92 * 2) HELPER TYPES
93 *****************/93 *****************/
94interface TextualRange {94interface TextualRange {
95    String text();95    String text();
9696
97    int startOffset(); // inclusive97    int startOffset(); // inclusive
9898
99    int endOffset(); // exclusive99    int endOffset(); // exclusive
100}100}
101101
102interface Seq {102interface Seq {
103103
104    /**104    /**
105     * Stub for <a href="https://www.jooq.org/products/jOOλ/javadoc/0.9.12/org/jooq/lambda/Seq.html#ofType-java.util.str
eam.Stream-java.lang.Class-">Seq.ofType()</a>.
105     * Stub for <a href="https://www.jooq.org/products/jOOλ/javadoc/0.9.12/org/jooq/lambda/Seq.html#ofType-java.util.str
eam.Stream-java.lang.Class-">Seq.ofType()</a>.
106     */106     */
107    @SuppressWarnings("unchecked")107    @SuppressWarnings("unchecked")
108    static <T, U> Stream<U> ofType(Stream<? extends T> stream, Class<? extends U> type) {108    static <T, U> Stream<U> ofType(Stream<? extends T> stream, Class<? extends U> type) {
109        return stream.filter(type::isInstance).map(t -> (U) t);109        return stream.filter(type::isInstance).map(t -> (U) t);
110    }110    }
111}111}
112112
113/**113/**
114 * Defines the stage of text processing (AXIS Y).114 * Defines the stage of text processing (AXIS Y).
115 */115 */
116enum Stage {116enum Stage {
117    UNPROCESSED,117    UNPROCESSED,
118    TOKENIZED, // tokens present118    TOKENIZED, // tokens present
119    SENTENCIZED, // sentences present119    SENTENCIZED, // sentences present
120    TAGGED, // parts of speech present120    TAGGED, // parts of speech present
121    PARSED // syntax present121    PARSED // syntax present
122}122}
123123
124/* ***************************124/* ***************************
125 * 3) SOLUTION USING SUBTYPING125 * 3) SOLUTION USING SUBTYPING
126 *****************************/126 *****************************/
127127
128/*128/*
129 * 3.A) GENERIC HIERARCHY (AXIS Y OVER X)129 * 3.A) GENERIC HIERARCHY (AXIS Y OVER X)
130 */130 */
131131
132//132//
133// 3.A.I) UNPROCESSED133// 3.A.I) UNPROCESSED
134//134//
135interface LocalizedText extends TextualRange {135interface LocalizedText extends TextualRange {
136    Locale locale();136    Locale locale();
137137
138    default Stage maxStage() {138    default Stage maxStage() {
139        return Stage.UNPROCESSED;139        return Stage.UNPROCESSED;
140    }140    }
141}141}
142142
143//143//
144// 3.A.II) WITH TOKENS144// 3.A.II) WITH TOKENS
145//145//
146enum TokenType {146enum TokenType {
147    WORD, NUMERIC // SIMPLIFICATION147    WORD, NUMERIC // SIMPLIFICATION
148}148}
149149
150interface Token extends TextualRange {150interface Token extends TextualRange {
151    TokenType tokenType();151    TokenType tokenType();
152}152}
153153
154interface TokenizedText extends LocalizedText {154interface TokenizedText extends LocalizedText {
155    Stream<? extends Token> tokenStream();155    Stream<? extends Token> tokenStream();
156156
157    int tokenCount();157    int tokenCount();
158158
159    @Override159    @Override
160    default Stage maxStage() {160    default Stage maxStage() {
161        return Stage.TOKENIZED;161        return Stage.TOKENIZED;
162    }162    }
163}163}
164164
165//165//
166// 3.A.III) WITH SENTENCES166// 3.A.III) WITH SENTENCES
167//167//
168interface Sentence extends TextualRange {168interface Sentence extends TextualRange {
169    List<? extends Token> tokens();169    List<? extends Token> tokens();
170170
171    default Stage stage() {171    default Stage stage() {
172        return Stage.SENTENCIZED;172        return Stage.SENTENCIZED;
173    }173    }
174}174}
175175
176interface SentencizedText extends TokenizedText {176interface SentencizedText extends TokenizedText {
177    List<? extends Sentence> sentences();177    List<? extends Sentence> sentences();
178178
179    @Override179    @Override
180    default Stage maxStage() {180    default Stage maxStage() {
181        return Stage.SENTENCIZED;181        return Stage.SENTENCIZED;
182    }182    }
183}183}
184184
185//185//
186// 3.A.IV) WITH PARTS OF SPEECH186// 3.A.IV) WITH PARTS OF SPEECH
187//187//
188interface TaggedToken<P extends PartOfSpeech> extends Token {188interface TaggedToken extends Token {
189    P partOfSpeech(); // see section 1.A above189    PartOfSpeech partOfSpeech(); // see section 1.A above
190}190}
191191
192interface TaggedSentence<P extends PartOfSpeech> extends Sentence {192interface TaggedSentence extends Sentence {
193    @Override193    @Override
194    List<? extends TaggedToken<P>> tokens();194    List<? extends TaggedToken> tokens();
195195
196    @Override196    @Override
197    default Stage stage() {197    default Stage stage() {
198        return Stage.TAGGED;198        return Stage.TAGGED;
199    }199    }
200}200}
201201
202interface TaggedText<P extends PartOfSpeech> extends SentencizedText {202interface TaggedText extends SentencizedText {
203    // some (or even all) sentences may remain untagged203    // some (or even all) sentences may remain untagged
204    Stream<? extends TaggedSentence<P>> taggedSentenceStream();204    Stream<? extends TaggedSentence> taggedSentenceStream();
205205
206    @Override206    @Override
207    default Stage maxStage() {207    default Stage maxStage() {
208        return Stage.TAGGED;208        return Stage.TAGGED;
209    }209    }
210}210}
211211
212//212//
213// 3.A.V) WITH SYNTAX213// 3.A.V) WITH SYNTAX
214//214//
215interface Constituent<C extends ConstituentType, P extends PartOfSpeech> {215interface Constituent {
216    Stream<? extends Constituent<C, P>> childStream();216    Stream<? extends Constituent> childStream();
217}217}
218218
219interface ConstituentBranch<C extends ConstituentType, P extends PartOfSpeech> extends Constituent<C, P> {219interface ConstituentBranch extends Constituent {
220    C type(); // see section 1.B above220    ConstituentType type(); // see section 1.B above
221}221}
222222
223interface ConstituentLeaf<C extends ConstituentType, P extends PartOfSpeech> extends Constituent<C, P> {223interface ConstituentLeaf extends Constituent {
224    TaggedToken<P> token();224    TaggedToken token();
225225
226    @Override226    @Override
227    default Stream<? extends Constituent<C, P>> childStream() {227    default Stream<? extends Constituent> childStream() {
228        return Stream.empty();228        return Stream.empty();
229    }229    }
230}230}
231231
232interface Dependency<D extends DependencyType, P extends PartOfSpeech> {232interface Dependency {
233    D type(); // see section 1.C above233    DependencyType type(); // see section 1.C above
234234
235    TaggedToken<P> governor();235    TaggedToken governor();
236236
237    TaggedToken<P> dependent();237    TaggedToken dependent();
238}238}
239239
240interface SentenceSyntax<C extends ConstituentType, D extends DependencyType, P extends PartOfSpeech> {240interface SentenceSyntax {
241    ConstituentBranch<C, P> constituentTree();241    ConstituentBranch constituentTree();
242242
243    List<? extends Dependency<D, P>> dependencies();243    List<? extends Dependency> dependencies();
244}244}
245245
246interface ParsedSentence<C extends ConstituentType, D extends DependencyType, P extends PartOfSpeech> extends TaggedSent
ence<P> {
246interface ParsedSentence extends TaggedSentence {
247    SentenceSyntax<C, D, P> syntax();247    SentenceSyntax syntax();
248248
249    @Override249    @Override
250    default Stage stage() {250    default Stage stage() {
251        return Stage.PARSED;251        return Stage.PARSED;
252    }252    }
253}253}
254254
255interface ParsedText<C extends ConstituentType, D extends DependencyType, P extends PartOfSpeech> extends TaggedText<P> 
{
255interface ParsedText extends TaggedText {
256    // some (or even all) sentences may remain unparsed256    // some (or even all) sentences may remain unparsed
257    Stream<? extends ParsedSentence<C, D, P>> parsedSentenceStream();257    Stream<? extends ParsedSentence> parsedSentenceStream();
258258
259    @Override259    @Override
260    default Stage maxStage() {260    default Stage maxStage() {
261        return Stage.PARSED;261        return Stage.PARSED;
262    }262    }
263}263}
264264
265/*
266 * 3.B) LANGUAGE-SPECIFIC HIERARCHY (AXIS Z OVER Y OVER X)
267 */
268
269//
270// 3.B.I) ENGLISH
271//
272
273// 3.B.I.a) ENGLISH PARTS OF SPEECH
274interface EnglishTaggedToken extends TaggedToken {
275    @Override
276    EnglishPartOfSpeech partOfSpeech();
277}
278
279interface EnglishTaggedSentence extends TaggedSentence {
280    @Override
281    List<? extends EnglishTaggedToken> tokens();
282}
283
284interface EnglishTaggedText extends TaggedText {
285    @Override // some (or even all) sentences may remain untagged
286    default Stream<? extends EnglishTaggedSentence> taggedSentenceStream() {
287        return Seq.ofType(sentences().stream(), EnglishTaggedSentence.class);
288    }
289}
290
291// 3.B.I.b) ENGLISH SYNTAX
292interface EnglishConstituent extends Constituent {
293    @Override
294    Stream<? extends EnglishConstituent> childStream();
295}
296
297interface EnglishConstituentBranch extends EnglishConstituent, ConstituentBranch {
298    @Override
299    EnglishConstituentType type();
300}
301
302interface EnglishConstituentLeaf extends EnglishConstituent, ConstituentLeaf {
303    @Override
304    EnglishTaggedToken token();
305
306    @Override
307    default Stream<? extends EnglishConstituent> childStream() {
308        return Stream.empty();
309    }
310}
311
312interface EnglishDependency extends Dependency {
313    @Override
314    EnglishDependencyType type();
315
316    @Override
317    EnglishTaggedToken governor();
318
319    @Override
320    EnglishTaggedToken dependent();
321}
322
323interface EnglishSentenceSyntax extends SentenceSyntax {
324    @Override
325    EnglishConstituentBranch constituentTree();
326
327    @Override
328    List<? extends EnglishDependency> dependencies();
329}
330
331interface EnglishParsedSentence extends EnglishTaggedSentence, ParsedSentence {
332    @Override
333    EnglishSentenceSyntax syntax();
334}
335
336interface EnglishParsedText extends EnglishTaggedText, ParsedText {
337    @Override // some (or even all) sentences may remain unparsed
338    default Stream<? extends EnglishParsedSentence> parsedSentenceStream() {
339        return Seq.ofType(sentences().stream(), EnglishParsedSentence.class);
340    }
341}
342
343//
344// 3.B.II) GERMAN
345//
346
347// 3.B.II.a) GERMAN PARTS OF SPEECH
348interface GermanTaggedToken extends TaggedToken {
349    @Override
350    GermanPartOfSpeech partOfSpeech();
351}
352
353interface GermanTaggedSentence extends TaggedSentence {
354    @Override
355    List<? extends GermanTaggedToken> tokens();
356}
357
358interface GermanTaggedText extends TaggedText {
359    @Override
360    default Stream<? extends GermanTaggedSentence> taggedSentenceStream() {
361        return Seq.ofType(sentences().stream(), GermanTaggedSentence.class);
362    }
363}
364
365// 3.B.II.b) GERMAN SYNTAX (missing as of yet)
366
367
265/* ***********************368/* ***********************
266 * 4) PRODUCERS OF THE API369 * 4) PRODUCERS OF THE API
267 *************************/370 *************************/
268371
269interface TextProcessingRequest { // SIMPLIFICATION372interface TextProcessingRequest { // SIMPLIFICATION
270    Locale locale();373    Locale locale();
271374
272    String text();375    String text();
273376
274    Stage targetStage();377    Stage targetStage();
275}378}
276379
277interface TextProcessor {380interface TextProcessor {
278    LocalizedText processText(TextProcessingRequest request);381    LocalizedText processText(TextProcessingRequest request);
279}382}
280383
281/* ***********************384/* ***********************
282 * 5) CONSUMERS OF THE API385 * 5) CONSUMERS OF THE API
283 *************************/386 *************************/
284387
285/*388/*
286 * 5.A) DIRECT CONSUMERS389 * 5.A) DIRECT CONSUMERS
287 */390 */
288391
289class GermanPostpositionChecker {392class GermanPostpositionChecker {
290    void checkTaggedText(TaggedText<GermanPartOfSpeech> text) {393    void checkTaggedText(GermanTaggedText text) {
291        text.taggedSentenceStream().forEach(this::checkTaggedSentence);394        text.taggedSentenceStream().forEach(this::checkTaggedSentence);
292    }395    }
293396
294    private void checkTaggedSentence(TaggedSentence<GermanPartOfSpeech> sentence) {397    private void checkTaggedSentence(GermanTaggedSentence sentence) {
295        sentence.tokens().stream()398        sentence.tokens().stream()
296                .filter(this::isPostposition)399                .filter(this::isPostposition)
297                .forEach(this::checkPostposition);400                .forEach(this::checkPostposition);
298    }401    }
299402
300    private boolean isPostposition(TaggedToken<GermanPartOfSpeech> token) {403    private boolean isPostposition(GermanTaggedToken token) {
301        return token.partOfSpeech().isPostposition();404        return token.partOfSpeech().isPostposition();
302    }405    }
303406
304407
305    private void checkPostposition(TaggedToken<GermanPartOfSpeech> token) {408    private void checkPostposition(GermanTaggedToken token) {
306        // logic409        // logic
307    }410    }
308}411}
309412
310class EnglishNominalSubjectChecker {413class EnglishNominalSubjectChecker {
311414
312    void checkNominalSubjects(ParsedText<?, EnglishDependencyType, EnglishPartOfSpeech> text) {415    void checkNominalSubjects(EnglishParsedText text) {
313        text.parsedSentenceStream().forEach(this::checkNominalSubjects);416        text.parsedSentenceStream().forEach(this::checkNominalSubjects);
314    }417    }
315418
316    private void checkNominalSubjects(ParsedSentence<?, EnglishDependencyType, EnglishPartOfSpeech> sentence) {419    private void checkNominalSubjects(EnglishParsedSentence sentence) {
317        sentence.syntax().dependencies().stream()420        sentence.syntax().dependencies().stream()
318                .filter(this::isCertainTypeOfNominalSubjectDependency)421                .filter(this::isCertainTypeOfNominalSubjectDependency)
319                .forEach(this::checkNominalSubject);422                .forEach(this::checkNominalSubject);
320    }423    }
321424
322    private boolean isCertainTypeOfNominalSubjectDependency(Dependency<EnglishDependencyType, EnglishPartOfSpeech> depen
dency) {
425    private boolean isCertainTypeOfNominalSubjectDependency(EnglishDependency dependency) {
323        return dependency.type() == EnglishDependencyType.NOMINAL_SUBJECT && true; // SIMPLIFICATION426        return dependency.type() == EnglishDependencyType.NOMINAL_SUBJECT && true; // SIMPLIFICATION
324    }427    }
325428
326    private void checkNominalSubject(Dependency<EnglishDependencyType, EnglishPartOfSpeech> dependency) {429    private void checkNominalSubject(EnglishDependency dependency) {
327        checkNominalGovernor(dependency.governor());430        checkNominalGovernor(dependency.governor());
328        checkNominalDependent(dependency.dependent());431        checkNominalDependent(dependency.dependent());
329    }432    }
330433
331    private void checkNominalGovernor(TaggedToken<EnglishPartOfSpeech> governor) {434    private void checkNominalGovernor(EnglishTaggedToken governor) {
332        if (checkGovernorPartOfSpeech(governor.partOfSpeech())) {435        if (checkGovernorPartOfSpeech(governor.partOfSpeech())) {
333            // logic436            // logic
334        }437        }
335    }438    }
336439
337    private void checkNominalDependent(TaggedToken<EnglishPartOfSpeech> dependent) {440    private void checkNominalDependent(EnglishTaggedToken dependent) {
338        if (checkDependentPartOfSpeech(dependent.partOfSpeech())) {441        if (checkDependentPartOfSpeech(dependent.partOfSpeech())) {
339            // logic442            // logic
340        }443        }
341    }444    }
342445
343    private boolean checkGovernorPartOfSpeech(EnglishPartOfSpeech partOfSpeech) {446    private boolean checkGovernorPartOfSpeech(EnglishPartOfSpeech partOfSpeech) {
344        return true; // SIMPLIFICATION447        return true; // SIMPLIFICATION
345    }448    }
346449
347    private boolean checkDependentPartOfSpeech(EnglishPartOfSpeech partOfSpeech) {450    private boolean checkDependentPartOfSpeech(EnglishPartOfSpeech partOfSpeech) {
348        return true; // SIMPLIFICATION451        return true; // SIMPLIFICATION
349    }452    }
350}453}
351454
352class EnglishRelevantConstituentHandler {455class EnglishRelevantConstituentHandler {
353456
354    void handleRelevantConstituents(ParsedText<EnglishConstituentType, ?, EnglishPartOfSpeech> text) {457    void handleRelevantConstituents(EnglishParsedText text) {
355        text.parsedSentenceStream().forEach(this::handleRelevantConstiuents);458        text.parsedSentenceStream().forEach(this::handleRelevantConstiuents);
356    }459    }
357460
358    private void handleRelevantConstiuents(ParsedSentence<EnglishConstituentType, ?, EnglishPartOfSpeech> sentence) {461    private void handleRelevantConstiuents(EnglishParsedSentence sentence) {
359        Constituents.flatConstituentStream(sentence.syntax().constituentTree())462        EnglishConstituents.flatConstituentStream(sentence.syntax().constituentTree())
360                .filter(this::isRelevantConstituent)463                .filter(this::isRelevantConstituent)
361                .forEach(this::handleRelevantConstituent);464                .forEach(this::handleRelevantConstituent);
362    }465    }
363466
364    private boolean isRelevantConstituent(Constituent<EnglishConstituentType, EnglishPartOfSpeech> constituent) {467    private boolean isRelevantConstituent(EnglishConstituent constituent) {
365        return true; // SIMPLIFICATION468        return true; // SIMPLIFICATION
366    }469    }
367470
368    private void handleRelevantConstituent(Constituent<EnglishConstituentType, EnglishPartOfSpeech> constituent) {471    private void handleRelevantConstituent(EnglishConstituent constituent) {
369        // logic472        // logic
370    }473    }
371}474}
372475
373class Constituents {476class EnglishConstituents {
374    /**477    /**
375     * Returns the constituent and all its descendants as a flattended Stream.478     * Returns the constituent and all its descendants as a flattended Stream.
376     */479     */
377    static <C extends ConstituentType, P extends PartOfSpeech> Stream<Constituent<C, P>> flatConstituentStream(Constitue
nt<C, P> constituent) {
480    static Stream<EnglishConstituent> flatConstituentStream(EnglishConstituent constituent) {
378        return Stream.concat(481        return Stream.concat(
379                Stream.of(constituent),482                Stream.of(constituent),
380                constituent.childStream().flatMap(Constituents::flatConstituentStream)483                constituent.childStream().flatMap(EnglishConstituents::flatConstituentStream)
381        );484        );
382    }485    }
383}486}
384487
385488
386/*489/*
387 * 5.B) INDIRECT CONSUMERS490 * 5.B) INDIRECT CONSUMERS
388 */491 */
389interface ProcessedTextConsumer { // SIMPLIFICATION492interface ProcessedTextConsumer { // SIMPLIFICATION
390    Locale supportedLocale();493    Locale supportedLocale();
391494
392    Stage requiredStage();495    Stage requiredStage();
393496
394    void consume(LocalizedText text);497    void consume(LocalizedText text);
395}498}
396499
397class SampleUniversalTokenizedTextConsumer implements ProcessedTextConsumer {500class SampleUniversalTokenizedTextConsumer implements ProcessedTextConsumer {
398501
399    @Override502    @Override
400    public Locale supportedLocale() {503    public Locale supportedLocale() {
401        return Locale.ROOT;504        return Locale.ROOT;
402    }505    }
403506
404    @Override507    @Override
405    public Stage requiredStage() {508    public Stage requiredStage() {
406        return Stage.TOKENIZED;509        return Stage.TOKENIZED;
407    }510    }
408511
409    @Override512    @Override
410    public void consume(LocalizedText text) {513    public void consume(LocalizedText text) {
411        handleTokenizedText((TokenizedText) text);514        handleTokenizedText((TokenizedText) text);
412    }515    }
413516
414    private void handleTokenizedText(TokenizedText tokenizedText) {517    private void handleTokenizedText(TokenizedText tokenizedText) {
415        // logic518        // logic
416    }519    }
417}520}
418521
419class SampleGermanTaggedConsumer implements ProcessedTextConsumer {522class SampleGermanTaggedConsumer implements ProcessedTextConsumer {
420523
421    @Override524    @Override
422    public Locale supportedLocale() {525    public Locale supportedLocale() {
423        return Locale.GERMAN;526        return Locale.GERMAN;
424    }527    }
425528
426    @Override529    @Override
427    public Stage requiredStage() {530    public Stage requiredStage() {
428        return Stage.TAGGED;531        return Stage.TAGGED;
429    }532    }
430533
431    @Override534    @Override
432    public void consume(LocalizedText text) {535    public void consume(LocalizedText text) {
433        // UNSAFE UNCHECKED CAST!536        GermanTaggedText germanTaggedText = (GermanTaggedText) text; // SAFE CAST
434        TaggedText<GermanPartOfSpeech> germanTaggedText = (TaggedText<GermanPartOfSpeech>) text;
435        new GermanPostpositionChecker().checkTaggedText(germanTaggedText);537        new GermanPostpositionChecker().checkTaggedText(germanTaggedText);
436    }538    }
437}539}
438540
439class SampleEnglishParsedTextConsumer implements ProcessedTextConsumer {541class SampleEnglishParsedTextConsumer implements ProcessedTextConsumer {
440542
441    @Override543    @Override
442    public Locale supportedLocale() {544    public Locale supportedLocale() {
443        return Locale.ENGLISH;545        return Locale.ENGLISH;
444    }546    }
445547
446    @Override548    @Override
447    public Stage requiredStage() {549    public Stage requiredStage() {
448        return Stage.PARSED;550        return Stage.PARSED;
449    }551    }
450552
451    @Override553    @Override
452    public void consume(LocalizedText text) {554    public void consume(LocalizedText text) {
453        // UNSAFE UNCHECKED CAST!555        EnglishParsedText englishParsedText = (EnglishParsedText) text; // SAFE CAST
454        ParsedText<?, EnglishDependencyType, EnglishPartOfSpeech> englishParsedText
455                = (ParsedText<?, EnglishDependencyType, EnglishPartOfSpeech>) text;
456        new EnglishNominalSubjectChecker().checkNominalSubjects(englishParsedText);556        new EnglishNominalSubjectChecker().checkNominalSubjects(englishParsedText);
457    }557    }
458}558}
459559
460560