/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class displays the GUI for the file analyzer program.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2011-07-18
*/



import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import java.awt.datatransfer.*;
import java.awt.event.*;
import javax.swing.*;



public class TextAnalysisGui extends JApplet implements FocusListener, ComponentListener
{
   private static final String copyright = "Copyright (c) 2012 by Alexander Wait - All Rights Reserved";
   
   private static final String APPLET_INTRO = "TYPE OR PASTE (CTRL V) ABOVE";
  
   private static final long serialVersionUID = 1L;
   
   
   static boolean isApplication = false;
   
   static boolean runRestricted = false;
   
   static boolean isVisible = false;
   
   
   private static final int FRAME_SIZE_X = 380;
   
   private static final int FRAME_SIZE_Y = 550;
  
   
   //************************************** START INITIALISATION CODE **************************************//


   /**
    * Browser constructor.
    */
   public void init()
   {
      if (!isApplication)
      {
         String copyrightParam = getParameter("copyright");
          
         if ((copyrightParam == null) || !copyrightParam.equals(copyright)) 
         {
            Message.showMessage("Invalid Copyright", "WARNING", "warning"); 
         }       
           
         else if (!getDocumentBase().getHost().equals(Domain.getDomain()))
         {
            Message.showMessage("Unauthorised Applet Use", "ERROR", "error");
         }
 
         else
         {
            try {getToolkit().getSystemClipboard();}
  
            catch (java.security.AccessControlException e) {runRestricted = true;}
            
  
            initialiser(); includeResizeEvent(); setSize(FRAME_SIZE_X, FRAME_SIZE_Y); 
         
            if(runRestricted) {copy.setEnabled(false);}
         }
      }  
   }
   
   
   
   /**
    * Application constructor.
    * ESCA-JAVA0076:
    */
   public TextAnalysisGui()
   {
      if (isApplication)
      {  
         initialiser(); 
    
    
         frame = new JFrame(); 
          
         frame.setMinimumSize(new Dimension(FRAME_SIZE_X, FRAME_SIZE_Y));
         
         frame.setSize(FRAME_SIZE_X,FRAME_SIZE_Y); 
          
         frame.setLocationRelativeTo(null); 
          
         frame.setTitle("Text Analysis Program"); 
          
         frame.add(contentPane);
  
         
         setVisibility();  
      }
   }
   
   
   
   /**
    * GUI initializer.
    */
   private void initialiser()
   {
      // Initialize content pane and layout.
   
      contentPane = getContentPane(); 
      
      contentPane.setLayout(new GridBagLayout()); 
      
      
      
      // Initialize text area GUI components.
      
      header = new JTextArea(); header.setLineWrap(true); 
      
      header.setWrapStyleWord(true); header.addFocusListener(this);
      
      header.setFont(new Font("Serif", Font.BOLD, 15)); 
      
      
      display = new JTextArea(); display.setEditable(false); 
      
      display.append(Tools.returnNewline(1) + Tools.returnSpace(2) + APPLET_INTRO); 
      
      
      
      // Initialize text field GUI components.
      
      countDisplay = new JTextField(); countDisplay.setEditable(false);
      
      countDisplay.setBorder(BorderFactory.createLineBorder(Color.gray));
      
      
      
      // Initialize combo box GUI components.
      
      frequencyBox = new JComboBox(comboHeading);
      
      frequencyBox.addActionListener(new ComboBoxHandler());
      
      frequencyBox.setMaximumRowCount(2); 
      
      frequencyBox.setSelectedIndex(0); 
      
      
      
      // Initialize button GUI components.
      
      copy = new JButton(new ImageIcon(this.getClass().getResource
      (
         "files/images/TextAnalysisCopyNormal.png"))
      ); 
          
      
      copy.setRolloverIcon(new ImageIcon(this.getClass().getResource
      (
         "files/images/TextAnalysisCopyRollover.png"))
      );

      
      copy.setPressedIcon(new ImageIcon(this.getClass().getResource
      (
         "files/images/TextAnalysisCopyPressed.png"))
      );
      
      
      copy.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
      
      copy.addActionListener(new CopyButtonListener());
    
      
      analyse = new JButton(new ImageIcon(this.getClass().getResource
      (
         "files/images/TextAnalysisRunNormal.png"))
      ); 
    
      
      analyse.setRolloverIcon(new ImageIcon(this.getClass().getResource
      (
         "files/images/TextAnalysisRunRollover.png"))
      );

      
      analyse.setPressedIcon(new ImageIcon(this.getClass().getResource
      (
         "files/images/TextAnalysisRunPressed.png"))
      );   
       
      
      analyse.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
    
      analyse.addActionListener(new RunButtonListener());
      
      
      
      // Initialize check box GUI components.
      
      alphabeticalCheck = new JCheckBox(" ALPHABETICAL SORT ", false); 
      
      alphabeticalCheck.addItemListener(new HandlerClass());
      
      alphabeticalCheck.setFocusPainted(false); 
      
      
      frequencyCheck = new JCheckBox(" FREQUENCY SORT ", false); 
      
      frequencyCheck.addItemListener(new HandlerClass()); 
      
      frequencyCheck.setFocusPainted(false); 
      

      
      // Initialize progress bar GUI components.
      
      progressBar = new JProgressBar(); 
     
      progressBar.setStringPainted(true); 
      
      progressBar.setString("PENDING"); 
      
      
      
      // Initialize scroll pane GUI components.
      
      headerScroll = new JScrollPane(header,
      
      JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 
      
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);

      
      displayScroll = new JScrollPane(display, 
      
      JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, 
      
      JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
      
      
      
      // Initialize JPanel GUI components.
      
      buttonPanel = new JPanel();
      
      buttonPanel.setLayout(new FlowLayout(FlowLayout.LEADING));
      
      buttonPanel.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
      

      
      // Add GUI components to JPanels.
      
      buttonPanel.add(copy); buttonPanel.add(analyse);
      
     
      
      // Method calls for GUI initialization.
      
      gridBagConstraints(); setColors(); setGraphicIcons();
   }
   
   
   
   /**
    * Sets the background color.
    */
   private void setColors()
   {
      contentPane.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      ); 
      
      buttonPanel.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      ); 
      
      header.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      display.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
     
      frequencyCheck.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      alphabeticalCheck.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
      progressBar.setBackground
      (
         new Color (ColorFunctions.red(), ColorFunctions.green(), ColorFunctions.blue())
      );
      
   }
   
   
   
   /**
    * Sets icons for graphical elements.
    */
   private void setGraphicIcons()
   {
      alphabeticalCheck.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalUnselected.png")));
             
      alphabeticalCheck.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalSelected.png")));

      alphabeticalCheck.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledUnselected.png")));

      alphabeticalCheck.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledSelected.png")));
      
      
      frequencyCheck.setIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalUnselected.png")));
             
      frequencyCheck.setSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxNormalSelected.png")));

      frequencyCheck.setDisabledIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledUnselected.png")));

      frequencyCheck.setDisabledSelectedIcon(new ImageIcon
      (this.getClass().getResource("files/images/CheckBoxDisabledSelected.png")));
      
   }
   
   
   
   /**
    * Sets the grid bag layout.
    * ESCA-JAVA0076:
    */
   private void gridBagConstraints()
   {
      // Initialize grid bag layout of GUI.
      
      constraints = new GridBagConstraints();
      
      constraints.fill = GridBagConstraints.HORIZONTAL;
      
      
      
      // Grid bag constraints 1.
      
      constraints.insets = new Insets(10,0,0,0);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 45;

      constraints.gridwidth = 4;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 0;
      
      
      contentPane.add(headerScroll, constraints);
      
      
      
      // Grid bag constraints 2.
      
      constraints.insets = new Insets(0,0,0,0);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 280;

      constraints.gridwidth = 4;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 1;
      
      
      contentPane.add(displayScroll, constraints);
      
      
      
      // Grid bag constraints 3.
      
      constraints.insets = new Insets(10,10,0,5);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 0;

      constraints.gridwidth = 2;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 2;
      
      
      contentPane.add(frequencyBox, constraints);
      
      
      
      // Grid bag constraints 4.
      
      constraints.insets = new Insets(10,5,0,10);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 7;

      constraints.gridwidth = 2;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 2; 
      
      constraints.gridy = 2;
      
      
      contentPane.add(countDisplay, constraints);
      
      
      
      // Grid bag constraints 5.
      
      constraints.insets = new Insets(10,20,0,5);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 7;

      constraints.gridwidth = 2;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 3;
      
      
      contentPane.add(frequencyCheck, constraints);
      
      
      
      // Grid bag constraints 6.
      
      constraints.insets = new Insets(10,5,0,20);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 7;

      constraints.gridwidth = 2;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 2; 
      
      constraints.gridy = 3;
      
      
      contentPane.add(alphabeticalCheck, constraints);
      
      
      
      // Grid bag constraints 7.
      
      constraints.insets = new Insets(10,35,0,5);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 0;

      constraints.gridwidth = 2;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 0; 
      
      constraints.gridy = 4;
      
      
      contentPane.add(progressBar, constraints);
      
      
      
      // Grid bag constraints 8.
      
      constraints.insets = new Insets(10,5,0,30);
      
      
      constraints.ipadx = 0; 
      
      constraints.ipady = 0;

      constraints.gridwidth = 2;
      
      constraints.weightx = 0; 
      
      constraints.weighty = 0; 
      
      constraints.gridx = 2; 
      
      constraints.gridy = 4;
      
      
      contentPane.add(buttonPanel, constraints);
   }
   
   
   //*************************************** END INITIALISATION CODE ***************************************//
   
   
   //************************************* START INTERFACE EVENT CODE **************************************//
   
   
   private class AnalysisUpdate extends Thread 
   {
      private static final long RUN_DELAY = 600L;

      /** 
       * Thread that controls render method.
       * 
       * @param type
       */
      private AnalysisUpdate(String type) 
      {
         setDaemon(true); run = type;
      }
      
      
      /**
       * ESCA-JAVA0087:
       * ESCA-JAVA0266:
       */
      public void run() 
      {
         try {sleep(RUN_DELAY);}

         catch (InterruptedException e)
         
         {System.out.println(Tools.thisPathAndLine() + e + "\n");}

         runAnalysis(run);
      }

      private String run;
   }
   
   

   private class Progress extends Thread 
   {

      private static final long PROGRESS_DELAY = 300L; 

      /**
       * Thread that controls progress bar.
       */
      private Progress() 
      {
         setDaemon(true);
      }
  
      
      /**
       * ESCA-JAVA0087:
       * ESCA-JAVA0266:
       */
      public void run() 
      {
         try {sleep(PROGRESS_DELAY);}
         
         catch (InterruptedException e)
         
         {System.out.println(Tools.thisPathAndLine() + e + "\n");}

         indeterminentMode(true);
      }
   }



   private class Finalise extends Thread 
   {

      /**
       * Thread that controls image loading.
       */
      private Finalise() 
      {
         setDaemon(true);
      }
  
      
      /**
       * ESCA-JAVA0266:
       */
      public void run() 
      {
         try {first.join();}

         catch (InterruptedException e)
         
         {System.out.println(Tools.thisPathAndLine() + e + "\n");}

         indeterminentMode(false); alphabeticalCheck.setEnabled(true);
         
         frequencyCheck.setEnabled(true); 
         
         if (isApplication) {analysisComplete = true;}
        
      }
   }
   
   
   
   public class ComboBoxHandler implements ActionListener 
   {

      /** 
       * Listener for the combination box. 
       */
      public void actionPerformed(ActionEvent event) 
      {
         freq = (String)frequencyBox.getSelectedItem();
      
         if (!freq.equals("Select (f)"))
         {
            threadUpdate("comboCount");
         }  
      }
   }



   private class HandlerClass implements ItemListener
   {
      
      /** 
       * Listener for the check box. 
       */
      private HandlerClass()
      {
         ButtonGroup group = new ButtonGroup(); 
         
         group.add(alphabeticalCheck); group.add(frequencyCheck);
      }

      public void itemStateChanged(ItemEvent event)
      {
         if ((!analysisComplete) && (!header.getText().equals("")))
         {
            if ((analysisComplete) || (!isApplication))
            {
               if (frequencyCheck.isSelected())
               {
                  alphabeticalCheck.setEnabled(false);
               
                  threadUpdate("sortFrequency");
               }

               if (alphabeticalCheck.isSelected())
               {
                  frequencyCheck.setEnabled(false);
               
                  threadUpdate("sortAlphabetically");
               }
            }
         }
      }
      
   }



   private class RunButtonListener
   implements ActionListener
   {
  
      /** 
       * Listener for the 'run' button. 
       */
      public void actionPerformed(ActionEvent event)
      {
         if ((!analysisComplete) && (!header.getText().equals("")))
         {   
            threadUpdate("scan");
         }
      }
   }



   private class CopyButtonListener
   implements ActionListener
   {

      /** 
       * Listener for the copy button. 
       */
      public void actionPerformed(ActionEvent event)
      {
         StringSelection ss = new StringSelection(display.getText());
         
         Toolkit.getDefaultToolkit().getSystemClipboard().setContents(ss, null);
      }
   }
   
   
   
   public void focusGained(FocusEvent e) {header.setText("");}
   
   
   public void focusLost(FocusEvent e) {}
   
   
   /**
    * Overrides ComponentListener.
    */
   public void componentMoved(ComponentEvent e) {}
   
   
   public void componentResized(ComponentEvent e) {}
   
   
   public void componentShown(ComponentEvent e) {setContentDisplay(true);}
   
   
   public void componentHidden(ComponentEvent e) {setContentDisplay(false);}

   
   //************************************** END INTERFACE EVENT CODE ***************************************//
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Sets the visibility of the frame.
    */
   public void setVisibility()
   {
   
      if (isVisible) {frame.setVisible(true);}
      
      else {frame.setVisible(false);} 
   }
   
   
   
   /**
    * Displays or Hides contents of GUI.
    * @param shown
    */
   public void setContentDisplay(boolean shown)
   {
      contentPane.setVisible(shown);
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//

   
   //**************************************** START PRIVATE METHODS ****************************************//
   

   /**
    * Initializes the threads.
    * @param category
    */
   private void threadUpdate(String category) 
   {
      first = new AnalysisUpdate(category); second = new Progress(); 
      
      third = new Finalise(); first.start(); second.start(); third.start();

      return;
   }

   

   /**
    * Calls the sort functions.
    * ESCA-JAVA0266: 
    * @param alphabetic
    */
   private void runFrequencyAlphabeticalSort(boolean alphabetic)
   {
      if (alphabetic)
      {
         try {analysis.sortWordsByAlphabetical();}
         
         catch (NullPointerException e)
         {System.out.println(Tools.thisPathAndLine() + e + "\n");}
      }

      else
      {
         try {analysis.sortWordsByFrequency();}
         
         catch (NullPointerException e)
         {System.out.println(Tools.thisPathAndLine() + e + "\n");}
      }
   }



   /**
    * Sets indeterminate progress. 
    * @param indet
    */
   private void indeterminentMode(boolean indet)
   {
      if (indet)
      {
         progressBar.setString("PROCESSING ...");
      }

      else
      {
         progressBar.setString("COMPLETE");
      }

      progressBar.setIndeterminate(indet); 
   }



   /**
    * Switches for different update modes.
    * ESCA-JAVA0266: 
    * @param type 
    */
   private void runAnalysis(String type)
   {
      if (type.equals("scan"))
      {
         analysis = new TextAnalysis(header.getText());

         for (int i = 0; i < analysis.getFrequencyHash().size(); i ++)
         {
            frequencyBox.addItem(Integer.toString(analysis.getFrequencyHash().get(i)));
                    
         }
      }

      if (type.equals("comboCount"))
      {
         countDisplay.setText(" Count: " + 
         analysis.returnCountOfFrequency(Integer.parseInt(freq)));
      }

      if (type.equals("sortAlphabetically"))
      {
         runFrequencyAlphabeticalSort(true);
      }

      if (type.equals("sortFrequency"))
      {
         runFrequencyAlphabeticalSort(false);
      }
      
    
      header.setText(analysis.returnHeaderInformation());
      
      display.setText(analysis.returnWordInformation());
      
      display.setCaretPosition(0);
   }
   
   
   
   /**
    * Window resize event.
    */
   private void includeResizeEvent()
   {
      this.addComponentListener 
      (
         new ComponentAdapter() 
         {
            public void componentResized(ComponentEvent e) 
            {
               appletDisplayHandler();
            }
          
         }
      ); 
   }
   
   
   
   /**
    * Controls the JApplet component visibility. 
    * ESCA-JAVA0266:
    */
   private void appletDisplayHandler()
   {
      final String ZOOM_WARNING = 
   
      "It appears that web pages in your browser are zoomed out. \n\n" +
      "In order to display the applet, your browser needs to be set \n" +
      "at its default zoom level of 100% or greater. \n\n" +
      "Sorry about that.";
   
   
      if ((getWidth() < FRAME_SIZE_X) || (getHeight() < FRAME_SIZE_Y))
      {
         contentPane.setVisible(false);  
      
         
         if (!zoomWarningShown) 
         {
            Message.showMessage(ZOOM_WARNING, "Browser zoom setting", "warning");
            
            zoomWarningShown = true;
         } 
      }
       
      else 
      {
         contentPane.setVisible(true);
      } 
   }


   //***************************************** END PRIVATE METHODS *****************************************//


   //********************************************** START MAIN *********************************************//
   
   
   /**
    * Main
    * @param a
    */
   public static void main(String[] a)
   {  
      isApplication = true;
      
      isVisible = true;
      
      new TextAnalysisGui();  
   }
   
   
   //*********************************************** END MAIN **********************************************//


   /**
    * ESCA-JAVA0007:
    */
   public JFrame frame;
   
   private String freq;
   private JPanel buttonPanel;
   private JButton analyse, copy;
   private Container contentPane;
   private TextAnalysis analysis;
   private JTextField countDisplay;
   private JProgressBar progressBar;
   private boolean analysisComplete;
   private boolean zoomWarningShown;
   private JTextArea display, header;
   private Thread first, second, third;
   private JComboBox frequencyBox;
   private GridBagConstraints constraints;
   private String[] comboHeading = {"Select (f)"};
   private JScrollPane headerScroll, displayScroll;
   private JCheckBox alphabeticalCheck, frequencyCheck;
   
   
   //********************************************** END CLASS **********************************************//

}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class analyzes word statistics within a file.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2011-07-18
*/



import java.util.ArrayList;
import java.util.Collections;



public class TextAnalysis
{

   //************************************** START INITIALISATION CODE **************************************//

   
   /**
    * Analyzer constructor.
    * @param text
    */
   public TextAnalysis(String text)
   {
      contents = text;
      
      analyseFieldWords(); storeUniques();
      
      storeWordFrequency(); storeUniqueFrequency();
      
   }
   

   //*************************************** END INITIALISATION CODE ***************************************//
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   

   /**
    * Sorts 'wordHash' and 'wordFrequency' contents by frequency in descending order. 
    */
   public void sortWordsByFrequency()
   {
      for (int i = 0; i < wordFrequency.size(); i ++)
      {
         for (int j = i; j < wordFrequency.size(); j ++)
         {
            if (wordFrequency.get(j) > wordFrequency.get(i))
            {
               String first = wordHash.get(j); 
               
               String second = wordHash.get(i);
               
               int freqFirst = wordFrequency.get(j); 
              
               int freqSecond = wordFrequency.get(i);

               
               wordHash.set(i, first); 
               
               wordHash.set(j, second);
               
               wordFrequency.set(i, freqFirst); 
               
               wordFrequency.set(j, freqSecond);
            }  
         }
      }
   }



   /**
    *  Sorts 'wordHash' and 'wordFrequency' by alphabetical order of words. 
    */
   public void sortWordsByAlphabetical()
   {
      for (int i = 0; i < wordHash.size(); i ++)
      {
         for (int j = i; j < wordHash.size(); j ++)
         {
            String wordTest = wordHash.get(j); String wordCompare = wordHash.get(i);

            if (isWordAlphabeticallyFirst(wordCompare, wordTest))
            {
               int freqCompare = wordFrequency.get(i); 
               
               int freqTest = wordFrequency.get(j);

               
               wordHash.set(i, wordTest); 
               
               wordHash.set(j, wordCompare);
               
               wordFrequency.set(i, freqTest); 
               
               wordFrequency.set(j, freqCompare);
            }
         }
      }
   }
   
   
   
   /**
    * Builds the header contents.
    * @return info
    */
   public String returnHeaderInformation()
   {
      String info = "";

      info += (Tools.returnSpace(2) + "Sentence count:  " + 
      sentenceCount + Tools.returnSpace(2));
      
      info += (Tools.returnNewline(1) + Tools.returnSpace(2) + "Total word count:  " + 
      wordDuplicates.size() + Tools.returnSpace(2));

      info += (Tools.returnNewline(1) + Tools.returnSpace(2) + "Unique word count:  " + 
      wordHash.size() + Tools.returnSpace(2));

      return info;
   }



   /**
    * Builds the display contents.
    * @return info 
    */
   public String returnWordInformation()
   {
      String info = Tools.returnNewline(1);

      
      for (int i = 0; i < wordHash.size(); i ++)
      {
         info += (Tools.returnSpace(2) + "Word:  " + wordHash.get(i) + Tools.returnSpace(2) +
        
         Tools.returnNewline(1) + Tools.returnSpace(2) + "Frequency:  " + 
         
         wordFrequency.get(i) + Tools.returnSpace(2) + Tools.returnNewline(1));

         
         if (i != (wordHash.size() - 1)) {info += (Tools.returnNewline(1));}
      }

      return info;
   }
   
   
   
   /**
    * Returns the count of a frequency.
    * @param val 
    * @return count 
    */
   public int returnCountOfFrequency(int val)
   {
      int count = 0;

      
      for (int i = 0; i < wordFrequency.size(); i ++)
      {
         if (wordFrequency.get(i) == val)
         {
            count ++;
         }
      }

      return count;
   }

   
   
   /**
    * Returns the frequency hash array list.
    * ESCA-JAVA0259:
    * @return
    */
   public ArrayList getFrequencyHash()
   {
      return frequencyHash;
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//


   //**************************************** START PRIVATE METHODS ****************************************//

   
   /**
    * Reads the selected file line by line.
    * ESCA-JAVA0166:
    * ESCA-JAVA0266:
    */
   private void analyseFieldWords()
   {
      try
      {
         storeWords(contents);
      }

      catch (Exception e) {System.out.println(Tools.thisPathAndLine() + e + "\n");}
   }
   
   

   /**
    *  Extracts words from a line of information and stores the words in an array.
    *  @param line
    */
   private void storeWords(String line)
   {
      String wordBuilder = ""; boolean flag = false;

      for (int i = 0; i < line.length(); i ++)
      {
         if (isCharacterValid(line.charAt(i), line, i))
         {
            flag = true; wordBuilder += Character.toLowerCase(line.charAt(i));

            if (i == line.length() - 1)
            {
               wordDuplicates.add(wordBuilder); flag = false; wordBuilder = "";
            }
         }

         else 
         {
            if (flag) 
            { 
               wordDuplicates.add(wordBuilder); flag = false; wordBuilder = "";
            }

            if (line.charAt(i) == '.')
            {
               sentenceCount ++;
            }
         }
      }
   }



   /**
    * Tests if a character can be present within a word.
    * @param symbol
    * @param lineText
    * @param charIndex
    * @return valid
    */
   private boolean isCharacterValid(char symbol, String lineText, int charIndex)
   {
      boolean valid = false;
      
      for (char element : Validation.lowerCase) 
      {
         if ((element == symbol) || (Character.toUpperCase(element) == symbol))
         {
            valid = true;
         }
      }

      for (String element : validCharacters) 
      {
         if (element.equals(Character.toString(symbol)) 
         && isLettersSurrounded(lineText, charIndex))
         {
            valid = true;
         }
      }

      return valid;
   }



   /**
    *  Tests if a character is immediately surrounded by letters. 
    *  @param lineText 
    *  @param charIndex 
    *  @return pass
    */
   private static boolean isLettersSurrounded(String lineText, int charIndex)
   {
      boolean pass = false; 
      
      boolean lowerSurrounded = false; boolean upperSurrounded = false;
      
      int lowerBounds = charIndex - 1; int upperBounds = charIndex + 1;

      
      if ((lowerBounds >= 0) && (upperBounds < lineText.length()))
      {
         for (char element : Validation.lowerCase) 
         {
            if ((Character.toString(element).equals
            (Character.toString(lineText.charAt(lowerBounds)))) 
            || (Character.toString(Character.toUpperCase(element)).equals
            (Character.toString(lineText.charAt(lowerBounds)))))
            {
               lowerSurrounded = true;
            }

            if ((Character.toString(element).equals
            (Character.toString(lineText.charAt(upperBounds)))) 
            || (Character.toString(Character.toUpperCase(element)).equals
            (Character.toString(lineText.charAt(upperBounds)))))
            {
               upperSurrounded = true;
            }
            
            if (lowerSurrounded && upperSurrounded)
            {
               pass = true;
            }
         }
      }

      return pass;
   }



   /**
    * Stores words without duplicates in a new array called 'wordHash'. 
    */
   private void storeUniques()
   {
      for (int i = 0; i < wordDuplicates.size(); i ++)
      {
         if (!wordInHash(wordDuplicates.get(i)))
         {
            wordHash.add(wordDuplicates.get(i));
         }
      }
   }



   /**
    * Tests if word already stored in 'wordHash'
    * @param word
    * @return stored
    */
   private boolean wordInHash(String word)
   {
      boolean stored = false;

      for (int i = 0; i < wordHash.size(); i ++)
      {
         if (wordHash.get(i).equals(word))
         {
            stored = true;
         }
      }

      return stored;
   }



   /**
    *  Stored the frequency of each unique word in an array. 
    */
   private void storeWordFrequency()
   {
      for (int i = 0; i < wordHash.size(); i ++)
      {
         int counter = 0;

         for (int j = 0; j < wordDuplicates.size(); j ++)
         {
            if (wordHash.get(i).equals(wordDuplicates.get(j)))
            {
               counter ++;
            }
         }

         wordFrequency.add(counter);
      }
   }



   /**
    * Sets a hash of the frequency values. 
    */
   private void storeUniqueFrequency()
   {
      for (int i = 0; i < wordFrequency.size(); i ++)
      {
         frequencySort.add(wordFrequency.get(i));
      }

      
      Collections.sort(frequencySort); 
      
      int val = frequencySort.get(0); 
      
      frequencyHash.add(val);

      
      for (int i = 0; i < frequencySort.size(); i ++)
      {
         if (frequencySort.get(i) != val)
         {
            val = frequencySort.get(i);

            frequencyHash.add(val);
         }
      }
   }
   


   /**
    * Test two words for alphabetical order.
    * @param compareWord
    * @param testWord
    * @return isWordFirst
    */
   private boolean isWordAlphabeticallyFirst(String compareWord, String testWord)
   {
      int loopTerminate = 0; 
      
      boolean isWordFirst = false; boolean testWordShorter = false;
      
      if (compareWord.length() > testWord.length()) 
      {loopTerminate = testWord.length(); testWordShorter = true;}

      else if (compareWord.length() < testWord.length()) 
      {loopTerminate = compareWord.length();}

      else {loopTerminate = compareWord.length();}

      for (int i = 0; i < loopTerminate; i ++)
      {
         if (isCharAlphabeticallyFirst(compareWord.charAt(i), testWord.charAt(i)))
         {
            isWordFirst = true; break;
         }

         else
         {
            if (compareWord.charAt(i) == testWord.charAt(i)) 
            {
               if ((i == (loopTerminate - 1)) && (testWordShorter))
               {
                  isWordFirst = true; break;
               }

               continue;
            }

            else {break;}
         }
      }

      return isWordFirst;
   
   }



   /**
    * Tests two characters for alphabetical order.
    * @param compareChar
    * @param testChar
    * @return isCharFirst
    */
   private boolean isCharAlphabeticallyFirst(char compareChar, char testChar)
   {
      boolean isCharFirst = false; 
      
      boolean isCompareApostrophe = false; boolean isTestApostrophe = false;

      for (String element : validCharacters) 
      {
         if (element.equals(Character.toString(testChar))) 
         {isTestApostrophe = true;}

         if (element.equals(Character.toString(compareChar))) 
         {isCompareApostrophe = true;}
      }

      if (isTestApostrophe && (!isCompareApostrophe)) 
      {isCharFirst = true;}

      if (!isCharFirst)
      {
         int compareIndex = 0; int testIndex = 0;  
         
         boolean compareExecuted = false; boolean testExecuted = false;

         for (int i = 0; i < Validation.lowerCase.length; i ++)
         {
            if (Validation.lowerCase[i] == compareChar) 
            {compareIndex = i; compareExecuted = true;}

            if (Validation.lowerCase[i] == testChar) 
            {testIndex = i; testExecuted = true;}

            if (compareExecuted && testExecuted) {break;}
         }

         if (testIndex < compareIndex) {isCharFirst = true;}
      }

      return isCharFirst;
   }


   //***************************************** END PRIVATE METHODS *****************************************//
   

   private String contents;
   private int sentenceCount;
   private final String[] validCharacters = {"'", "’"};
   
   private ArrayList wordHash = new ArrayList();
   private ArrayList wordDuplicates = new ArrayList();
   private ArrayList wordFrequency = new ArrayList();
   private ArrayList frequencySort = new ArrayList();
   private ArrayList frequencyHash = new ArrayList();
   
   
   //********************************************** END CLASS **********************************************//
 
}


/*
   COPYRIGHT (C) 2010 -2013 by Alexander Wait. All Rights Reserved.

   This class defines colors and color methods.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-05-18
*/



public class ColorFunctions
{

   private static final int HEXADECIMAL_BASE = 16;
   
   private static final int COLOR_COMPONENT_RED = 250;
   
   private static final int COLOR_COMPONENT_GREEN = 250;
   
   private static final int COLOR_COMPONENT_BLUE = 250;
   
   
   
   private ColorFunctions() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//

   
   /**
    * Returns the color in hexadecimal format.
    * @param sliderValue
    * @return
    */
   public static String returnHexadecimalColor(int sliderValue)
   {
      String compFirst = ""; String compSecond = ""; int counter = -1;
 
      for (int i = 0; i < HEXADECIMAL_BASE; i ++)
      {
         compFirst = returnComponent(i);

          for (int j = 0; j < HEXADECIMAL_BASE; j ++)
          {
             compSecond = returnComponent(j); counter ++; 
  
             if (counter == sliderValue)
             {
                break;
             }
             
          }
  
          if (counter == sliderValue)
          {
             break;
          }
  
       }
   
       return 
       (
          "#" + compFirst + compSecond + compFirst + 
          
          compSecond + compFirst + compSecond
       );
   
   }
   
   
   
   /**
    * Return the set red color component 
    * for setting the programs background color. 
    * @return
    */
   public static int red()
   {
      return COLOR_COMPONENT_RED;
   }
   
   
   
   /**
    * Return the set green color component 
    * for setting the programs background color. 
    * @return
    */
   public static int green()
   {
      return COLOR_COMPONENT_GREEN;
   }
   
   
   
   /**
    * Return the set blue color component 
    * for setting the programs background color. 
    * @return
    */
   public static int blue()
   {
      return COLOR_COMPONENT_BLUE;
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//


   //**************************************** START PRIVATE METHODS ****************************************//
   
   
   /**
    * Returns the hexadecimal component.
    * ESCA-JAVA0076:
    * @param index
    * @return
    */
   private static String returnComponent(int index)
   {
      String component = "";
  
      switch (index)
      {
         case 10: component = "A"; break; case 11: component = "B"; break;  
         
         case 12: component = "C"; break; case 13: component = "D"; break; 
         
         case 14: component = "E"; break; case 15: component = "F"; break;
   
         default: component = Integer.toString(index); break;
      }
   
      return component;   
   }
   
 
   //***************************************** END PRIVATE METHODS *****************************************//

   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class returns the domain attributes.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-07-06
*/



public class Domain 
{
  
   private static final String DOMAIN = "javaika.com";

   private static final boolean RUN_LOCAL = false; 
   
   private static final boolean prefix = true;
   
   private static final String PORT = "80";
   
   
   private Domain() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Returns the domain name.
    * @return
    */
   public static final String getDomain()
   {
      if (prefix)
      {
         return ("www." + DOMAIN);
      }
      
      else
      {
         return (DOMAIN);
      }
   }
   
   
   
   /**
    * Returns the port number.
    * @return
    */
   public static final String getPort()
   {
      if (RUN_LOCAL)
      {
         return (":" + PORT);
         
      }
      
      else {return ("");} 
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //********************************************** END CLASS **********************************************//

}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class displays message dialogs.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2011-07-18
*/



import javax.swing.*;



public class Message
{

   private Message(){}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//


   /**
    * Displays a message dialog.
    * @param text
    * @param heading
    * @param type 
    */
   public static void showMessage(String text, String heading, String type)
   {
      new JOptionPane(); Object[] options = {}; 

      if (type.equals("error"))
      {
         JOptionPane.showOptionDialog(null, text, heading,  
         JOptionPane.YES_OPTION, JOptionPane.ERROR_MESSAGE, null, options, null);
      }

      if (type.equals("information"))
      {
         JOptionPane.showOptionDialog(null, text, heading, 
         JOptionPane.YES_OPTION, JOptionPane.INFORMATION_MESSAGE, null, options, null);
      }

      if (type.equals("warning"))
      {
         JOptionPane.showOptionDialog(null, text, heading, 
         JOptionPane.YES_OPTION, JOptionPane.WARNING_MESSAGE, null, options, null);
      }

      if (type.equals("question"))
      {
         JOptionPane.showOptionDialog(null, text, heading, 
         JOptionPane.YES_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, null);
      }
   }
   
   
   //***************************************** END PUBLIC METHODS ******************************************//
   
   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class provides handy tools.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2012-02-01
*/



public class Tools 
{

   private static final int EXCEPTION_LINE_BEAK = 2;
   
   
   private Tools() {}
   
   
   //**************************************** START PUBLIC METHODS *****************************************//


   /**
    * This method returns the line number and path where it's called.
    * The syntax new Exception().getStackTrace()[0].getLineNumber() 
    * will only give the current line number of the source file.
    * @return
    */
   public static String thisPathAndLine()
   {
   
      String lineAndPath = ""; String stackTrace = "";
 
      stackTrace = new Exception().getStackTrace()[1].toString();
      
      
      for (int i = stackTrace.length()-1; i >= 0; i --)
      {
         if (stackTrace.charAt(i) == ')') {continue;} 
        
         else if (stackTrace.charAt(i) == '(') {break;}
        
         else {lineAndPath = (stackTrace.charAt(i) + lineAndPath);}
      }
         
      return lineAndPath + returnNewline(EXCEPTION_LINE_BEAK);
      
   }
   
   
   
   /**
    * Delays execution.
    * @param length
    */
   public static void delay(long length) 
   {
      for (long i = 0; i < length; i ++) {}
   }
   
  
 
   /**
    * This method returns a space.
    * @param length
    * @return
    */
   public static String returnSpace(int length)
   {
      String space = "";
      
      
      for (int i = 0; i < length; i ++)
      {
         space += " ";
      }
      
      return space;
   }
   
   
   
   /**
    * Assigns newlines to a string.
    * @param lines
    * @return
    */
   public static String returnNewline(int lines)
   {
      String newline = "";
      
      
      for (int i = 0; i < lines; i++)
      {
         newline += "\n";
      }
      
      
      return newline;
   
   }
   
   
   
   /**
    * Returns the users desktop path.
    * @return
    */
   public static String returnDesktopPath()
   {
      return (System.getProperty("user.home") + "/Desktop").replace("\\", "/") + "/"; 
   }
   

   //***************************************** END PUBLIC METHODS ******************************************//

   
   //********************************************** END CLASS **********************************************//
   
}


/*
   COPYRIGHT (C) 2010 - 2013 by Alexander Wait. All Rights Reserved.

   This class is used for sophisticated validation of data.

   @site http://www.javaika.com
   @author Alexander Wait
   @version 2010-07-18
*/



import java.util.regex.Pattern;



public class Validation
{

   //************************************** START INITIALISATION CODE **************************************//


   private static final String IP_ADDRESS_PATTERN = 
   
   "^([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." +

   "([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\." + "([01]?\\d\\d?|2[0-4]\\d|25[0-5])$";
   
   
   private static final String NUMBER_PATTERN = "[+-]?[0-9]*[.]?[0-9]*";
   
   private static final String ALPHANUMERIC_PATTERN = "[A-Za-z0-9]*";
   
   private static final String LETTER_PATTERN = "[A-Za-z]*";
   
   private static final String INTEGER_PATTERN = "[0-9]*";



   /**
    *  Validation constructor.
    */
   public Validation()
   {
      count = 0;
   }
   
   
   //*************************************** END INITIALISATION CODE ***************************************//

   
   //**************************************** START PUBLIC METHODS *****************************************//
   
   
   /**
    * Tests a string against a supplied mask string.
    * The key for testing a string is as follows.
    * '^' represents a upper case letter.
    * '#' represents a lower case letter.
    * '?' represents a digit.
    * @param maskString
    * @param testString 
    * @return result()
    */
   public boolean maskValidation(String maskString, String testString)
   {
      count = 0;

      
      if (maskString.length() == testString.length())
      {
         for (int i = 0; i < maskString.length(); i ++)
         {
            if (maskString.charAt(i) == testString.charAt(i))
            {
               count ++;
            }

            if (maskString.charAt(i) == '?')
            {
               for (char element : digit) 
               {
                  if (testString.charAt(i) == element) 
                  {
                     count ++;
                  }
               }
            }

            if (maskString.charAt(i) == '#')
            {
               for (char element : lowerCase) 
               {
                  if (testString.charAt(i) == element)
                  {
                     count ++;
                  }
               }
            }

            if (maskString.charAt(i) == '^')
            {
               for (char element : upperCase) 
               {
                  if (testString.charAt(i) == element)
                  {
                     count ++;
                  }
               }
            }
         }
      }
      
      
      if (count != testString.length()) {return false;}
      
      else {return true;}
   }
   
   
   
   /**
    * Checks the validation of an IP address.
    * @param testString
    * @return
    */
   public boolean ipAddressValidation(String testString)
   {
      pattern = Pattern.compile(IP_ADDRESS_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of an integer.
    * @param testString
    * @return
    */
   public boolean integerValidation(String testString)
   {
      pattern = Pattern.compile(INTEGER_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of a letter string.
    * @param testString
    * @return
    */
   public boolean letterValidation(String testString)
   {
      pattern = Pattern.compile(LETTER_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of an alphanumeric string.
    * @param testString
    * @return
    */
   public boolean alphanumericValidation(String testString)
   {
      pattern = Pattern.compile(ALPHANUMERIC_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }
   
   
   
   /**
    * Checks the validation of an alphanumeric string.
    * @param testString
    * @return
    */
   public boolean numberValidation(String testString)
   {
      pattern = Pattern.compile(NUMBER_PATTERN);
      
      
      return (pattern.matcher(testString).matches());
   }


   //***************************************** END PUBLIC METHODS ******************************************//


   private int count;
   
   private Pattern pattern;


   /**
    * ESCA-JAVA0007:
    */
   public static String[] numberOperator = {"PI", "e"};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] digit = {'0','1','2','3','4','5','6','7','8','9'};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] simpleOperator = {'-', '+', 'v', '^', '/', 'x', '*', ','};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] number = 
   {'-','+','.','0','1','2','3','4','5','6','7','8','9','E','I','n','f','i','t','y'};
   
   /**
    * ESCA-JAVA0007:
    */
   public static String[] singleOperator = {"Sin", "Cos", "Tan", "Fac", "Inv", "Abs"};
   
   /**
    * ESCA-JAVA0007:
    */
   public static String[] doubleOperator = {"Log", "Mod", "Pwr", "Pnr", "Cwr", "Cnr"};
  
   /**
    * ESCA-JAVA0007:
    */
   public static char[] lowerCase = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
   'p','q','r','s','t','u','v','w','x','y','z'};
   
   /**
    * ESCA-JAVA0007:
    */
   public static char[] upperCase = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O',
   'P','Q','R','S','T','U','V','W','X','Y','Z'};
   
   
   //********************************************** END CLASS **********************************************//

}