code: /* LanguageTool, a natural language style checker
   * Copyright (C) 2014 Daniel Naber (http://www.danielnaber.de)
   *
   * This library is free software; you can redistribute it and/or
   * modify it under the terms of the GNU Lesser General Public
   * License as published by the Free Software Foundation; either
   * version 2.1 of the License, or (at your option) any later version.
   *
   * This library is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   * Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public
   * License along with this library; if not, write to the Free Software
   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
   * USA
   */
  package org.languagetool.tagging;
  
  import morfologik.stemming.Dictionary;
  import morfologik.stemming.*;
  import org.languagetool.JLanguageTool;
  
  import java.io.IOException;
  import java.net.URL;
  import java.util.*;
  
  /**
   * Tags a word using a Morfologik binary dictionary.
   * @since 2.8
   */
  public class MorfologikTagger implements WordTagger {
  
    private final URL dictUrl;
  
    private Dictionary dictionary;
  
    private boolean internTags;
  
    public MorfologikTagger(String dictPath) {
      this(JLanguageTool.getDataBroker().getFromResourceDirAsUrl(Objects.requireNonNull(dictPath)));
    }
  
    MorfologikTagger(URL dictUrl) {
      this.dictUrl = Objects.requireNonNull(dictUrl);
    }
    
    /**
     * Constructs a MorfologikTagger with the given morfologik dictionary.
     * @since 3.4
     */
    public MorfologikTagger(Dictionary dictionary) {
      this(dictionary, false);
    }
  
    public MorfologikTagger(Dictionary dictionary, boolean internTags) {
      this.dictUrl = null;
      this.dictionary = dictionary;
      this.internTags = internTags;
    }
  
    private synchronized Dictionary getDictionary() throws IOException {
      if (dictionary == null) {
        dictionary = Dictionary.read(dictUrl);
      }
      return dictionary;
    }
  
    public boolean getInternTags() {
      return internTags;
    }
  
    public void setInternTags(boolean enabled) {
      internTags = enabled;
    }
  
    @Override
    public List<TaggedWord> tag(String word) {
      List<TaggedWord> result = new ArrayList<>();
      try {
        IStemmer dictLookup = new DictionaryLookup(getDictionary());
        List<WordData> lookup = dictLookup.lookup(word);
        for (WordData wordData : lookup) {
          String tag = wordData.getTag() == null ? null : wordData.getTag().toString();
          // Remove frequency data from tags (if exists)
          // The frequency data is in the last byte (without a separator)
          if (dictionary.metadata.isFrequencyIncluded() && tag != null && tag.length() > 1) {
            tag = tag.substring(0, tag.length() - 1);
          }
          String stem = wordData.getStem() == null ? null : wordData.getStem().toString();
          TaggedWord taggedWord = new TaggedWord(stem, (internTags && tag != null) ? tag.intern() : tag);
          result.add(taggedWord);
        }
      } catch (IOException e) {
        throw new RuntimeException("Could not tag word '" + word + "'", e);
      }
      return result;
    }
  
  }
  