/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package at.illecker.storm.examples.util.unsupervised.util;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import edu.stanford.nlp.ling.TaggedWord;
import edu.stanford.nlp.tagger.maxent.MaxentTagger;
import edu.stanford.nlp.tagger.maxent.TaggerConfig;

public class POSTagger {

  public static final String TAGGER_MODEL = System.getProperty("user.dir")
      + File.separator + "resources" + File.separator + "POSmodels"
      + File.separator + "gate-EN-twitter-fast.model";

  private static final Logger LOG = LoggerFactory.getLogger(POSTagger.class);
  private static final POSTagger instance = new POSTagger();

  private MaxentTagger m_posTagger; // Standford POS Tagger
  private NameEntities m_nameEntities;
  private SlangCorrection m_slangCorrection;
  private Interjections m_interjections;

  private POSTagger() {
    // Load POS Tagger
    LOG.info("Load POSTagger with model: " + TAGGER_MODEL);
    TaggerConfig posTaggerConf = new TaggerConfig("-model", TAGGER_MODEL);
    m_posTagger = new MaxentTagger(TAGGER_MODEL, posTaggerConf, false);

    // Load NameEntities
    m_nameEntities = NameEntities.getInstance();
    // Load SlangCorrection
    m_slangCorrection = SlangCorrection.getInstance();
    // Load Interjections
    m_interjections = Interjections.getInstance();
  }

  public static POSTagger getInstance() {
    return instance;
  }

  public List<TaggedWord> tagSentence(List<String> tokens) {
    List<TaggedWord> untaggedTokens = new ArrayList<TaggedWord>();

    for (String token : tokens) {
      TaggedWord preTaggedToken = new TaggedWord(token);
      String tokenLowerCase = token.toLowerCase();

      // set custom tags
      if (token.indexOf("#") == 0) {
        preTaggedToken.setTag("HT");
      }
      if (token.indexOf("@") == 0) {
        preTaggedToken.setTag("USR");
      }
      if ((token.indexOf(".com") > -1) || (token.indexOf("http:") == 0)
          || (token.indexOf("www.") == 0)) {
        preTaggedToken.setTag("URL");
      }
      if ((token.toLowerCase().equals("rt"))
          || ((token.substring(0, 1).equals("R")) && (token.toLowerCase()
              .equals("retweet")))) {
        preTaggedToken.setTag("RT");
      }

      // Name entities
      if (m_nameEntities.isNameEntity(tokenLowerCase)) {
        LOG.info("NE labelled for " + token);
        preTaggedToken.setTag("NNP");
      }

      // Slang correction
      String correction = m_slangCorrection.getCorrection(tokenLowerCase);
      if (correction != null) {
        LOG.info("Correcting " + token + " to " + correction);
        token = correction;
        preTaggedToken = new TaggedWord(correction);
      }

      // Interjections
      if (m_interjections.isInterjection(tokenLowerCase)) {
        LOG.info("Interjection labelled for " + token);
        preTaggedToken.setTag("UH");
      }

      untaggedTokens.add(preTaggedToken);
    }

    return m_posTagger.tagSentence(untaggedTokens, true);
  }

  public static void main(String[] args) {
    String text = "Gas by my house hit $3.39 !!!! I'm going to Chapel Hill on Sat . :)";
    System.out.println("text: '" + text + "'");

    POSTagger posTagger = POSTagger.getInstance();

    List<String> tokens = Tokenizer.tokenize(text);
    List<TaggedWord> taggedSentence = posTagger.tagSentence(tokens);
    for (TaggedWord w : taggedSentence) {
      System.out.println("token: '" + w.word() + "' tag: '" + w.tag() + "'");
    }
  }
}

@@ -905,16 +905,43 @@
 ayList;%0A
+import java.util.Iterator;%0A
 import j
@@ -2410,37 +2410,113 @@
     
-for (String token : tokens) %7B
+Iterator%3CString%3E iter = tokens.iterator();%0A    while (iter.hasNext()) %7B%0A      String token = iter.next();
 %0A   
@@ -2730,84 +2730,608 @@
     
-%7D%0A      if (token.indexOf(%22@%22) == 0) %7B%0A        preTaggedToken.setTag(%22USR%22);
+  if ((token.length() == 1) && (iter.hasNext())) %7B%0A          String nextToken = iter.next();%0A          preTaggedToken.setWord(preTaggedToken.word() + nextToken);%0A          token = nextToken;%0A        %7D%0A      %7D%0A      if (token.indexOf(%22@%22) == 0) %7B%0A        preTaggedToken.setTag(%22USR%22);%0A        if ((token.length() == 1) && (iter.hasNext())) %7B%0A          String nextToken = iter.next();%0A          preTaggedToken.setWord(preTaggedToken.word() + nextToken);%0A          token = nextToken;%0A          if (preTaggedToken.word().indexOf(%22#%22) == 0) %7B%0A            preTaggedToken.setTag(%22HT%22);%0A          %7D%0A        %7D
 %0A   
@@ -3800,17 +3800,25 @@
 .info(%22N
-E
+ameEntity
  labelle
@@ -4033,16 +4033,21 @@
 G.info(%22
+Slang
 Correcti
@@ -4049,16 +4049,21 @@
 recting 
+from 
 %22 + toke
@@ -4408,24 +4408,83 @@
 en);%0A    %7D%0A%0A
+    LOG.info(%22tagSentence: %22 + untaggedTokens.toString());%0A
     return m

Update POSTagger to recognize #@ pattern