// Path: src/main/java/org/oscii/lex/Expression.java
// public class Expression {
//     public final String text;
//     public final String degraded_text; // Lowercased, etc.
//     public final String language; // ISO-639-1 code (2-letter), e.g., "zh"
//     // Tag inventory: http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
//     public String languageTag; // RFC5654 language tag, e.g., "zh-cmn-Hans-CN"
//     public final String source;
// 
//     public Expression(String text, String degraded_text, String languageTag) {
//         this(text, degraded_text, languageTag, "");
//     }
// 
//     public Expression(String text, String degraded_text, String languageTag, String source) {
//         this.text = text;
//         this.degraded_text = degraded_text == null ? Lexicon.degrade(text) : degraded_text;
//         this.languageTag = languageTag;
//         // TODO(denero) Split language tag to open language
//         this.language = languageTag;
//         this.source = source;
//     }
// 
//     public Expression(String text, String languageTag) {
//         this(text, Lexicon.degrade(text), languageTag);
//     }
// 
//     @Override
//     public String toString() {
//         return "Expression{" +
//                 "text='" + text + '\'' +
//                 "language='" + language + '\'' +
//                 "source='" + source + '\'' +
//                 '}';
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Expression that = (Expression) o;
// 
//         if (!language.equals(that.language)) return false;
//         if (!text.equals(that.text)) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = text.hashCode();
//         result = 31 * result + language.hashCode();
//         return result;
//     }
// }
// 
// Path: src/main/java/org/oscii/lex/Meaning.java
// public class Meaning {
//     public final Expression expression;
//     public final List<String> pos = new ArrayList<>();
//     public final List<Definition> definitions = new ArrayList<>();
//     public final List<Translation> translations = new ArrayList<>();
//     public final List<Expression> synonyms = new ArrayList<>();
// 
//     @Override
//     public String toString() {
//         return "Meaning{" +
//                 "expression=" + expression +
//                 ", definitions=" + definitions +
//                 ", translations=" + translations +
//                 '}';
//     }
// 
//     public Meaning(Expression expression) {
//         this.expression = expression;
//     }
// }


import gnu.trove.THashMap;
import org.oscii.lex.Expression;
import org.oscii.lex.Meaning;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toMap;
package org.oscii.concordance;




/**
 * Interface to access corpus statistics and examples
 */
public abstract class AlignedCorpus {
    static ParallelFiles paths(String path, String sourceLanguage, String targetLanguage) {
        Function<String, Path> p = ext -> Paths.get(String.format("%s.%s-%s.%s", path, sourceLanguage, targetLanguage, ext));
        return new ParallelFiles(p.apply(sourceLanguage), p.apply(targetLanguage), p.apply("align"));
    }

    public boolean exists(String path, String sourceLanguage, String targetLanguage) {
        return paths(path, sourceLanguage, targetLanguage).stream().allMatch(Files::exists);
    }

    /*
     * Read parallel files.
     */
    public abstract void read(String path, String sourceLanguage, String targetLanguage, int max) throws IOException;

    /*
     * Return a function that takes phrases in another language and returns translation frequencies.
     */
    public abstract Function<Expression, Double> translationFrequencies(Expression source);

    /*
     * Score a meaning for the purpose of ranking.
     */
// Path: src/main/java/org/oscii/lex/Expression.java
// public class Expression {
//     public final String text;
//     public final String degraded_text; // Lowercased, etc.
//     public final String language; // ISO-639-1 code (2-letter), e.g., "zh"
//     // Tag inventory: http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
//     public String languageTag; // RFC5654 language tag, e.g., "zh-cmn-Hans-CN"
//     public final String source;
// 
//     public Expression(String text, String degraded_text, String languageTag) {
//         this(text, degraded_text, languageTag, "");
//     }
// 
//     public Expression(String text, String degraded_text, String languageTag, String source) {
//         this.text = text;
//         this.degraded_text = degraded_text == null ? Lexicon.degrade(text) : degraded_text;
//         this.languageTag = languageTag;
//         // TODO(denero) Split language tag to open language
//         this.language = languageTag;
//         this.source = source;
//     }
// 
//     public Expression(String text, String languageTag) {
//         this(text, Lexicon.degrade(text), languageTag);
//     }
// 
//     @Override
//     public String toString() {
//         return "Expression{" +
//                 "text='" + text + '\'' +
//                 "language='" + language + '\'' +
//                 "source='" + source + '\'' +
//                 '}';
//     }
// 
//     @Override
//     public boolean equals(Object o) {
//         if (this == o) return true;
//         if (o == null || getClass() != o.getClass()) return false;
// 
//         Expression that = (Expression) o;
// 
//         if (!language.equals(that.language)) return false;
//         if (!text.equals(that.text)) return false;
// 
//         return true;
//     }
// 
//     @Override
//     public int hashCode() {
//         int result = text.hashCode();
//         result = 31 * result + language.hashCode();
//         return result;
//     }
// }
// 
// Path: src/main/java/org/oscii/lex/Meaning.java
// public class Meaning {
//     public final Expression expression;
//     public final List<String> pos = new ArrayList<>();
//     public final List<Definition> definitions = new ArrayList<>();
//     public final List<Translation> translations = new ArrayList<>();
//     public final List<Expression> synonyms = new ArrayList<>();
// 
//     @Override
//     public String toString() {
//         return "Meaning{" +
//                 "expression=" + expression +
//                 ", definitions=" + definitions +
//                 ", translations=" + translations +
//                 '}';
//     }
// 
//     public Meaning(Expression expression) {
//         this.expression = expression;
//     }
// }


// Path: src/main/java/org/oscii/concordance/AlignedCorpus.java
import gnu.trove.THashMap;
import org.oscii.lex.Expression;
import org.oscii.lex.Meaning;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Stream;
import static java.util.stream.Collectors.toMap;

package org.oscii.concordance;




/**
 * Interface to access corpus statistics and examples
 */
public abstract class AlignedCorpus {
    static ParallelFiles paths(String path, String sourceLanguage, String targetLanguage) {
        Function<String, Path> p = ext -> Paths.get(String.format("%s.%s-%s.%s", path, sourceLanguage, targetLanguage, ext));
        return new ParallelFiles(p.apply(sourceLanguage), p.apply(targetLanguage), p.apply("align"));
    }

    public boolean exists(String path, String sourceLanguage, String targetLanguage) {
        return paths(path, sourceLanguage, targetLanguage).stream().allMatch(Files::exists);
    }

    /*
     * Read parallel files.
     */
    public abstract void read(String path, String sourceLanguage, String targetLanguage, int max) throws IOException;

    /*
     * Return a function that takes phrases in another language and returns translation frequencies.
     */
    public abstract Function<Expression, Double> translationFrequencies(Expression source);

    /*
     * Score a meaning for the purpose of ranking.
     */
    public void scoreMeaning(Meaning m) {};