// This file is part of NameTag.
//
// Copyright 2013 by Institute of Formal and Applied Linguistics, Faculty of
// Mathematics and Physics, Charles University in Prague, Czech Republic.
//
// NameTag 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 3 of
// the License, or (at your option) any later version.
//
// NameTag 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 NameTag.  If not, see <http://www.gnu.org/licenses/>.

import cz.cuni.mff.ufal.nametag.*;
import java.util.Scanner;

class RunNer {
  public static void recognizeVertical(Ner ner) {
    Forms forms = new Forms();
    NamedEntities entities = new NamedEntities();
    Scanner reader = new Scanner(System.in);

    int lines = 0;
    boolean not_eof = true;
    while (not_eof) {
      String line;

      forms.clear();
      while ((not_eof = reader.hasNextLine()) && !(line = reader.nextLine()).isEmpty())
        forms.add(line);

      if (!forms.isEmpty()) {
        ner.recognize(forms, entities);

        for (int i = 0; i < entities.size(); i++) {
          NamedEntity entity = entities.get(i);

          StringBuilder entity_ids = new StringBuilder(), entity_text = new StringBuilder();
          for (int j = entity.getStart(); j < entity.getStart() + entity.getLength(); j++) {
            if (j > entity.getStart()) {
              entity_ids.append(',');
              entity_ids.append(' ');
            }
            entity_ids.append(lines + j + 1);
            entity_text.append(forms.get(j));
          }
          System.out.printf("%s\t%s\t%s\n", entity_ids.toString(), entity.getType(), entity_text.toString());
        }
      }
      lines += forms.size() + 1;
    }
  }

  public static String encodeEntities(String text) {
    return text.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;").replaceAll("\"", "&quot;");
  }

  public static void recognizeUntokenized(Ner ner) {
    NamedEntities entities = new NamedEntities();
    Scanner reader = new Scanner(System.in);

    boolean not_eof = true;
    while (not_eof) {
      StringBuilder textBuilder = new StringBuilder();
      String line;

      // Read block
      while ((not_eof = reader.hasNextLine()) && !(line = reader.nextLine()).isEmpty()) {
        textBuilder.append(line);
        textBuilder.append('\n');
      }
      if (not_eof) textBuilder.append('\n');

      // Tokenize and recognize
      String text = textBuilder.toString();
      ner.tokenizeAndRecognize(text, entities);

      // TODO: Write entities
    }
  }

  public static void main(String[] args) {
    int argi = 0;
    if (argi < args.length && args[argi].equals("-v")) argi++;
    boolean use_vertical = argi > 0;

    if (!(argi < args.length)) {
      System.err.println("Usage: RunNer ner_model");
      System.exit(1);
    }

    System.err.print("Loading ner: ");
    Ner ner = Ner.load(args[argi]);
    if (ner == null) {
      System.err.println("Cannot load recognizer from file '" + args[argi] + "'");
      System.exit(1);
    }
    System.err.println("done");

    if (use_vertical) recognizeVertical(ner);
    else recognizeUntokenized(ner);
  }
}

@@ -896,16 +896,40 @@
 Scanner;
+%0Aimport java.util.Stack;
 %0A%0Aclass 
@@ -1625,16 +1625,22 @@
 (int j =
+ (int)
  entity.
@@ -2427,24 +2427,71 @@
 (System.in);
+%0A    Stack%3CInteger%3E openEntities = new Stack();
 %0A%0A    boolea
@@ -2975,14 +2975,8 @@
  // 
-TODO: 
 Writ
@@ -2985,16 +2985,1384 @@
 entities
+%0A      int unprinted = 0;%0A      for (int i = 0; i %3C entities.size(); i++) %7B%0A        NamedEntity entity = entities.get(i);%0A        int entity_start = (int) entity.getStart(), entity_length = (int) entity.getLength();%0A%0A        // Close entities that end sooned than current entity%0A        while (!openEntities.empty() && openEntities.peek() %3C entity_start) %7B%0A          if (unprinted %3C openEntities.peek()) System.out.print(encodeEntities(text.substring(unprinted, openEntities.peek())));%0A          unprinted = openEntities.pop();%0A          System.out.print(%22%3C/ne%3E%22);%0A        %7D%0A%0A        // Print text just before the entity, open it and add end to the stack%0A        if (unprinted %3C entity_start) System.out.print(encodeEntities(text.substring(unprinted, entity_start)));%0A        unprinted = entity_start;%0A        System.out.printf(%22%3Cne type=%5C%22%25s%5C%22%3E%22, entity.getType());%0A        openEntities.push(entity_start + entity_length);%0A      %7D%0A%0A      // Close unclosed entities%0A      while (!openEntities.empty()) %7B%0A        if (unprinted %3C openEntities.peek()) System.out.print(encodeEntities(text.substring(unprinted, openEntities.peek())));%0A        unprinted = openEntities.pop();%0A        System.out.print(%22%3C/ne%3E%22);%0A      %7D%0A%0A      // Write rest of the text (should be just spaces)%0A      if (unprinted %3C text.length()) System.out.print(encodeEntities(text.substring(unprinted)));
 %0A    %7D%0A 

Implement XML-line entity print for untokenized input.