///////////////////////////////////////////////////////////////////////////////
//Copyright (C) 2014 Joliciel Informatique
//
//This file is part of Talismane.
//
//Talismane is free software: you can redistribute it and/or modify
//it under the terms of the GNU Affero General Public License as published by
//the Free Software Foundation, either version 3 of the License, or
//(at your option) any later version.
//
//Talismane 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 Affero General Public License for more details.
//
//You should have received a copy of the GNU Affero General Public License
//along with Talismane.  If not, see <http://www.gnu.org/licenses/>.
//////////////////////////////////////////////////////////////////////////////
package com.joliciel.talismane.tokeniser.features;

import com.joliciel.talismane.TalismaneException;
import com.joliciel.talismane.machineLearning.features.BooleanFeature;
import com.joliciel.talismane.machineLearning.features.FeatureResult;
import com.joliciel.talismane.machineLearning.features.RuntimeEnvironment;
import com.joliciel.talismane.tokeniser.Token;
import com.joliciel.talismane.tokeniser.TokenSequence;

/**
 * Returns true if this is the first word in the sentence.<br/>
 * Will skip initial punctuation (e.g. quotation marks) or numbered lists,
 * returning true for the first word following such constructs.
 * 
 * @author Assaf Urieli
 *
 */
public final class FirstWordInSentenceFeature extends AbstractTokenFeature<Boolean>implements BooleanFeature<TokenWrapper> {
  public FirstWordInSentenceFeature() {
  }

  public FirstWordInSentenceFeature(TokenAddressFunction<TokenWrapper> addressFunction) {
    this.setAddressFunction(addressFunction);
  }

  @Override
  public FeatureResult<Boolean> checkInternal(TokenWrapper tokenWrapper, RuntimeEnvironment env) throws TalismaneException {
    TokenWrapper innerWrapper = this.getToken(tokenWrapper, env);
    if (innerWrapper == null)
      return null;
    Token token = innerWrapper.getToken();

    FeatureResult<Boolean> result = null;

    boolean firstWord = (token.getIndex() == 0);
    if (!firstWord) {
      TokenSequence tokenSequence = token.getTokenSequence();
      int startIndex = 0;
      String word0 = "";
      String word1 = "";
      String word2 = "";
      if (tokenSequence.size() > 0)
        word0 = tokenSequence.get(0).getAnalyisText();
      if (tokenSequence.size() > 1)
        word1 = tokenSequence.get(1).getAnalyisText();
      if (tokenSequence.size() > 2)
        word2 = tokenSequence.get(2).getAnalyisText();

      boolean word0IsInteger = false;
      try {
        Integer.parseInt(word0);
        word0IsInteger = true;
      } catch (NumberFormatException nfe) {
        word0IsInteger = false;
      }

      boolean word1IsInteger = false;
      try {
        Integer.parseInt(word1);
        word1IsInteger = true;
      } catch (NumberFormatException nfe) {
        word1IsInteger = false;
      }

      if (word0.equals("\"") || word0.equals("-") || word0.equals("--") || word0.equals("—") || word0.equals("*") || word0.equals("(")) {
        startIndex = 1;
      } else if ((word0IsInteger || word0.length() == 1) && (word1.equals(")") || word1.equals("."))) {
        startIndex = 2;
      } else if (word0.equals("(") && (word1IsInteger || word1.length() == 1) && word2.equals(")")) {
        startIndex = 3;
      }
      firstWord = (token.getIndex() == startIndex);
    } // have token

    result = this.generateResult(firstWord);

    return result;
  }
}

@@ -935,16 +935,49 @@
 tures;%0A%0A
+import java.util.regex.Pattern;%0A%0A
 import c
@@ -1018,16 +1018,16 @@
 eption;%0A
-
 import c
@@ -1704,16 +1704,76 @@
 pper%3E %7B%0A
+  static Pattern integerPattern = Pattern.compile(%22%5C%5Cd+%22);%0A%0A
   public
@@ -2832,373 +2832,120 @@
 r = 
-false;%0A      try %7B%0A        Integer.parseInt(word0);%0A        word0IsInteger = true;%0A      %7D catch (NumberFormatException nfe) %7B%0A        word0IsInteger = false;%0A      %7D%0A%0A      boolean word1IsInteger = false;%0A      try %7B%0A        Integer.parseInt(word1);%0A        word1IsInteger = true;%0A      %7D catch (NumberFormatException nfe) %7B%0A        word1IsInteger = false;%0A      %7D
+integerPattern.matcher(word0).matches();%0A      boolean word1IsInteger = integerPattern.matcher(word1).matches();
 %0A%0A  

Improve performance on FirstWordInSentenceFeature