package org.sotnya.lemmatizer.uk.engine;

import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.elasticsearch.common.logging.ESLogger;
import org.elasticsearch.common.logging.ESLoggerFactory;

import java.io.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * Class to serve purposes of term-to-lemma substitution.
 * Handles mapping retrieval, terms normalisation and lookup for proper lemmas in mapping.
 */
public class UkrainianLemmatizer {
    private static final ESLogger logger = ESLoggerFactory.getLogger(UkrainianLemmatizer.class.getSimpleName());
    private static final Map<String, String> dictionary;
    /**
     * Before the lookup we replace some symbols to their alternatives are being used in mapping.
     * Right now there is the single substitution case: ukrainian apostrophes with to english single quote.
     */
    private static final Map<Character, Character> replaceItems = new HashMap<Character, Character>(2) {{
        put('’', '\'');
        put('ʼ', '\'');
    }};
    /**
     * Ignore stress symbol
     */
    private static final String[] IGNORE_CHARS = new String[] { "\u0301" };


    static {
        // load mapping from file (must be changed to faster and memory-efficient type)
        final String fileName = "mapping_sorted.csv";
        final String separator = ",";
        final ClassLoader loader = UkrainianLemmatizer.class.getClassLoader();

        logger.debug("Started loading dictionary");

        try (BufferedReader reader = new BufferedReader(new InputStreamReader(loader.getResourceAsStream(fileName), "UTF8"))) {
            dictionary = reader.lines()
                    .map(line -> line.split(separator))
                    .collect(Collectors.toMap(p -> p[0], p -> p[1]));
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }

        logger.debug(String.format("Finished loading dictionary. %d entities delivered gently.", dictionary.size()));
        // Let's wait some additional second but we'll keep our heap clean from
        // lots of short-lived objects created during the loading.
        System.gc();
    }

    /**
     * @param termAtt Token (word) we should compare with existing in our dictionary.
     *
     * @return Optional value which is defined in case if we have related lemma in dict.
     */
    public Optional<CharSequence> lemmatize(CharTermAttribute termAtt) {
        String term = termAtt.toString();

        for (Map.Entry<Character, Character> e : replaceItems.entrySet()) {
            if( term.indexOf(e.getKey()) != -1 ) {
                term = term.replace(e.getKey(), e.getValue());
            }
        }

        for (String ignoreChar: IGNORE_CHARS) {
            if( term.contains(ignoreChar) ) {
                term = term.replace(ignoreChar, "");
            }
        }

        return dictionary.containsKey(term) ? Optional.of(dictionary.get(term)) : Optional.empty();
    }
}
@@ -1049,9 +1049,14 @@
 ut('
-%E2%80%99
+%5Cu2019
 ', '
@@ -1078,9 +1078,14 @@
 ut('
-%CA%BC
+%5Cu02BC
 ', '
@@ -1098,16 +1098,17 @@
     %7D%7D;%0A
+%0A
     /**%0A
@@ -1206,16 +1206,24 @@
 ring%5B%5D %7B
+%0A       
  %22%5Cu0301
@@ -1223,16 +1223,20 @@
 %22%5Cu0301%22
+%0A   
  %7D;%0A%0A%0A  
@@ -2632,63 +2632,8 @@
 ) %7B%0A
-            if( term.indexOf(e.getKey()) != -1 ) %7B%0A    
     
@@ -2687,30 +2687,16 @@
 lue());%0A
-            %7D%0A
         

remove unhelful if statement; use codes for unicode apostrophes