
import java.awt.Font;
import java.io.File;
import java.util.Scanner;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/*
 * Recursive SortedSingleLinkedListWordExample.java
 *
 * @author Bill Kraynek
 */
public class RecursiveSortedSingleLinkedListWordExample {

    public static void main(String[] args) {
        Node header = new Node();
        int maxWordLength = 0;
        try {
            Scanner fileScanner = new Scanner(new File("src/RecursiveSortedSingleLinkedListWordExample.java"));
            fileScanner.useDelimiter("[^a-zA-Z]+");
            while (fileScanner.hasNext()) {
                Word aWord = new Word(fileScanner.next());
                if (maxWordLength < aWord.getWord().length()) {
                    maxWordLength = aWord.getWord().length();
                }// end if
                sortedInsert(header, aWord);
            } // end while
        } catch (Exception e) {
            e.printStackTrace();
        } // end try/catch
        String out = "";
        String blanks = "  ";
        for (int i = 0; i < maxWordLength; i++) {
            blanks += " ";
        }// end for
        Node p = header;
        while (p.next != null) {
            String word = p.next.data.getWord();
            out += word + blanks.substring(word.length()) + p.next.data.getCount() + "\n";
            p = p.next;
        } // end while
        JTextArea outArea = new JTextArea(30, 50);
        outArea.setFont(new Font(Font.MONOSPACED, Font.BOLD, 15));
        outArea.setText(out);
        JOptionPane.showMessageDialog(null, new JScrollPane(outArea));
    } // end constructor

    static void sortedInsert(Node list, Word item) {
        if (list.next == null) {
            list.next = new Node(item, null);
            return;
        }// end if
        if (item.compareTo(list.next.data) < 0) {
            list.next = new Node(item, list.next);
            return;
        }// end if
        if (item.compareTo(list.next.data) == 0) {
            list.next.data.incrementCount();
            return;
        }// end if
        sortedInsert(list.next, item);
    }
}

class Word implements Comparable<Word> {
    private String word;
    private int count;
    public Word(String word) {
        this.word = word;
        count = 1;
    }
    String getWord() {
        return word;
    }
    int getCount() {
        return count;
    }
    public void incrementCount() {
        count++;
    }
    public int compareTo(Word rhs) {
        return this.getWord().compareTo(rhs.getWord());
    }
    public boolean equals(Object rhs) {
        if (rhs == null) {
            return false;
        }
        if (!this.getClass().equals(rhs.getClass())) {
            return false;
        }
        return (this.word.equals(((Word) rhs).word));
    }
    public int hashCode() {
        return word.hashCode();
    }
}

class Node {
    Word data;
    Node next;
    Node() {
    }
    Node(Word data) {
        this.data = data;
    } // end
    Node(Word data, Node next) {
        this.data = data;
        this.next = next;
    } // end
    public String toString() {
        return data + "";
    } // end toString
} // end Node


