/**
  * File: FirstTokenizer.java
  * Content: Retrieves the methods with body in a program, returning the line number and
  *    the method signature in a ordered list.
  *    The method to obtain the methods is quite simplistic, that's the reason because
  *    the logic is implemented on a different file, to make it easier to change the
  *    logic to some better algorithm
  * Author: LuisM Pena
  * Date: 21st March 2001
  * Version: 0.60.00
  * Last change:
  *
  *
  **/

package preprocessors;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.File;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.StreamTokenizer;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

class FirstTokenizer
{

  public class Line
  {
    public int line;
    public String signature;
    public Line(int l, String s) {line=l; signature=s;}
  };

  List process(File file) throws IOException
  {
    level=0;
    prevNewLine=false;
    signature = new ArrayList();
    lines = new ArrayList();
    BufferedReader toClose=null;
    try
    {
      toClose=new BufferedReader(new InputStreamReader(new FileInputStream(file)));
      tokenizer=new StreamTokenizer(toClose);

      tokenizer.eolIsSignificant(true);
      tokenizer.slashStarComments(true);
      tokenizer.slashSlashComments(true);
      tokenizer.quoteChar('\"');

      while(tokenizer.nextToken()!=StreamTokenizer.TT_EOF)
        if (tokenizer.ttype==StreamTokenizer.TT_EOL)
          newLine();
        else
          newToken(tokenizer.ttype==StreamTokenizer.TT_WORD);
    }
    finally
    {
      if (toClose!=null)
        toClose.close();
    }

    return lines;
  }

  void newToken(boolean word)
  {
    if (tokenizer.ttype=='{')
    {
      if ((level!=1) || !prevNewLine)
        signature.clear();
      ++level;
    }
    else if (tokenizer.ttype=='}')
    {
      signature.clear();
      --level;
    }
    else if (tokenizer.ttype==';')
      signature.clear();
    else if (level==1)
    {
      if (word)
        signature.add(tokenizer.sval);
      else
        signature.add(String.valueOf((char) tokenizer.ttype));
    }
    else
      signature.clear();

    prevNewLine=false;
  }

  void newLine()
  {
    if (level==2 && (!signature.isEmpty()))
    {
      String sign=getSignature();
      if (sign!=null)
        lines.add(new Line(tokenizer.lineno(), getSignature()));
      signature.clear();
    }
    prevNewLine=true;
  }

  String getSignature()
  {
    signature.remove("public");
    signature.remove("protected");
    signature.remove("private");
    signature.remove("static");

    int noget=signature.indexOf("throws");
    if (noget!=-1)
      signature=signature.subList(0,noget);

    String ret=null;

    if(!signature.isEmpty() && (signature.get(signature.size()-1).equals(")")))
    {
      Iterator it=signature.iterator();

      StringBuffer rets=new StringBuffer();

      while(it.hasNext())
      {
        rets.append((String)(it.next()));
        if (it.hasNext())
          rets.append(" ");
      }

      ret = rets.toString();
    }
    return ret;
  }

  StreamTokenizer tokenizer;
  int level;
  boolean prevNewLine;
  List signature;
  List lines;
}