Index: /trunk/gsdl/packages/kea/kea-3.0/ACKNOWLEDGMENTS
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/ACKNOWLEDGMENTS	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/ACKNOWLEDGMENTS	(revision 8815)
@@ -0,0 +1,2 @@
+This product includes software developed by the
+Apache Software Foundation (http://www.apache.org/).
Index: /trunk/gsdl/packages/kea/kea-3.0/COPYING
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/COPYING	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/COPYING	(revision 8815)
@@ -0,0 +1,345 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 		59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	Appendix: How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) 19yy  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program 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 General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) 19yy name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
Index: /trunk/gsdl/packages/kea/kea-3.0/Counter.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/Counter.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/Counter.java	(revision 8815)
@@ -0,0 +1,73 @@
+/*
+ *    Counter.java
+ *    Copyright (C) 2000 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.io.*;
+
+/**
+ * Class that implements a simple counter.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public class Counter implements Serializable {
+  
+  /** Integer value stored */
+    private int m_val = 1;
+  
+  /**
+   * Initializes the counter to 1
+   */
+  public Counter() {
+    
+    m_val = 1;
+  }
+  
+  /**
+   * Initializes the counter to the given value
+   */
+  public Counter(int val) {
+    
+    m_val = val;
+  }
+  
+  /**
+   * Increments the counter.
+   */
+  public void increment() {
+    
+    m_val++;
+  }
+  
+  /**
+   * Gets the value.
+   * @return the value
+   */
+  public int value() {
+    
+    return m_val;
+  }
+  
+  /**
+   * Returns string containing value.
+   */
+  public String toString() {
+    
+    return String.valueOf(m_val);
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/GermanStemmer.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/GermanStemmer.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/GermanStemmer.java	(revision 8815)
@@ -0,0 +1,309 @@
+
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2001 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution,
+ *    if any, must include the following acknowledgment:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgment may appear in the software itself,
+ *    if and wherever such third-party acknowledgments normally appear.
+ *
+ * 4. The names "Apache" and "Apache Software Foundation" and
+ *    "Apache Lucene" must not be used to endorse or promote products
+ *    derived from this software without prior written permission. For
+ *    written permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache",
+ *    "Apache Lucene", nor may "Apache" appear in their name, without
+ *    prior written permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * <http://www.apache.org/>.
+ */
+
+/**
+ * A stemmer for German words. The algorithm is based on the report
+ * "A Fast and Simple Stemming Algorithm for German Words" by Jörg
+ * Caumanns (joerg.caumanns@isst.fhg.de).
+ *
+ * Changed stem() from protected to public.
+ * Changed coding for umlaute to unicode.
+ *
+ * @author    Gerhard Schwarz
+ * @version   $Id$
+ */
+public class GermanStemmer extends Stemmer
+{
+    /**
+     * Buffer for the terms while stemming them.
+     */
+    private StringBuffer sb = new StringBuffer();
+
+    /**
+     * Indicates if a term is handled as a noun.
+     */
+    private boolean uppercase = false;
+
+    /**
+     * Amount of characters that are removed with <tt>substitute()</tt> while stemming.
+     */
+    private int substCount = 0;
+
+    /**
+     * Stemms the given term to an unique <tt>discriminator</tt>.
+     *
+     * @param term  The term that should be stemmed.
+     * @return      Discriminator for <tt>term</tt>
+     */
+    public String stem( String term )
+    {
+	// Mark a possible noun.
+	uppercase = Character.isUpperCase( term.charAt( 0 ) );
+	// Use lowercase for medium stemming.
+	term = term.toLowerCase();
+	if ( !isStemmable( term ) )
+	    return term;
+	// Reset the StringBuffer.
+	sb.delete( 0, sb.length() );
+	sb.insert( 0, term );
+	// Stemming starts here...
+	substitute( sb );
+	strip( sb );
+	optimize( sb );
+	resubstitute( sb );
+	removeParticleDenotion( sb );
+	return sb.toString();
+    }
+
+    /**
+     * Checks if a term could be stemmed.
+     *
+     * @return  true if, and only if, the given term consists in letters.
+     */
+    private boolean isStemmable( String term )
+    {
+	for ( int c = 0; c < term.length(); c++ ) {
+	    if ( !Character.isLetter( term.charAt( c ) ) ) return false;
+	}
+	return true;
+    }
+
+    /**
+     * suffix stripping (stemming) on the current term. The stripping is reduced
+     * to the seven "base" suffixes "e", "s", "n", "t", "em", "er" and * "nd",
+     * from which all regular suffixes are build of. The simplification causes
+     * some overstemming, and way more irregular stems, but still provides unique.
+     * discriminators in the most of those cases.
+     * The algorithm is context free, except of the length restrictions.
+     */
+    private void strip( StringBuffer buffer )
+    {
+	boolean doMore = true;
+	while ( doMore && buffer.length() > 3 ) {
+	    if ( ( buffer.length() + substCount > 5 ) &&
+		buffer.substring( buffer.length() - 2, buffer.length() ).equals( "nd" ) )
+	    {
+		buffer.delete( buffer.length() - 2, buffer.length() );
+	    }
+	    else if ( ( buffer.length() + substCount > 4 ) &&
+		buffer.substring( buffer.length() - 2, buffer.length() ).equals( "em" ) ) {
+		buffer.delete( buffer.length() - 2, buffer.length() );
+	    }
+	    else if ( ( buffer.length() + substCount > 4 ) &&
+		buffer.substring( buffer.length() - 2, buffer.length() ).equals( "er" ) ) {
+		buffer.delete( buffer.length() - 2, buffer.length() );
+	    }
+	    else if ( buffer.charAt( buffer.length() - 1 ) == 'e' ) {
+		buffer.deleteCharAt( buffer.length() - 1 );
+	    }
+	    else if ( buffer.charAt( buffer.length() - 1 ) == 's' ) {
+		buffer.deleteCharAt( buffer.length() - 1 );
+	    }
+	    else if ( buffer.charAt( buffer.length() - 1 ) == 'n' ) {
+		buffer.deleteCharAt( buffer.length() - 1 );
+	    }
+	    // "t" occurs only as suffix of verbs.
+	    else if ( buffer.charAt( buffer.length() - 1 ) == 't' && !uppercase ) {
+		buffer.deleteCharAt( buffer.length() - 1 );
+	    }
+	    else {
+		doMore = false;
+	    }
+	}
+    }
+
+    /**
+     * Does some optimizations on the term. This optimisations are
+     * contextual.
+     */
+    private void optimize( StringBuffer buffer )
+    {
+	// Additional step for female plurals of professions and inhabitants.
+	if ( buffer.length() > 5 && buffer.substring( buffer.length() - 5, buffer.length() ).equals( "erin*" ) ) {
+	    buffer.deleteCharAt( buffer.length() -1 );
+	    strip( buffer );
+	}
+	// Additional step for irregular plural nouns like "Matrizen -> Matrix".
+	if ( buffer.charAt( buffer.length() - 1 ) == ( 'z' ) ) {
+	    buffer.setCharAt( buffer.length() - 1, 'x' );
+	}
+    }
+
+    /**
+     * Removes a particle denotion ("ge") from a term.
+     */
+    private void removeParticleDenotion( StringBuffer buffer )
+    {
+	if ( buffer.length() > 4 ) {
+	    for ( int c = 0; c < buffer.length() - 3; c++ ) {
+		if ( buffer.substring( c, c + 4 ).equals( "gege" ) ) {
+		    buffer.delete( c, c + 2 );
+		    return;
+		}
+	    }
+	}
+    }
+
+    /**
+     * Do some substitutions for the term to reduce overstemming:
+     *
+     * - Substitute Umlauts with their corresponding vowel: äöü -> aou,
+     *   "ß" is substituted by "ss"
+     * - Substitute a second char of a pair of equal characters with
+     *   an asterisk: ?? -> ?*
+     * - Substitute some common character combinations with a token:
+     *   sch/ch/ei/ie/ig/st -> $/§/%/&/#/!
+     */
+    private void substitute( StringBuffer buffer )
+    {
+	substCount = 0;
+	for ( int c = 0; c < buffer.length(); c++ ) {
+	    // Replace the second char of a pair of the equal characters with an asterisk
+	    if ( c > 0 && buffer.charAt( c ) == buffer.charAt ( c - 1 )  ) {
+		buffer.setCharAt( c, '*' );
+	    }
+	    // Substitute Umlauts.
+	    else if ( buffer.charAt( c ) == '\u00E4' ) {
+		buffer.setCharAt( c, 'a' );
+	    }
+	    else if ( buffer.charAt( c ) == '\u00F6' ) {
+		buffer.setCharAt( c, 'o' );
+	    }
+	    else if ( buffer.charAt( c ) == '\u00FC' ) {
+		buffer.setCharAt( c, 'u' );
+	    }
+	    // Take care that at least one character is left left side from the current one
+	    if ( c < buffer.length() - 1 ) {
+		if ( buffer.charAt( c ) == '\u00DF' ) {
+		    buffer.setCharAt( c, 's' );
+		    buffer.insert( c + 1, 's' );
+		    substCount++;
+		}
+		// Masking several common character combinations with an token
+		else if ( ( c < buffer.length() - 2 ) && buffer.charAt( c ) == 's' &&
+		    buffer.charAt( c + 1 ) == 'c' && buffer.charAt( c + 2 ) == 'h' )
+		{
+		    buffer.setCharAt( c, '$' );
+		    buffer.delete( c + 1, c + 3 );
+		    substCount =+ 2;
+		}
+		else if ( buffer.charAt( c ) == 'c' && buffer.charAt( c + 1 ) == 'h' ) {
+		    buffer.setCharAt( c, '§' );
+		    buffer.deleteCharAt( c + 1 );
+		    substCount++;
+		}
+		else if ( buffer.charAt( c ) == 'e' && buffer.charAt( c + 1 ) == 'i' ) {
+		    buffer.setCharAt( c, '%' );
+		    buffer.deleteCharAt( c + 1 );
+		    substCount++;
+		}
+		else if ( buffer.charAt( c ) == 'i' && buffer.charAt( c + 1 ) == 'e' ) {
+		    buffer.setCharAt( c, '&' );
+		    buffer.deleteCharAt( c + 1 );
+		    substCount++;
+		}
+		else if ( buffer.charAt( c ) == 'i' && buffer.charAt( c + 1 ) == 'g' ) {
+		    buffer.setCharAt( c, '#' );
+		    buffer.deleteCharAt( c + 1 );
+		    substCount++;
+		}
+		else if ( buffer.charAt( c ) == 's' && buffer.charAt( c + 1 ) == 't' ) {
+		    buffer.setCharAt( c, '!' );
+		    buffer.deleteCharAt( c + 1 );
+		    substCount++;
+		}
+	    }
+	}
+    }
+
+    /**
+     * Undoes the changes made by substitute(). That are character pairs and
+     * character combinations. Umlauts will remain as their corresponding vowel,
+     * as "ß" remains as "ss".
+     */
+    private void resubstitute( StringBuffer buffer )
+    {
+	for ( int c = 0; c < buffer.length(); c++ ) {
+	    if ( buffer.charAt( c ) == '*' ) {
+		char x = buffer.charAt( c - 1 );
+		buffer.setCharAt( c, x );
+	    }
+	    else if ( buffer.charAt( c ) == '$' ) {
+		buffer.setCharAt( c, 's' );
+		buffer.insert( c + 1, new char[]{'c', 'h'}, 0, 2 );
+	    }
+	    else if ( buffer.charAt( c ) == '§' ) {
+		buffer.setCharAt( c, 'c' );
+		buffer.insert( c + 1, 'h' );
+	    }
+	    else if ( buffer.charAt( c ) == '%' ) {
+		buffer.setCharAt( c, 'e' );
+		buffer.insert( c + 1, 'i' );
+	    }
+	    else if ( buffer.charAt( c ) == '&' ) {
+		buffer.setCharAt( c, 'i' );
+		buffer.insert( c + 1, 'e' );
+	    }
+	    else if ( buffer.charAt( c ) == '#' ) {
+		buffer.setCharAt( c, 'i' );
+		buffer.insert( c + 1, 'g' );
+	    }
+	    else if ( buffer.charAt( c ) == '!' ) {
+		buffer.setCharAt( c, 's' );
+		buffer.insert( c + 1, 't' );
+	    }
+	}
+    }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/IteratedLovinsStemmer.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/IteratedLovinsStemmer.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/IteratedLovinsStemmer.java	(revision 8815)
@@ -0,0 +1,76 @@
+/*
+ *    IteratedLovinsStemmer.java
+ *    Copyright (C) 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.util.*;
+
+/**
+ * Implements the iterated version of the Lovins stemmer.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public class IteratedLovinsStemmer extends LovinsStemmer {
+
+  /**
+   * Iterated stemming of the given word.
+   */
+  public String stem(String str) {
+
+    if (str.length() <= 2) {
+      return str;
+    }
+    String stemmed = super.stem(str);
+    while (!stemmed.equals(str)) {
+      str = stemmed;
+      stemmed = super.stem(stemmed);
+    }
+    return stemmed;
+  }
+
+  /**
+   * Stems text coming into stdin and writes it to stdout.
+   */
+  public static void main(String[] ops) {
+
+    IteratedLovinsStemmer ls = new IteratedLovinsStemmer();
+
+    try {
+      int num;
+      StringBuffer wordBuffer = new StringBuffer();
+      while ((num = System.in.read()) != -1) {
+	char c = (char)num;
+	if (((num >= (int)'A') && (num <= (int)'Z')) ||
+	    ((num >= (int)'a') && (num <= (int)'z'))) {
+	  wordBuffer.append(c);
+	} else {
+	  if (wordBuffer.length() > 0) {
+	    System.out.print(ls.stem(wordBuffer.toString().
+				     toLowerCase()));
+	    wordBuffer = new StringBuffer();
+	  }
+	  System.out.print(c);
+	}
+      }
+    } catch (Exception e) {
+      System.err.println(e.getMessage());
+    }
+  }
+}
+    
+
Index: /trunk/gsdl/packages/kea/kea-3.0/KEAFilter.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/KEAFilter.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/KEAFilter.java	(revision 8815)
@@ -0,0 +1,1496 @@
+/*
+ *    KEAFilter.java
+ *    Copyright (C) 2000, 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.util.*;
+import java.io.*;
+
+import weka.core.*;
+import weka.filters.*;
+import weka.classifiers.*;
+
+/**
+ * This filter converts the incoming data into data appropriate for
+ * keyphrase classification. It assumes that the dataset contains two
+ * string attributes. The first attribute should contain the text of a
+ * document. The second attribute should contain the keyphrases
+ * associated with that document (if present). 
+ *
+ * The filter converts every instance (i.e. document) into a set of
+ * instances, one for each word-based n-gram in the document. The
+ * string attribute representing the document is replaced by some
+ * numeric features, the estimated probability of each n-gram being a
+ * keyphrase, and the rank of this phrase in the document according to
+ * the probability.  Each new instances also has a class value
+ * associated with it. The class is "true" if the n-gram is a true
+ * keyphrase, and "false" otherwise. Of course, if the input document
+ * doesn't come with author-assigned keyphrases, the class values for
+ * that document will be missing.  
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+  */
+public class KEAFilter extends Filter implements OptionHandler {
+
+  /** Index of attribute containing the documents */
+  private int m_DocumentAtt = 0;
+
+  /** Index of attribute containing the keyphrases */
+  private int m_KeyphrasesAtt = 1;
+
+  /** The maximum length of phrases */
+  private int m_MaxPhraseLength = 3;
+
+  /** The minimum length of phrases */
+  private int m_MinPhraseLength = 1;
+
+  /** Is keyphrase frequency attribute being used? */
+  private boolean m_KFused = false;
+
+  /** Flag for debugging mode */
+  private boolean m_Debug = false;
+
+  /** Determines whether internal periods are allowed */
+  private boolean m_DisallowInternalPeriods = false;
+
+  /** The minimum number of occurences of a phrase */
+  private int m_MinNumOccur = 2;
+
+  /** The number of features describing a phrase */
+  private int m_NumFeatures = 2;
+
+  /* Indices of attributes in m_ClassifierData */
+  private int m_TfidfIndex = 0;
+  private int m_FirstOccurIndex = 1;
+  private int m_KeyFreqIndex = 2;
+
+  /** The punctuation filter used by this filter */
+  private KEAPhraseFilter m_PunctFilter = null;
+
+  /** The numbers filter used by this filter */
+  private NumbersFilter m_NumbersFilter = null;
+ 
+  /** The actual classifier used to compute probabilities */
+  private DistributionClassifier m_Classifier = null;
+
+  /** The dictionary containing the document frequencies */
+  private HashMap m_Dictionary = null;
+
+  /** The dictionary containing the keyphrases */
+  private HashMap m_KeyphraseDictionary = null;
+
+  /** The number of documents in the global frequencies corpus */
+  private int m_NumDocs = 0;
+
+  /** Template for the classifier data */
+  private Instances m_ClassifierData = null;
+
+  /** The stemmer to be used */
+  private Stemmer m_Stemmer = new IteratedLovinsStemmer();
+
+  /** The list of stop words to be used */
+  private Stopwords m_Stopwords = new StopwordsEnglish();
+
+  /** Determines whether check for proper nouns is performed */
+  private boolean m_CheckForProperNouns = true;
+
+  /**
+   * Get the M_CheckProperNouns value.
+   * @return the M_CheckProperNouns value.
+   */
+  public boolean getCheckForProperNouns() {
+    return m_CheckForProperNouns;
+  }
+
+  /**
+   * Set the M_CheckProperNouns value.
+   * @param newM_CheckProperNouns The new M_CheckProperNouns value.
+   */
+  public void setCheckForProperNouns(boolean newM_CheckProperNouns) {
+    this.m_CheckForProperNouns = newM_CheckProperNouns;
+  }
+  
+  /**
+   * Get the M_Stopwords value.
+   * @return the M_Stopwords value.
+   */
+  public Stopwords getStopwords() {
+    return m_Stopwords;
+  }
+
+  /**
+   * Set the M_Stopwords value.
+   * @param newM_Stopwords The new M_Stopwords value.
+   */
+  public void setStopwords(Stopwords newM_Stopwords) {
+    this.m_Stopwords = newM_Stopwords;
+  }
+
+  
+  /**
+   * Get the Stemmer value.
+   * @return the Stemmer value.
+   */
+  public Stemmer getStemmer() {
+
+    return m_Stemmer;
+  }
+
+  /**
+   * Set the Stemmer value.
+   * @param newStemmer The new Stemmer value.
+   */
+  public void setStemmer(Stemmer newStemmer) {
+
+    this.m_Stemmer = newStemmer;
+  }
+
+  /**
+   * Get the value of MinNumOccur.
+   *
+   * @return Value of MinNumOccur.
+   */
+  public int getMinNumOccur() {
+    
+    return m_MinNumOccur;
+  }
+  
+  /**
+   * Set the value of MinNumOccur.
+   *
+   * @param newMinNumOccur Value to assign to MinNumOccur.
+   */
+  public void setMinNumOccur(int newMinNumOccur) {
+    
+    m_MinNumOccur = newMinNumOccur;
+  }
+  
+  /**
+   * Get the value of MaxPhraseLength.
+   *
+   * @return Value of MaxPhraseLength.
+   */
+  public int getMaxPhraseLength() {
+    
+    return m_MaxPhraseLength;
+  }
+  
+  /**
+   * Set the value of MaxPhraseLength.
+   *
+   * @param newMaxPhraseLength Value to assign to MaxPhraseLength.
+   */
+  public void setMaxPhraseLength(int newMaxPhraseLength) {
+    
+    m_MaxPhraseLength = newMaxPhraseLength;
+  }
+  
+  /**
+   * Get the value of MinPhraseLength.
+   *
+   * @return Value of MinPhraseLength.
+   */
+  public int getMinPhraseLength() {
+    
+    return m_MinPhraseLength;
+  }
+  
+  /**
+   * Set the value of MinPhraseLength.
+   *
+   * @param newMinPhraseLength Value to assign to MinPhraseLength.
+   */
+  public void setMinPhraseLength(int newMinPhraseLength) {
+    
+    m_MinPhraseLength = newMinPhraseLength;
+  }
+
+  /**
+   * Returns the index of the stemmed phrases in the output ARFF file.
+   */
+  public int getStemmedPhraseIndex() {
+
+    return m_DocumentAtt;
+  }
+
+  /**
+   * Returns the index of the unstemmed phrases in the output ARFF file.
+   */
+  public int getUnstemmedPhraseIndex() {
+
+    return m_DocumentAtt + 1;
+  }
+
+  /**
+   * Returns the index of the phrases' probabilities in the output ARFF file.
+   */
+  public int getProbabilityIndex() {
+
+    int index = m_DocumentAtt + 4;
+
+    if (m_Debug) {
+      if (m_KFused) {
+	index++;
+      }
+    }
+    return index;
+  }
+
+  /**
+   * Returns the index of the phrases' ranks in the output ARFF file.
+   */
+  public int getRankIndex() {
+
+    return getProbabilityIndex() + 1;
+  }
+
+  /**
+   * Get the value of DocumentAtt.
+   *
+   * @return Value of DocumentAtt.
+   */
+  public int getDocumentAtt() {
+    
+    return m_DocumentAtt;
+  }
+  
+  /**
+   * Set the value of DocumentAtt.
+   *
+   * @param newDocumentAtt Value to assign to DocumentAtt.
+   */
+  public void setDocumentAtt(int newDocumentAtt) {
+    
+    m_DocumentAtt = newDocumentAtt;
+  }
+  
+  /**
+   * Get the value of KeyphraseAtt.
+   *
+   * @return Value of KeyphraseAtt.
+   */
+  public int getKeyphrasesAtt() {
+    
+    return m_KeyphrasesAtt;
+  }
+  
+  /**
+   * Set the value of KeyphrasesAtt.
+   *
+   * @param newKeyphrasesAtt Value to assign to KeyphrasesAtt.
+   */
+  public void setKeyphrasesAtt(int newKeyphrasesAtt) {
+    
+    m_KeyphrasesAtt = newKeyphrasesAtt;
+  }
+  
+  
+  /**
+   * Get the value of Debug.
+   *
+   * @return Value of Debug.
+   */
+  public boolean getDebug() {
+    
+    return m_Debug;
+  }
+  
+  /**
+   * Set the value of Debug.
+   *
+   * @param newDebug Value to assign to Debug.
+   */
+  public void setDebug(boolean newDebug) {
+    
+    m_Debug = newDebug;
+  }
+
+  /**
+   * Sets whether keyphrase frequency attribute is used.
+   */
+  public void setKFused(boolean flag) {
+
+    m_KFused = flag;
+    if (flag) {
+      m_NumFeatures = 3;
+    } else {
+      m_NumFeatures = 2;
+    }
+  }
+
+  /**
+   * Gets whether keyphrase frequency attribute is used.
+   */
+  public boolean getKFused() {
+
+    return m_KFused;
+  }
+
+  /**
+   * Get whether the supplied columns are to be processed
+   *
+   * @return true if the supplied columns won't be processed
+   */
+  public boolean getDisallowInternalPeriods() {
+
+    return m_DisallowInternalPeriods;
+  }
+
+  /**
+   * Set whether selected columns should be processed. If true the 
+   * selected columns won't be processed.
+   *
+   * @param invert the new invert setting
+   */
+  public void setDisallowInternalPeriods(boolean disallow) {
+
+    m_DisallowInternalPeriods = disallow;
+  }
+
+  /**
+   * Parses a given list of options controlling the behaviour of this object.
+   * Valid options are:<p>
+   *
+   * -K<br>
+   * Specifies whether keyphrase frequency statistic is used.<p>
+   *
+   * -M length<br>
+   * Sets the maximum phrase length (default: 3).<p>
+   *
+   * -L length<br>
+   * Sets the minimum phrase length (default: 1).<p>
+   *
+   * -D<br>
+   * Turns debugging mode on.<p>
+   *
+   * -I index<br>
+   * Sets the index of the attribute containing the documents (default: 0).<p>
+   *
+   * -J index<br>
+   * Sets the index of the attribute containing the keyphrases (default: 1).<p>
+   *
+   * -P<br>
+   * Disallow internal periods <p>
+   *
+   * -O number<br>
+   * The minimum number of times a phrase needs to occur (default: 2). <p>
+   *
+   * @param options the list of options as an array of strings
+   * @exception Exception if an option is not supported
+   */
+  public void setOptions(String[] options) throws Exception {
+
+    setKFused(Utils.getFlag('K', options));
+    setDebug(Utils.getFlag('D', options));
+    String docAttIndexString = Utils.getOption('I', options);
+    if (docAttIndexString.length() > 0) {
+      setDocumentAtt(Integer.parseInt(docAttIndexString) - 1);
+    } else {
+      setDocumentAtt(0);
+    }
+    String keyphraseAttIndexString = Utils.getOption('J', options);
+    if (keyphraseAttIndexString.length() > 0) {
+      setKeyphrasesAtt(Integer.parseInt(keyphraseAttIndexString) - 1);
+    } else {
+      setKeyphrasesAtt(1);
+    }
+    String maxPhraseLengthString = Utils.getOption('M', options);
+    if (maxPhraseLengthString.length() > 0) {
+      setMaxPhraseLength(Integer.parseInt(maxPhraseLengthString));
+    } else {
+      setMaxPhraseLength(3);
+    }
+    String minPhraseLengthString = Utils.getOption('M', options);
+    if (minPhraseLengthString.length() > 0) {
+      setMinPhraseLength(Integer.parseInt(minPhraseLengthString));
+    } else {
+      setMinPhraseLength(1);
+    }
+    String minNumOccurString = Utils.getOption('O', options);
+    if (minNumOccurString.length() > 0) {
+      setMinNumOccur(Integer.parseInt(minNumOccurString));
+    } else {
+      setMinNumOccur(2);
+    }
+    setDisallowInternalPeriods(Utils.getFlag('P', options));
+   }
+
+  /**
+   * Gets the current settings of the filter.
+   *
+   * @return an array of strings suitable for passing to setOptions
+   */
+  public String [] getOptions() {
+
+    String [] options = new String [13];
+    int current = 0;
+
+    if (getKFused()) {
+      options[current++] = "-K";
+    }
+    if (getDebug()) {
+      options[current++] = "-D";
+    }
+    options[current++] = "-I"; 
+    options[current++] = "" + (getDocumentAtt() + 1);
+    options[current++] = "-J"; 
+    options[current++] = "" + (getKeyphrasesAtt() + 1);
+    options[current++] = "-M"; 
+    options[current++] = "" + (getMaxPhraseLength());
+    options[current++] = "-L"; 
+    options[current++] = "" + (getMinPhraseLength());
+    options[current++] = "-O"; 
+    options[current++] = "" + (getMinNumOccur());
+
+    if (getDisallowInternalPeriods()) {
+      options[current++] = "-P";
+    }
+
+    while (current < options.length) {
+      options[current++] = "";
+    }
+    return options;
+  }
+
+  /**
+   * Returns an enumeration describing the available options
+   *
+   * @return an enumeration of all the available options
+   */
+  public Enumeration listOptions() {
+
+    Vector newVector = new Vector(7);
+
+    newVector.addElement(new Option(
+	      "\tSpecifies whether keyphrase frequency statistic is used.",
+              "K", 0, "-K"));
+    newVector.addElement(new Option(
+	      "\tSets the maximum phrase length (default: 3).",
+              "M", 1, "-M <length>"));
+    newVector.addElement(new Option(
+	      "\tSets the minimum phrase length (default: 1).",
+              "L", 1, "-L <length>"));
+    newVector.addElement(new Option(
+	      "\tTurns debugging mode on.",
+              "D", 0, "-D"));
+    newVector.addElement(new Option(
+	      "\tSets the index of the document attribute (default: 0).",
+              "I", 1, "-I"));
+    newVector.addElement(new Option(
+	      "\tSets the index of the keyphrase attribute (default: 1).",
+              "J", 1, "-J"));
+    newVector.addElement(new Option(
+	      "\tDisallow internal periods.",
+              "P", 0, "-P"));
+    newVector.addElement(new Option(
+	      "\tSet the minimum number of occurences (default: 2).",
+              "O", 1, "-O"));
+
+    return newVector.elements();
+  }
+
+  /**
+   * Returns a string describing this filter
+   *
+   * @return a description of the filter suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String globalInfo() {
+    return "Converts incoming data into data appropriate for " +
+      "keyphrase classification.";
+  }
+
+  /**
+   * Sets the format of the input instances.
+   *
+   * @param instanceInfo an Instances object containing the input
+   * instance structure (any instances contained in the object are
+   * ignored - only the structure is required).
+   * @return true if the outputFormat may be collected immediately 
+   */
+  public boolean setInputFormat(Instances instanceInfo) throws Exception {
+
+    if (instanceInfo.classIndex() >= 0) {
+      throw new Exception("Don't know what do to if class index set!");
+    }
+    if (!instanceInfo.attribute(m_KeyphrasesAtt).isString() ||
+	!instanceInfo.attribute(m_DocumentAtt).isString()) {
+      throw new Exception("Keyphrase attribute and document attribute " +
+			  "need to be string attributes.");
+    }
+    m_PunctFilter = new KEAPhraseFilter();
+    int[] arr = new int[1];
+    arr[0] = m_DocumentAtt;
+    m_PunctFilter.setAttributeIndicesArray(arr);
+    m_PunctFilter.setInputFormat(instanceInfo);
+    m_PunctFilter.setDisallowInternalPeriods(getDisallowInternalPeriods());
+    m_NumbersFilter = new NumbersFilter();
+    m_NumbersFilter.setInputFormat(m_PunctFilter.getOutputFormat());
+    super.setInputFormat(m_NumbersFilter.getOutputFormat());
+    return false;
+  }
+
+  /**
+   * Input an instance for filtering. Ordinarily the instance is processed
+   * and made available for output immediately. Some filters require all
+   * instances be read before producing output.
+   *
+   * @param instance the input instance
+   * @return true if the filtered instance may now be
+   * collected with output().
+   * @exception Exception if the input instance was not of the correct 
+   * format or if there was a problem with the filtering.
+   */
+  public boolean input(Instance instance) throws Exception {
+
+    if (getInputFormat() == null) {
+      throw new Exception("No input instance format defined");
+    }
+    if (m_NewBatch) {
+      resetQueue();
+      m_NewBatch = false;
+    }
+
+    if (m_Debug) {
+      System.err.println("-- Reading instance");
+    }
+
+    m_PunctFilter.input(instance);
+    m_PunctFilter.batchFinished();
+    instance = m_PunctFilter.output();
+
+    m_NumbersFilter.input(instance);
+    m_NumbersFilter.batchFinished();
+    instance = m_NumbersFilter.output();
+    
+    if (m_Dictionary == null) {
+      bufferInput(instance);
+      return false;
+    } else {
+      FastVector vector = convertInstance(instance, false);
+      Enumeration enum = vector.elements();
+      while (enum.hasMoreElements()) {
+	Instance inst = (Instance)enum.nextElement();
+	push(inst);
+      }
+      return true;
+    }
+  }
+
+  /**
+   * Signify that this batch of input to the filter is finished. 
+   * If the filter requires all instances prior to filtering,
+   * output() may now be called to retrieve the filtered instances.
+   *
+   * @return true if there are instances pending output
+   * @exception Exception if no input structure has been defined
+   */
+  public boolean batchFinished() throws Exception {
+
+    if (getInputFormat() == null) {
+      throw new Exception("No input instance format defined");
+    }
+    if (m_Dictionary == null) {
+      buildGlobalDictionaries();
+      buildClassifier();
+      convertPendingInstances();
+    } 
+    flushInput();
+    m_NewBatch = true;
+    return (numPendingOutput() != 0);
+  }
+
+  /**
+   * Builds the global dictionaries.
+   */
+  private void buildGlobalDictionaries() throws Exception {
+
+    if (m_Debug) {
+      System.err.println("--- Building global dictionaries");
+    }
+    
+    // Build dictionary of n-grams with associated
+    // document frequencies
+    m_Dictionary = new HashMap();
+    for (int i = 0; i < getInputFormat().numInstances(); i++) {
+      String str = getInputFormat().instance(i).stringValue(m_DocumentAtt);
+      HashMap hash = getPhrasesForDictionary(str);
+      Iterator it = hash.keySet().iterator();
+      while (it.hasNext()) {
+	String phrase = (String)it.next();
+	Counter counter = (Counter)m_Dictionary.get(phrase);
+	if (counter == null) {
+	  m_Dictionary.put(phrase, new Counter());
+	} else {
+	  counter.increment();
+	}
+      }
+    }
+    
+    if (m_KFused) {
+      
+      // Build dictionary of n-grams that occur as keyphrases
+      // with associated keyphrase frequencies
+      m_KeyphraseDictionary = new HashMap();
+      for (int i = 0; i < getInputFormat().numInstances(); i++) {
+	String str = getInputFormat().instance(i).stringValue(m_KeyphrasesAtt);
+	HashMap hash = getGivenKeyphrases(str, false);
+	if (hash != null) {
+	  Iterator it = hash.keySet().iterator();
+	  while (it.hasNext()) {
+	    String phrase = (String)it.next();
+	    Counter counter = (Counter)m_KeyphraseDictionary.get(phrase);
+	    if (counter == null) {
+	      m_KeyphraseDictionary.put(phrase, new Counter());
+	    } else {
+	      counter.increment();
+	    }
+	  }
+	}
+      }
+    } else {
+      m_KeyphraseDictionary = null;
+    }
+    
+    // Set the number of documents in the global corpus
+    m_NumDocs = getInputFormat().numInstances();
+  }
+ 
+  /**
+   * Builds the classifier.
+   */
+  private void buildClassifier() throws Exception {
+    
+    // Generate input format for classifier
+    FastVector atts = new FastVector();
+    for (int i = 0; i < getInputFormat().numAttributes(); i++) {
+      if (i == m_DocumentAtt) {
+	atts.addElement(new Attribute("TFxIDF"));
+	atts.addElement(new Attribute("First_occurrence"));
+	if (m_KFused) {
+	  atts.addElement(new Attribute("Keyphrase_frequency"));
+	}
+      } else if (i == m_KeyphrasesAtt) {
+	FastVector vals = new FastVector(2);
+	vals.addElement("False");
+	vals.addElement("True");
+	atts.addElement(new Attribute("Keyphrase?", vals));
+      } 
+    }
+    m_ClassifierData = new Instances("ClassifierData", atts, 0);
+    m_ClassifierData.setClassIndex(m_NumFeatures);
+    
+    if (m_Debug) {
+      System.err.println("--- Converting instances for classifier");
+    }
+    
+    // Convert pending input instances into data for classifier
+    for(int i = 0; i < getInputFormat().numInstances(); i++) {
+      Instance current = getInputFormat().instance(i);
+
+      // Get the key phrases for the document
+      String keyphrases = current.stringValue(m_KeyphrasesAtt);
+      HashMap hashKeyphrases = getGivenKeyphrases(keyphrases, false);
+      HashMap hashKeysEval = getGivenKeyphrases(keyphrases, true);
+
+      // Get the phrases for the document
+      HashMap hash = new HashMap();
+      int length = getPhrases(hash, current.stringValue(m_DocumentAtt));
+
+      // Compute the feature values for each phrase and
+      // add the instance to the data for the classifier
+      Iterator it = hash.keySet().iterator();
+      while (it.hasNext()) {
+	String phrase = (String)it.next();
+	FastVector phraseInfo = (FastVector)hash.get(phrase);
+	double[] vals =  featVals(phrase, phraseInfo, true,
+				  hashKeysEval, hashKeyphrases, length);
+	Instance inst = new Instance(current.weight(), vals);
+	m_ClassifierData.add(inst);
+      }
+    }
+    
+    if (m_Debug) {
+      System.err.println("--- Building classifier");
+    }
+    
+    // Build classifier
+    FilteredClassifier fclass = new FilteredClassifier();
+    fclass.setClassifier(new weka.classifiers.NaiveBayesSimple());
+    fclass.setFilter(new DiscretizeFilter());
+    m_Classifier = fclass;
+    m_Classifier.buildClassifier(m_ClassifierData);
+
+    if (m_Debug) {
+      System.err.println(m_Classifier);
+    }
+
+    // Save space
+    m_ClassifierData = new Instances(m_ClassifierData, 0);
+  }
+
+  /** 
+   * Conmputes the feature values for a given phrase.
+   */
+  private double[] featVals(String phrase, FastVector phraseInfo, 
+			    boolean training, HashMap hashKeysEval,
+			    HashMap hashKeyphrases, int length) {
+
+    // Compute feature values
+    Counter counterLocal = (Counter)phraseInfo.elementAt(1);
+    double[] newInst = new double[m_NumFeatures + 1];
+	  
+    // Compute TFxIDF
+    Counter counterGlobal = (Counter)m_Dictionary.get(phrase);
+    double localVal = counterLocal.value(), globalVal = 0;
+    if (counterGlobal != null) {
+      globalVal = counterGlobal.value();
+      if (training) {
+	globalVal = globalVal - 1;
+      }
+    }
+    
+    // Just devide by length to get approximation of probability
+    // that phrase in document is our phrase
+    newInst[m_TfidfIndex] = (localVal / ((double)length)) *
+      (-Math.log((globalVal + 1)/ ((double)m_NumDocs + 1)));
+	  
+    // Compute first occurrence
+    Counter counterFirst = (Counter)phraseInfo.elementAt(0);
+    newInst[m_FirstOccurIndex] = (double)counterFirst.value() /
+      (double)length;
+    
+    // Is keyphrase frequency attribute being used?
+    if (m_KFused) {
+      Counter keyphraseC = (Counter)m_KeyphraseDictionary.get(phrase);
+      if ((training) && (hashKeyphrases != null) &&
+	  (hashKeyphrases.containsKey(phrase))) {
+	newInst[m_KeyFreqIndex] = keyphraseC.value() - 1;
+      } else {
+	if (keyphraseC != null) {
+	  newInst[m_KeyFreqIndex] = keyphraseC.value();
+	} else {
+	  newInst[m_KeyFreqIndex] = 0;
+	}
+      }
+    }
+
+    // Compute class value
+    String phraseInEvalFormat = evalFormat((String)phraseInfo.elementAt(2));
+    if (hashKeysEval == null) { // no author-assigned keyphrases
+      newInst[m_NumFeatures] = Instance.missingValue();
+    } else if (!hashKeysEval.containsKey(phraseInEvalFormat)) {
+      newInst[m_NumFeatures] = 0; // No keyphrase
+    } else {
+      hashKeysEval.remove(phraseInEvalFormat);
+      newInst[m_NumFeatures] = 1; // Keyphrase
+    }
+    return newInst;
+  }
+
+  /**
+   * Sets output format and converts pending input instances.
+   */
+  private void convertPendingInstances() throws Exception {
+
+    if (m_Debug) {
+      System.err.println("--- Converting pending instances");
+    }
+    
+    // Create output format for filter
+    FastVector atts = new FastVector();
+    for (int i = 0; i < getInputFormat().numAttributes(); i++) {
+      if (i == m_DocumentAtt) {
+	atts.addElement(new Attribute("N-gram", null));
+	atts.addElement(new Attribute("N-gram-original", null));
+	atts.addElement(new Attribute("TFxIDF"));
+	atts.addElement(new Attribute("First_occurrence"));
+	if (m_Debug) {
+	  if (m_KFused) {
+	    atts.addElement(new Attribute("Keyphrase_frequency"));
+	  }
+	}
+	atts.addElement(new Attribute("Probability"));
+	atts.addElement(new Attribute("Rank"));
+      } else if (i == m_KeyphrasesAtt) {
+	FastVector vals = new FastVector(2);
+	vals.addElement("False");
+	vals.addElement("True");
+	atts.addElement(new Attribute("Keyphrase?", vals));
+      } else {
+	atts.addElement(getInputFormat().attribute(i));
+      }
+    }
+    Instances outFormat = new Instances("KEAdata", atts, 0);
+    setOutputFormat(outFormat);
+    
+    // Convert pending input instances into output data
+    for(int i = 0; i < getInputFormat().numInstances(); i++) {
+      Instance current = getInputFormat().instance(i);
+      FastVector vector = convertInstance(current, true);
+      Enumeration enum = vector.elements();
+      while (enum.hasMoreElements()) {
+	Instance inst = (Instance)enum.nextElement();
+	push(inst);
+      }
+    }
+  } 
+
+  /**
+   * Converts an instance.
+   */
+  private FastVector convertInstance(Instance instance, boolean training) 
+    throws Exception {
+
+    FastVector vector = new FastVector();
+
+    if (m_Debug) {
+      System.err.println("-- Converting instance");
+    }
+
+    // Get the key phrases for the document
+    HashMap hashKeyphrases = null;
+    HashMap hashKeysEval = null;
+    if (!instance.isMissing(m_KeyphrasesAtt)) {
+      String keyphrases = instance.stringValue(m_KeyphrasesAtt);
+      hashKeyphrases = getGivenKeyphrases(keyphrases, false);
+      hashKeysEval = getGivenKeyphrases(keyphrases, true);
+    }
+
+    // Get the phrases for the document
+    HashMap hash = new HashMap();
+    int length = getPhrases(hash, instance.stringValue(m_DocumentAtt));
+
+    // Compute number of extra attributes
+    int numFeatures = 5;
+    if (m_Debug) {
+      if (m_KFused) {
+	numFeatures = numFeatures + 1;
+      }
+    } 
+
+    // Set indices of key attributes
+    int phraseAttIndex = m_DocumentAtt;
+    int tfidfAttIndex = m_DocumentAtt + 2;
+    int distAttIndex = m_DocumentAtt + 3;
+    int probsAttIndex = m_DocumentAtt + numFeatures - 1;
+
+    // Go through the phrases and convert them into instances
+    Iterator it = hash.keySet().iterator();
+    while (it.hasNext()) {
+      String phrase = (String)it.next();
+      FastVector phraseInfo = (FastVector)hash.get(phrase);
+      double[] vals =  featVals(phrase, phraseInfo, training,
+				hashKeysEval, hashKeyphrases, length);
+      Instance inst = new Instance(instance.weight(), vals);
+      inst.setDataset(m_ClassifierData);
+
+      // Get probability of phrase being key phrase
+      double[] probs = m_Classifier.distributionForInstance(inst);
+      double prob = probs[1];
+
+      // Compute attribute values for final instance
+      double[] newInst = 
+	new double[instance.numAttributes() + numFeatures];
+      int pos = 0;
+      for (int i = 0; i < instance.numAttributes(); i++) {
+	if (i == m_DocumentAtt) {
+	    
+	  // Add phrase
+	  int index = outputFormatPeek().attribute(pos).
+	    addStringValue(phrase);
+	  newInst[pos++] = index;
+	  
+	  // Add original version
+	  index = outputFormatPeek().attribute(pos).
+	    addStringValue((String)phraseInfo.elementAt(2));
+	  newInst[pos++] = index;
+
+	  // Add TFxIDF
+	  newInst[pos++] = inst.value(m_TfidfIndex);
+	    
+	  // Add distance
+	  newInst[pos++] = inst.value(m_FirstOccurIndex);
+
+	    // Add other features
+	  if (m_Debug) {
+	    if (m_KFused) {
+	      newInst[pos++] = inst.value(m_KeyFreqIndex);
+	    }
+	  }
+
+	  // Add probability 
+	  probsAttIndex = pos;
+	  newInst[pos++] = prob;
+
+	  // Set rank to missing (computed below)
+	  newInst[pos++] = Instance.missingValue();
+	} else if (i == m_KeyphrasesAtt) {
+	  newInst[pos++] = inst.classValue();
+	} else {
+	  newInst[pos++] = instance.value(i);
+	}
+      }
+      Instance ins = new Instance(instance.weight(), newInst);
+      ins.setDataset(outputFormatPeek());
+      vector.addElement(ins);
+    }
+
+    // Add dummy instances for keyphrases that don't occur
+    // in the document
+    if (hashKeysEval != null) {
+      Iterator phrases = hashKeysEval.keySet().iterator();
+      while (phrases.hasNext()) {
+	String phrase = (String)phrases.next();
+	double[] newInst = 
+	  new double[instance.numAttributes() + numFeatures];
+	int pos = 0;
+	for (int i = 0; i < instance.numAttributes(); i++) {
+	  if (i == m_DocumentAtt) {
+	    
+	    // Add phrase
+	    int index = outputFormatPeek().attribute(pos).
+	      addStringValue(phrase);
+	    newInst[pos++] = (double)index;
+	    
+	    // Add original version
+	    index = outputFormatPeek().attribute(pos).
+	      addStringValue((String)hashKeysEval.get(phrase));
+	    newInst[pos++] = (double)index;
+	    
+	    // Add TFxIDF
+	    newInst[pos++] = Instance.missingValue();
+	    
+	    // Add distance
+	    newInst[pos++] = Instance.missingValue();
+	      
+	    // Add other features
+	    if (m_Debug) {
+	      if (m_KFused) {
+		newInst[pos++] = Instance.missingValue();
+	      }
+	    }
+
+	    // Add probability and rank
+	    newInst[pos++] = -Double.MAX_VALUE;
+	    newInst[pos++] = Instance.missingValue();
+	  } else if (i == m_KeyphrasesAtt) {
+	    newInst[pos++] = 1; // Keyphrase
+	  } else {
+	    newInst[pos++] = instance.value(i);
+	  } 
+	}
+	Instance inst = new Instance(instance.weight(), newInst);
+	inst.setDataset(outputFormatPeek());
+	vector.addElement(inst);
+      }
+    }
+
+    // Sort phrases according to their distance (stable sort)
+    double[] vals = new double[vector.size()];
+    for (int i = 0; i < vals.length; i++) {
+      vals[i] = ((Instance)vector.elementAt(i)).value(distAttIndex);
+    }
+    FastVector newVector = new FastVector(vector.size());
+    int[] sortedIndices = Utils.stableSort(vals);
+    for (int i = 0; i < vals.length; i++) {
+      newVector.addElement(vector.elementAt(sortedIndices[i]));
+    }
+    vector = newVector;
+
+    // Sort phrases according to their tfxidf value (stable sort)
+    for (int i = 0; i < vals.length; i++) {
+      vals[i] = -((Instance)vector.elementAt(i)).value(tfidfAttIndex);
+    }
+    newVector = new FastVector(vector.size());
+    sortedIndices = Utils.stableSort(vals);
+    for (int i = 0; i < vals.length; i++) {
+      newVector.addElement(vector.elementAt(sortedIndices[i]));
+    }
+    vector = newVector;
+
+    // Sort phrases according to their probability (stable sort)
+    for (int i = 0; i < vals.length; i++) {
+      vals[i] = 1 - ((Instance)vector.elementAt(i)).value(probsAttIndex);
+    }
+    newVector = new FastVector(vector.size());
+    sortedIndices = Utils.stableSort(vals);
+    for (int i = 0; i < vals.length; i++) {
+      newVector.addElement(vector.elementAt(sortedIndices[i]));
+    }
+    vector = newVector;
+
+    // Compute rank of phrases. Check for subphrases that are ranked
+    // lower than superphrases and assign probability -1 and set the
+    // rank to Integer.MAX_VALUE
+    int rank = 1;
+    for (int i = 0; i < vals.length; i++) {
+      Instance currentInstance = (Instance)vector.elementAt(i);
+
+      // Short cut: if phrase very unlikely make rank very low and continue
+      if (Utils.grOrEq(vals[i], 1.0)) {
+	currentInstance.setValue(probsAttIndex + 1, Integer.MAX_VALUE);
+	continue;
+      }
+
+      // Otherwise look for super phrase starting with first phrase
+      // in list that has same probability, TFxIDF value, and distance as
+      // current phrase. We do this to catch all superphrases
+      // that have same probability, TFxIDF value and distance as current phrase.
+      int startInd = i;
+      while (startInd < vals.length) {
+	Instance inst = (Instance)vector.elementAt(startInd);
+	if ((inst.value(tfidfAttIndex) != 
+	     currentInstance.value(tfidfAttIndex)) ||
+	    (inst.value(probsAttIndex) != 
+	     currentInstance.value(probsAttIndex)) ||
+	    (inst.value(distAttIndex) !=
+	     currentInstance.value(distAttIndex))) {
+	  break;
+	}
+	startInd++;
+      }
+      String val = currentInstance.stringValue(phraseAttIndex);
+      boolean foundSuperphrase = false;
+      for (int j = startInd - 1; j >= 0; j--) {
+	if (j != i) {
+	  Instance candidate = (Instance)vector.elementAt(j);
+	  String potSuperphrase = candidate.stringValue(phraseAttIndex);
+	  if (val.length() <= potSuperphrase.length()) {
+	    if (KEAFilter.contains(val, potSuperphrase)) {
+	      foundSuperphrase = true;
+	      break;
+	    }
+	  }
+	}
+      }
+      if (foundSuperphrase) {
+	currentInstance.setValue(probsAttIndex + 1, Integer.MAX_VALUE);
+      } else {
+	currentInstance.setValue(probsAttIndex + 1, rank++);
+      }
+    }
+    return vector;
+  }
+    
+  /** 
+   * Checks whether one phrase is a subphrase of another phrase.
+   */
+  private static boolean contains(String sub, String sup) {
+
+    int i = 0;
+    while (i + sub.length() - 1 < sup.length()) {
+      int j;
+      for (j = 0; j < sub.length(); j++) {
+	if (sub.charAt(j) != sup.charAt(i + j)) {
+	  break;
+	}
+      }
+      if (j == sub.length()) {
+	if ((i + j) < sup.length()) {
+	  if (sup.charAt(i + j) == ' ') {
+	    return true;
+	  } else {
+	    return false;
+	  }
+	} else {
+	  return true;
+	}
+      }
+
+      // Skip forward to next space
+      do {
+	i++;
+      } while ((i < sup.length()) && (sup.charAt(i) != ' '));
+      i++;
+    }
+    return false;
+  }
+
+  /**
+   * Returns a hashtable. Fills the hashtable
+   * with the stemmed n-grams occuring in the given string
+   * (as keys) and the number of times it occurs.
+   */
+  private HashMap getPhrasesForDictionary(String str) {
+
+    String[] buffer = new String[m_MaxPhraseLength];
+    HashMap hash = new HashMap();
+
+    StringTokenizer tok = new StringTokenizer(str, "\n");
+    while (tok.hasMoreTokens()) {
+      String phrase = tok.nextToken();
+      int numSeen = 0;
+      StringTokenizer wordTok = new StringTokenizer(phrase, " ");
+      while (wordTok.hasMoreTokens()) {
+	String word = wordTok.nextToken();
+	
+	// Store word in buffer
+	for (int i = 0; i < m_MaxPhraseLength - 1; i++) {
+	  buffer[i] = buffer[i + 1];
+	}
+	buffer[m_MaxPhraseLength - 1] = word;
+	
+	// How many are buffered?
+	numSeen++;
+	if (numSeen > m_MaxPhraseLength) {
+	  numSeen = m_MaxPhraseLength;
+	}
+	
+	// Don't consider phrases that end with a stop word
+	if (m_Stopwords.isStopword(buffer[m_MaxPhraseLength - 1])) {
+	  continue;
+	}
+	
+	// Loop through buffer and add phrases to hashtable
+	StringBuffer phraseBuffer = new StringBuffer();
+	for (int i = 1; i <= numSeen; i++) {
+	  if (i > 1) {
+	    phraseBuffer.insert(0, ' ');
+	  }
+	  phraseBuffer.insert(0, buffer[m_MaxPhraseLength - i]);
+	  
+	  // Don't consider phrases that begin with a stop word
+	  if ((i > 1) && 
+	      (m_Stopwords.isStopword(buffer[m_MaxPhraseLength - i]))) {
+	    continue;
+	  }
+	  
+	  // Only consider phrases with minimum length
+	  if (i >= m_MinPhraseLength) {
+	    
+	    // Stem string
+	    String orig = phraseBuffer.toString();
+	    String internal = internalFormat(orig);
+	    Counter count = (Counter)hash.get(internal);
+	    if (count == null) {
+	      hash.put(internal, new Counter());
+	    } else {
+	      count.increment();
+	    }
+	    
+	    // Add components if phrase is single word before
+	    // conversion into internal format (i.e. error-correcting)
+	    /*if ((orig.indexOf(' ') == -1) &&
+	      (internal.indexOf(' ') != -1)) {
+	      StringTokenizer tokW = new StringTokenizer(internal, " ");
+	      while (tokW.hasMoreTokens()) {
+	      String comp = (String)tokW.nextToken();
+	      Counter countW = (Counter)hash.get(comp);
+	      if (countW == null) {
+	      hash.put(comp, new Counter());
+	      } else {
+	      countW.increment();
+	      }
+	      }
+	      }*/
+	  }
+	}
+      }
+    }
+    return hash;
+  }
+
+  /**
+   * Expects an empty hashtable. Fills the hashtable
+   * with the stemmed n-grams occuring in the given string
+   * (as keys). Stores the position, the number of occurences,
+   * and the most commonly occurring orgininal version of
+   * each n-gram.
+   *
+   * N-grams that occur less than m_MinNumOccur are not used.
+   *
+   * Returns the total number of words (!) in the string.
+   */
+  private int getPhrases(HashMap hash, String str) {
+
+    String[] buffer = new String[m_MaxPhraseLength];
+    
+    StringTokenizer tok = new StringTokenizer(str, "\n");
+    int pos = 1; 
+    while (tok.hasMoreTokens()) {
+      String phrase = tok.nextToken();
+      int numSeen = 0;
+      StringTokenizer wordTok = new StringTokenizer(phrase, " ");
+      while (wordTok.hasMoreTokens()) {
+	String word = wordTok.nextToken();
+	
+	// Store word in buffer
+	for (int i = 0; i < m_MaxPhraseLength - 1; i++) {
+	  buffer[i] = buffer[i + 1];
+	}
+	buffer[m_MaxPhraseLength - 1] = word;
+	
+	// How many are buffered?
+	numSeen++;
+	if (numSeen > m_MaxPhraseLength) {
+	  numSeen = m_MaxPhraseLength;
+	}
+	
+	// Don't consider phrases that end with a stop word
+	if (m_Stopwords.isStopword(buffer[m_MaxPhraseLength - 1])) {
+	  pos++;
+	  continue;
+	}
+	
+	// Loop through buffer and add phrases to hashtable
+	StringBuffer phraseBuffer = new StringBuffer();
+	for (int i = 1; i <= numSeen; i++) {
+	  if (i > 1) {
+	    phraseBuffer.insert(0, ' ');
+	  }
+	  phraseBuffer.insert(0, buffer[m_MaxPhraseLength - i]);
+	  
+	  // Don't consider phrases that begin with a stop word
+	  if ((i > 1) && 
+	      (m_Stopwords.isStopword(buffer[m_MaxPhraseLength - i]))) {
+	    continue;
+	  }
+	  
+	  // Only consider phrases with minimum length
+	  if (i >= m_MinPhraseLength) {
+	    
+	    // Stem string
+	    String phrStr = phraseBuffer.toString();
+	    String internal = internalFormat(phrStr);
+	    FastVector vec = (FastVector)hash.get(internal);
+	    if (vec == null) {
+	      vec = new FastVector(3);
+	      
+	      // HashMap for storing all versions
+	      HashMap secHash = new HashMap();
+	      secHash.put(phrStr, new Counter());
+	      
+	      // Update hashtable with all the info
+	      vec.addElement(new Counter(pos + 1 - i));
+	      vec.addElement(new Counter());
+	      vec.addElement(secHash);
+	      hash.put(internal, vec);
+	    } else {
+	      
+	      // Update number of occurrences
+	      ((Counter)((FastVector)vec).elementAt(1)).increment();
+	      
+	      // Update hashtable storing different versions
+	      HashMap secHash = (HashMap)vec.elementAt(2);
+	      Counter count = (Counter)secHash.get(phrStr);
+	      if (count == null) {
+		secHash.put(phrStr, new Counter());
+	      } else {
+		count.increment();
+	      }
+	    }
+	  }
+	}
+	pos++;
+      }
+    }
+    
+    // Replace secondary hashtables with most commonly occurring
+    // version of each phrase (canonical) form. Delete all words
+    // that are proper nouns.
+    Iterator phrases = hash.keySet().iterator();
+    while (phrases.hasNext()) {
+      String phrase = (String)phrases.next();
+      FastVector info = (FastVector)hash.get(phrase);
+
+      // Occurring less than m_MinNumOccur?
+      if (((Counter)((FastVector)info).elementAt(1)).value() < m_MinNumOccur) {
+	phrases.remove();
+	continue;
+      }
+
+      // Get canonical form
+      String canForm = canonicalForm((HashMap)info.elementAt(2));
+      if (canForm == null) {
+	phrases.remove();
+      } else {
+	info.setElementAt(canForm, 2);
+      }
+    }
+    return pos;
+  }
+
+  /**
+   * Create canonical form of phrase.
+   */
+  private String canonicalForm(HashMap secHash) {
+
+    int max = 0; String bestVersion = null;
+    boolean allFullyHyphenated = true;
+    int num = 0;
+    Iterator versions = secHash.keySet().iterator();
+    while (versions.hasNext()) {
+      num++;
+      String version = (String)versions.next();
+
+      // Are all the words joined up?
+      if (!isFullyHyphenated(version)) {
+	allFullyHyphenated = false;
+      }
+
+      // Check for how often this version occurs
+      Counter count = (Counter)secHash.get(version);
+      if (count.value() > max) {
+	max = count.value();
+	bestVersion = version;
+      }
+    }
+    if ((getCheckForProperNouns()) && (num == 1) && properNoun(bestVersion)) {
+    //if (allProperNouns) {
+      return null;
+    } else {
+      if (isFullyHyphenated(bestVersion) &&
+	  !allFullyHyphenated) {
+	bestVersion = bestVersion.replace('-', ' ');
+      }
+      return bestVersion;
+    }
+  }
+
+  /**
+   * Checks whether the given phrase is
+   * fully hyphenated.
+   */
+  private boolean isFullyHyphenated(String str) {
+    
+    return (str.indexOf(' ') == -1);
+  }
+
+  /**
+   * Checks whether the given string is a 
+   * proper noun.
+   *
+   * @return true if it is a potential proper noun
+   */
+  private static boolean properNoun(String str) {
+
+    // Is it more than one word?
+    if (str.indexOf(' ') != -1) {
+      return false;
+    }
+
+    // Does it start with an upper-case character?
+    if (Character.isLowerCase(str.charAt(0))) {
+      return false;
+    } 
+
+    // Is there at least one character that's
+    // not upper-case?
+    for (int i = 1; i < str.length(); i++) {
+      /*if (Character.isUpperCase(str.charAt(i))) {
+	return false;
+	}*/
+      if (!Character.isUpperCase(str.charAt(i))) {
+	return true;
+      }
+    }
+    //return true;
+    return false;
+  }
+
+  /**
+   * Generates the evaluation format of a phrase.
+   */
+  private String evalFormat(String str) {
+    
+    return m_Stemmer.stemString(str);
+  }
+
+  /** 
+   * Generates the internal format of a phrase.
+   */
+  private String internalFormat(String str) {
+
+    // Remove some non-alphanumeric characters
+    str = str.replace('-', ' ');
+    str = str.replace('/', ' ');
+    str = str.replace('&', ' ');
+
+    // Stem string
+    return m_Stemmer.stemString(str);
+  }
+
+  /**
+   * Gets all the phrases in the given string and puts them into the
+   * hashtable.  Also stores the original version of the stemmed
+   * phrase in the hash table.  
+   */
+  private HashMap getGivenKeyphrases(String str,
+				       boolean forEval) {
+
+    FastVector vector = new FastVector();
+    HashMap hash = new HashMap();
+    
+    StringTokenizer tok = new StringTokenizer(str, "\n");
+    while (tok.hasMoreTokens()) {
+      String orig = tok.nextToken();
+      orig = orig.trim();
+      if (orig.length() > 0) {
+	String modified;
+	if (!forEval) {
+	  modified = internalFormat(orig);
+	} else {
+	  modified = evalFormat(orig);
+	}
+	if (!hash.containsKey(modified)) {
+	  hash.put(modified, orig);
+	} else {
+	  if (forEval) {
+	    System.err.println("WARNING: stem of author-assigned keyphrase " +
+			       orig + " matches existing stem (skipping it)!");
+	  }
+	}
+      }
+    }
+    if (hash.size() == 0) {
+      return null;
+    } else {
+      return hash;
+    }
+  }
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param argv should contain arguments to the filter: use -h for help
+   */
+  public static void main(String [] argv) {
+    
+    try {
+      if (Utils.getFlag('b', argv)) {
+	Filter.batchFilterFile(new KEAFilter(), argv);
+      } else {
+	Filter.filterFile(new KEAFilter(), argv);
+      }
+    } catch (Exception ex) {
+      System.out.println(ex.getMessage());
+    }
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/KEAKeyphraseExtractor.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/KEAKeyphraseExtractor.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/KEAKeyphraseExtractor.java	(revision 8815)
@@ -0,0 +1,532 @@
+/*
+ *    KEAKeyphraseExtractor.java
+ *    Copyright (C) 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+import java.io.*;
+import java.util.*;
+import weka.core.*;
+import weka.filters.*;
+
+/**
+ * Extracts keyphrases from the documents in a given directory.
+ * Assumes that the file names for the documents end with ".txt".
+ * Puts extracted keyphrases into corresponding files ending with
+ * ".key" (if those are not already present). Optionally an encoding
+ * for the documents/keyphrases can be defined (e.g. for Chinese
+ * text). Documents for which ".key" exists, are used for evaluation.
+ *
+ * Valid options are:<p>
+ *
+ * -l "directory name"<br>
+ * Specifies name of directory.<p>
+ *
+ * -m "model name"<br>
+ * Specifies name of model.<p>
+ *
+ * -e "encoding"<br>
+ * Specifies encoding.<p>
+ *
+ * -n <br>
+ * Specifies number of phrases to be output (default: 5).<p>
+ *
+ * -d<br>
+ * Turns debugging mode on.<p>
+ *
+ * -a<br>
+ * Also write stemmed phrase and score into ".key" file.<p>
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public class KEAKeyphraseExtractor implements OptionHandler {
+  
+  /** Name of directory */
+  String m_dirName = null;
+  
+  /** Name of model */
+  String m_modelName = null;
+
+  /** Encoding */
+  String m_encoding = "default";
+
+  /** Debugging mode? */
+  boolean m_debug = false;
+
+  /** The KEA filter object */
+  KEAFilter m_KEAFilter = null;
+  
+  /** The number of phrases to extract. */
+  int m_numPhrases = 5;
+
+  /** Also write stemmed phrase and score into .key file. */
+  boolean m_AdditionalInfo = false;
+  
+  /**
+   * Get the value of AdditionalInfo.
+   *
+   * @return Value of AdditionalInfo.
+   */
+  public boolean getAdditionalInfo() {
+    
+    return m_AdditionalInfo;
+  }
+  
+  /**
+   * Set the value of AdditionalInfo.
+   *
+   * @param newAdditionalInfo Value to assign to AdditionalInfo.
+   */
+  public void setAdditionalInfo(boolean newAdditionalInfo) {
+    
+    m_AdditionalInfo = newAdditionalInfo;
+  }
+  
+  /**
+   * Get the value of numPhrases.
+   *
+   * @return Value of numPhrases.
+   */
+  public int getNumPhrases() {
+    
+    return m_numPhrases;
+  }
+  
+  /**
+   * Set the value of numPhrases.
+   *
+   * @param newnumPhrases Value to assign to numPhrases.
+   */
+  public void setNumPhrases(int newnumPhrases) {
+    
+    m_numPhrases = newnumPhrases;
+  }
+  
+  /**
+   * Get the value of debug.
+   *
+   * @return Value of debug.
+   */
+  public boolean getDebug() {
+    
+    return m_debug;
+  }
+  
+  /**
+   * Set the value of debug.
+   *
+   * @param newdebug Value to assign to debug.
+   */
+  public void setDebug(boolean newdebug) {
+    
+    m_debug = newdebug;
+  }
+  
+  /**
+   * Get the value of encoding.
+   *
+   * @return Value of encoding.
+   */
+  public String getEncoding() {
+    
+    return m_encoding;
+  }
+  
+  /**
+   * Set the value of encoding.
+   *
+   * @param newencoding Value to assign to encoding.
+   */
+  public void setEncoding(String newencoding) {
+    
+    m_encoding = newencoding;
+  }
+  
+  /**
+   * Get the value of modelName.
+   *
+   * @return Value of modelName.
+   */
+  public String getModelName() {
+    
+    return m_modelName;
+  }
+  
+  /**
+   * Set the value of modelName.
+   *
+   * @param newmodelName Value to assign to modelName.
+   */
+  public void setModelName(String newmodelName) {
+    
+    m_modelName = newmodelName;
+  }
+  
+  /**
+   * Get the value of dirName.
+   *
+   * @return Value of dirName.
+   */
+  public String getDirName() {
+    
+    return m_dirName;
+  }
+  
+  /**
+   * Set the value of dirName.
+   *
+   * @param newdirName Value to assign to dirName.
+   */
+  public void setDirName(String newdirName) {
+    
+    m_dirName = newdirName;
+  }
+  
+  /**
+   * Parses a given list of options controlling the behaviour of this object.
+   * Valid options are:<p>
+   *
+   * -l "directory name"<br>
+   * Specifies name of directory.<p>
+   *
+   * -m "model name"<br>
+   * Specifies name of model.<p>
+   *
+   * -e "encoding"<br>
+   * Specifies encoding.<p>
+   *
+   * -n<br>
+   * Specifies number of phrases to be output (default: 5).<p>
+   *
+   * -d<br>
+   * Turns debugging mode on.<p>
+   *
+   * -a<br>
+   * Also write stemmed phrase and score into ".key" file.<p>
+   *
+   * @param options the list of options as an array of strings
+   * @exception Exception if an option is not supported
+   */
+  public void setOptions(String[] options) throws Exception {
+
+    String dirName = Utils.getOption('l', options);
+    if (dirName.length() > 0) {
+      setDirName(dirName);
+    } else {
+      setDirName(null);
+      throw new Exception("Name of directory required argument.");
+    }
+    String modelName = Utils.getOption('m', options);
+    if (modelName.length() > 0) {
+      setModelName(modelName);
+    } else {
+      setModelName(null);
+      throw new Exception("Name of model required argument.");
+    }
+    String encoding = Utils.getOption('e', options);
+    if (encoding.length() > 0) {
+      setEncoding(encoding);
+    } else {
+      setEncoding("default");
+    }
+    String numPhrases = Utils.getOption('n', options);
+    if (numPhrases.length() > 0) {
+      setNumPhrases(Integer.parseInt(numPhrases));
+    } else {
+      setNumPhrases(5);
+    }
+    setDebug(Utils.getFlag('d', options));
+    setAdditionalInfo(Utils.getFlag('a', options));
+    Utils.checkForRemainingOptions(options);
+   }
+
+  /**
+   * Gets the current option settings.
+   *
+   * @return an array of strings suitable for passing to setOptions
+   */
+  public String [] getOptions() {
+
+    String [] options = new String [10];
+    int current = 0;
+
+    options[current++] = "-l"; 
+    options[current++] = "" + (getDirName());
+    options[current++] = "-m"; 
+    options[current++] = "" + (getModelName());
+    options[current++] = "-e"; 
+    options[current++] = "" + (getEncoding());
+    options[current++] = "-n"; 
+    options[current++] = "" + (getNumPhrases());
+    if (getDebug()) {
+      options[current++] = "-d";
+    }
+    if (getAdditionalInfo()) {
+      options[current++] = "-a";
+    }
+
+    while (current < options.length) {
+      options[current++] = "";
+    }
+    return options;
+  }
+
+  /**
+   * Returns an enumeration describing the available options.
+   *
+   * @return an enumeration of all the available options
+   */
+  public Enumeration listOptions() {
+
+    Vector newVector = new Vector(6);
+
+    newVector.addElement(new Option(
+	      "\tSpecifies name of directory.",
+              "l", 1, "-l <directory name>"));
+    newVector.addElement(new Option(
+	      "\tSpecifies name of model.",
+              "m", 1, "-m <model name>"));
+    newVector.addElement(new Option(
+	      "\tSpecifies encoding.",
+              "e", 1, "-e <encoding>"));
+    newVector.addElement(new Option(
+	      "\tSpecifies number of phrases to be output (default: 5).",
+              "n", 1, "-n"));
+    newVector.addElement(new Option(
+	      "\tTurns debugging mode on.",
+              "d", 0, "-d"));
+    newVector.addElement(new Option(
+	      "\tAlso write stemmed phrase and score into \".key\" file.",
+              "a", 0, "-a"));
+
+    return newVector.elements();
+  }
+
+  /**
+   * Collects the stems of the file names.
+   */
+  public Hashtable collectStems() throws Exception {
+
+    Hashtable stems = new Hashtable();
+
+    try {
+      File dir = new File(m_dirName);
+      String[] files = dir.list();
+      for (int i = 0; i < files.length; i++) {
+	if (files[i].endsWith(".txt")) {
+	  String stem = files[i].substring(0, files[i].length() - 4);
+	  if (!stems.containsKey(stem)) {
+	    stems.put(stem, new Double(0));
+	  }
+	}
+      }
+    } catch (Exception e) {
+      throw new Exception("Problem opening directory " + m_dirName);
+    }
+    return stems;
+  }
+
+  /**
+   * Builds the model from the files
+   */
+  public void extractKeyphrases(Hashtable stems) throws Exception {
+    
+    Vector stats = new Vector();
+
+    // Check whether there is actually any data
+    if (stems.size() == 0) {
+      throw new Exception("Couldn't find any data!");
+    }
+
+    FastVector atts = new FastVector(2);
+    atts.addElement(new Attribute("doc", null));
+    atts.addElement(new Attribute("keyphrases", null));
+    Instances data = new Instances("keyphrase_training_data", atts, 0);
+
+    // Extract keyphrases
+    Enumeration elem = stems.keys();
+    while (elem.hasMoreElements()) {
+      String str = (String)elem.nextElement();
+      double[] newInst = new double[2];
+      try {
+	File txt = new File(m_dirName + "/" + str + ".txt");
+	InputStreamReader is;
+	if (!m_encoding.equals("default")) {
+	  is = new InputStreamReader(new FileInputStream(txt), m_encoding);
+	} else {
+	  is = new InputStreamReader(new FileInputStream(txt));
+	}
+	StringBuffer txtStr = new StringBuffer();
+	int c;
+	while ((c = is.read()) != -1) {
+	  txtStr.append((char)c);
+	}
+	newInst[0] = (double)data.attribute(0).addStringValue(txtStr.toString());
+      } catch (Exception e) {
+	if (m_debug) {
+	  System.err.println("Can't read document " + str + ".txt");
+	}
+	newInst[0] = Instance.missingValue();
+      }
+      try {
+	File key = new File(m_dirName + "/" + str + ".key");
+	InputStreamReader is; 
+	if (!m_encoding.equals("default")) {
+	  is = new InputStreamReader(new FileInputStream(key), m_encoding);
+	} else {
+	  is = new InputStreamReader(new FileInputStream(key));
+	}
+	StringBuffer keyStr = new StringBuffer();
+	int c;
+	while ((c = is.read()) != -1) {
+	  keyStr.append((char)c);
+	}      
+	newInst[1] = (double)data.attribute(1).addStringValue(keyStr.toString());
+      } catch (Exception e) {
+	if (m_debug) {
+	  System.err.println("No keyphrases for stem " + str + ".");
+	}
+	newInst[1] = Instance.missingValue();
+      }
+      data.add(new Instance(1.0, newInst));
+      m_KEAFilter.input(data.instance(0));
+      data = data.stringFreeStructure();
+      if (m_debug) {
+	System.err.println("-- Document: " + str);
+      }
+      Instance[] topRankedInstances = new Instance[m_numPhrases];
+      Instance inst;
+      while ((inst = m_KEAFilter.output()) != null) {
+	int index = (int)inst.value(m_KEAFilter.getRankIndex()) - 1;
+	if (index < m_numPhrases) {
+	  topRankedInstances[index] = inst;
+	}
+      }
+      if (m_debug) {
+	System.err.println("-- Keyphrases and feature values:");
+      }
+      FileOutputStream out = null;
+      PrintWriter printer = null; 
+      File key = new File(m_dirName + "/" + str + ".key");
+      if (!key.exists()) {
+	out = new FileOutputStream(m_dirName + "/" + str + ".key");
+	if (!m_encoding.equals("default")) {
+	  printer = new PrintWriter(new OutputStreamWriter(out, m_encoding));
+	} else {
+	  printer = new PrintWriter(out);
+	}
+      }
+      double numExtracted = 0, numCorrect = 0;
+      for (int i = 0; i < m_numPhrases; i++) {
+	if (topRankedInstances[i] != null) {
+	  if (!topRankedInstances[i].
+	      isMissing(topRankedInstances[i].numAttributes() - 1)) {
+	    numExtracted += 1.0;
+	  }
+	  if ((int)topRankedInstances[i].
+	      value(topRankedInstances[i].numAttributes() - 1) == 
+	      topRankedInstances[i].
+	      attribute(topRankedInstances[i].numAttributes() - 1).
+	      indexOfValue("True")) {
+	    numCorrect += 1.0;
+	  }
+	  if (printer != null) {
+	    printer.print(topRankedInstances[i].
+			  stringValue(m_KEAFilter.getUnstemmedPhraseIndex()));
+	    if (m_AdditionalInfo) {
+	      printer.print("\t");
+	      printer.print(topRankedInstances[i].
+			  stringValue(m_KEAFilter.getStemmedPhraseIndex()));
+	      printer.print("\t");
+	      printer.print(Utils.
+			    doubleToString(topRankedInstances[i].
+					   value(m_KEAFilter.
+						 getProbabilityIndex()), 4));
+	    }
+	    printer.println();
+	  }
+	  if (m_debug) {
+	    System.err.println(topRankedInstances[i]);
+	  }
+	}
+      }
+      if (numExtracted > 0) {
+	if (m_debug) {
+	  System.err.println("-- " + numCorrect + " correct");
+	}
+	stats.addElement(new Double(numCorrect));
+      }
+      if (printer != null) {
+	printer.flush();
+	printer.close();
+	out.close();
+      }
+    }
+    double[] st = new double[stats.size()];
+    for (int i = 0; i < stats.size(); i++) {
+      st[i] = ((Double)stats.elementAt(i)).doubleValue();
+    }
+    double avg = Utils.mean(st);
+    double stdDev = Math.sqrt(Utils.variance(st));
+    System.err.println("Avg. number of correct keyphrases: " +
+		       Utils.doubleToString(avg, 2) + " +/- " + 
+		       Utils.doubleToString(stdDev, 2));
+    System.err.println("Based on " + stats.size() + " documents");
+    m_KEAFilter.batchFinished();
+  }
+  
+  /** 
+   * Loads the extraction model from the file.
+   */
+  public void loadModel() throws Exception {
+    
+    BufferedInputStream inStream =
+      new BufferedInputStream(new FileInputStream(m_modelName));
+    ObjectInputStream in = new ObjectInputStream(inStream);
+    m_KEAFilter = (KEAFilter)in.readObject();
+    in.close();
+  }
+  
+  /**
+   * The main method.  
+   */
+  public static void main(String[] ops) {
+    
+    KEAKeyphraseExtractor kmb = new KEAKeyphraseExtractor();
+    try {
+      kmb.setOptions(ops);
+      System.err.print("Extracting keyphrases with options: ");
+      String[] optionSettings = kmb.getOptions();
+      for (int i = 0; i < optionSettings.length; i++) {
+	System.err.print(optionSettings[i] + " ");
+      }
+      System.err.println();
+      kmb.loadModel();
+      kmb.extractKeyphrases(kmb.collectStems());
+    } catch (Exception e) {
+      e.printStackTrace();
+      System.err.println(e.getMessage());
+      System.err.println("\nOptions:\n");
+      Enumeration enum = kmb.listOptions();
+      while (enum.hasMoreElements()) {
+	Option option = (Option) enum.nextElement();
+	System.err.println(option.synopsis());
+	System.err.println(option.description());
+      }
+    }
+  }
+}
+
Index: /trunk/gsdl/packages/kea/kea-3.0/KEAModelBuilder.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/KEAModelBuilder.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/KEAModelBuilder.java	(revision 8815)
@@ -0,0 +1,689 @@
+/*
+ *    KEAModelBuilder.java
+ *    Copyright (C) 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.io.*;
+import java.util.*;
+import weka.core.*;
+import weka.filters.*;
+
+/**
+ * Builds a keyphrase extraction model from the documents in a given
+ * directory.  Assumes that the file names for the documents end with
+ * ".txt".  Assumes that files containing corresponding
+ * author-assigned keyphrases end with ".key". Optionally an encoding
+ * for the documents/keyphrases can be defined (e.g. for Chinese
+ * text).
+ *
+ * Valid options are:<p>
+ *
+ * -l "directory name"<br>
+ * Specifies name of directory.<p>
+ *
+ * -m "model name"<br>
+ * Specifies name of model.<p>
+ *
+ * -e "encoding"<br>
+ * Specifies encoding.<p>
+ *
+ * -d<br>
+ * Turns debugging mode on.<p>
+ *
+ * -k<br>
+ * Use keyphrase frequency statistic.<p>
+ *
+ * -p<br>
+ * Disallow internal periods.<p>
+ *
+ * -x "length"<br>
+ * Sets maximum phrase length (default: 3).<p>
+ *
+ * -y "length"<br>
+ * Sets minimum phrase length (default: 1).<p>
+ *
+ * -o "number"<br>
+ * The minimum number of times a phrase needs to occur (default: 2). <p>
+ *
+ * -s "name of class implementing list of stop words"<br>
+ * Sets list of stop words to used (default: StopwordsEnglish).<p>
+ *
+ * -t "name of class implementing stemmer"<br>
+ * Sets stemmer to use (default: IteratedLovinsStemmer). <p>
+ *
+ * -n<br>
+ * Do not check for proper nouns. <p>
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public class KEAModelBuilder implements OptionHandler {
+  
+  /** Name of directory */
+  String m_dirName = null;
+  
+  /** Name of model */
+  String m_modelName = null;
+
+  /** Encoding */
+  String m_encoding = "default";
+
+  /** Debugging mode? */
+  boolean m_debug = false;
+
+  /** Use keyphrase frequency attribute? */
+  boolean m_useKFrequency = false;
+
+  /** Disallow internal periods? */
+  boolean m_disallowIPeriods = false;
+
+  /** The maximum length of phrases */
+  private int m_MaxPhraseLength = 3;
+
+  /** The minimum length of phrases */
+  private int m_MinPhraseLength = 1;
+
+  /** The minimum number of occurences of a phrase */
+  private int m_MinNumOccur = 2;
+
+  /** The KEA filter object */
+  KEAFilter m_KEAFilter = null;
+
+  /** The stemmer to be used */
+  private Stemmer m_Stemmer = new IteratedLovinsStemmer();
+
+  /** The list of stop words to be used */
+  private Stopwords m_Stopwords = new StopwordsEnglish();
+
+  /** Determines whether check for proper nouns is performed */
+  private boolean m_CheckForProperNouns = true;
+
+  /**
+   * Get the M_CheckProperNouns value.
+   * @return the M_CheckProperNouns value.
+   */
+  public boolean getCheckForProperNouns() {
+    return m_CheckForProperNouns;
+  }
+
+  /**
+   * Set the M_CheckProperNouns value.
+   * @param newM_CheckProperNouns The new M_CheckProperNouns value.
+   */
+  public void setCheckForProperNouns(boolean newM_CheckProperNouns) {
+    this.m_CheckForProperNouns = newM_CheckProperNouns;
+  }
+
+  /**
+   * Get the M_Stopwords value.
+   * @return the M_Stopwords value.
+   */
+  public Stopwords getStopwords() {
+
+    return m_Stopwords;
+  }
+
+  /**
+   * Set the M_Stopwords value.
+   * @param newM_Stopwords The new M_Stopwords value.
+   */
+  public void setStopwords(Stopwords newM_Stopwords) {
+
+    this.m_Stopwords = newM_Stopwords;
+  }
+
+  
+  /**
+   * Get the Stemmer value.
+   * @return the Stemmer value.
+   */
+  public Stemmer getStemmer() {
+
+    return m_Stemmer;
+  }
+
+  /**
+   * Set the Stemmer value.
+   * @param newStemmer The new Stemmer value.
+   */
+  public void setStemmer(Stemmer newStemmer) {
+
+    this.m_Stemmer = newStemmer;
+  }
+  
+  /**
+   * Get the value of MinNumOccur.
+   *
+   * @return Value of MinNumOccur.
+   */
+  public int getMinNumOccur() {
+    
+    return m_MinNumOccur;
+  }
+  
+  /**
+   * Set the value of MinNumOccur.
+   *
+   * @param newMinNumOccur Value to assign to MinNumOccur.
+   */
+  public void setMinNumOccur(int newMinNumOccur) {
+    
+    m_MinNumOccur = newMinNumOccur;
+  }
+  
+  /**
+   * Get the value of MaxPhraseLength.
+   *
+   * @return Value of MaxPhraseLength.
+   */
+  public int getMaxPhraseLength() {
+    
+    return m_MaxPhraseLength;
+  }
+  
+  /**
+   * Set the value of MaxPhraseLength.
+   *
+   * @param newMaxPhraseLength Value to assign to MaxPhraseLength.
+   */
+  public void setMaxPhraseLength(int newMaxPhraseLength) {
+    
+    m_MaxPhraseLength = newMaxPhraseLength;
+  }
+  
+  /**
+   * Get the value of MinPhraseLength.
+   *
+   * @return Value of MinPhraseLength.
+   */
+  public int getMinPhraseLength() {
+    
+    return m_MinPhraseLength;
+  }
+  
+  /**
+   * Set the value of MinPhraseLength.
+   *
+   * @param newMinPhraseLength Value to assign to MinPhraseLength.
+   */
+  public void setMinPhraseLength(int newMinPhraseLength) {
+    
+    m_MinPhraseLength = newMinPhraseLength;
+  }
+  
+  /**
+   * Get the value of disallowIPeriods.
+   *
+   * @return Value of disallowIPeriods.
+   */
+  public boolean getDisallowIPeriods() {
+    
+    return m_disallowIPeriods;
+  }
+  
+  /**
+   * Set the value of disallowIPeriods.
+   *
+   * @param newdisallowIPeriods Value to assign to disallowIPeriods.
+   */
+  public void setDisallowIPeriods(boolean newdisallowIPeriods) {
+    
+    m_disallowIPeriods = newdisallowIPeriods;
+  }
+  
+  /**
+   * Get the value of useKFrequency.
+   *
+   * @return Value of useKFrequency.
+   */
+  public boolean getUseKFrequency() {
+    
+    return m_useKFrequency;
+  }
+  
+  /**
+   * Set the value of useKFrequency.
+   *
+   * @param newuseKFrequency Value to assign to useKFrequency.
+   */
+  public void setUseKFrequency(boolean newuseKFrequency) {
+    
+    m_useKFrequency = newuseKFrequency;
+  }
+  
+  /**
+   * Get the value of debug.
+   *
+   * @return Value of debug.
+   */
+  public boolean getDebug() {
+    
+    return m_debug;
+  }
+  
+  /**
+   * Set the value of debug.
+   *
+   * @param newdebug Value to assign to debug.
+   */
+  public void setDebug(boolean newdebug) {
+    
+    m_debug = newdebug;
+  }
+  
+  /**
+   * Get the value of encoding.
+   *
+   * @return Value of encoding.
+   */
+  public String getEncoding() {
+    
+    return m_encoding;
+  }
+  
+  /**
+   * Set the value of encoding.
+   *
+   * @param newencoding Value to assign to encoding.
+   */
+  public void setEncoding(String newencoding) {
+    
+    m_encoding = newencoding;
+  }
+  
+  /**
+   * Get the value of modelName.
+   *
+   * @return Value of modelName.
+   */
+  public String getModelName() {
+    
+    return m_modelName;
+  }
+  
+  /**
+   * Set the value of modelName.
+   *
+   * @param newmodelName Value to assign to modelName.
+   */
+  public void setModelName(String newmodelName) {
+    
+    m_modelName = newmodelName;
+  }
+  
+  /**
+   * Get the value of dirName.
+   *
+   * @return Value of dirName.
+   */
+  public String getDirName() {
+    
+    return m_dirName;
+  }
+  
+  /**
+   * Set the value of dirName.
+   *
+   * @param newdirName Value to assign to dirName.
+   */
+  public void setDirName(String newdirName) {
+    
+    m_dirName = newdirName;
+  }
+  
+  /**
+   * Parses a given list of options controlling the behaviour of this object.
+   * Valid options are:<p>
+   *
+   * -l "directory name" <br>
+   * Specifies name of directory.<p>
+   *
+   * -m "model name" <br>
+   * Specifies name of model.<p>
+   *
+   * -e "encoding" <br>
+   * Specifies encoding.<p>
+   *
+   * -d<br>
+   * Turns debugging mode on.<p>
+   *
+   * -k<br>
+   * Use keyphrase frequency statistic.<p>
+   *
+   * -p<br>
+   * Disallow internal periods. <p>
+   *
+   * -x "length"<br>
+   * Sets maximum phrase length (default: 3).<p>
+   *
+   * -y "length"<br>
+   * Sets minimum phrase length (default: 3).<p>
+   *
+   * -o "number"<br>
+   * The minimum number of times a phrase needs to occur (default: 2). <p>
+   *
+   * -s "name of class implementing list of stop words"<br>
+   * Sets list of stop words to used (default: StopwordsEnglish).<p>
+   *
+   * -t "name of class implementing stemmer"<br>
+   * Sets stemmer to use (default: IteratedLovinsStemmer). <p>
+   *
+   * -n<br>
+   * Do not check for proper nouns. <p>
+   *
+   * @param options the list of options as an array of strings
+   * @exception Exception if an option is not supported
+   */
+  public void setOptions(String[] options) throws Exception {
+
+    String dirName = Utils.getOption('l', options);
+    if (dirName.length() > 0) {
+      setDirName(dirName);
+    } else {
+      setDirName(null);
+      throw new Exception("Name of directory required argument.");
+    }
+    String modelName = Utils.getOption('m', options);
+    if (modelName.length() > 0) {
+      setModelName(modelName);
+    } else {
+      setModelName(null);
+      throw new Exception("Name of model required argument.");
+    }
+    String encoding = Utils.getOption('e', options);
+    if (encoding.length() > 0) {
+      setEncoding(encoding);
+    } else {
+      setEncoding("default");
+    }
+    String maxPhraseLengthString = Utils.getOption('x', options);
+    if (maxPhraseLengthString.length() > 0) {
+      setMaxPhraseLength(Integer.parseInt(maxPhraseLengthString));
+    } else {
+      setMaxPhraseLength(3);
+    }
+    String minPhraseLengthString = Utils.getOption('y', options);
+    if (minPhraseLengthString.length() > 0) {
+      setMinPhraseLength(Integer.parseInt(minPhraseLengthString));
+    } else {
+      setMinPhraseLength(1);
+    }
+    String minNumOccurString = Utils.getOption('o', options);
+    if (minNumOccurString.length() > 0) {
+      setMinNumOccur(Integer.parseInt(minNumOccurString));
+    } else {
+      setMinNumOccur(2);
+    }
+    String stopwordsString = Utils.getOption('s', options);
+    if (stopwordsString.length() > 0) {
+      setStopwords((Stopwords)Class.forName(stopwordsString).newInstance());
+    }
+    String stemmerString = Utils.getOption('t', options);
+    if (stemmerString.length() > 0) {
+      setStemmer((Stemmer)Class.forName(stemmerString).newInstance());
+    }
+    setDebug(Utils.getFlag('d', options));
+    setUseKFrequency(Utils.getFlag('k', options));
+    setDisallowIPeriods(Utils.getFlag('p', options));
+    setCheckForProperNouns(!Utils.getFlag('n', options));
+    Utils.checkForRemainingOptions(options);
+   }
+
+  /**
+   * Gets the current option settings.
+   *
+   * @return an array of strings suitable for passing to setOptions
+   */
+  public String [] getOptions() {
+
+    String [] options = new String [20];
+    int current = 0;
+
+    options[current++] = "-l"; 
+    options[current++] = "" + (getDirName());
+    options[current++] = "-m"; 
+    options[current++] = "" + (getModelName());
+    options[current++] = "-e"; 
+    options[current++] = "" + (getEncoding());
+    if (getUseKFrequency()) {
+      options[current++] = "-k";
+    }
+    if (getDebug()) {
+      options[current++] = "-d";
+    }
+    if (getDisallowIPeriods()) {
+      options[current++] = "-p";
+    }
+    options[current++] = "-x"; 
+    options[current++] = "" + (getMaxPhraseLength());
+    options[current++] = "-y"; 
+    options[current++] = "" + (getMinPhraseLength());
+    options[current++] = "-o"; 
+    options[current++] = "" + (getMinNumOccur());
+    options[current++] = "-s"; 
+    options[current++] = "" + (getStopwords().getClass().getName());
+    options[current++] = "-t"; 
+    options[current++] = "" + (getStemmer().getClass().getName());
+    if (getCheckForProperNouns()) {
+      options[current++] = "-n";
+    }
+
+    while (current < options.length) {
+      options[current++] = "";
+    }
+    return options;
+  }
+
+  /**
+   * Returns an enumeration describing the available options.
+   *
+   * @return an enumeration of all the available options
+   */
+  public Enumeration listOptions() {
+
+    Vector newVector = new Vector(12);
+
+    newVector.addElement(new Option(
+	      "\tSpecifies name of directory.",
+              "l", 1, "-l <directory name>"));
+    newVector.addElement(new Option(
+	      "\tSpecifies name of model.",
+              "m", 1, "-m <model name>"));
+    newVector.addElement(new Option(
+	      "\tSpecifies encoding.",
+              "e", 1, "-e <encoding>"));
+    newVector.addElement(new Option(
+	      "\tTurns debugging mode on.",
+              "d", 0, "-d"));
+    newVector.addElement(new Option(
+	      "\tUse keyphrase frequency statistic.",
+              "k", 0, "-k"));
+    newVector.addElement(new Option(
+	      "\tDisallow internal periods.",
+              "p", 0, "-p"));
+    newVector.addElement(new Option(
+	      "\tSets the maximum phrase length (default: 3).",
+              "x", 1, "-x <length>"));
+    newVector.addElement(new Option(
+	      "\tSets the minimum phrase length (default: 1).",
+              "y", 1, "-y <length>"));
+    newVector.addElement(new Option(
+	      "\tSet the minimum number of occurences (default: 2).",
+              "o", 1, "-o"));
+    newVector.addElement(new Option(
+	      "\tSets the list of stopwords to use (default: StopwordsEnglish).",
+              "s", 1, "-s <name of stopwords class>"));
+    newVector.addElement(new Option(
+	      "\tSet the stemmer to use (default: IteratedLovinsStemmer).",
+              "t", 1, "-t <name of stemmer class>"));
+    newVector.addElement(new Option(
+	      "\tDo not check for proper nouns.",
+              "n", 0, "-n"));
+ 
+    return newVector.elements();
+  }
+
+  /**
+   * Collects the stems of the file names.
+   */
+  public Hashtable collectStems() throws Exception {
+
+    Hashtable stems = new Hashtable();
+
+    try {
+      File dir = new File(m_dirName);
+      String[] files = dir.list();
+      for (int i = 0; i < files.length; i++) {
+	if (files[i].endsWith(".key") ||
+	    files[i].endsWith(".txt")) {
+	  String stem = files[i].substring(0, files[i].length() - 4);
+	  if (!stems.containsKey(stem)) {
+	    stems.put(stem, new Double(0));
+	  }
+	}
+      }
+    } catch (Exception e) {
+      throw new Exception("Problem opening directory " + m_dirName);
+    }
+    return stems;
+  }
+
+  /**
+   * Builds the model from the files
+   */
+  public void buildModel(Hashtable stems) throws Exception {
+    
+    // Check whether there is actually any data
+    if (stems.size() == 0) {
+      throw new Exception("Couldn't find any data!");
+    }
+
+    FastVector atts = new FastVector(2);
+    atts.addElement(new Attribute("doc", null));
+    atts.addElement(new Attribute("keyphrases", null));
+    Instances data = new Instances("keyphrase_training_data", atts, 0);
+
+    // Build model
+    m_KEAFilter = new KEAFilter();
+    m_KEAFilter.setDebug(m_debug);
+    m_KEAFilter.setDisallowInternalPeriods(getDisallowIPeriods());
+    m_KEAFilter.setKFused(getUseKFrequency());
+    m_KEAFilter.setMaxPhraseLength(getMaxPhraseLength());
+    m_KEAFilter.setMinPhraseLength(getMinPhraseLength());
+    m_KEAFilter.setMinNumOccur(getMinNumOccur());
+    m_KEAFilter.setInputFormat(data);
+    m_KEAFilter.setStemmer(getStemmer());
+    m_KEAFilter.setStopwords(getStopwords());
+    m_KEAFilter.setCheckForProperNouns(getCheckForProperNouns());
+    Enumeration elem = stems.keys();
+    while (elem.hasMoreElements()) {
+      String str = (String)elem.nextElement();
+      double[] newInst = new double[2];
+      try {
+	File txt = new File(m_dirName + "/" + str + ".txt");
+	InputStreamReader is;
+	if (!m_encoding.equals("default")) {
+	  is = new InputStreamReader(new FileInputStream(txt), m_encoding);
+	} else {
+	  is = new InputStreamReader(new FileInputStream(txt));
+	}
+	StringBuffer txtStr = new StringBuffer();
+	int c;
+	while ((c = is.read()) != -1) {
+	  txtStr.append((char)c);
+	}
+	newInst[0] = (double)data.attribute(0).addStringValue(txtStr.toString());
+      } catch (Exception e) {
+	if (m_debug) {
+	  System.err.println("Can't find document for stem " + str + ".");
+	}
+	newInst[0] = Instance.missingValue();
+      }
+      try {
+	File key = new File(m_dirName + "/" + str + ".key");
+	InputStreamReader is; 
+	if (!m_encoding.equals("default")) {
+	  is = new InputStreamReader(new FileInputStream(key), m_encoding);
+	} else {
+	  is = new InputStreamReader(new FileInputStream(key));
+	}
+	StringBuffer keyStr = new StringBuffer();
+	int c;
+	while ((c = is.read()) != -1) {
+	  keyStr.append((char)c);
+	}      
+	newInst[1] = (double)data.attribute(1).addStringValue(keyStr.toString());
+      } catch (Exception e) {
+	if (m_debug) {
+	  System.err.println("Can't find keyphrases for stem " + str + ".");
+	}
+	newInst[1] = Instance.missingValue();
+      }
+      data.add(new Instance(1.0, newInst));
+      m_KEAFilter.input(data.instance(0));
+      data = data.stringFreeStructure();
+    }
+    m_KEAFilter.batchFinished();
+    
+    // Get rid of instances in filter
+    Instance dummy;
+    while ((dummy = m_KEAFilter.output()) != null) {};
+  }
+  
+  /** 
+   * Saves the extraction model to the file.
+   */
+  public void saveModel() throws Exception {
+    
+    BufferedOutputStream bufferedOut = 
+      new BufferedOutputStream(new FileOutputStream(m_modelName));
+    ObjectOutputStream out = new ObjectOutputStream(bufferedOut);
+    out.writeObject(m_KEAFilter);
+    out.flush();
+    out.close();
+  }
+  
+  /**
+   * The main method.  
+   */
+  public static void main(String[] ops) {
+    
+    KEAModelBuilder kmb = new KEAModelBuilder();
+    try {
+      kmb.setOptions(ops);
+      System.err.print("Building model with options: ");
+      String[] optionSettings = kmb.getOptions();
+      for (int i = 0; i < optionSettings.length; i++) {
+	System.err.print(optionSettings[i] + " ");
+      }
+      System.err.println();
+      kmb.buildModel(kmb.collectStems());
+      kmb.saveModel();
+    } catch (Exception e) {
+      e.printStackTrace();
+      System.err.println(e.getMessage());
+      System.err.println("\nOptions:\n");
+      Enumeration enum = kmb.listOptions();
+      while (enum.hasMoreElements()) {
+	Option option = (Option) enum.nextElement();
+	System.err.println(option.synopsis());
+	System.err.println(option.description());
+      }
+    }
+  }
+}
+
Index: /trunk/gsdl/packages/kea/kea-3.0/KEAPhraseFilter.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/KEAPhraseFilter.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/KEAPhraseFilter.java	(revision 8815)
@@ -0,0 +1,487 @@
+/*
+ *    KEAPhraseFilter.java
+ *    Copyright (C) 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.util.*;
+
+import weka.core.*;
+import weka.filters.*;
+
+/**
+ * This filter splits the text in selected string
+ * attributes into phrases. The resulting
+ * string attributes contain these phrases
+ * separated by '\n' characters.
+ *
+ * Phrases are identified according to the
+ * following definitions:
+ * 
+ * A phrase is a sequence of words interrupted
+ * only by sequences of whitespace characters,
+ * where each sequence of whitespace characters
+ * contains at most one '\n'.
+ *
+ * A word is a sequence of letters or digits
+ * that contains at least one letter, with
+ * the following exceptions:
+ *
+ * a) '.', '@', '_', '&', '/', '-' are allowed
+ * if surrounded by letters or digits,
+ *
+ * b) '\'' is allowed if preceeded by a letter
+ * or digit,
+ * 
+ * c) '-', '/' are also allowed if succeeded by
+ * whitespace characters followed by another
+ * word. In that case the whitespace characters
+ * will be deleted.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public class KEAPhraseFilter extends Filter implements OptionHandler {
+
+  /** Stores which columns to select as a funky range */
+  protected Range m_SelectCols = new Range();
+
+  /** Determines whether internal periods are allowed */
+  protected boolean m_DisallowInternalPeriods = false;
+
+  /**
+   * Returns a string describing this filter
+   *
+   * @return a description of the filter suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String globalInfo() {
+    return "This filter splits the text contained " +
+      "by the selected string attributes into phrases.";
+  }
+
+  /**
+   * Returns an enumeration describing the available options
+   *
+   * @return an enumeration of all the available options
+   */
+  public Enumeration listOptions() {
+
+    Vector newVector = new Vector(3);
+
+    newVector.addElement(new Option(
+              "\tSpecify list of attributes to process. First and last are valid\n"
+	      +"\tindexes. (default none)",
+              "R", 1, "-R <index1,index2-index4,...>"));
+    newVector.addElement(new Option(
+	      "\tInvert matching sense",
+              "V", 0, "-V"));
+    newVector.addElement(new Option(
+	      "\tDisallow internal periods",
+              "P", 0, "-P"));
+
+    return newVector.elements();
+  }
+
+  /**
+   * Parses a given list of options controlling the behaviour of this object.
+   * Valid options are:<p>
+   *
+   * -R index1,index2-index4,...<br>
+   * Specify list of attributes to process. First and last are valid indexes.
+   * (default none)<p>
+   *
+   * -V<br>
+   * Invert matching sense <p>
+   *
+   * -P<br>
+   * Disallow internal periods <p>
+   *
+   * @param options the list of options as an array of strings
+   * @exception Exception if an option is not supported
+   */
+  public void setOptions(String[] options) throws Exception {
+
+    String list = Utils.getOption('R', options);
+    if (list.length() != 0) {
+      setAttributeIndices(list);
+    }
+    setInvertSelection(Utils.getFlag('V', options));
+
+    setDisallowInternalPeriods(Utils.getFlag('P', options));
+    
+    if (getInputFormat() != null) {
+      setInputFormat(getInputFormat());
+    }
+  }
+
+  /**
+   * Gets the current settings of the filter.
+   *
+   * @return an array of strings suitable for passing to setOptions
+   */
+  public String [] getOptions() {
+
+    String [] options = new String [4];
+    int current = 0;
+
+    if (getInvertSelection()) {
+      options[current++] = "-V";
+    }
+    if (getDisallowInternalPeriods()) {
+      options[current++] = "-P";
+    }
+    if (!getAttributeIndices().equals("")) {
+      options[current++] = "-R"; options[current++] = getAttributeIndices();
+    }
+
+    while (current < options.length) {
+      options[current++] = "";
+    }
+    return options;
+  }
+
+  /**
+   * Sets the format of the input instances.
+   *
+   * @param instanceInfo an Instances object containing the input
+   * instance structure (any instances contained in the object are
+   * ignored - only the structure is required).
+   * @return true if the outputFormat may be collected immediately 
+   */
+  public boolean setInputFormat(Instances instanceInfo) throws Exception {
+
+    super.setInputFormat(instanceInfo);
+    setOutputFormat(instanceInfo);
+    m_SelectCols.setUpper(instanceInfo.numAttributes() - 1);
+
+    return true;
+  }
+
+  /**
+   * Input an instance for filtering. Ordinarily the instance is processed
+   * and made available for output immediately. Some filters require all
+   * instances be read before producing output.
+   *
+   * @param instance the input instance
+   * @return true if the filtered instance may now be
+   * collected with output().
+   * @exception Exception if the input instance was not of the correct 
+   * format or if there was a problem with the filtering.
+   */
+  public boolean input(Instance instance) throws Exception {
+
+    if (getInputFormat() == null) {
+      throw new Exception("No input instance format defined");
+    }
+    if (m_NewBatch) {
+      resetQueue();
+      m_NewBatch = false;
+    }
+    convertInstance(instance);
+    return true;
+  }
+
+  /**
+   * Signify that this batch of input to the filter is finished. If
+   * the filter requires all instances prior to filtering, output()
+   * may now be called to retrieve the filtered instances. Any
+   * subsequent instances filtered should be filtered based on setting
+   * obtained from the first batch (unless the inputFormat has been
+   * re-assigned or new options have been set). This default
+   * implementation assumes all instance processing occurs during
+   * inputFormat() and input().
+   *
+   * @return true if there are instances pending output
+   * @exception NullPointerException if no input structure has been defined,
+   * @exception Exception if there was a problem finishing the batch.
+   */
+  public boolean batchFinished() throws Exception {
+
+    if (getInputFormat() == null) {
+      throw new NullPointerException("No input instance format defined");
+    }
+    m_NewBatch = true;
+    return (numPendingOutput() != 0);
+  }
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param argv should contain arguments to the filter: use -h for help
+   */
+  public static void main(String [] argv) {
+    
+    try {
+      if (Utils.getFlag('b', argv)) {
+	Filter.batchFilterFile(new KEAPhraseFilter(), argv);
+      } else {
+	Filter.filterFile(new KEAPhraseFilter(), argv);
+      }
+    } catch (Exception ex) {
+      System.out.println(ex.getMessage());
+    }
+  }
+ 
+  /** 
+   * Converts an instance by removing all non-alphanumeric characters
+   * from its string attribute values.
+   */
+  private void convertInstance(Instance instance) throws Exception {
+  
+    double[] instVals = new double[instance.numAttributes()];
+
+    for (int i = 0; i < instance.numAttributes(); i++) {
+      if (!instance.attribute(i).isString() || 
+	  instance.isMissing(i)) {
+	instVals[i] = instance.value(i);
+      } else {
+	if (!m_SelectCols.isInRange(i)) {
+	  int index = getOutputFormat().attribute(i).
+	    addStringValue(instance.stringValue(i));
+	  instVals[i] = (double)index;
+	  continue;
+	}
+	String str = instance.stringValue(i);
+	StringBuffer resultStr = new StringBuffer();
+	int j = 0;
+	boolean phraseStart = true;
+	boolean seenNewLine = false;
+	boolean haveSeenHyphen = false;
+	boolean haveSeenSlash = false;
+	while (j < str.length()) {
+	  boolean isWord = false;
+	  boolean potNumber = false;
+	  int startj = j;
+	  while (j < str.length()) {
+	    char ch = str.charAt(j);
+	    if (Character.isLetterOrDigit(ch)) {
+	      potNumber = true;
+	      if (Character.isLetter(ch)) {
+		isWord = true;
+	      }
+	      j++;
+	    } else if ((!m_DisallowInternalPeriods && (ch == '.')) ||
+		       (ch == '@') ||
+		       (ch == '_') ||
+		       (ch == '&') ||
+		       (ch == '/') ||
+		       (ch == '-')) {
+	      if ((j > 0) && (j  + 1 < str.length()) &&
+		  Character.isLetterOrDigit(str.charAt(j - 1)) &&
+		  Character.isLetterOrDigit(str.charAt(j + 1))) {
+		j++;
+	      } else {
+		break;
+	      }
+	    } else if (ch == '\'') {
+	      if ((j > 0) &&
+		  Character.isLetterOrDigit(str.charAt(j - 1))) {
+		j++;
+	      } else {
+		break;
+	      }
+	    } else {
+	      break;
+	    }
+	  }
+	  if (isWord == true) {
+	    if (!phraseStart) {
+	      if (haveSeenHyphen) {
+		resultStr.append('-');
+	      } else if (haveSeenSlash) {
+		resultStr.append('/');
+	      } else {
+		resultStr.append(' ');
+	      }
+	    }
+	    resultStr.append(str.substring(startj, j));
+	    if (j == str.length()) {
+	      break;
+	    }
+	    phraseStart = false;
+	    seenNewLine = false;
+	    haveSeenHyphen = false;
+	    haveSeenSlash = false;
+	    if (Character.isWhitespace(str.charAt(j))) {
+	      if (str.charAt(j) == '\n') {
+		seenNewLine = true;
+	      } 
+	    } else if (str.charAt(j) == '-') {
+	      haveSeenHyphen = true;
+	    } else if (str.charAt(j) == '/') {
+	      haveSeenSlash = true;
+	    } else {
+	      phraseStart = true;
+	      resultStr.append('\n');
+	    }
+	    j++;
+	  } else if (j == str.length()) {
+	    break;
+	  } else if (str.charAt(j) == '\n') {
+	    if (seenNewLine) {
+	      if (phraseStart == false) {
+		resultStr.append('\n');
+		phraseStart = true;
+	      }
+	    } else if (potNumber) {
+	      if (phraseStart == false) {
+		phraseStart = true;
+		resultStr.append('\n');
+	      }
+	    }
+	    seenNewLine = true;
+	    j++;
+	  } else if (Character.isWhitespace(str.charAt(j))) {
+	    if (potNumber) {
+	      if (phraseStart == false) {
+		phraseStart = true;
+		resultStr.append('\n');
+	      }
+	    }
+	    j++;
+	  } else {
+	    if (phraseStart == false) {
+	      resultStr.append('\n');
+	      phraseStart = true;
+	    }
+	    j++;
+	  }
+	}
+	int index = getOutputFormat().attribute(i).
+	  addStringValue(resultStr.toString());
+	instVals[i] = (double)index;
+      }
+    }
+    Instance inst = new Instance(instance.weight(), instVals);
+    inst.setDataset(getOutputFormat());
+    push(inst);
+  }
+
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String invertSelectionTipText() {
+
+    return "If set to false, the specified attributes will be processed;"
+      + " If set to true, specified attributes won't be processed.";
+  }
+
+  /**
+   * Get whether the supplied columns are to be processed
+   *
+   * @return true if the supplied columns won't be processed
+   */
+  public boolean getInvertSelection() {
+
+    return m_SelectCols.getInvert();
+  }
+
+  /**
+   * Set whether selected columns should be processed. If true the 
+   * selected columns won't be processed.
+   *
+   * @param invert the new invert setting
+   */
+  public void setInvertSelection(boolean invert) {
+
+    m_SelectCols.setInvert(invert);
+  }
+
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String disallowInternalPeriodsTipText() {
+
+    return "If set to false, internal periods are allowed.";
+  }
+
+  /**
+   * Get whether the supplied columns are to be processed
+   *
+   * @return true if the supplied columns won't be processed
+   */
+  public boolean getDisallowInternalPeriods() {
+
+    return m_DisallowInternalPeriods;
+  }
+
+  /**
+   * Set whether selected columns should be processed. If true the 
+   * selected columns won't be processed.
+   *
+   * @param invert the new invert setting
+   */
+  public void setDisallowInternalPeriods(boolean disallow) {
+
+    m_DisallowInternalPeriods = disallow;
+  }
+
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String attributeIndicesTipText() {
+
+    return "Specify range of attributes to act on."
+      + " This is a comma separated list of attribute indices, with"
+      + " \"first\" and \"last\" valid values. Specify an inclusive"
+      + " range with \"-\". E.g: \"first-3,5,6-10,last\".";
+  }
+
+  /**
+   * Get the current range selection.
+   *
+   * @return a string containing a comma separated list of ranges
+   */
+  public String getAttributeIndices() {
+
+    return m_SelectCols.getRanges();
+  }
+
+  /**
+   * Set which attributes are to be processed
+   *
+   * @param rangeList a string representing the list of attributes.  Since
+   * the string will typically come from a user, attributes are indexed from
+   * 1. <br>
+   * eg: first-3,5,6-last
+   */
+  public void setAttributeIndices(String rangeList) {
+
+    m_SelectCols.setRanges(rangeList);
+  }
+
+  /**
+   * Set which attributes are to be processed
+   *
+   * @param attributes an array containing indexes of attributes to select.
+   * Since the array will typically come from a program, attributes are indexed
+   * from 0.
+   */
+  public void setAttributeIndicesArray(int [] attributes) {
+    
+    setAttributeIndices(Range.indicesToRangeList(attributes));
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/LovinsStemmer.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/LovinsStemmer.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/LovinsStemmer.java	(revision 8815)
@@ -0,0 +1,890 @@
+/*
+ *    LovinsStemmer.java
+ *    Copyright (C) 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.util.*;
+import java.io.*;
+
+/** 
+ * Implements the Lovins stemmer.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public class LovinsStemmer extends Stemmer implements Serializable {
+
+  /** C version compatibility mode (emulates bugs
+      in original C implementation) */
+  private static boolean m_CompMode = true;
+
+  /** The hash tables containing the list of endings. */
+  private static HashMap m_l11 = null;
+  private static HashMap m_l10 = null;
+  private static HashMap m_l9 = null;
+  private static HashMap m_l8 = null;
+  private static HashMap m_l7 = null;
+  private static HashMap m_l6 = null;
+  private static HashMap m_l5 = null;
+  private static HashMap m_l4 = null;
+  private static HashMap m_l3 = null;
+  private static HashMap m_l2 = null;
+  private static HashMap m_l1 = null;
+
+  static {
+
+    m_l11 = new HashMap();
+    m_l11.put("alistically", "B");
+    m_l11.put("arizability", "A");
+    m_l11.put("izationally", "B");
+    m_l10 = new HashMap();
+    m_l10.put("antialness", "A");
+    m_l10.put("arisations", "A");
+    m_l10.put("arizations", "A");
+    m_l10.put("entialness", "A");
+    m_l9 = new HashMap();
+    m_l9.put("allically", "C");
+    m_l9.put("antaneous", "A");
+    m_l9.put("antiality", "A");
+    m_l9.put("arisation", "A");
+    m_l9.put("arization", "A");
+    m_l9.put("ationally", "B");
+    m_l9.put("ativeness", "A");
+    m_l9.put("eableness", "E");
+    m_l9.put("entations", "A");
+    m_l9.put("entiality", "A");
+    m_l9.put("entialize", "A");
+    m_l9.put("entiation", "A");
+    m_l9.put("ionalness", "A");
+    m_l9.put("istically", "A");
+    m_l9.put("itousness", "A");
+    m_l9.put("izability", "A");
+    m_l9.put("izational", "A");
+    m_l8 = new HashMap();
+    m_l8.put("ableness", "A");
+    m_l8.put("arizable", "A");
+    m_l8.put("entation", "A");
+    m_l8.put("entially", "A");
+    m_l8.put("eousness", "A");
+    m_l8.put("ibleness", "A");
+    m_l8.put("icalness", "A");
+    m_l8.put("ionalism", "A");
+    m_l8.put("ionality", "A");
+    m_l8.put("ionalize", "A");
+    m_l8.put("iousness", "A");
+    m_l8.put("izations", "A");
+    m_l8.put("lessness", "A");
+    m_l7 = new HashMap();
+    m_l7.put("ability", "A");
+    m_l7.put("aically", "A");
+    m_l7.put("alistic", "B");
+    m_l7.put("alities", "A");
+    m_l7.put("ariness", "E");
+    m_l7.put("aristic", "A");
+    m_l7.put("arizing", "A");
+    m_l7.put("ateness", "A");
+    m_l7.put("atingly", "A");
+    m_l7.put("ational", "B");
+    m_l7.put("atively", "A");
+    m_l7.put("ativism", "A");
+    m_l7.put("elihood", "E");
+    m_l7.put("encible", "A");
+    m_l7.put("entally", "A");
+    m_l7.put("entials", "A");
+    m_l7.put("entiate", "A");
+    m_l7.put("entness", "A");
+    m_l7.put("fulness", "A");
+    m_l7.put("ibility", "A");
+    m_l7.put("icalism", "A");
+    m_l7.put("icalist", "A");
+    m_l7.put("icality", "A");
+    m_l7.put("icalize", "A");
+    m_l7.put("ication", "G");
+    m_l7.put("icianry", "A");
+    m_l7.put("ination", "A");
+    m_l7.put("ingness", "A");
+    m_l7.put("ionally", "A");
+    m_l7.put("isation", "A");
+    m_l7.put("ishness", "A");
+    m_l7.put("istical", "A");
+    m_l7.put("iteness", "A");
+    m_l7.put("iveness", "A");
+    m_l7.put("ivistic", "A");
+    m_l7.put("ivities", "A");
+    m_l7.put("ization", "F");
+    m_l7.put("izement", "A");
+    m_l7.put("oidally", "A");
+    m_l7.put("ousness", "A");
+    m_l6 = new HashMap();
+    m_l6.put("aceous", "A");
+    m_l6.put("acious", "B");
+    m_l6.put("action", "G");
+    m_l6.put("alness", "A");
+    m_l6.put("ancial", "A");
+    m_l6.put("ancies", "A");
+    m_l6.put("ancing", "B");
+    m_l6.put("ariser", "A");
+    m_l6.put("arized", "A");
+    m_l6.put("arizer", "A");
+    m_l6.put("atable", "A");
+    m_l6.put("ations", "B");
+    m_l6.put("atives", "A");
+    m_l6.put("eature", "Z");
+    m_l6.put("efully", "A");
+    m_l6.put("encies", "A");
+    m_l6.put("encing", "A");
+    m_l6.put("ential", "A");
+    m_l6.put("enting", "C");
+    m_l6.put("entist", "A");
+    m_l6.put("eously", "A");
+    m_l6.put("ialist", "A");
+    m_l6.put("iality", "A");
+    m_l6.put("ialize", "A");
+    m_l6.put("ically", "A");
+    m_l6.put("icance", "A");
+    m_l6.put("icians", "A");
+    m_l6.put("icists", "A");
+    m_l6.put("ifully", "A");
+    m_l6.put("ionals", "A");
+    m_l6.put("ionate", "D");
+    m_l6.put("ioning", "A");
+    m_l6.put("ionist", "A");
+    m_l6.put("iously", "A");
+    m_l6.put("istics", "A");
+    m_l6.put("izable", "E");
+    m_l6.put("lessly", "A");
+    m_l6.put("nesses", "A");
+    m_l6.put("oidism", "A");
+    m_l5 = new HashMap();
+    m_l5.put("acies", "A");
+    m_l5.put("acity", "A");
+    m_l5.put("aging", "B");
+    m_l5.put("aical", "A");
+    if (!m_CompMode) {
+      m_l5.put("alist", "A");
+    }
+    m_l5.put("alism", "B");
+    m_l5.put("ality", "A");
+    m_l5.put("alize", "A");
+    m_l5.put("allic", "b");
+    m_l5.put("anced", "B");
+    m_l5.put("ances", "B");
+    m_l5.put("antic", "C");
+    m_l5.put("arial", "A");
+    m_l5.put("aries", "A");
+    m_l5.put("arily", "A");
+    m_l5.put("arity", "B");
+    m_l5.put("arize", "A");
+    m_l5.put("aroid", "A");
+    m_l5.put("ately", "A");
+    m_l5.put("ating", "I");
+    m_l5.put("ation", "B");
+    m_l5.put("ative", "A");
+    m_l5.put("ators", "A");
+    m_l5.put("atory", "A");
+    m_l5.put("ature", "E");
+    m_l5.put("early", "Y");
+    m_l5.put("ehood", "A");
+    m_l5.put("eless", "A");
+    if (!m_CompMode) {
+      m_l5.put("elily", "A");
+    } else {
+      m_l5.put("elity", "A");
+    }
+    m_l5.put("ement", "A");
+    m_l5.put("enced", "A");
+    m_l5.put("ences", "A");
+    m_l5.put("eness", "E");
+    m_l5.put("ening", "E");
+    m_l5.put("ental", "A");
+    m_l5.put("ented", "C");
+    m_l5.put("ently", "A");
+    m_l5.put("fully", "A");
+    m_l5.put("ially", "A");
+    m_l5.put("icant", "A");
+    m_l5.put("ician", "A");
+    m_l5.put("icide", "A");
+    m_l5.put("icism", "A");
+    m_l5.put("icist", "A");
+    m_l5.put("icity", "A");
+    m_l5.put("idine", "I");
+    m_l5.put("iedly", "A");
+    m_l5.put("ihood", "A");
+    m_l5.put("inate", "A");
+    m_l5.put("iness", "A");
+    m_l5.put("ingly", "B");
+    m_l5.put("inism", "J");
+    m_l5.put("inity", "c");
+    m_l5.put("ional", "A");
+    m_l5.put("ioned", "A");
+    m_l5.put("ished", "A");
+    m_l5.put("istic", "A");
+    m_l5.put("ities", "A");
+    m_l5.put("itous", "A");
+    m_l5.put("ively", "A");
+    m_l5.put("ivity", "A");
+    m_l5.put("izers", "F");
+    m_l5.put("izing", "F");
+    m_l5.put("oidal", "A");
+    m_l5.put("oides", "A");
+    m_l5.put("otide", "A");
+    m_l5.put("ously", "A");
+    m_l4 = new HashMap();
+    m_l4.put("able", "A");
+    m_l4.put("ably", "A");
+    m_l4.put("ages", "B");
+    m_l4.put("ally", "B");
+    m_l4.put("ance", "B");
+    m_l4.put("ancy", "B");
+    m_l4.put("ants", "B");
+    m_l4.put("aric", "A");
+    m_l4.put("arly", "K");
+    m_l4.put("ated", "I");
+    m_l4.put("ates", "A");
+    m_l4.put("atic", "B");
+    m_l4.put("ator", "A");
+    m_l4.put("ealy", "Y");
+    m_l4.put("edly", "E");
+    m_l4.put("eful", "A");
+    m_l4.put("eity", "A");
+    m_l4.put("ence", "A");
+    m_l4.put("ency", "A");
+    m_l4.put("ened", "E");
+    m_l4.put("enly", "E");
+    m_l4.put("eous", "A");
+    m_l4.put("hood", "A");
+    m_l4.put("ials", "A");
+    m_l4.put("ians", "A");
+    m_l4.put("ible", "A");
+    m_l4.put("ibly", "A");
+    m_l4.put("ical", "A");
+    m_l4.put("ides", "L");
+    m_l4.put("iers", "A");
+    m_l4.put("iful", "A");
+    m_l4.put("ines", "M");
+    m_l4.put("ings", "N");
+    m_l4.put("ions", "B");
+    m_l4.put("ious", "A");
+    m_l4.put("isms", "B");
+    m_l4.put("ists", "A");
+    m_l4.put("itic", "H");
+    m_l4.put("ized", "F");
+    m_l4.put("izer", "F");
+    m_l4.put("less", "A");
+    m_l4.put("lily", "A");
+    m_l4.put("ness", "A");
+    m_l4.put("ogen", "A");
+    m_l4.put("ward", "A");
+    m_l4.put("wise", "A");
+    m_l4.put("ying", "B");
+    m_l4.put("yish", "A");
+    m_l3 = new HashMap();
+    m_l3.put("acy", "A");
+    m_l3.put("age", "B");
+    m_l3.put("aic", "A");
+    m_l3.put("als", "b");
+    m_l3.put("ant", "B");
+    m_l3.put("ars", "O");
+    m_l3.put("ary", "F");
+    m_l3.put("ata", "A");
+    m_l3.put("ate", "A");
+    m_l3.put("eal", "Y");
+    m_l3.put("ear", "Y");
+    m_l3.put("ely", "E");
+    m_l3.put("ene", "E");
+    m_l3.put("ent", "C");
+    m_l3.put("ery", "E");
+    m_l3.put("ese", "A");
+    m_l3.put("ful", "A");
+    m_l3.put("ial", "A");
+    m_l3.put("ian", "A");
+    m_l3.put("ics", "A");
+    m_l3.put("ide", "L");
+    m_l3.put("ied", "A");
+    m_l3.put("ier", "A");
+    m_l3.put("ies", "P");
+    m_l3.put("ily", "A");
+    m_l3.put("ine", "M");
+    m_l3.put("ing", "N");
+    m_l3.put("ion", "Q");
+    m_l3.put("ish", "C");
+    m_l3.put("ism", "B");
+    m_l3.put("ist", "A");
+    m_l3.put("ite", "a");
+    m_l3.put("ity", "A");
+    m_l3.put("ium", "A");
+    m_l3.put("ive", "A");
+    m_l3.put("ize", "F");
+    m_l3.put("oid", "A");
+    m_l3.put("one", "R");
+    m_l3.put("ous", "A");
+    m_l2 = new HashMap();
+    m_l2.put("ae", "A"); 
+    m_l2.put("al", "b");
+    m_l2.put("ar", "X");
+    m_l2.put("as", "B");
+    m_l2.put("ed", "E");
+    m_l2.put("en", "F");
+    m_l2.put("es", "E");
+    m_l2.put("ia", "A");
+    m_l2.put("ic", "A");
+    m_l2.put("is", "A");
+    m_l2.put("ly", "B");
+    m_l2.put("on", "S");
+    m_l2.put("or", "T");
+    m_l2.put("um", "U");
+    m_l2.put("us", "V");
+    m_l2.put("yl", "R");
+    m_l2.put("s\'", "A");
+    m_l2.put("\'s", "A");
+    m_l1 = new HashMap();
+    m_l1.put("a", "A");
+    m_l1.put("e", "A");
+    m_l1.put("i", "A");
+    m_l1.put("o", "A");
+    m_l1.put("s", "W");
+    m_l1.put("y", "B");	
+  }
+
+  /**
+   * Finds and removes ending from given word.
+   */
+  private String removeEnding(String word) {
+
+    int length = word.length();
+    int el = 11;
+
+    while (el > 0) {
+      if (length - el > 1) {
+	String ending = word.substring(length - el);
+	String conditionCode = null;
+	switch (el) {
+	case 11: conditionCode = (String)m_l11.get(ending);
+	  break;
+	case 10: conditionCode = (String)m_l10.get(ending);
+	  break; 
+	case 9: conditionCode = (String)m_l9.get(ending);
+	  break;
+	case 8: conditionCode = (String)m_l8.get(ending);
+	  break;   
+	case 7: conditionCode = (String)m_l7.get(ending);
+	  break;   
+	case 6: conditionCode = (String)m_l6.get(ending);
+	  break;   
+	case 5: conditionCode = (String)m_l5.get(ending);
+	  break;   
+	case 4: conditionCode = (String)m_l4.get(ending);
+	  break;   
+	case 3: conditionCode = (String)m_l3.get(ending);
+	  break;   
+	case 2: conditionCode = (String)m_l2.get(ending);
+	  break;   
+	case 1: conditionCode = (String)m_l1.get(ending);
+	  break;   
+	default:
+	}
+	if (conditionCode != null) {
+	  switch (conditionCode.charAt(0)) {
+	  case 'A':
+	    return word.substring(0, length - el);
+	  case 'B':
+	    if (length - el > 2) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'C':
+	    if (length - el > 3) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'D':
+	    if (length - el > 4) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'E':
+	    if (word.charAt(length - el - 1) != 'e') {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'F':
+	    if ((length - el > 2) &&
+		(word.charAt(length - el - 1) != 'e')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'G':
+	    if ((length - el > 2) &&
+		(word.charAt(length - el - 1) == 'f')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'H':
+	    if ((word.charAt(length - el - 1) == 't') ||
+		((word.charAt(length - el - 1) == 'l') &&
+		 (word.charAt(length - el - 2) == 'l'))) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'I':
+	    if ((word.charAt(length - el - 1) != 'o') &&
+		(word.charAt(length - el - 1) != 'e')) { 
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'J':
+	    if ((word.charAt(length - el - 1) != 'a') &&
+		(word.charAt(length - el - 1) != 'e')) { 
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'K':
+	    if ((length - el > 2) &&
+		((word.charAt(length - el - 1) == 'l') ||
+		 (word.charAt(length - el - 1) == 'i') ||
+		 ((word.charAt(length - el - 1) == 'e') &&
+		  (word.charAt(length - el - 3) == 'u')))) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'L':
+	    if ((word.charAt(length - el - 1) != 'u') &&
+		(word.charAt(length - el - 1) != 'x') &&
+		((word.charAt(length - el - 1) != 's') ||
+		 (word.charAt(length - el - 2) == 'o'))) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'M':
+	    if ((word.charAt(length - el - 1) != 'a') &&
+		(word.charAt(length - el - 1) != 'c') &&
+		(word.charAt(length - el - 1) != 'e') &&
+		(word.charAt(length - el - 1) != 'm')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'N':
+	    if ((length - el > 3) || 
+		((length - el == 3) &&
+		 ((word.charAt(length - el - 3) != 's')))) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'O':
+	    if ((word.charAt(length - el - 1) == 'l') ||
+		(word.charAt(length - el - 1) == 'i')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'P':
+	    if (word.charAt(length - el - 1) != 'c') {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'Q':
+	    if ((length - el > 2) &&
+		(word.charAt(length - el - 1) != 'l') &&
+		(word.charAt(length - el - 1) != 'n')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'R':
+	    if ((word.charAt(length - el - 1) == 'n') ||
+		(word.charAt(length - el - 1) == 'r')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'S':
+	    if (((word.charAt(length - el - 1) == 'r') &&
+		 (word.charAt(length - el - 2) == 'd')) ||
+		((word.charAt(length - el - 1) == 't') &&
+		 (word.charAt(length - el - 2) != 't'))) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'T':
+	    if ((word.charAt(length - el - 1) == 's') ||
+		((word.charAt(length - el - 1) == 't') &&
+		 (word.charAt(length - el - 2) != 'o'))) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'U':
+	    if ((word.charAt(length - el - 1) == 'l') ||
+		(word.charAt(length - el - 1) == 'm') ||
+		(word.charAt(length - el - 1) == 'n') ||
+		(word.charAt(length - el - 1) == 'r')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'V':
+	    if (word.charAt(length - el - 1) == 'c') {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'W':
+	    if ((word.charAt(length - el - 1) != 's') &&
+		(word.charAt(length - el - 1) != 'u')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'X':
+	    if ((word.charAt(length - el - 1) == 'l') ||
+		(word.charAt(length - el - 1) == 'i') ||
+		((length - el > 2) &&
+		 (word.charAt(length - el - 1) == 'e') &&
+		 (word.charAt(length - el - 3) == 'u'))) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'Y':
+	    if ((word.charAt(length - el - 1) == 'n') &&
+		(word.charAt(length - el - 2) == 'i')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'Z':
+	    if (word.charAt(length - el - 1) != 'f') {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'a':
+	    if ((word.charAt(length - el - 1) == 'd') ||
+		(word.charAt(length - el - 1) == 'f') ||
+		(((word.charAt(length - el - 1) == 'h') &&
+		  (word.charAt(length - el - 2) == 'p'))) ||
+		(((word.charAt(length - el - 1) == 'h') &&
+		  (word.charAt(length - el - 2) == 't'))) ||
+		(word.charAt(length - el - 1) == 'l') ||
+		(((word.charAt(length - el - 1) == 'r') &&
+		  (word.charAt(length - el - 2) == 'e'))) ||
+		(((word.charAt(length - el - 1) == 'r') &&
+		  (word.charAt(length - el - 2) == 'o'))) ||
+		(((word.charAt(length - el - 1) == 's') &&
+		  (word.charAt(length - el - 2) == 'e'))) ||
+		(word.charAt(length - el - 1) == 't')) {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  case 'b':
+	    if (m_CompMode) {
+	      if (((length - el == 3 ) &&
+		   (!((word.charAt(length - el - 1) == 't') &&
+		      (word.charAt(length - el - 2) == 'e') &&
+		      (word.charAt(length - el - 3) == 'm')))) ||
+		  ((length - el > 3) &&
+		   (!((word.charAt(length - el - 1) == 't') &&
+		      (word.charAt(length - el - 2) == 's') &&
+		      (word.charAt(length - el - 3) == 'y') &&
+		      (word.charAt(length - el - 4) == 'r'))))) {
+		return word.substring(0, length - el);
+	      }
+	    } else {
+	      if ((length - el > 2) &&
+		  (!((word.charAt(length - el - 1) == 't') &&
+		     (word.charAt(length - el - 2) == 'e') &&
+		     (word.charAt(length - el - 3) == 'm'))) &&
+		  ((length - el < 4) ||
+		   (!((word.charAt(length - el - 1) == 't') &&
+		      (word.charAt(length - el - 2) == 's') &&
+		      (word.charAt(length - el - 3) == 'y') &&
+		      (word.charAt(length - el - 4) == 'r'))))) {
+		return word.substring(0, length - el);
+	      }
+	    } 
+	    break;
+	  case 'c':
+	    if (word.charAt(length - el - 1) == 'l') {
+	      return word.substring(0, length - el);
+	    }
+	    break;
+	  default:
+	    throw new IllegalArgumentException("Fatal error.");
+	  }
+	}
+      }
+      el--;
+    }
+    return word;
+  }
+
+  /**
+   * Recodes ending of given word.
+   */
+  private String recodeEnding(String word) {
+
+    int lastPos = word.length() - 1;
+
+    // Rule 1
+    if (word.endsWith("bb") ||
+	word.endsWith("dd") ||
+	word.endsWith("gg") ||
+	word.endsWith("ll") ||
+	word.endsWith("mm") ||
+	word.endsWith("nn") ||
+	word.endsWith("pp") ||
+	word.endsWith("rr") ||
+	word.endsWith("ss") ||
+	word.endsWith("tt")) {
+      word = word.substring(0, lastPos);
+      lastPos--;
+    }
+
+    // Rule 2
+    if (word.endsWith("iev")) {
+      word = word.substring(0, lastPos - 2).concat("ief");
+    }
+
+    // Rule 3
+    if (word.endsWith("uct")) {
+      word = word.substring(0, lastPos - 2).concat("uc");
+      lastPos--;
+    }
+
+    // Rule 4
+    if (word.endsWith("umpt")) {
+      word = word.substring(0, lastPos - 3).concat("um");
+      lastPos -= 2;
+    }
+
+    // Rule 5
+    if (word.endsWith("rpt")) {
+      word = word.substring(0, lastPos - 2).concat("rb");
+      lastPos--;
+    }
+
+    // Rule 6
+    if (word.endsWith("urs")) {
+      word = word.substring(0, lastPos - 2).concat("ur");
+      lastPos--;
+    }
+
+    // Rule 7
+    if (word.endsWith("istr")) {
+      word = word.substring(0, lastPos - 3).concat("ister");
+      lastPos++;
+    }
+ 
+    // Rule 7a
+    if (word.endsWith("metr")) {
+      word = word.substring(0, lastPos - 3).concat("meter");
+      lastPos++;
+    }
+
+    // Rule 8
+    if (word.endsWith("olv")) {
+      word = word.substring(0, lastPos - 2).concat("olut");
+      lastPos++;
+    }
+ 
+    // Rule 9
+    if (word.endsWith("ul")) {
+      if ((lastPos - 2 < 0) ||
+	  ((word.charAt(lastPos - 2) != 'a') &&
+	   (word.charAt(lastPos - 2) != 'i') &&
+	   (word.charAt(lastPos - 2) != 'o'))) {
+	word = word.substring(0, lastPos - 1).concat("l");
+	lastPos--;
+      }
+    }
+
+    // Rule 10
+    if (word.endsWith("bex")) {
+      word = word.substring(0, lastPos - 2).concat("bic");
+    }
+
+    // Rule 11
+    if (word.endsWith("dex")) {
+      word = word.substring(0, lastPos - 2).concat("dic");
+    }
+
+    // Rule 12
+    if (word.endsWith("pex")) {
+      word = word.substring(0, lastPos - 2).concat("pic");
+    }
+
+    // Rule 13
+    if (word.endsWith("tex")) {
+      word = word.substring(0, lastPos - 2).concat("tic");
+    }
+
+    // Rule 14
+    if (word.endsWith("ax")) {
+      word = word.substring(0, lastPos - 1).concat("ac");
+    }
+
+    // Rule 15
+    if (word.endsWith("ex")) {
+      word = word.substring(0, lastPos - 1).concat("ec");
+    }
+
+    // Rule 16
+    if (word.endsWith("ix")) {
+      word = word.substring(0, lastPos - 1).concat("ic");
+    }
+
+    // Rule 17
+    if (word.endsWith("lux")) {
+      word = word.substring(0, lastPos - 2).concat("luc");
+    }
+
+    // Rule 18
+    if (word.endsWith("uad")) {
+      word = word.substring(0, lastPos - 2).concat("uas");
+    }
+
+    // Rule 19
+    if (word.endsWith("vad")) {
+      word = word.substring(0, lastPos - 2).concat("vas");
+    }
+
+    // Rule 20
+    if (word.endsWith("cid")) {
+      word = word.substring(0, lastPos - 2).concat("cis");
+    }
+
+    // Rule 21
+    if (word.endsWith("lid")) {
+      word = word.substring(0, lastPos - 2).concat("lis");
+    }
+
+    // Rule 22
+    if (word.endsWith("erid")) {
+      word = word.substring(0, lastPos - 3).concat("eris");
+    }
+
+    // Rule 23
+    if (word.endsWith("pand")) {
+      word = word.substring(0, lastPos - 3).concat("pans");
+    }
+ 
+    // Rule 24
+    if (word.endsWith("end")) {
+      if ((lastPos - 3 < 0) ||
+	   (word.charAt(lastPos - 3) != 's')) {
+	word = word.substring(0, lastPos - 2).concat("ens");
+      }
+    }
+
+    // Rule 25
+    if (word.endsWith("ond")) {
+      word = word.substring(0, lastPos - 2).concat("ons");
+    }
+
+    // Rule 26
+    if (word.endsWith("lud")) {
+      word = word.substring(0, lastPos - 2).concat("lus");
+    }
+
+    // Rule 27
+    if (word.endsWith("rud")) {
+      word = word.substring(0, lastPos - 2).concat("rus");
+    }
+
+    // Rule 28
+    if (word.endsWith("her")) {
+      if ((lastPos - 3 < 0) ||
+	  ((word.charAt(lastPos - 3) != 'p') &&
+	   (word.charAt(lastPos - 3) != 't'))) {
+	word = word.substring(0, lastPos - 2).concat("hes");
+      }
+    }
+
+    // Rule 29
+    if (word.endsWith("mit")) {
+      word = word.substring(0, lastPos - 2).concat("mis");
+    }
+
+    // Rule 30
+    if (word.endsWith("end")) {
+      if ((lastPos - 3 < 0) ||
+	  (word.charAt(lastPos - 3) != 'm')) {
+	word = word.substring(0, lastPos - 2).concat("ens");
+      }
+    }
+
+    // Rule 31
+    if (word.endsWith("ert")) {
+      word = word.substring(0, lastPos - 2).concat("ers");
+    }
+
+    // Rule 32
+    if (word.endsWith("et")) {
+      if ((lastPos - 2 < 0) ||
+	  (word.charAt(lastPos - 2) != 'n')) {
+	word = word.substring(0, lastPos - 1).concat("es");
+      }
+    }
+
+    // Rule 33
+    if (word.endsWith("yt")) {
+      word = word.substring(0, lastPos - 1).concat("ys");
+    }
+
+    // Rule 34
+    if (word.endsWith("yz")) {
+      word = word.substring(0, lastPos - 1).concat("ys");
+    }
+
+    return word;
+  }
+
+  /**
+   * Returns the stemmed version of the given word.
+   * 
+   * @param word a string consisting of a single word
+   */
+  public String stem(String word) {
+
+    if (word.length() > 2) {
+      return recodeEnding(removeEnding(word.toLowerCase()));
+    } else {
+      return word.toLowerCase();
+    }
+  }
+
+  /**
+   * Stems text coming into stdin and writes it to stdout.
+   */
+  public static void main(String[] ops) {
+
+    LovinsStemmer ls = new LovinsStemmer();
+
+    try {
+      int num;
+      StringBuffer wordBuffer = new StringBuffer();
+      while ((num = System.in.read()) != -1) {
+	char c = (char)num;
+	if (((num >= (int)'A') && (num <= (int)'Z')) ||
+	    ((num >= (int)'a') && (num <= (int)'z'))) {
+	  wordBuffer.append(c);
+	} else {
+	  if (wordBuffer.length() > 0) {
+	    System.out.print(ls.stem(wordBuffer.toString().
+				     toLowerCase()));
+	    wordBuffer = new StringBuffer();
+	  }
+	  System.out.print(c);
+	}
+      }
+    } catch (Exception e) {
+      System.err.println(e.getMessage());
+    }
+  }
+}
+    
+
Index: /trunk/gsdl/packages/kea/kea-3.0/NumbersFilter.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/NumbersFilter.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/NumbersFilter.java	(revision 8815)
@@ -0,0 +1,182 @@
+/*
+ *    NumbersFilter.java
+ *    Copyright (C) 2000 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import weka.core.*;
+import weka.filters.*;
+
+import java.util.*;
+
+/**
+ * Removes all numbers from all the string attributes in the given
+ * dataset. Assumes that words are separated by whitespace.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public class NumbersFilter extends Filter {
+
+  /**
+   * Returns a string describing this filter
+   *
+   * @return a description of the filter suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String globalInfo() {
+      return "Removes all numbers from all the string attributes in " +
+      "the given dataset. Assumes that words are separated by whitespace.";
+  }
+
+  /**
+   * Signify that this batch of input to the filter is finished. If
+   * the filter requires all instances prior to filtering, output()
+   * may now be called to retrieve the filtered instances. Any
+   * subsequent instances filtered should be filtered based on setting
+   * obtained from the first batch (unless the inputFormat has been
+   * re-assigned or new options have been set). This default
+   * implementation assumes all instance processing occurs during
+   * inputFormat() and input().
+   *
+   * @return true if there are instances pending output
+   * @exception NullPointerException if no input structure has been defined,
+   * @exception Exception if there was a problem finishing the batch.
+   */
+  public boolean batchFinished() throws Exception {
+
+    if (getInputFormat() == null) {
+      throw new NullPointerException("No input instance format defined");
+    }
+    m_NewBatch = true;
+    return (numPendingOutput() != 0);
+  }
+
+  /**
+   * Sets the format of the input instances.
+   *
+   * @param instanceInfo an Instances object containing the input
+   * instance structure (any instances contained in the object are
+   * ignored - only the structure is required).
+   * @return true if the outputFormat may be collected immediately 
+   */
+  public boolean setInputFormat(Instances instanceInfo) throws Exception {
+
+    super.setInputFormat(instanceInfo);
+    setOutputFormat(instanceInfo);
+    return true;
+  }
+
+  /**
+   * Input an instance for filtering. Ordinarily the instance is processed
+   * and made available for output immediately. Some filters require all
+   * instances be read before producing output.
+   *
+   * @param instance the input instance
+   * @return true if the filtered instance may now be
+   * collected with output().
+   * @exception Exception if the input instance was not of the correct 
+   * format or if there was a problem with the filtering.
+   */
+  public boolean input(Instance instance) throws Exception {
+
+    if (getInputFormat() == null) {
+      throw new Exception("No input instance format defined");
+    }
+    if (m_NewBatch) {
+      resetQueue();
+      m_NewBatch = false;
+    }
+    convertInstance(instance);
+    return true;
+  }
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param argv should contain arguments to the filter: use -h for help
+   */
+  public static void main(String [] argv) {
+    
+    try {
+      if (Utils.getFlag('b', argv)) {
+	Filter.batchFilterFile(new NumbersFilter(), argv);
+      } else {
+	Filter.filterFile(new NumbersFilter(), argv);
+      }
+    } catch (Exception ex) {
+      System.out.println(ex.getMessage());
+    }
+  }
+ 
+  /** 
+   * Converts an instance. A phrase boundary is inserted where
+   * a number is found.
+   */
+  private void convertInstance(Instance instance) throws Exception {
+  
+    double[] instVals = new double[instance.numAttributes()];
+
+    for (int i = 0; i < instance.numAttributes(); i++) {
+      if ((!instance.attribute(i).isString()) || instance.isMissing(i)) {
+	instVals[i] = instance.value(i);
+      } else {
+	String str = instance.stringValue(i);
+	StringBuffer resultStr = new StringBuffer();
+	StringTokenizer tok = new StringTokenizer(str, " \t\n", true);
+	while (tok.hasMoreTokens()) {
+	  String token = tok.nextToken();
+
+	  // Everything that doesn't contain at least
+	  // one letter is considered to be a number
+	  boolean isNumber = true;
+	  for (int j = 0; j < token.length(); j++) {
+	    if (Character.isLetter(token.charAt(j))) {
+	      isNumber = false;
+	      break;
+	    }
+	  }
+	  if (!isNumber) {
+	    resultStr.append(token);
+	  } else {
+	    if (token.equals(" ") || token.equals("\t") ||
+		token.equals("\n")) {
+	      resultStr.append(token);
+	    } else {
+	      resultStr.append(" \n ");
+	    }
+	  }
+	}
+	int index = getOutputFormat().attribute(i).addStringValue(resultStr.toString());
+	instVals[i] = (double)index;
+      }
+    }
+    Instance inst = new Instance(instance.weight(), instVals);
+    inst.setDataset(getOutputFormat());
+    push(inst);
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/README
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/README	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/README	(revision 8815)
@@ -0,0 +1,284 @@
+=====================================================================
+                                                                       
+                              ======                                   
+                              README                                   
+                              ======                                   
+                                                                       
+                             KEA 3.0
+                          18 March 2004
+                                                                       
+           Java Programs for Automatic Keyphrase Extraction
+                                                                       
+               Copyright (C) 2000, 2001, 2004  Eibe Frank
+
+                   email: eibe@cs.waikato.ac.nz            
+                                                                       
+=====================================================================
+
+Contents:
+---------
+
+1. Installation
+
+2. Getting started
+
+   - Building a keyphrase extraction model
+   - Extracting keyphrases
+   - Important comment
+
+3. Examples
+
+4. Other documentation
+
+5. Copyright
+
+----------------------------------------------------------------------
+
+NOTE:
+-----
+
+This distribution includes a cut-down version of WEKA, the GPL'ed
+machine learning workbench available from 
+
+  http://www.cs.waikato.ac.nz/ml/weka.
+
+----------------------------------------------------------------------
+
+1. Installation:
+----------------
+
+KEA is implemented as a set of Java classes (located in the same
+directory as this README file). To run KEA you need to tell the Java
+Virtual Machine where to look for KEA classes.  One possible way of
+doing this is to add the directory that contains this README file to
+the CLASSPATH environment variable that is used by the Java Virtual
+Machine.
+
+Under Linux you would do the following:
+
+a) Set KEAHOME to be the directory which contains this README.
+
+b) Add $KEAHOME to your CLASSPATH environment variable.
+
+The on-line documentation (generated from the source code) is located
+in the doc directory. You might want to do the following to have the
+documentation handy in you web browser:
+
+c) Bookmark $KEAHOME/doc/packages.html in your web browser.
+
+----------------------------------------------------------------------
+
+2. Getting started:
+-------------------
+
+Building a keyphrase extraction model
+=====================================
+
+To extract keyphrases for new documents, you first need to build a KEA
+keyphrase extraction model from a set of documents (preferably from
+the same domain) for which you have author- assigned keyphrases. To
+this end you have to go through the following steps:
+
+a) Create a directory, called, for example, "training_documents",
+   containing the documents that you want to use for training the
+   keyphrase extractor.
+
+b) Rename the document files in that directory so that they end with
+   the suffix ".txt".
+
+c) Delete the author-assigned keyphrases from those documents
+   and put them into separate ".key" files. For example, if
+   your document file is called doc1.txt, move the keyphrases
+   into a new file called "doc1.key". It is important that
+   you put each keyphrase on a separate line in the .key file!
+
+d) Build the keyphrase extraction model by running the
+   KEAModelBuilder:
+
+   java KEAModelBuilder -l <name_of_directory> -m <name_of_model>
+
+   This will use the documents in <name_of_directory> to build a
+   keyphrase extraction model and save it in <name_of_model>.
+
+KEAModelBuilder has a few other options that you can view if you run
+KEAModelBuilder without any arguments. Here is a list of all the
+options:
+
+-l <directory name>
+	Specifies name of directory.
+-m <model name>
+	Specifies name of model.
+-e <encoding>
+	Specifies encoding.
+-d
+	Turns debugging mode on.
+-k
+	Use keyphrase frequency statistic.
+-p
+	Disallow internal periods.
+-x <length>
+	Sets the maximum phrase length (default: 3).
+-y <length>
+	Sets the minimum phrase length (default: 1).
+-o <number>
+	The minimum number of times a phrase needs to occur 
+	(default: 2).
+-s <name of stopwords class>
+        Sets the list of stopwords to use (default: StopwordsEnglish).
+-t <name of stemmer class>
+        Set the stemmer to use (default: IteratedLovinsStemmer).
+-n
+        Do not check for proper nouns.
+   
+The -e option allows you to specify a different character encoding
+supported by Java. For example, to extract keyphrases from Chinese
+documents encoded using GBK, you would use specify "-e GBK" as an
+argument.
+
+The -d option generates some output that shows the progress of the
+model builder.
+
+If -k is set, the keyphrase frequency attribute is used in the
+model. For more info on this, have a look at the paper on
+"Domain-specific keyphrase extraction" listed below. Using this option
+improves accuracy if the domain of the documents for which you want to
+extract keyphrases is the same as the domain of the training
+documents. In other words, if you want to extract keyphrases from
+papers on radiology, and your training documents are about radiology,
+you should use this option.
+
+If -p is set, KEA does not consider phrases with internal periods as
+candidate keyphrases. It is important to use this if a full stop is
+not always followed by white space in the documents.
+
+Using -s and -t you can set different classes for stopword detection
+and stemming respectively (for languages other than English).
+
+Using -d you turn KEA's heuristic for detecting proper nouns off. This
+is important for languages like German, where all nouns start with an
+uppercase letter, not just proper nouns.
+
+Extracting keyphrases
+=====================
+
+To extract keyphrases for some documents, put them into an empty
+directory. Then rename them so that they end with the suffix ".txt".
+
+If you've previously built a keyphrase extraction model you can now
+apply keyphrases for these documents using:
+
+java KEAKeyphraseExtractor -l <name_of_directory> -m <name_of_model>
+
+This will create a ".key" file for each document in the
+directory. Each file will contain five extracted keyphrases for the
+corresponding document.
+
+If a ".key" file is already present it won't be overwritten.  Instead,
+the keyphrases present in that file will be used to evaluate the
+extraction model. The stemmed extracted phrases are compared to the
+stemmed versions of the phrases in the ".key"
+file. KEAKeyphraseExtractor reports the number of hits among the total
+number of extracted phrases for those documents that have associated
+".key" files in the directory.
+
+KEAKeyphraseExtractor has a few options. Here they are:
+
+-l <directory name>
+	Specifies name of directory.
+-m <model name>
+	Specifies name of model.
+-e <encoding>
+	Specifies encoding.
+-n
+	Specifies number of phrases to be output (default: 5).
+-d
+	Turns debugging mode on.
+-a
+	Also write stemmed phrase and score into ".key" file.
+
+Important comment
+-----------------
+
+To get good results, it is important that the input text for KEA is as
+"clean" as possible. That means html tags etc. in the input documents
+need to be deleted before the model is built and before keyphrases are
+extracted from new documents.
+
+----------------------------------------------------------------------
+
+3. Examples:
+------------
+
+The directory contains two example collections, each split up into a
+train and test directory. Note that these collections are only
+included to show how the system can be applied to actual documents.
+Due to the lack of data, the accuracy isn't very good on either
+example collection.
+
+Collection A
+------------
+
+A collection of abstracts taken from computer science technical
+reports:
+
+   CSTR_abstracts_train
+   CSTR_abstracts_test
+
+To build a model from the training data, try:
+
+   java KEAModelBuilder -l CSTR_abstracts_train -m CSTR_abstracts_model
+
+To evaluate that model on the test data, try:
+
+   java KEAKeyphraseExtractor -l CSTR_abstracts_test -m CSTR_abstracts_model
+
+Collection B
+------------
+
+A small collection of Chinese documents (in GBK encoding):
+
+   Journals_train
+   Journals_test
+
+To build a model from the training data, try:
+
+   java KEAModelBuilder -l Chinese_train -m Chinese_model -e GBK
+
+To evaluate that model on the test data, try:
+
+   java KEAKeyphraseExtractor -l Chinese_test -m Chinese_model -e GBK 
+
+----------------------------------------------------------------------
+
+4. Other documentation:
+-----------------------
+
+There are several papers on the KEA algorithm, listed below. Note that
+this implementation differs slightly from the version described in the
+papers, mainly in the pre-processing step (i.e. in the way candidate
+keyphrases are generated). For more info on the new method please
+consult the online documentation.
+
+Witten I.H., Paynter G.W., Frank E., Gutwin C. and Nevill-Manning
+C.G. (2000) "KEA: Practical automatic keyphrase extraction." Working
+Paper 00/5, Department of Computer Science, The University of Waikato.
+
+Witten I.H., Paynter G.W., Frank E., Gutwin C. and Nevill-Manning
+C.G. (1999) "KEA: Practical automatic keyphrase extraction." Proc. DL
+'99, pp. 254-256. (Poster presentation.)
+
+Frank E., Paynter G.W., Witten I.H., Gutwin C. and Nevill-Manning
+C.G. (1999) "Domain-specific keyphrase extraction" Proc. Sixteenth
+International Joint Conference on Artificial Intelligence, Morgan
+Kaufmann Publishers, San Francisco, CA, pp. 668-673.
+
+-----------------------------------------------------------------------
+
+5. Copyright:
+-------------
+
+KEA is distributed under the GNU public license. Please read the file
+COPYING.
+
+-----------------------------------------------------------------------
+
Index: /trunk/gsdl/packages/kea/kea-3.0/Stemmer.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/Stemmer.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/Stemmer.java	(revision 8815)
@@ -0,0 +1,68 @@
+/*
+ *    Stemmer.java
+ *    Copyright (C) 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Abstract class for stemmers.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public abstract class Stemmer implements Serializable {
+
+  /**
+   * Iterated stemming of the given word.
+   */
+  public abstract String stem(String str);
+
+  /**
+   * Stems everything in the given string.
+   */
+  public String stemString(String str) {
+
+    StringBuffer result = new StringBuffer();
+    int start = -1;
+    for (int j = 0; j < str.length(); j++) {
+      char c = str.charAt(j);
+      if (Character.isLetterOrDigit(c)) {
+	if (start == -1) {
+	  start = j;
+	}
+      } else if (c == '\'') {
+	if (start == -1) {
+	  result.append(c);
+	}
+      } else {
+	if (start != -1) {
+	  result.append(stem(str.substring(start, j)));
+	  start = -1;
+	}
+	result.append(c);
+      }
+    }
+    if (start != -1) {
+      result.append(stem(str.substring(start, str.length())));
+    }
+    return result.toString();  
+  }
+}
+    
+
Index: /trunk/gsdl/packages/kea/kea-3.0/Stopwords.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/Stopwords.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/Stopwords.java	(revision 8815)
@@ -0,0 +1,38 @@
+/*
+ *    Stopwords.java
+ *    Copyright (C) 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Class that can test whether a given string is a stop word.
+ * Lowercases all words before the test.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public abstract class Stopwords implements Serializable {
+  
+  /** 
+   * Returns true if the given string is a stop word.
+   */
+  public abstract boolean isStopword(String str);
+}
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/StopwordsEnglish.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/StopwordsEnglish.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/StopwordsEnglish.java	(revision 8815)
@@ -0,0 +1,504 @@
+/*
+ *    StopwordsEnglish.java
+ *    Copyright (C) 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.util.*;
+
+/**
+ * Class that can test whether a given string is a stop word.
+ * Lowercases all words before the test.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public class StopwordsEnglish extends Stopwords {
+  
+  /** The hashtable containing the list of stopwords */
+  private static Hashtable m_Stopwords = null;
+
+  static {
+   
+    if (m_Stopwords == null) {
+      m_Stopwords = new Hashtable();
+      Double dummy = new Double(0);
+      
+      m_Stopwords.put("a", dummy);
+      m_Stopwords.put("abaft", dummy);
+      m_Stopwords.put("aboard", dummy);
+      m_Stopwords.put("about", dummy);
+      m_Stopwords.put("above", dummy);
+      m_Stopwords.put("across", dummy);
+      m_Stopwords.put("afore", dummy);
+      m_Stopwords.put("aforesaid", dummy);
+      m_Stopwords.put("after", dummy);
+      m_Stopwords.put("again", dummy);
+      m_Stopwords.put("against", dummy);
+      m_Stopwords.put("agin", dummy);
+      m_Stopwords.put("ago", dummy);
+      m_Stopwords.put("aint", dummy);
+      m_Stopwords.put("albeit", dummy);
+      m_Stopwords.put("all", dummy);
+      m_Stopwords.put("almost", dummy);
+      m_Stopwords.put("alone", dummy);
+      m_Stopwords.put("along", dummy);
+      m_Stopwords.put("alongside", dummy);
+      m_Stopwords.put("already", dummy);
+      m_Stopwords.put("also", dummy);
+      m_Stopwords.put("although", dummy);
+      m_Stopwords.put("always", dummy);
+      m_Stopwords.put("am", dummy);
+      m_Stopwords.put("american", dummy);
+      m_Stopwords.put("amid", dummy);
+      m_Stopwords.put("amidst", dummy);
+      m_Stopwords.put("among", dummy);
+      m_Stopwords.put("amongst", dummy);
+      m_Stopwords.put("an", dummy);
+      m_Stopwords.put("and", dummy);
+      m_Stopwords.put("anent", dummy);
+      m_Stopwords.put("another", dummy);
+      m_Stopwords.put("any", dummy);
+      m_Stopwords.put("anybody", dummy);
+      m_Stopwords.put("anyone", dummy);
+      m_Stopwords.put("anything", dummy);
+      m_Stopwords.put("are", dummy);
+      m_Stopwords.put("aren't", dummy);
+      m_Stopwords.put("around", dummy);
+      m_Stopwords.put("as", dummy);
+      m_Stopwords.put("aslant", dummy);
+      m_Stopwords.put("astride", dummy);
+      m_Stopwords.put("at", dummy);
+      m_Stopwords.put("athwart", dummy);
+      m_Stopwords.put("away", dummy);
+      m_Stopwords.put("b", dummy);
+      m_Stopwords.put("back", dummy);
+      m_Stopwords.put("bar", dummy);
+      m_Stopwords.put("barring", dummy);
+      m_Stopwords.put("be", dummy);
+      m_Stopwords.put("because", dummy);
+      m_Stopwords.put("been", dummy);
+      m_Stopwords.put("before", dummy);
+      m_Stopwords.put("behind", dummy);
+      m_Stopwords.put("being", dummy);
+      m_Stopwords.put("below", dummy);
+      m_Stopwords.put("beneath", dummy);
+      m_Stopwords.put("beside", dummy);
+      m_Stopwords.put("besides", dummy);
+      m_Stopwords.put("best", dummy);
+      m_Stopwords.put("better", dummy);
+      m_Stopwords.put("between", dummy);
+      m_Stopwords.put("betwixt", dummy);
+      m_Stopwords.put("beyond", dummy);
+      m_Stopwords.put("both", dummy);
+      m_Stopwords.put("but", dummy);
+      m_Stopwords.put("by", dummy);
+      m_Stopwords.put("c", dummy);
+      m_Stopwords.put("can", dummy);
+      m_Stopwords.put("cannot", dummy);
+      m_Stopwords.put("can't", dummy);
+      m_Stopwords.put("certain", dummy);
+      m_Stopwords.put("circa", dummy);
+      m_Stopwords.put("close", dummy);
+      m_Stopwords.put("concerning", dummy);
+      m_Stopwords.put("considering", dummy);
+      m_Stopwords.put("cos", dummy);
+      m_Stopwords.put("could", dummy);
+      m_Stopwords.put("couldn't", dummy);
+      m_Stopwords.put("couldst", dummy);
+      m_Stopwords.put("d", dummy);
+      m_Stopwords.put("dare", dummy);
+      m_Stopwords.put("dared", dummy);
+      m_Stopwords.put("daren't", dummy);
+      m_Stopwords.put("dares", dummy);
+      m_Stopwords.put("daring", dummy);
+      m_Stopwords.put("despite", dummy);
+      m_Stopwords.put("did", dummy);
+      m_Stopwords.put("didn't", dummy);
+      m_Stopwords.put("different", dummy);
+      m_Stopwords.put("directly", dummy);
+      m_Stopwords.put("do", dummy);
+      m_Stopwords.put("does", dummy);
+      m_Stopwords.put("doesn't", dummy);
+      m_Stopwords.put("doing", dummy);
+      m_Stopwords.put("done", dummy);
+      m_Stopwords.put("don't", dummy);
+      m_Stopwords.put("dost", dummy);
+      m_Stopwords.put("doth", dummy);
+      m_Stopwords.put("down", dummy);
+      m_Stopwords.put("during", dummy);
+      m_Stopwords.put("durst", dummy);
+      m_Stopwords.put("e", dummy);
+      m_Stopwords.put("each", dummy);
+      m_Stopwords.put("early", dummy);
+      m_Stopwords.put("either", dummy);
+      m_Stopwords.put("em", dummy);
+      m_Stopwords.put("english", dummy);
+      m_Stopwords.put("enough", dummy);
+      m_Stopwords.put("ere", dummy);
+      m_Stopwords.put("even", dummy);
+      m_Stopwords.put("ever", dummy);
+      m_Stopwords.put("every", dummy);
+      m_Stopwords.put("everybody", dummy);
+      m_Stopwords.put("everyone", dummy);
+      m_Stopwords.put("everything", dummy);
+      m_Stopwords.put("except", dummy);
+      m_Stopwords.put("excepting", dummy);
+      m_Stopwords.put("f", dummy);
+      m_Stopwords.put("failing", dummy);
+      m_Stopwords.put("far", dummy);
+      m_Stopwords.put("few", dummy);
+      m_Stopwords.put("first", dummy);
+      m_Stopwords.put("five", dummy);
+      m_Stopwords.put("following", dummy);
+      m_Stopwords.put("for", dummy);
+      m_Stopwords.put("four", dummy);
+      m_Stopwords.put("from", dummy);
+      m_Stopwords.put("g", dummy);
+      m_Stopwords.put("gonna", dummy);
+      m_Stopwords.put("gotta", dummy);
+      m_Stopwords.put("h", dummy);
+      m_Stopwords.put("had", dummy);
+      m_Stopwords.put("hadn't", dummy);
+      m_Stopwords.put("hard", dummy);
+      m_Stopwords.put("has", dummy);
+      m_Stopwords.put("hasn't", dummy);
+      m_Stopwords.put("hast", dummy);
+      m_Stopwords.put("hath", dummy);
+      m_Stopwords.put("have", dummy);
+      m_Stopwords.put("haven't", dummy);
+      m_Stopwords.put("having", dummy);
+      m_Stopwords.put("he", dummy);
+      m_Stopwords.put("he'd", dummy);
+      m_Stopwords.put("he'll", dummy);
+      m_Stopwords.put("her", dummy);
+      m_Stopwords.put("here", dummy);
+      m_Stopwords.put("here's", dummy);
+      m_Stopwords.put("hers", dummy);
+      m_Stopwords.put("herself", dummy);
+      m_Stopwords.put("he's", dummy);
+      m_Stopwords.put("high", dummy);
+      m_Stopwords.put("him", dummy);
+      m_Stopwords.put("himself", dummy);
+      m_Stopwords.put("his", dummy);
+      m_Stopwords.put("home", dummy);
+      m_Stopwords.put("how", dummy);
+      m_Stopwords.put("howbeit", dummy);
+      m_Stopwords.put("however", dummy);
+      m_Stopwords.put("how's", dummy);
+      m_Stopwords.put("i", dummy);
+      m_Stopwords.put("id", dummy);
+      m_Stopwords.put("if", dummy);
+      m_Stopwords.put("ill", dummy);
+      m_Stopwords.put("i'm", dummy);
+      m_Stopwords.put("immediately", dummy);
+      m_Stopwords.put("important", dummy);
+      m_Stopwords.put("in", dummy);
+      m_Stopwords.put("inside", dummy);
+      m_Stopwords.put("instantly", dummy);
+      m_Stopwords.put("into", dummy);
+      m_Stopwords.put("is", dummy);
+      m_Stopwords.put("isn't", dummy);
+      m_Stopwords.put("it", dummy);
+      m_Stopwords.put("it'll", dummy);
+      m_Stopwords.put("it's", dummy);
+      m_Stopwords.put("its", dummy);
+      m_Stopwords.put("itself", dummy);
+      m_Stopwords.put("i've", dummy);
+      m_Stopwords.put("j", dummy);
+      m_Stopwords.put("just", dummy);
+      m_Stopwords.put("k", dummy);
+      m_Stopwords.put("l", dummy);
+      m_Stopwords.put("large", dummy);
+      m_Stopwords.put("last", dummy);
+      m_Stopwords.put("later", dummy);
+      m_Stopwords.put("least", dummy);
+      m_Stopwords.put("left", dummy);
+      m_Stopwords.put("less", dummy);
+      m_Stopwords.put("lest", dummy);
+      m_Stopwords.put("let's", dummy);
+      m_Stopwords.put("like", dummy);
+      m_Stopwords.put("likewise", dummy);
+      m_Stopwords.put("little", dummy);
+      m_Stopwords.put("living", dummy);
+      m_Stopwords.put("long", dummy);
+      m_Stopwords.put("m", dummy);
+      m_Stopwords.put("many", dummy);
+      m_Stopwords.put("may", dummy);
+      m_Stopwords.put("mayn't", dummy);
+      m_Stopwords.put("me", dummy);
+      m_Stopwords.put("mid", dummy);
+      m_Stopwords.put("midst", dummy);
+      m_Stopwords.put("might", dummy);
+      m_Stopwords.put("mightn't", dummy);
+      m_Stopwords.put("mine", dummy);
+      m_Stopwords.put("minus", dummy);
+      m_Stopwords.put("more", dummy);
+      m_Stopwords.put("most", dummy);
+      m_Stopwords.put("much", dummy);
+      m_Stopwords.put("must", dummy);
+      m_Stopwords.put("mustn't", dummy);
+      m_Stopwords.put("my", dummy);
+      m_Stopwords.put("myself", dummy);
+      m_Stopwords.put("n", dummy);
+      m_Stopwords.put("near", dummy);
+      m_Stopwords.put("'neath", dummy);
+      m_Stopwords.put("need", dummy);
+      m_Stopwords.put("needed", dummy);
+      m_Stopwords.put("needing", dummy);
+      m_Stopwords.put("needn't", dummy);
+      m_Stopwords.put("needs", dummy);
+      m_Stopwords.put("neither", dummy);
+      m_Stopwords.put("never", dummy);
+      m_Stopwords.put("nevertheless", dummy);
+      m_Stopwords.put("new", dummy);
+      m_Stopwords.put("next", dummy);
+      m_Stopwords.put("nigh", dummy);
+      m_Stopwords.put("nigher", dummy);
+      m_Stopwords.put("nighest", dummy);
+      m_Stopwords.put("nisi", dummy);
+      m_Stopwords.put("no", dummy);
+      m_Stopwords.put("no-one", dummy);
+      m_Stopwords.put("nobody", dummy);
+      m_Stopwords.put("none", dummy);
+      m_Stopwords.put("nor", dummy);
+      m_Stopwords.put("not", dummy);
+      m_Stopwords.put("nothing", dummy);
+      m_Stopwords.put("notwithstanding", dummy);
+      m_Stopwords.put("now", dummy);
+      m_Stopwords.put("o", dummy);
+      m_Stopwords.put("o'er", dummy);
+      m_Stopwords.put("of", dummy);
+      m_Stopwords.put("off", dummy);
+      m_Stopwords.put("often", dummy);
+      m_Stopwords.put("on", dummy);
+      m_Stopwords.put("once", dummy);
+      m_Stopwords.put("one", dummy);
+      m_Stopwords.put("oneself", dummy);
+      m_Stopwords.put("only", dummy);
+      m_Stopwords.put("onto", dummy);
+      m_Stopwords.put("open", dummy);
+      m_Stopwords.put("or", dummy);
+      m_Stopwords.put("other", dummy);
+      m_Stopwords.put("otherwise", dummy);
+      m_Stopwords.put("ought", dummy);
+      m_Stopwords.put("oughtn't", dummy);
+      m_Stopwords.put("our", dummy);
+      m_Stopwords.put("ours", dummy);
+      m_Stopwords.put("ourselves", dummy);
+      m_Stopwords.put("out", dummy);
+      m_Stopwords.put("outside", dummy);
+      m_Stopwords.put("over", dummy);
+      m_Stopwords.put("own", dummy);
+      m_Stopwords.put("p", dummy);
+      m_Stopwords.put("past", dummy);
+      m_Stopwords.put("pending", dummy);
+      m_Stopwords.put("per", dummy);
+      m_Stopwords.put("perhaps", dummy);
+      m_Stopwords.put("plus", dummy);
+      m_Stopwords.put("possible", dummy);
+      m_Stopwords.put("present", dummy);
+      m_Stopwords.put("probably", dummy);
+      m_Stopwords.put("provided", dummy);
+      m_Stopwords.put("providing", dummy);
+      m_Stopwords.put("public", dummy);
+      m_Stopwords.put("q", dummy);
+      m_Stopwords.put("qua", dummy);
+      m_Stopwords.put("quite", dummy);
+      m_Stopwords.put("r", dummy);
+      m_Stopwords.put("rather", dummy);
+      m_Stopwords.put("re", dummy);
+      m_Stopwords.put("real", dummy);
+      m_Stopwords.put("really", dummy);
+      m_Stopwords.put("respecting", dummy);
+      m_Stopwords.put("right", dummy);
+      m_Stopwords.put("round", dummy);
+      m_Stopwords.put("s", dummy);
+      m_Stopwords.put("same", dummy);
+      m_Stopwords.put("sans", dummy);
+      m_Stopwords.put("save", dummy);
+      m_Stopwords.put("saving", dummy);
+      m_Stopwords.put("second", dummy);
+      m_Stopwords.put("several", dummy);
+      m_Stopwords.put("shall", dummy);
+      m_Stopwords.put("shalt", dummy);
+      m_Stopwords.put("shan't", dummy);
+      m_Stopwords.put("she", dummy);
+      m_Stopwords.put("shed", dummy);
+      m_Stopwords.put("shell", dummy);
+      m_Stopwords.put("she's", dummy);
+      m_Stopwords.put("short", dummy);
+      m_Stopwords.put("should", dummy);
+      m_Stopwords.put("shouldn't", dummy);
+      m_Stopwords.put("since", dummy);
+      m_Stopwords.put("six", dummy);
+      m_Stopwords.put("small", dummy);
+      m_Stopwords.put("so", dummy);
+      m_Stopwords.put("some", dummy);
+      m_Stopwords.put("somebody", dummy);
+      m_Stopwords.put("someone", dummy);
+      m_Stopwords.put("something", dummy);
+      m_Stopwords.put("sometimes", dummy);
+      m_Stopwords.put("soon", dummy);
+      m_Stopwords.put("special", dummy);
+      m_Stopwords.put("still", dummy);
+      m_Stopwords.put("such", dummy);
+      m_Stopwords.put("summat", dummy);
+      m_Stopwords.put("supposing", dummy);
+      m_Stopwords.put("sure", dummy);
+      m_Stopwords.put("t", dummy);
+      m_Stopwords.put("than", dummy);
+      m_Stopwords.put("that", dummy);
+      m_Stopwords.put("that'd", dummy);
+      m_Stopwords.put("that'll", dummy);
+      m_Stopwords.put("that's", dummy);
+      m_Stopwords.put("the", dummy);
+      m_Stopwords.put("thee", dummy);
+      m_Stopwords.put("their", dummy);
+      m_Stopwords.put("theirs", dummy);
+      m_Stopwords.put("their's", dummy);
+      m_Stopwords.put("them", dummy);
+      m_Stopwords.put("themselves", dummy);
+      m_Stopwords.put("then", dummy);
+      m_Stopwords.put("there", dummy);
+      m_Stopwords.put("there's", dummy);
+      m_Stopwords.put("these", dummy);
+      m_Stopwords.put("they", dummy);
+      m_Stopwords.put("they'd", dummy);
+      m_Stopwords.put("they'll", dummy);
+      m_Stopwords.put("they're", dummy);
+      m_Stopwords.put("they've", dummy);
+      m_Stopwords.put("thine", dummy);
+      m_Stopwords.put("this", dummy);
+      m_Stopwords.put("tho", dummy);
+      m_Stopwords.put("those", dummy);
+      m_Stopwords.put("thou", dummy);
+      m_Stopwords.put("though", dummy);
+      m_Stopwords.put("three", dummy);
+      m_Stopwords.put("thro'", dummy);
+      m_Stopwords.put("through", dummy);
+      m_Stopwords.put("throughout", dummy);
+      m_Stopwords.put("thru", dummy);
+      m_Stopwords.put("thyself", dummy);
+      m_Stopwords.put("till", dummy);
+      m_Stopwords.put("to", dummy);
+      m_Stopwords.put("today", dummy);
+      m_Stopwords.put("together", dummy);
+      m_Stopwords.put("too", dummy);
+      m_Stopwords.put("touching", dummy);
+      m_Stopwords.put("toward", dummy);
+      m_Stopwords.put("towards", dummy);
+      m_Stopwords.put("true", dummy);
+      m_Stopwords.put("'twas", dummy);
+      m_Stopwords.put("'tween", dummy);
+      m_Stopwords.put("'twere", dummy);
+      m_Stopwords.put("'twill", dummy);
+      m_Stopwords.put("'twixt", dummy);
+      m_Stopwords.put("two", dummy);
+      m_Stopwords.put("'twould", dummy);
+      m_Stopwords.put("u", dummy);
+      m_Stopwords.put("under", dummy);
+      m_Stopwords.put("underneath", dummy);
+      m_Stopwords.put("unless", dummy);
+      m_Stopwords.put("unlike", dummy);
+      m_Stopwords.put("until", dummy);
+      m_Stopwords.put("unto", dummy);
+      m_Stopwords.put("up", dummy);
+      m_Stopwords.put("upon", dummy);
+      m_Stopwords.put("us", dummy);
+      m_Stopwords.put("used", dummy);
+      m_Stopwords.put("usually", dummy);
+      m_Stopwords.put("v", dummy);
+      m_Stopwords.put("versus", dummy);
+      m_Stopwords.put("very", dummy);
+      m_Stopwords.put("via", dummy);
+      m_Stopwords.put("vice", dummy);
+      m_Stopwords.put("vis-a-vis", dummy);
+      m_Stopwords.put("w", dummy);
+      m_Stopwords.put("wanna", dummy);
+      m_Stopwords.put("wanting", dummy);
+      m_Stopwords.put("was", dummy);
+      m_Stopwords.put("wasn't", dummy);
+      m_Stopwords.put("way", dummy);
+      m_Stopwords.put("we", dummy);
+      m_Stopwords.put("we'd", dummy);
+      m_Stopwords.put("well", dummy);
+      m_Stopwords.put("were", dummy);
+      m_Stopwords.put("weren't", dummy);
+      m_Stopwords.put("wert", dummy);
+      m_Stopwords.put("we've", dummy);
+      m_Stopwords.put("what", dummy);
+      m_Stopwords.put("whatever", dummy);
+      m_Stopwords.put("what'll", dummy);
+      m_Stopwords.put("what's", dummy);
+      m_Stopwords.put("when", dummy);
+      m_Stopwords.put("whencesoever", dummy);
+      m_Stopwords.put("whenever", dummy);
+      m_Stopwords.put("when's", dummy);
+      m_Stopwords.put("whereas", dummy);
+      m_Stopwords.put("where's", dummy);
+      m_Stopwords.put("whether", dummy);
+      m_Stopwords.put("which", dummy);
+      m_Stopwords.put("whichever", dummy);
+      m_Stopwords.put("whichsoever", dummy);
+      m_Stopwords.put("while", dummy);
+      m_Stopwords.put("whilst", dummy);
+      m_Stopwords.put("who", dummy);
+      m_Stopwords.put("who'd", dummy);
+      m_Stopwords.put("whoever", dummy);
+      m_Stopwords.put("whole", dummy);
+      m_Stopwords.put("who'll", dummy);
+      m_Stopwords.put("whom", dummy);
+      m_Stopwords.put("whore", dummy);
+      m_Stopwords.put("who's", dummy);
+      m_Stopwords.put("whose", dummy);
+      m_Stopwords.put("whoso", dummy);
+      m_Stopwords.put("whosoever", dummy);
+      m_Stopwords.put("will", dummy);
+      m_Stopwords.put("with", dummy);
+      m_Stopwords.put("within", dummy);
+      m_Stopwords.put("without", dummy);
+      m_Stopwords.put("wont", dummy);
+      m_Stopwords.put("would", dummy);
+      m_Stopwords.put("wouldn't", dummy);
+      m_Stopwords.put("wouldst", dummy);
+      m_Stopwords.put("x", dummy);
+      m_Stopwords.put("y", dummy);
+      m_Stopwords.put("ye", dummy);
+      m_Stopwords.put("yet", dummy);
+      m_Stopwords.put("you", dummy);
+      m_Stopwords.put("you'd", dummy);
+      m_Stopwords.put("you'll", dummy);
+      m_Stopwords.put("your", dummy);
+      m_Stopwords.put("you're", dummy);
+      m_Stopwords.put("yours", dummy);
+      m_Stopwords.put("yourself", dummy);
+      m_Stopwords.put("yourselves", dummy);
+      m_Stopwords.put("you've", dummy);
+      m_Stopwords.put("z", dummy);
+    }
+  }
+  
+  /** 
+   * Returns true if the given string is a stop word.
+   */
+  public boolean isStopword(String str) {
+
+    return m_Stopwords.containsKey(str.toLowerCase());
+  }
+}
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/StopwordsGerman.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/StopwordsGerman.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/StopwordsGerman.java	(revision 8815)
@@ -0,0 +1,330 @@
+/*
+ *    StopwordsGerman.java
+ *    Copyright (C) 2001 Eibe Frank
+ *
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+import java.util.*;
+
+/**
+ * Class that can test whether a given string is a stop word.
+ * Lowercases all words before the test.
+ *
+ * This list of German stop words has been obtained from
+ * http://snowball.tartarus.org/german/stop.txt
+ *
+ * But I have deleted/changed some words that I haven't seen before.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version 1.0
+ */
+public class StopwordsGerman extends Stopwords {
+  
+  /** The hashtable containing the list of stopwords */
+  private static Hashtable m_Stopwords = null;
+
+  static {
+   
+    if (m_Stopwords == null) {
+      m_Stopwords = new Hashtable();
+      Double dummy = new Double(0);
+
+      m_Stopwords.put("aber", dummy);
+
+      m_Stopwords.put("alle", dummy);
+      m_Stopwords.put("allem", dummy);
+      m_Stopwords.put("allen", dummy);
+      m_Stopwords.put("aller", dummy);
+      m_Stopwords.put("alles", dummy);
+
+      m_Stopwords.put("als", dummy);
+      m_Stopwords.put("also", dummy);
+      m_Stopwords.put("am", dummy);
+      m_Stopwords.put("an", dummy);
+
+      m_Stopwords.put("ander", dummy);
+      m_Stopwords.put("andere", dummy);
+      m_Stopwords.put("anderem", dummy);
+      m_Stopwords.put("anderen", dummy);
+      m_Stopwords.put("anderer", dummy);
+      m_Stopwords.put("anderes", dummy);
+      m_Stopwords.put("anderm", dummy);
+      m_Stopwords.put("andern", dummy);
+      m_Stopwords.put("anders", dummy);
+
+      m_Stopwords.put("auch", dummy);
+      m_Stopwords.put("auf", dummy);
+      m_Stopwords.put("aus", dummy);
+      m_Stopwords.put("bei", dummy);
+      m_Stopwords.put("bin", dummy);
+      m_Stopwords.put("bis", dummy);
+      m_Stopwords.put("bist", dummy);
+      m_Stopwords.put("da", dummy);
+      m_Stopwords.put("damit", dummy);
+      m_Stopwords.put("dann", dummy);
+      
+      m_Stopwords.put("der", dummy);
+      m_Stopwords.put("den", dummy);
+      m_Stopwords.put("des", dummy);
+      m_Stopwords.put("dem", dummy);
+      m_Stopwords.put("die", dummy);
+      m_Stopwords.put("das", dummy);
+
+      m_Stopwords.put("da\u00df", dummy);
+
+      m_Stopwords.put("derselbe", dummy);
+      m_Stopwords.put("derselben", dummy);
+      m_Stopwords.put("denselben", dummy);
+      m_Stopwords.put("desselben", dummy);
+      m_Stopwords.put("demselben", dummy);
+      m_Stopwords.put("dieselbe", dummy);
+      m_Stopwords.put("dieselben", dummy);
+      m_Stopwords.put("dasselbe", dummy);
+
+      m_Stopwords.put("dazu", dummy);
+
+      m_Stopwords.put("dein", dummy);
+      m_Stopwords.put("deine", dummy);
+      m_Stopwords.put("deinem", dummy);
+      m_Stopwords.put("deinen", dummy);
+      m_Stopwords.put("deiner", dummy);
+      m_Stopwords.put("deines", dummy);
+
+      m_Stopwords.put("denn", dummy);
+      
+      m_Stopwords.put("derer", dummy);
+      m_Stopwords.put("dessen", dummy);
+      
+      m_Stopwords.put("dich", dummy);
+      m_Stopwords.put("dir", dummy);
+      m_Stopwords.put("du", dummy);
+
+      m_Stopwords.put("dies", dummy);
+      m_Stopwords.put("diese", dummy);
+      m_Stopwords.put("diesem", dummy);
+      m_Stopwords.put("diesen", dummy);
+      m_Stopwords.put("dieser", dummy);
+      m_Stopwords.put("dieses", dummy);
+
+      m_Stopwords.put("doch", dummy);
+      m_Stopwords.put("dort", dummy);
+
+      m_Stopwords.put("durch", dummy);
+
+      m_Stopwords.put("ein", dummy);
+      m_Stopwords.put("eine", dummy);
+      m_Stopwords.put("einem", dummy);
+      m_Stopwords.put("einen", dummy);
+      m_Stopwords.put("einer", dummy);
+      m_Stopwords.put("eines", dummy);
+
+      m_Stopwords.put("einig", dummy);
+      m_Stopwords.put("einige", dummy);
+      m_Stopwords.put("einigem", dummy);
+      m_Stopwords.put("einigen", dummy);
+      m_Stopwords.put("einiger", dummy);
+      m_Stopwords.put("einiges", dummy);
+
+      m_Stopwords.put("einmal", dummy);
+
+      m_Stopwords.put("er", dummy);
+      m_Stopwords.put("ihn", dummy);
+      m_Stopwords.put("ihm", dummy);
+
+      m_Stopwords.put("es", dummy);
+      m_Stopwords.put("etwas", dummy);
+
+      m_Stopwords.put("euer", dummy);
+      m_Stopwords.put("eure", dummy);
+      m_Stopwords.put("eurem", dummy);
+      m_Stopwords.put("euren", dummy);
+      m_Stopwords.put("eurer", dummy);
+      m_Stopwords.put("eures", dummy);
+
+      m_Stopwords.put("f\u00fcr", dummy);
+      m_Stopwords.put("gegen", dummy);
+      m_Stopwords.put("gewesen", dummy);
+      m_Stopwords.put("hab", dummy);
+      m_Stopwords.put("habe", dummy);
+      m_Stopwords.put("haben", dummy);
+      m_Stopwords.put("hat", dummy);
+      m_Stopwords.put("hatte", dummy);
+      m_Stopwords.put("hatten", dummy);
+      m_Stopwords.put("hier", dummy);
+      m_Stopwords.put("hin", dummy);
+      m_Stopwords.put("hinter", dummy);
+      
+      m_Stopwords.put("ich", dummy);
+      m_Stopwords.put("mich", dummy);
+      m_Stopwords.put("mir", dummy);
+
+      m_Stopwords.put("ihr", dummy);
+      m_Stopwords.put("ihre", dummy);
+      m_Stopwords.put("ihrem", dummy);
+      m_Stopwords.put("ihren", dummy);
+      m_Stopwords.put("ihrer", dummy);
+      m_Stopwords.put("ihres", dummy);
+      m_Stopwords.put("euch", dummy);
+
+      m_Stopwords.put("im", dummy);
+      m_Stopwords.put("in", dummy);
+      m_Stopwords.put("indem", dummy);
+      m_Stopwords.put("ins", dummy);
+      m_Stopwords.put("ist", dummy);
+
+      m_Stopwords.put("jede", dummy);
+      m_Stopwords.put("jedem", dummy);
+      m_Stopwords.put("jeden", dummy);
+      m_Stopwords.put("jeder", dummy);
+      m_Stopwords.put("jedes", dummy);
+
+      m_Stopwords.put("jene", dummy);
+      m_Stopwords.put("jenem", dummy);
+      m_Stopwords.put("jenen", dummy);
+      m_Stopwords.put("jener", dummy);
+      m_Stopwords.put("jenes", dummy);
+
+      m_Stopwords.put("jetzt", dummy);
+      m_Stopwords.put("kann", dummy);
+
+      m_Stopwords.put("kein", dummy);
+      m_Stopwords.put("keine", dummy);
+      m_Stopwords.put("keinem", dummy);
+      m_Stopwords.put("keinen", dummy);
+      m_Stopwords.put("keiner", dummy);
+      m_Stopwords.put("keines", dummy);
+
+      m_Stopwords.put("k\u00f6nnen", dummy);
+      m_Stopwords.put("k\u00f6nnte", dummy);
+      m_Stopwords.put("machen", dummy);
+      m_Stopwords.put("man", dummy);
+
+      m_Stopwords.put("manche", dummy);
+      m_Stopwords.put("manchem", dummy);
+      m_Stopwords.put("manchen", dummy);
+      m_Stopwords.put("mancher", dummy);
+      m_Stopwords.put("manches", dummy);
+
+      m_Stopwords.put("mein", dummy);
+      m_Stopwords.put("meine", dummy);
+      m_Stopwords.put("meinem", dummy);
+      m_Stopwords.put("meinen", dummy);
+      m_Stopwords.put("meiner", dummy);
+      m_Stopwords.put("meines", dummy);
+
+      m_Stopwords.put("mit", dummy);
+      m_Stopwords.put("muss", dummy);
+      m_Stopwords.put("musste", dummy);
+      m_Stopwords.put("nach", dummy);
+      m_Stopwords.put("nicht", dummy);
+      m_Stopwords.put("nichts", dummy);
+      m_Stopwords.put("noch", dummy);
+      m_Stopwords.put("nun", dummy);
+      m_Stopwords.put("nur", dummy);
+      m_Stopwords.put("ob", dummy);
+      m_Stopwords.put("oder", dummy);
+      m_Stopwords.put("ohne", dummy);
+      m_Stopwords.put("sehr", dummy);
+
+      m_Stopwords.put("sein", dummy);
+      m_Stopwords.put("seine", dummy);
+      m_Stopwords.put("seinem", dummy);
+      m_Stopwords.put("seinen", dummy);
+      m_Stopwords.put("seiner", dummy);
+      m_Stopwords.put("seines", dummy);
+
+      m_Stopwords.put("selbst", dummy);
+      m_Stopwords.put("sich", dummy);
+      
+      m_Stopwords.put("sie", dummy);
+      m_Stopwords.put("ihnen", dummy);
+
+      m_Stopwords.put("sind", dummy);
+      m_Stopwords.put("so", dummy);
+
+      m_Stopwords.put("solche", dummy);
+      m_Stopwords.put("solchem", dummy);
+      m_Stopwords.put("solchen", dummy);
+      m_Stopwords.put("solcher", dummy);
+      m_Stopwords.put("solches", dummy);
+
+      m_Stopwords.put("soll", dummy);
+      m_Stopwords.put("sollte", dummy);
+      m_Stopwords.put("sondern", dummy);
+      m_Stopwords.put("sonst", dummy);
+      m_Stopwords.put("\00fcber", dummy);
+      m_Stopwords.put("um", dummy);
+      m_Stopwords.put("und", dummy);
+
+      m_Stopwords.put("uns", dummy);
+      m_Stopwords.put("unser", dummy);
+      m_Stopwords.put("unserem", dummy);
+      m_Stopwords.put("unseren", dummy);
+      m_Stopwords.put("unsere", dummy);
+      m_Stopwords.put("unseres", dummy);
+
+      m_Stopwords.put("unter", dummy);
+      m_Stopwords.put("viel", dummy);
+      m_Stopwords.put("vom", dummy);
+      m_Stopwords.put("von", dummy);
+      m_Stopwords.put("vor", dummy);
+      m_Stopwords.put("w\u00e4hrend", dummy);
+      m_Stopwords.put("war", dummy);
+      m_Stopwords.put("waren", dummy);
+      m_Stopwords.put("warst", dummy);
+      m_Stopwords.put("was", dummy);
+      m_Stopwords.put("weg", dummy);
+      m_Stopwords.put("weil", dummy);
+      m_Stopwords.put("weiter", dummy);
+
+      m_Stopwords.put("welche", dummy);
+      m_Stopwords.put("welchem", dummy);
+      m_Stopwords.put("welchen", dummy);
+      m_Stopwords.put("welcher", dummy);
+      m_Stopwords.put("welches", dummy);
+
+      m_Stopwords.put("wenn", dummy);
+      m_Stopwords.put("werde", dummy);
+      m_Stopwords.put("werden", dummy);
+      m_Stopwords.put("wie", dummy);
+      m_Stopwords.put("wieder", dummy);
+      m_Stopwords.put("will", dummy);
+      m_Stopwords.put("wir", dummy);
+      m_Stopwords.put("wird", dummy);
+      m_Stopwords.put("wirst", dummy);
+      m_Stopwords.put("wo", dummy);
+      m_Stopwords.put("wollen", dummy);
+      m_Stopwords.put("wollte", dummy);
+      m_Stopwords.put("w\u00fcrde", dummy);
+      m_Stopwords.put("w\u00fcrden", dummy);
+      m_Stopwords.put("zu", dummy);
+      m_Stopwords.put("zum", dummy);
+      m_Stopwords.put("zur", dummy);
+      m_Stopwords.put("zwar", dummy);
+      m_Stopwords.put("zwischen", dummy);
+    }
+  }
+  
+  /** 
+   * Returns true if the given string is a stop word.
+   */
+  public boolean isStopword(String str) {
+
+    return m_Stopwords.containsKey(str.toLowerCase());
+  }
+}
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/Counter.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/Counter.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/Counter.html	(revision 8815)
@@ -0,0 +1,318 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:48 NZDT 2004 -->
+<TITLE>
+Counter
+</TITLE>
+<META NAME="keywords" CONTENT="Counter,Counter class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Counter";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV CLASS&nbsp;
+&nbsp;<A HREF="GermanStemmer.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="Counter.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class Counter</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<B>Counter</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.io.Serializable</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>Counter</B><DT>extends java.lang.Object<DT>implements java.io.Serializable</DL>
+
+<P>
+Class that implements a simple counter.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="Counter">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="Counter.html#Counter()">Counter</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Initializes the counter to 1</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="Counter.html#Counter(int)">Counter</A></B>(int&nbsp;val)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Initializes the counter to the given value</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="Counter.html#increment()">increment</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Increments the counter.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="Counter.html#toString()">toString</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns string containing value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="Counter.html#value()">value</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gets the value.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="Counter()"><!-- --></A><H3>
+Counter</H3>
+<PRE>
+public <B>Counter</B>()</PRE>
+<DL>
+<DD>Initializes the counter to 1
+<P>
+</DL>
+<HR>
+
+<A NAME="Counter(int)"><!-- --></A><H3>
+Counter</H3>
+<PRE>
+public <B>Counter</B>(int&nbsp;val)</PRE>
+<DL>
+<DD>Initializes the counter to the given value
+<P>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="increment()"><!-- --></A><H3>
+increment</H3>
+<PRE>
+public void <B>increment</B>()</PRE>
+<DL>
+<DD>Increments the counter.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="value()"><!-- --></A><H3>
+value</H3>
+<PRE>
+public int <B>value</B>()</PRE>
+<DL>
+<DD>Gets the value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the value</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="toString()"><!-- --></A><H3>
+toString</H3>
+<PRE>
+public java.lang.String <B>toString</B>()</PRE>
+<DL>
+<DD>Returns string containing value.
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>toString</CODE> in class <CODE>java.lang.Object</CODE></DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV CLASS&nbsp;
+&nbsp;<A HREF="GermanStemmer.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="Counter.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/GermanStemmer.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/GermanStemmer.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/GermanStemmer.html	(revision 8815)
@@ -0,0 +1,268 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:49 NZDT 2004 -->
+<TITLE>
+GermanStemmer
+</TITLE>
+<META NAME="keywords" CONTENT="GermanStemmer,GermanStemmer class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="GermanStemmer";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="Counter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="IteratedLovinsStemmer.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="GermanStemmer.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class GermanStemmer</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<A HREF="Stemmer.html">Stemmer</A>
+        |
+        +--<B>GermanStemmer</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.io.Serializable</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>GermanStemmer</B><DT>extends <A HREF="Stemmer.html">Stemmer</A></DL>
+
+<P>
+A stemmer for German words. The algorithm is based on the report
+ "A Fast and Simple Stemming Algorithm for German Words" by Jörg
+ Caumanns (joerg.caumanns@isst.fhg.de).
+
+ Changed stem() from protected to public.
+ Changed coding for umlaute to unicode.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="GermanStemmer">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="GermanStemmer.html#GermanStemmer()">GermanStemmer</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="GermanStemmer.html#stem(java.lang.String)">stem</A></B>(java.lang.String&nbsp;term)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stemms the given term to an unique <tt>discriminator</tt>.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_Stemmer"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class <A HREF="Stemmer.html">Stemmer</A></B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><A HREF="Stemmer.html#stemString(java.lang.String)">stemString</A></CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="GermanStemmer()"><!-- --></A><H3>
+GermanStemmer</H3>
+<PRE>
+public <B>GermanStemmer</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="stem(java.lang.String)"><!-- --></A><H3>
+stem</H3>
+<PRE>
+public java.lang.String <B>stem</B>(java.lang.String&nbsp;term)</PRE>
+<DL>
+<DD>Stemms the given term to an unique <tt>discriminator</tt>.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE><A HREF="Stemmer.html#stem(java.lang.String)">stem</A></CODE> in class <CODE><A HREF="Stemmer.html">Stemmer</A></CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>term</CODE> - The term that should be stemmed.
+<DT><B>Returns:</B><DD>Discriminator for <tt>term</tt></DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="Counter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="IteratedLovinsStemmer.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="GermanStemmer.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/IteratedLovinsStemmer.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/IteratedLovinsStemmer.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/IteratedLovinsStemmer.html	(revision 8815)
@@ -0,0 +1,285 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:49 NZDT 2004 -->
+<TITLE>
+IteratedLovinsStemmer
+</TITLE>
+<META NAME="keywords" CONTENT="IteratedLovinsStemmer,IteratedLovinsStemmer class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="IteratedLovinsStemmer";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="GermanStemmer.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="KEAFilter.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="IteratedLovinsStemmer.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class IteratedLovinsStemmer</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<A HREF="Stemmer.html">Stemmer</A>
+        |
+        +--<A HREF="LovinsStemmer.html">LovinsStemmer</A>
+              |
+              +--<B>IteratedLovinsStemmer</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.io.Serializable</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>IteratedLovinsStemmer</B><DT>extends <A HREF="LovinsStemmer.html">LovinsStemmer</A></DL>
+
+<P>
+Implements the iterated version of the Lovins stemmer.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="IteratedLovinsStemmer">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="IteratedLovinsStemmer.html#IteratedLovinsStemmer()">IteratedLovinsStemmer</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="IteratedLovinsStemmer.html#main(java.lang.String[])">main</A></B>(java.lang.String[]&nbsp;ops)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stems text coming into stdin and writes it to stdout.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="IteratedLovinsStemmer.html#stem(java.lang.String)">stem</A></B>(java.lang.String&nbsp;str)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterated stemming of the given word.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_Stemmer"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class <A HREF="Stemmer.html">Stemmer</A></B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><A HREF="Stemmer.html#stemString(java.lang.String)">stemString</A></CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="IteratedLovinsStemmer()"><!-- --></A><H3>
+IteratedLovinsStemmer</H3>
+<PRE>
+public <B>IteratedLovinsStemmer</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="stem(java.lang.String)"><!-- --></A><H3>
+stem</H3>
+<PRE>
+public java.lang.String <B>stem</B>(java.lang.String&nbsp;str)</PRE>
+<DL>
+<DD>Iterated stemming of the given word.
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE><A HREF="LovinsStemmer.html#stem(java.lang.String)">stem</A></CODE> in class <CODE><A HREF="LovinsStemmer.html">LovinsStemmer</A></CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>str</CODE> - a string consisting of a single word</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="main(java.lang.String[])"><!-- --></A><H3>
+main</H3>
+<PRE>
+public static void <B>main</B>(java.lang.String[]&nbsp;ops)</PRE>
+<DL>
+<DD>Stems text coming into stdin and writes it to stdout.
+<P>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="GermanStemmer.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="KEAFilter.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="IteratedLovinsStemmer.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/KEAFilter.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/KEAFilter.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/KEAFilter.html	(revision 8815)
@@ -0,0 +1,1147 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:49 NZDT 2004 -->
+<TITLE>
+KEAFilter
+</TITLE>
+<META NAME="keywords" CONTENT="KEAFilter,KEAFilter class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="KEAFilter";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="IteratedLovinsStemmer.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="KEAKeyphraseExtractor.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="KEAFilter.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_weka.filters.Filter">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class KEAFilter</H2>
+<PRE>
+java.lang.Object
+  |
+  +--weka.filters.Filter
+        |
+        +--<B>KEAFilter</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>weka.core.OptionHandler, java.io.Serializable</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>KEAFilter</B><DT>extends weka.filters.Filter<DT>implements weka.core.OptionHandler</DL>
+
+<P>
+This filter converts the incoming data into data appropriate for
+ keyphrase classification. It assumes that the dataset contains two
+ string attributes. The first attribute should contain the text of a
+ document. The second attribute should contain the keyphrases
+ associated with that document (if present). 
+
+ The filter converts every instance (i.e. document) into a set of
+ instances, one for each word-based n-gram in the document. The
+ string attribute representing the document is replaced by some
+ numeric features, the estimated probability of each n-gram being a
+ keyphrase, and the rank of this phrase in the document according to
+ the probability.  Each new instances also has a class value
+ associated with it. The class is "true" if the n-gram is a true
+ keyphrase, and "false" otherwise. Of course, if the input document
+ doesn't come with author-assigned keyphrases, the class values for
+ that document will be missing.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="KEAFilter">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="fields_inherited_from_class_weka.filters.Filter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Fields inherited from class weka.filters.Filter</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>m_NewBatch</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="KEAFilter.html#KEAFilter()">KEAFilter</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#batchFinished()">batchFinished</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Signify that this batch of input to the filter is finished.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getCheckForProperNouns()">getCheckForProperNouns</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the M_CheckProperNouns value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getDebug()">getDebug</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of Debug.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getDisallowInternalPeriods()">getDisallowInternalPeriods</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get whether the supplied columns are to be processed</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getDocumentAtt()">getDocumentAtt</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of DocumentAtt.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getKeyphrasesAtt()">getKeyphrasesAtt</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of KeyphraseAtt.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getKFused()">getKFused</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gets whether keyphrase frequency attribute is used.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getMaxPhraseLength()">getMaxPhraseLength</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of MaxPhraseLength.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getMinNumOccur()">getMinNumOccur</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of MinNumOccur.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getMinPhraseLength()">getMinPhraseLength</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of MinPhraseLength.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getOptions()">getOptions</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gets the current settings of the filter.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getProbabilityIndex()">getProbabilityIndex</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the index of the phrases' probabilities in the output ARFF file.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getRankIndex()">getRankIndex</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the index of the phrases' ranks in the output ARFF file.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getStemmedPhraseIndex()">getStemmedPhraseIndex</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the index of the stemmed phrases in the output ARFF file.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;Stemmer</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getStemmer()">getStemmer</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the Stemmer value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;Stopwords</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getStopwords()">getStopwords</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the M_Stopwords value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#getUnstemmedPhraseIndex()">getUnstemmedPhraseIndex</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the index of the unstemmed phrases in the output ARFF file.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#globalInfo()">globalInfo</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns a string describing this filter</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#input(weka.core.Instance)">input</A></B>(weka.core.Instance&nbsp;instance)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Input an instance for filtering.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.util.Enumeration</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#listOptions()">listOptions</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns an enumeration describing the available options</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#main(java.lang.String[])">main</A></B>(java.lang.String[]&nbsp;argv)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Main method for testing this class.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setCheckForProperNouns(boolean)">setCheckForProperNouns</A></B>(boolean&nbsp;newM_CheckProperNouns)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the M_CheckProperNouns value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setDebug(boolean)">setDebug</A></B>(boolean&nbsp;newDebug)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of Debug.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setDisallowInternalPeriods(boolean)">setDisallowInternalPeriods</A></B>(boolean&nbsp;disallow)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set whether selected columns should be processed.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setDocumentAtt(int)">setDocumentAtt</A></B>(int&nbsp;newDocumentAtt)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of DocumentAtt.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setInputFormat(weka.core.Instances)">setInputFormat</A></B>(weka.core.Instances&nbsp;instanceInfo)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sets the format of the input instances.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setKeyphrasesAtt(int)">setKeyphrasesAtt</A></B>(int&nbsp;newKeyphrasesAtt)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of KeyphrasesAtt.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setKFused(boolean)">setKFused</A></B>(boolean&nbsp;flag)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sets whether keyphrase frequency attribute is used.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setMaxPhraseLength(int)">setMaxPhraseLength</A></B>(int&nbsp;newMaxPhraseLength)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of MaxPhraseLength.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setMinNumOccur(int)">setMinNumOccur</A></B>(int&nbsp;newMinNumOccur)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of MinNumOccur.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setMinPhraseLength(int)">setMinPhraseLength</A></B>(int&nbsp;newMinPhraseLength)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of MinPhraseLength.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setOptions(java.lang.String[])">setOptions</A></B>(java.lang.String[]&nbsp;options)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Parses a given list of options controlling the behaviour of this object.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setStemmer(Stemmer)">setStemmer</A></B>(Stemmer&nbsp;newStemmer)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the Stemmer value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAFilter.html#setStopwords(Stopwords)">setStopwords</A></B>(Stopwords&nbsp;newM_Stopwords)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the M_Stopwords value.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_weka.filters.Filter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class weka.filters.Filter</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>batchFilterFile, bufferInput, copyStringValues, copyStringValues, filterFile, flushInput, getInputFormat, getInputStringIndex, getOutputFormat, getOutputStringIndex, getStringIndices, inputFormat, isOutputFormatDefined, numPendingOutput, output, outputFormat, outputFormatPeek, outputPeek, push, resetQueue, setOutputFormat, useFilter</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="KEAFilter()"><!-- --></A><H3>
+KEAFilter</H3>
+<PRE>
+public <B>KEAFilter</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="getCheckForProperNouns()"><!-- --></A><H3>
+getCheckForProperNouns</H3>
+<PRE>
+public boolean <B>getCheckForProperNouns</B>()</PRE>
+<DL>
+<DD>Get the M_CheckProperNouns value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the M_CheckProperNouns value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setCheckForProperNouns(boolean)"><!-- --></A><H3>
+setCheckForProperNouns</H3>
+<PRE>
+public void <B>setCheckForProperNouns</B>(boolean&nbsp;newM_CheckProperNouns)</PRE>
+<DL>
+<DD>Set the M_CheckProperNouns value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newM_CheckProperNouns</CODE> - The new M_CheckProperNouns value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getStopwords()"><!-- --></A><H3>
+getStopwords</H3>
+<PRE>
+public Stopwords <B>getStopwords</B>()</PRE>
+<DL>
+<DD>Get the M_Stopwords value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the M_Stopwords value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setStopwords(Stopwords)"><!-- --></A><H3>
+setStopwords</H3>
+<PRE>
+public void <B>setStopwords</B>(Stopwords&nbsp;newM_Stopwords)</PRE>
+<DL>
+<DD>Set the M_Stopwords value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newM_Stopwords</CODE> - The new M_Stopwords value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getStemmer()"><!-- --></A><H3>
+getStemmer</H3>
+<PRE>
+public Stemmer <B>getStemmer</B>()</PRE>
+<DL>
+<DD>Get the Stemmer value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the Stemmer value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setStemmer(Stemmer)"><!-- --></A><H3>
+setStemmer</H3>
+<PRE>
+public void <B>setStemmer</B>(Stemmer&nbsp;newStemmer)</PRE>
+<DL>
+<DD>Set the Stemmer value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newStemmer</CODE> - The new Stemmer value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getMinNumOccur()"><!-- --></A><H3>
+getMinNumOccur</H3>
+<PRE>
+public int <B>getMinNumOccur</B>()</PRE>
+<DL>
+<DD>Get the value of MinNumOccur.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of MinNumOccur.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setMinNumOccur(int)"><!-- --></A><H3>
+setMinNumOccur</H3>
+<PRE>
+public void <B>setMinNumOccur</B>(int&nbsp;newMinNumOccur)</PRE>
+<DL>
+<DD>Set the value of MinNumOccur.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newMinNumOccur</CODE> - Value to assign to MinNumOccur.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getMaxPhraseLength()"><!-- --></A><H3>
+getMaxPhraseLength</H3>
+<PRE>
+public int <B>getMaxPhraseLength</B>()</PRE>
+<DL>
+<DD>Get the value of MaxPhraseLength.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of MaxPhraseLength.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setMaxPhraseLength(int)"><!-- --></A><H3>
+setMaxPhraseLength</H3>
+<PRE>
+public void <B>setMaxPhraseLength</B>(int&nbsp;newMaxPhraseLength)</PRE>
+<DL>
+<DD>Set the value of MaxPhraseLength.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newMaxPhraseLength</CODE> - Value to assign to MaxPhraseLength.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getMinPhraseLength()"><!-- --></A><H3>
+getMinPhraseLength</H3>
+<PRE>
+public int <B>getMinPhraseLength</B>()</PRE>
+<DL>
+<DD>Get the value of MinPhraseLength.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of MinPhraseLength.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setMinPhraseLength(int)"><!-- --></A><H3>
+setMinPhraseLength</H3>
+<PRE>
+public void <B>setMinPhraseLength</B>(int&nbsp;newMinPhraseLength)</PRE>
+<DL>
+<DD>Set the value of MinPhraseLength.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newMinPhraseLength</CODE> - Value to assign to MinPhraseLength.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getStemmedPhraseIndex()"><!-- --></A><H3>
+getStemmedPhraseIndex</H3>
+<PRE>
+public int <B>getStemmedPhraseIndex</B>()</PRE>
+<DL>
+<DD>Returns the index of the stemmed phrases in the output ARFF file.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getUnstemmedPhraseIndex()"><!-- --></A><H3>
+getUnstemmedPhraseIndex</H3>
+<PRE>
+public int <B>getUnstemmedPhraseIndex</B>()</PRE>
+<DL>
+<DD>Returns the index of the unstemmed phrases in the output ARFF file.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getProbabilityIndex()"><!-- --></A><H3>
+getProbabilityIndex</H3>
+<PRE>
+public int <B>getProbabilityIndex</B>()</PRE>
+<DL>
+<DD>Returns the index of the phrases' probabilities in the output ARFF file.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getRankIndex()"><!-- --></A><H3>
+getRankIndex</H3>
+<PRE>
+public int <B>getRankIndex</B>()</PRE>
+<DL>
+<DD>Returns the index of the phrases' ranks in the output ARFF file.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDocumentAtt()"><!-- --></A><H3>
+getDocumentAtt</H3>
+<PRE>
+public int <B>getDocumentAtt</B>()</PRE>
+<DL>
+<DD>Get the value of DocumentAtt.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of DocumentAtt.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDocumentAtt(int)"><!-- --></A><H3>
+setDocumentAtt</H3>
+<PRE>
+public void <B>setDocumentAtt</B>(int&nbsp;newDocumentAtt)</PRE>
+<DL>
+<DD>Set the value of DocumentAtt.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newDocumentAtt</CODE> - Value to assign to DocumentAtt.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getKeyphrasesAtt()"><!-- --></A><H3>
+getKeyphrasesAtt</H3>
+<PRE>
+public int <B>getKeyphrasesAtt</B>()</PRE>
+<DL>
+<DD>Get the value of KeyphraseAtt.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of KeyphraseAtt.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setKeyphrasesAtt(int)"><!-- --></A><H3>
+setKeyphrasesAtt</H3>
+<PRE>
+public void <B>setKeyphrasesAtt</B>(int&nbsp;newKeyphrasesAtt)</PRE>
+<DL>
+<DD>Set the value of KeyphrasesAtt.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newKeyphrasesAtt</CODE> - Value to assign to KeyphrasesAtt.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDebug()"><!-- --></A><H3>
+getDebug</H3>
+<PRE>
+public boolean <B>getDebug</B>()</PRE>
+<DL>
+<DD>Get the value of Debug.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of Debug.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDebug(boolean)"><!-- --></A><H3>
+setDebug</H3>
+<PRE>
+public void <B>setDebug</B>(boolean&nbsp;newDebug)</PRE>
+<DL>
+<DD>Set the value of Debug.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newDebug</CODE> - Value to assign to Debug.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setKFused(boolean)"><!-- --></A><H3>
+setKFused</H3>
+<PRE>
+public void <B>setKFused</B>(boolean&nbsp;flag)</PRE>
+<DL>
+<DD>Sets whether keyphrase frequency attribute is used.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getKFused()"><!-- --></A><H3>
+getKFused</H3>
+<PRE>
+public boolean <B>getKFused</B>()</PRE>
+<DL>
+<DD>Gets whether keyphrase frequency attribute is used.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDisallowInternalPeriods()"><!-- --></A><H3>
+getDisallowInternalPeriods</H3>
+<PRE>
+public boolean <B>getDisallowInternalPeriods</B>()</PRE>
+<DL>
+<DD>Get whether the supplied columns are to be processed
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>true if the supplied columns won't be processed</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDisallowInternalPeriods(boolean)"><!-- --></A><H3>
+setDisallowInternalPeriods</H3>
+<PRE>
+public void <B>setDisallowInternalPeriods</B>(boolean&nbsp;disallow)</PRE>
+<DL>
+<DD>Set whether selected columns should be processed. If true the 
+ selected columns won't be processed.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setOptions(java.lang.String[])"><!-- --></A><H3>
+setOptions</H3>
+<PRE>
+public void <B>setOptions</B>(java.lang.String[]&nbsp;options)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Parses a given list of options controlling the behaviour of this object.
+ Valid options are:<p>
+
+ -K<br>
+ Specifies whether keyphrase frequency statistic is used.<p>
+
+ -M length<br>
+ Sets the maximum phrase length (default: 3).<p>
+
+ -L length<br>
+ Sets the minimum phrase length (default: 1).<p>
+
+ -D<br>
+ Turns debugging mode on.<p>
+
+ -I index<br>
+ Sets the index of the attribute containing the documents (default: 0).<p>
+
+ -J index<br>
+ Sets the index of the attribute containing the keyphrases (default: 1).<p>
+
+ -P<br>
+ Disallow internal periods <p>
+
+ -O number<br>
+ The minimum number of times a phrase needs to occur (default: 2). <p>
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>setOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>options</CODE> - the list of options as an array of strings
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE> - if an option is not supported</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getOptions()"><!-- --></A><H3>
+getOptions</H3>
+<PRE>
+public java.lang.String[] <B>getOptions</B>()</PRE>
+<DL>
+<DD>Gets the current settings of the filter.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>getOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>an array of strings suitable for passing to setOptions</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="listOptions()"><!-- --></A><H3>
+listOptions</H3>
+<PRE>
+public java.util.Enumeration <B>listOptions</B>()</PRE>
+<DL>
+<DD>Returns an enumeration describing the available options
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>listOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>an enumeration of all the available options</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="globalInfo()"><!-- --></A><H3>
+globalInfo</H3>
+<PRE>
+public java.lang.String <B>globalInfo</B>()</PRE>
+<DL>
+<DD>Returns a string describing this filter
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>a description of the filter suitable for
+ displaying in the explorer/experimenter gui</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setInputFormat(weka.core.Instances)"><!-- --></A><H3>
+setInputFormat</H3>
+<PRE>
+public boolean <B>setInputFormat</B>(weka.core.Instances&nbsp;instanceInfo)
+                       throws java.lang.Exception</PRE>
+<DL>
+<DD>Sets the format of the input instances.
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>setInputFormat</CODE> in class <CODE>weka.filters.Filter</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>instanceInfo</CODE> - an Instances object containing the input
+ instance structure (any instances contained in the object are
+ ignored - only the structure is required).
+<DT><B>Returns:</B><DD>true if the outputFormat may be collected immediately
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="input(weka.core.Instance)"><!-- --></A><H3>
+input</H3>
+<PRE>
+public boolean <B>input</B>(weka.core.Instance&nbsp;instance)
+              throws java.lang.Exception</PRE>
+<DL>
+<DD>Input an instance for filtering. Ordinarily the instance is processed
+ and made available for output immediately. Some filters require all
+ instances be read before producing output.
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>input</CODE> in class <CODE>weka.filters.Filter</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>instance</CODE> - the input instance
+<DT><B>Returns:</B><DD>true if the filtered instance may now be
+ collected with output().
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE> - if the input instance was not of the correct 
+ format or if there was a problem with the filtering.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="batchFinished()"><!-- --></A><H3>
+batchFinished</H3>
+<PRE>
+public boolean <B>batchFinished</B>()
+                      throws java.lang.Exception</PRE>
+<DL>
+<DD>Signify that this batch of input to the filter is finished. 
+ If the filter requires all instances prior to filtering,
+ output() may now be called to retrieve the filtered instances.
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>batchFinished</CODE> in class <CODE>weka.filters.Filter</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>true if there are instances pending output
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE> - if no input structure has been defined</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="main(java.lang.String[])"><!-- --></A><H3>
+main</H3>
+<PRE>
+public static void <B>main</B>(java.lang.String[]&nbsp;argv)</PRE>
+<DL>
+<DD>Main method for testing this class.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>argv</CODE> - should contain arguments to the filter: use -h for help</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="IteratedLovinsStemmer.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="KEAKeyphraseExtractor.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="KEAFilter.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_weka.filters.Filter">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/KEAKeyphraseExtractor.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/KEAKeyphraseExtractor.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/KEAKeyphraseExtractor.html	(revision 8815)
@@ -0,0 +1,742 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:49 NZDT 2004 -->
+<TITLE>
+KEAKeyphraseExtractor
+</TITLE>
+<META NAME="keywords" CONTENT="KEAKeyphraseExtractor,KEAKeyphraseExtractor class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="KEAKeyphraseExtractor";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="KEAFilter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="KEAModelBuilder.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="KEAKeyphraseExtractor.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class KEAKeyphraseExtractor</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<B>KEAKeyphraseExtractor</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>weka.core.OptionHandler</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>KEAKeyphraseExtractor</B><DT>extends java.lang.Object<DT>implements weka.core.OptionHandler</DL>
+
+<P>
+Extracts keyphrases from the documents in a given directory.
+ Assumes that the file names for the documents end with ".txt".
+ Puts extracted keyphrases into corresponding files ending with
+ ".key" (if those are not already present). Optionally an encoding
+ for the documents/keyphrases can be defined (e.g. for Chinese
+ text). Documents for which ".key" exists, are used for evaluation.
+
+ Valid options are:<p>
+
+ -l "directory name"<br>
+ Specifies name of directory.<p>
+
+ -m "model name"<br>
+ Specifies name of model.<p>
+
+ -e "encoding"<br>
+ Specifies encoding.<p>
+
+ -n <br>
+ Specifies number of phrases to be output (default: 5).<p>
+
+ -d<br>
+ Turns debugging mode on.<p>
+
+ -a<br>
+ Also write stemmed phrase and score into ".key" file.<p>
+<P>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#KEAKeyphraseExtractor()">KEAKeyphraseExtractor</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.util.Hashtable</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#collectStems()">collectStems</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Collects the stems of the file names.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#extractKeyphrases(java.util.Hashtable)">extractKeyphrases</A></B>(java.util.Hashtable&nbsp;stems)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Builds the model from the files</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#getAdditionalInfo()">getAdditionalInfo</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of AdditionalInfo.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#getDebug()">getDebug</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of debug.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#getDirName()">getDirName</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of dirName.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#getEncoding()">getEncoding</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of encoding.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#getModelName()">getModelName</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of modelName.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#getNumPhrases()">getNumPhrases</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of numPhrases.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#getOptions()">getOptions</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gets the current option settings.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.util.Enumeration</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#listOptions()">listOptions</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns an enumeration describing the available options.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#loadModel()">loadModel</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Loads the extraction model from the file.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#main(java.lang.String[])">main</A></B>(java.lang.String[]&nbsp;ops)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The main method.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#setAdditionalInfo(boolean)">setAdditionalInfo</A></B>(boolean&nbsp;newAdditionalInfo)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of AdditionalInfo.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#setDebug(boolean)">setDebug</A></B>(boolean&nbsp;newdebug)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of debug.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#setDirName(java.lang.String)">setDirName</A></B>(java.lang.String&nbsp;newdirName)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of dirName.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#setEncoding(java.lang.String)">setEncoding</A></B>(java.lang.String&nbsp;newencoding)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of encoding.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#setModelName(java.lang.String)">setModelName</A></B>(java.lang.String&nbsp;newmodelName)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of modelName.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#setNumPhrases(int)">setNumPhrases</A></B>(int&nbsp;newnumPhrases)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of numPhrases.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAKeyphraseExtractor.html#setOptions(java.lang.String[])">setOptions</A></B>(java.lang.String[]&nbsp;options)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Parses a given list of options controlling the behaviour of this object.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="KEAKeyphraseExtractor()"><!-- --></A><H3>
+KEAKeyphraseExtractor</H3>
+<PRE>
+public <B>KEAKeyphraseExtractor</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="getAdditionalInfo()"><!-- --></A><H3>
+getAdditionalInfo</H3>
+<PRE>
+public boolean <B>getAdditionalInfo</B>()</PRE>
+<DL>
+<DD>Get the value of AdditionalInfo.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of AdditionalInfo.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setAdditionalInfo(boolean)"><!-- --></A><H3>
+setAdditionalInfo</H3>
+<PRE>
+public void <B>setAdditionalInfo</B>(boolean&nbsp;newAdditionalInfo)</PRE>
+<DL>
+<DD>Set the value of AdditionalInfo.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newAdditionalInfo</CODE> - Value to assign to AdditionalInfo.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getNumPhrases()"><!-- --></A><H3>
+getNumPhrases</H3>
+<PRE>
+public int <B>getNumPhrases</B>()</PRE>
+<DL>
+<DD>Get the value of numPhrases.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of numPhrases.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setNumPhrases(int)"><!-- --></A><H3>
+setNumPhrases</H3>
+<PRE>
+public void <B>setNumPhrases</B>(int&nbsp;newnumPhrases)</PRE>
+<DL>
+<DD>Set the value of numPhrases.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newnumPhrases</CODE> - Value to assign to numPhrases.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDebug()"><!-- --></A><H3>
+getDebug</H3>
+<PRE>
+public boolean <B>getDebug</B>()</PRE>
+<DL>
+<DD>Get the value of debug.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of debug.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDebug(boolean)"><!-- --></A><H3>
+setDebug</H3>
+<PRE>
+public void <B>setDebug</B>(boolean&nbsp;newdebug)</PRE>
+<DL>
+<DD>Set the value of debug.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newdebug</CODE> - Value to assign to debug.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getEncoding()"><!-- --></A><H3>
+getEncoding</H3>
+<PRE>
+public java.lang.String <B>getEncoding</B>()</PRE>
+<DL>
+<DD>Get the value of encoding.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of encoding.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setEncoding(java.lang.String)"><!-- --></A><H3>
+setEncoding</H3>
+<PRE>
+public void <B>setEncoding</B>(java.lang.String&nbsp;newencoding)</PRE>
+<DL>
+<DD>Set the value of encoding.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newencoding</CODE> - Value to assign to encoding.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getModelName()"><!-- --></A><H3>
+getModelName</H3>
+<PRE>
+public java.lang.String <B>getModelName</B>()</PRE>
+<DL>
+<DD>Get the value of modelName.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of modelName.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setModelName(java.lang.String)"><!-- --></A><H3>
+setModelName</H3>
+<PRE>
+public void <B>setModelName</B>(java.lang.String&nbsp;newmodelName)</PRE>
+<DL>
+<DD>Set the value of modelName.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newmodelName</CODE> - Value to assign to modelName.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDirName()"><!-- --></A><H3>
+getDirName</H3>
+<PRE>
+public java.lang.String <B>getDirName</B>()</PRE>
+<DL>
+<DD>Get the value of dirName.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of dirName.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDirName(java.lang.String)"><!-- --></A><H3>
+setDirName</H3>
+<PRE>
+public void <B>setDirName</B>(java.lang.String&nbsp;newdirName)</PRE>
+<DL>
+<DD>Set the value of dirName.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newdirName</CODE> - Value to assign to dirName.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setOptions(java.lang.String[])"><!-- --></A><H3>
+setOptions</H3>
+<PRE>
+public void <B>setOptions</B>(java.lang.String[]&nbsp;options)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Parses a given list of options controlling the behaviour of this object.
+ Valid options are:<p>
+
+ -l "directory name"<br>
+ Specifies name of directory.<p>
+
+ -m "model name"<br>
+ Specifies name of model.<p>
+
+ -e "encoding"<br>
+ Specifies encoding.<p>
+
+ -n<br>
+ Specifies number of phrases to be output (default: 5).<p>
+
+ -d<br>
+ Turns debugging mode on.<p>
+
+ -a<br>
+ Also write stemmed phrase and score into ".key" file.<p>
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>setOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>options</CODE> - the list of options as an array of strings
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE> - if an option is not supported</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getOptions()"><!-- --></A><H3>
+getOptions</H3>
+<PRE>
+public java.lang.String[] <B>getOptions</B>()</PRE>
+<DL>
+<DD>Gets the current option settings.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>getOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>an array of strings suitable for passing to setOptions</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="listOptions()"><!-- --></A><H3>
+listOptions</H3>
+<PRE>
+public java.util.Enumeration <B>listOptions</B>()</PRE>
+<DL>
+<DD>Returns an enumeration describing the available options.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>listOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>an enumeration of all the available options</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="collectStems()"><!-- --></A><H3>
+collectStems</H3>
+<PRE>
+public java.util.Hashtable <B>collectStems</B>()
+                                 throws java.lang.Exception</PRE>
+<DL>
+<DD>Collects the stems of the file names.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="extractKeyphrases(java.util.Hashtable)"><!-- --></A><H3>
+extractKeyphrases</H3>
+<PRE>
+public void <B>extractKeyphrases</B>(java.util.Hashtable&nbsp;stems)
+                       throws java.lang.Exception</PRE>
+<DL>
+<DD>Builds the model from the files
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="loadModel()"><!-- --></A><H3>
+loadModel</H3>
+<PRE>
+public void <B>loadModel</B>()
+               throws java.lang.Exception</PRE>
+<DL>
+<DD>Loads the extraction model from the file.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="main(java.lang.String[])"><!-- --></A><H3>
+main</H3>
+<PRE>
+public static void <B>main</B>(java.lang.String[]&nbsp;ops)</PRE>
+<DL>
+<DD>The main method.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="KEAFilter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="KEAModelBuilder.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="KEAKeyphraseExtractor.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/KEAModelBuilder.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/KEAModelBuilder.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/KEAModelBuilder.html	(revision 8815)
@@ -0,0 +1,1072 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:49 NZDT 2004 -->
+<TITLE>
+KEAModelBuilder
+</TITLE>
+<META NAME="keywords" CONTENT="KEAModelBuilder,KEAModelBuilder class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="KEAModelBuilder";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="KEAKeyphraseExtractor.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="KEAPhraseFilter.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="KEAModelBuilder.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class KEAModelBuilder</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<B>KEAModelBuilder</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>weka.core.OptionHandler</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>KEAModelBuilder</B><DT>extends java.lang.Object<DT>implements weka.core.OptionHandler</DL>
+
+<P>
+Builds a keyphrase extraction model from the documents in a given
+ directory.  Assumes that the file names for the documents end with
+ ".txt".  Assumes that files containing corresponding
+ author-assigned keyphrases end with ".key". Optionally an encoding
+ for the documents/keyphrases can be defined (e.g. for Chinese
+ text).
+
+ Valid options are:<p>
+
+ -l "directory name"<br>
+ Specifies name of directory.<p>
+
+ -m "model name"<br>
+ Specifies name of model.<p>
+
+ -e "encoding"<br>
+ Specifies encoding.<p>
+
+ -d<br>
+ Turns debugging mode on.<p>
+
+ -k<br>
+ Use keyphrase frequency statistic.<p>
+
+ -p<br>
+ Disallow internal periods.<p>
+
+ -x "length"<br>
+ Sets maximum phrase length (default: 3).<p>
+
+ -y "length"<br>
+ Sets minimum phrase length (default: 1).<p>
+
+ -o "number"<br>
+ The minimum number of times a phrase needs to occur (default: 2). <p>
+
+ -s "name of class implementing list of stop words"<br>
+ Sets list of stop words to used (default: StopwordsEnglish).<p>
+
+ -t "name of class implementing stemmer"<br>
+ Sets stemmer to use (default: IteratedLovinsStemmer). <p>
+
+ -n<br>
+ Do not check for proper nouns. <p>
+<P>
+
+<P>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="KEAModelBuilder.html#KEAModelBuilder()">KEAModelBuilder</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#buildModel(java.util.Hashtable)">buildModel</A></B>(java.util.Hashtable&nbsp;stems)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Builds the model from the files</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.util.Hashtable</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#collectStems()">collectStems</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Collects the stems of the file names.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getCheckForProperNouns()">getCheckForProperNouns</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the M_CheckProperNouns value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getDebug()">getDebug</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of debug.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getDirName()">getDirName</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of dirName.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getDisallowIPeriods()">getDisallowIPeriods</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of disallowIPeriods.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getEncoding()">getEncoding</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of encoding.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getMaxPhraseLength()">getMaxPhraseLength</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of MaxPhraseLength.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getMinNumOccur()">getMinNumOccur</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of MinNumOccur.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;int</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getMinPhraseLength()">getMinPhraseLength</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of MinPhraseLength.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getModelName()">getModelName</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of modelName.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getOptions()">getOptions</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gets the current option settings.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;Stemmer</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getStemmer()">getStemmer</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the Stemmer value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;Stopwords</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getStopwords()">getStopwords</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the M_Stopwords value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#getUseKFrequency()">getUseKFrequency</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the value of useKFrequency.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.util.Enumeration</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#listOptions()">listOptions</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns an enumeration describing the available options.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#main(java.lang.String[])">main</A></B>(java.lang.String[]&nbsp;ops)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The main method.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#saveModel()">saveModel</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Saves the extraction model to the file.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setCheckForProperNouns(boolean)">setCheckForProperNouns</A></B>(boolean&nbsp;newM_CheckProperNouns)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the M_CheckProperNouns value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setDebug(boolean)">setDebug</A></B>(boolean&nbsp;newdebug)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of debug.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setDirName(java.lang.String)">setDirName</A></B>(java.lang.String&nbsp;newdirName)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of dirName.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setDisallowIPeriods(boolean)">setDisallowIPeriods</A></B>(boolean&nbsp;newdisallowIPeriods)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of disallowIPeriods.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setEncoding(java.lang.String)">setEncoding</A></B>(java.lang.String&nbsp;newencoding)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of encoding.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setMaxPhraseLength(int)">setMaxPhraseLength</A></B>(int&nbsp;newMaxPhraseLength)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of MaxPhraseLength.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setMinNumOccur(int)">setMinNumOccur</A></B>(int&nbsp;newMinNumOccur)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of MinNumOccur.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setMinPhraseLength(int)">setMinPhraseLength</A></B>(int&nbsp;newMinPhraseLength)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of MinPhraseLength.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setModelName(java.lang.String)">setModelName</A></B>(java.lang.String&nbsp;newmodelName)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of modelName.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setOptions(java.lang.String[])">setOptions</A></B>(java.lang.String[]&nbsp;options)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Parses a given list of options controlling the behaviour of this object.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setStemmer(Stemmer)">setStemmer</A></B>(Stemmer&nbsp;newStemmer)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the Stemmer value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setStopwords(Stopwords)">setStopwords</A></B>(Stopwords&nbsp;newM_Stopwords)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the M_Stopwords value.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAModelBuilder.html#setUseKFrequency(boolean)">setUseKFrequency</A></B>(boolean&nbsp;newuseKFrequency)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set the value of useKFrequency.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="KEAModelBuilder()"><!-- --></A><H3>
+KEAModelBuilder</H3>
+<PRE>
+public <B>KEAModelBuilder</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="getCheckForProperNouns()"><!-- --></A><H3>
+getCheckForProperNouns</H3>
+<PRE>
+public boolean <B>getCheckForProperNouns</B>()</PRE>
+<DL>
+<DD>Get the M_CheckProperNouns value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the M_CheckProperNouns value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setCheckForProperNouns(boolean)"><!-- --></A><H3>
+setCheckForProperNouns</H3>
+<PRE>
+public void <B>setCheckForProperNouns</B>(boolean&nbsp;newM_CheckProperNouns)</PRE>
+<DL>
+<DD>Set the M_CheckProperNouns value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newM_CheckProperNouns</CODE> - The new M_CheckProperNouns value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getStopwords()"><!-- --></A><H3>
+getStopwords</H3>
+<PRE>
+public Stopwords <B>getStopwords</B>()</PRE>
+<DL>
+<DD>Get the M_Stopwords value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the M_Stopwords value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setStopwords(Stopwords)"><!-- --></A><H3>
+setStopwords</H3>
+<PRE>
+public void <B>setStopwords</B>(Stopwords&nbsp;newM_Stopwords)</PRE>
+<DL>
+<DD>Set the M_Stopwords value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newM_Stopwords</CODE> - The new M_Stopwords value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getStemmer()"><!-- --></A><H3>
+getStemmer</H3>
+<PRE>
+public Stemmer <B>getStemmer</B>()</PRE>
+<DL>
+<DD>Get the Stemmer value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>the Stemmer value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setStemmer(Stemmer)"><!-- --></A><H3>
+setStemmer</H3>
+<PRE>
+public void <B>setStemmer</B>(Stemmer&nbsp;newStemmer)</PRE>
+<DL>
+<DD>Set the Stemmer value.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newStemmer</CODE> - The new Stemmer value.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getMinNumOccur()"><!-- --></A><H3>
+getMinNumOccur</H3>
+<PRE>
+public int <B>getMinNumOccur</B>()</PRE>
+<DL>
+<DD>Get the value of MinNumOccur.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of MinNumOccur.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setMinNumOccur(int)"><!-- --></A><H3>
+setMinNumOccur</H3>
+<PRE>
+public void <B>setMinNumOccur</B>(int&nbsp;newMinNumOccur)</PRE>
+<DL>
+<DD>Set the value of MinNumOccur.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newMinNumOccur</CODE> - Value to assign to MinNumOccur.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getMaxPhraseLength()"><!-- --></A><H3>
+getMaxPhraseLength</H3>
+<PRE>
+public int <B>getMaxPhraseLength</B>()</PRE>
+<DL>
+<DD>Get the value of MaxPhraseLength.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of MaxPhraseLength.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setMaxPhraseLength(int)"><!-- --></A><H3>
+setMaxPhraseLength</H3>
+<PRE>
+public void <B>setMaxPhraseLength</B>(int&nbsp;newMaxPhraseLength)</PRE>
+<DL>
+<DD>Set the value of MaxPhraseLength.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newMaxPhraseLength</CODE> - Value to assign to MaxPhraseLength.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getMinPhraseLength()"><!-- --></A><H3>
+getMinPhraseLength</H3>
+<PRE>
+public int <B>getMinPhraseLength</B>()</PRE>
+<DL>
+<DD>Get the value of MinPhraseLength.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of MinPhraseLength.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setMinPhraseLength(int)"><!-- --></A><H3>
+setMinPhraseLength</H3>
+<PRE>
+public void <B>setMinPhraseLength</B>(int&nbsp;newMinPhraseLength)</PRE>
+<DL>
+<DD>Set the value of MinPhraseLength.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newMinPhraseLength</CODE> - Value to assign to MinPhraseLength.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDisallowIPeriods()"><!-- --></A><H3>
+getDisallowIPeriods</H3>
+<PRE>
+public boolean <B>getDisallowIPeriods</B>()</PRE>
+<DL>
+<DD>Get the value of disallowIPeriods.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of disallowIPeriods.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDisallowIPeriods(boolean)"><!-- --></A><H3>
+setDisallowIPeriods</H3>
+<PRE>
+public void <B>setDisallowIPeriods</B>(boolean&nbsp;newdisallowIPeriods)</PRE>
+<DL>
+<DD>Set the value of disallowIPeriods.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newdisallowIPeriods</CODE> - Value to assign to disallowIPeriods.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getUseKFrequency()"><!-- --></A><H3>
+getUseKFrequency</H3>
+<PRE>
+public boolean <B>getUseKFrequency</B>()</PRE>
+<DL>
+<DD>Get the value of useKFrequency.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of useKFrequency.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setUseKFrequency(boolean)"><!-- --></A><H3>
+setUseKFrequency</H3>
+<PRE>
+public void <B>setUseKFrequency</B>(boolean&nbsp;newuseKFrequency)</PRE>
+<DL>
+<DD>Set the value of useKFrequency.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newuseKFrequency</CODE> - Value to assign to useKFrequency.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDebug()"><!-- --></A><H3>
+getDebug</H3>
+<PRE>
+public boolean <B>getDebug</B>()</PRE>
+<DL>
+<DD>Get the value of debug.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of debug.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDebug(boolean)"><!-- --></A><H3>
+setDebug</H3>
+<PRE>
+public void <B>setDebug</B>(boolean&nbsp;newdebug)</PRE>
+<DL>
+<DD>Set the value of debug.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newdebug</CODE> - Value to assign to debug.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getEncoding()"><!-- --></A><H3>
+getEncoding</H3>
+<PRE>
+public java.lang.String <B>getEncoding</B>()</PRE>
+<DL>
+<DD>Get the value of encoding.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of encoding.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setEncoding(java.lang.String)"><!-- --></A><H3>
+setEncoding</H3>
+<PRE>
+public void <B>setEncoding</B>(java.lang.String&nbsp;newencoding)</PRE>
+<DL>
+<DD>Set the value of encoding.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newencoding</CODE> - Value to assign to encoding.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getModelName()"><!-- --></A><H3>
+getModelName</H3>
+<PRE>
+public java.lang.String <B>getModelName</B>()</PRE>
+<DL>
+<DD>Get the value of modelName.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of modelName.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setModelName(java.lang.String)"><!-- --></A><H3>
+setModelName</H3>
+<PRE>
+public void <B>setModelName</B>(java.lang.String&nbsp;newmodelName)</PRE>
+<DL>
+<DD>Set the value of modelName.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newmodelName</CODE> - Value to assign to modelName.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDirName()"><!-- --></A><H3>
+getDirName</H3>
+<PRE>
+public java.lang.String <B>getDirName</B>()</PRE>
+<DL>
+<DD>Get the value of dirName.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>Value of dirName.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDirName(java.lang.String)"><!-- --></A><H3>
+setDirName</H3>
+<PRE>
+public void <B>setDirName</B>(java.lang.String&nbsp;newdirName)</PRE>
+<DL>
+<DD>Set the value of dirName.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>newdirName</CODE> - Value to assign to dirName.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setOptions(java.lang.String[])"><!-- --></A><H3>
+setOptions</H3>
+<PRE>
+public void <B>setOptions</B>(java.lang.String[]&nbsp;options)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Parses a given list of options controlling the behaviour of this object.
+ Valid options are:<p>
+
+ -l "directory name" <br>
+ Specifies name of directory.<p>
+
+ -m "model name" <br>
+ Specifies name of model.<p>
+
+ -e "encoding" <br>
+ Specifies encoding.<p>
+
+ -d<br>
+ Turns debugging mode on.<p>
+
+ -k<br>
+ Use keyphrase frequency statistic.<p>
+
+ -p<br>
+ Disallow internal periods. <p>
+
+ -x "length"<br>
+ Sets maximum phrase length (default: 3).<p>
+
+ -y "length"<br>
+ Sets minimum phrase length (default: 3).<p>
+
+ -o "number"<br>
+ The minimum number of times a phrase needs to occur (default: 2). <p>
+
+ -s "name of class implementing list of stop words"<br>
+ Sets list of stop words to used (default: StopwordsEnglish).<p>
+
+ -t "name of class implementing stemmer"<br>
+ Sets stemmer to use (default: IteratedLovinsStemmer). <p>
+
+ -n<br>
+ Do not check for proper nouns. <p>
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>setOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>options</CODE> - the list of options as an array of strings
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE> - if an option is not supported</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getOptions()"><!-- --></A><H3>
+getOptions</H3>
+<PRE>
+public java.lang.String[] <B>getOptions</B>()</PRE>
+<DL>
+<DD>Gets the current option settings.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>getOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>an array of strings suitable for passing to setOptions</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="listOptions()"><!-- --></A><H3>
+listOptions</H3>
+<PRE>
+public java.util.Enumeration <B>listOptions</B>()</PRE>
+<DL>
+<DD>Returns an enumeration describing the available options.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>listOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>an enumeration of all the available options</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="collectStems()"><!-- --></A><H3>
+collectStems</H3>
+<PRE>
+public java.util.Hashtable <B>collectStems</B>()
+                                 throws java.lang.Exception</PRE>
+<DL>
+<DD>Collects the stems of the file names.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="buildModel(java.util.Hashtable)"><!-- --></A><H3>
+buildModel</H3>
+<PRE>
+public void <B>buildModel</B>(java.util.Hashtable&nbsp;stems)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Builds the model from the files
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="saveModel()"><!-- --></A><H3>
+saveModel</H3>
+<PRE>
+public void <B>saveModel</B>()
+               throws java.lang.Exception</PRE>
+<DL>
+<DD>Saves the extraction model to the file.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="main(java.lang.String[])"><!-- --></A><H3>
+main</H3>
+<PRE>
+public static void <B>main</B>(java.lang.String[]&nbsp;ops)</PRE>
+<DL>
+<DD>The main method.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="KEAKeyphraseExtractor.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="KEAPhraseFilter.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="KEAModelBuilder.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/KEAPhraseFilter.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/KEAPhraseFilter.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/KEAPhraseFilter.html	(revision 8815)
@@ -0,0 +1,817 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:49 NZDT 2004 -->
+<TITLE>
+KEAPhraseFilter
+</TITLE>
+<META NAME="keywords" CONTENT="KEAPhraseFilter,KEAPhraseFilter class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="KEAPhraseFilter";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="KEAModelBuilder.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="LovinsStemmer.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="KEAPhraseFilter.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class KEAPhraseFilter</H2>
+<PRE>
+java.lang.Object
+  |
+  +--weka.filters.Filter
+        |
+        +--<B>KEAPhraseFilter</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>weka.core.OptionHandler, java.io.Serializable</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>KEAPhraseFilter</B><DT>extends weka.filters.Filter<DT>implements weka.core.OptionHandler</DL>
+
+<P>
+This filter splits the text in selected string
+ attributes into phrases. The resulting
+ string attributes contain these phrases
+ separated by '\n' characters.
+
+ Phrases are identified according to the
+ following definitions:
+ 
+ A phrase is a sequence of words interrupted
+ only by sequences of whitespace characters,
+ where each sequence of whitespace characters
+ contains at most one '\n'.
+
+ A word is a sequence of letters or digits
+ that contains at least one letter, with
+ the following exceptions:
+
+ a) '.', '@', '_', '&', '/', '-' are allowed
+ if surrounded by letters or digits,
+
+ b) '\'' is allowed if preceeded by a letter
+ or digit,
+ 
+ c) '-', '/' are also allowed if succeeded by
+ whitespace characters followed by another
+ word. In that case the whitespace characters
+ will be deleted.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="KEAPhraseFilter">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#m_DisallowInternalPeriods">m_DisallowInternalPeriods</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Determines whether internal periods are allowed</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>protected &nbsp;weka.core.Range</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#m_SelectCols">m_SelectCols</A></B></CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stores which columns to select as a funky range</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="fields_inherited_from_class_weka.filters.Filter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Fields inherited from class weka.filters.Filter</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>m_NewBatch</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#KEAPhraseFilter()">KEAPhraseFilter</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#attributeIndicesTipText()">attributeIndicesTipText</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the tip text for this property</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#batchFinished()">batchFinished</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Signify that this batch of input to the filter is finished.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#disallowInternalPeriodsTipText()">disallowInternalPeriodsTipText</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the tip text for this property</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#getAttributeIndices()">getAttributeIndices</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get the current range selection.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#getDisallowInternalPeriods()">getDisallowInternalPeriods</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get whether the supplied columns are to be processed</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#getInvertSelection()">getInvertSelection</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Get whether the supplied columns are to be processed</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String[]</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#getOptions()">getOptions</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Gets the current settings of the filter.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#globalInfo()">globalInfo</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns a string describing this filter</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#input(weka.core.Instance)">input</A></B>(weka.core.Instance&nbsp;instance)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Input an instance for filtering.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#invertSelectionTipText()">invertSelectionTipText</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the tip text for this property</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.util.Enumeration</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#listOptions()">listOptions</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns an enumeration describing the available options</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#main(java.lang.String[])">main</A></B>(java.lang.String[]&nbsp;argv)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Main method for testing this class.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#setAttributeIndices(java.lang.String)">setAttributeIndices</A></B>(java.lang.String&nbsp;rangeList)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set which attributes are to be processed</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#setAttributeIndicesArray(int[])">setAttributeIndicesArray</A></B>(int[]&nbsp;attributes)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set which attributes are to be processed</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#setDisallowInternalPeriods(boolean)">setDisallowInternalPeriods</A></B>(boolean&nbsp;disallow)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set whether selected columns should be processed.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#setInputFormat(weka.core.Instances)">setInputFormat</A></B>(weka.core.Instances&nbsp;instanceInfo)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sets the format of the input instances.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#setInvertSelection(boolean)">setInvertSelection</A></B>(boolean&nbsp;invert)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Set whether selected columns should be processed.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="KEAPhraseFilter.html#setOptions(java.lang.String[])">setOptions</A></B>(java.lang.String[]&nbsp;options)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Parses a given list of options controlling the behaviour of this object.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_weka.filters.Filter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class weka.filters.Filter</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>batchFilterFile, bufferInput, copyStringValues, copyStringValues, filterFile, flushInput, getInputFormat, getInputStringIndex, getOutputFormat, getOutputStringIndex, getStringIndices, inputFormat, isOutputFormatDefined, numPendingOutput, output, outputFormat, outputFormatPeek, outputPeek, push, resetQueue, setOutputFormat, useFilter</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+<A NAME="field_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Field Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="m_SelectCols"><!-- --></A><H3>
+m_SelectCols</H3>
+<PRE>
+protected weka.core.Range <B>m_SelectCols</B></PRE>
+<DL>
+<DD>Stores which columns to select as a funky range
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<A NAME="m_DisallowInternalPeriods"><!-- --></A><H3>
+m_DisallowInternalPeriods</H3>
+<PRE>
+protected boolean <B>m_DisallowInternalPeriods</B></PRE>
+<DL>
+<DD>Determines whether internal periods are allowed
+<P>
+<DL>
+</DL>
+</DL>
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="KEAPhraseFilter()"><!-- --></A><H3>
+KEAPhraseFilter</H3>
+<PRE>
+public <B>KEAPhraseFilter</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="globalInfo()"><!-- --></A><H3>
+globalInfo</H3>
+<PRE>
+public java.lang.String <B>globalInfo</B>()</PRE>
+<DL>
+<DD>Returns a string describing this filter
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>a description of the filter suitable for
+ displaying in the explorer/experimenter gui</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="listOptions()"><!-- --></A><H3>
+listOptions</H3>
+<PRE>
+public java.util.Enumeration <B>listOptions</B>()</PRE>
+<DL>
+<DD>Returns an enumeration describing the available options
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>listOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>an enumeration of all the available options</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setOptions(java.lang.String[])"><!-- --></A><H3>
+setOptions</H3>
+<PRE>
+public void <B>setOptions</B>(java.lang.String[]&nbsp;options)
+                throws java.lang.Exception</PRE>
+<DL>
+<DD>Parses a given list of options controlling the behaviour of this object.
+ Valid options are:<p>
+
+ -R index1,index2-index4,...<br>
+ Specify list of attributes to process. First and last are valid indexes.
+ (default none)<p>
+
+ -V<br>
+ Invert matching sense <p>
+
+ -P<br>
+ Disallow internal periods <p>
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>setOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>options</CODE> - the list of options as an array of strings
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE> - if an option is not supported</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getOptions()"><!-- --></A><H3>
+getOptions</H3>
+<PRE>
+public java.lang.String[] <B>getOptions</B>()</PRE>
+<DL>
+<DD>Gets the current settings of the filter.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE>getOptions</CODE> in interface <CODE>weka.core.OptionHandler</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>an array of strings suitable for passing to setOptions</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setInputFormat(weka.core.Instances)"><!-- --></A><H3>
+setInputFormat</H3>
+<PRE>
+public boolean <B>setInputFormat</B>(weka.core.Instances&nbsp;instanceInfo)
+                       throws java.lang.Exception</PRE>
+<DL>
+<DD>Sets the format of the input instances.
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>setInputFormat</CODE> in class <CODE>weka.filters.Filter</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>instanceInfo</CODE> - an Instances object containing the input
+ instance structure (any instances contained in the object are
+ ignored - only the structure is required).
+<DT><B>Returns:</B><DD>true if the outputFormat may be collected immediately
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="input(weka.core.Instance)"><!-- --></A><H3>
+input</H3>
+<PRE>
+public boolean <B>input</B>(weka.core.Instance&nbsp;instance)
+              throws java.lang.Exception</PRE>
+<DL>
+<DD>Input an instance for filtering. Ordinarily the instance is processed
+ and made available for output immediately. Some filters require all
+ instances be read before producing output.
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>input</CODE> in class <CODE>weka.filters.Filter</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>instance</CODE> - the input instance
+<DT><B>Returns:</B><DD>true if the filtered instance may now be
+ collected with output().
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE> - if the input instance was not of the correct 
+ format or if there was a problem with the filtering.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="batchFinished()"><!-- --></A><H3>
+batchFinished</H3>
+<PRE>
+public boolean <B>batchFinished</B>()
+                      throws java.lang.Exception</PRE>
+<DL>
+<DD>Signify that this batch of input to the filter is finished. If
+ the filter requires all instances prior to filtering, output()
+ may now be called to retrieve the filtered instances. Any
+ subsequent instances filtered should be filtered based on setting
+ obtained from the first batch (unless the inputFormat has been
+ re-assigned or new options have been set). This default
+ implementation assumes all instance processing occurs during
+ inputFormat() and input().
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>batchFinished</CODE> in class <CODE>weka.filters.Filter</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>true if there are instances pending output
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.NullPointerException</CODE> - if no input structure has been defined,
+<DD><CODE>java.lang.Exception</CODE> - if there was a problem finishing the batch.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="main(java.lang.String[])"><!-- --></A><H3>
+main</H3>
+<PRE>
+public static void <B>main</B>(java.lang.String[]&nbsp;argv)</PRE>
+<DL>
+<DD>Main method for testing this class.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>argv</CODE> - should contain arguments to the filter: use -h for help</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="invertSelectionTipText()"><!-- --></A><H3>
+invertSelectionTipText</H3>
+<PRE>
+public java.lang.String <B>invertSelectionTipText</B>()</PRE>
+<DL>
+<DD>Returns the tip text for this property
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>tip text for this property suitable for
+ displaying in the explorer/experimenter gui</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getInvertSelection()"><!-- --></A><H3>
+getInvertSelection</H3>
+<PRE>
+public boolean <B>getInvertSelection</B>()</PRE>
+<DL>
+<DD>Get whether the supplied columns are to be processed
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>true if the supplied columns won't be processed</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setInvertSelection(boolean)"><!-- --></A><H3>
+setInvertSelection</H3>
+<PRE>
+public void <B>setInvertSelection</B>(boolean&nbsp;invert)</PRE>
+<DL>
+<DD>Set whether selected columns should be processed. If true the 
+ selected columns won't be processed.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>invert</CODE> - the new invert setting</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="disallowInternalPeriodsTipText()"><!-- --></A><H3>
+disallowInternalPeriodsTipText</H3>
+<PRE>
+public java.lang.String <B>disallowInternalPeriodsTipText</B>()</PRE>
+<DL>
+<DD>Returns the tip text for this property
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>tip text for this property suitable for
+ displaying in the explorer/experimenter gui</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getDisallowInternalPeriods()"><!-- --></A><H3>
+getDisallowInternalPeriods</H3>
+<PRE>
+public boolean <B>getDisallowInternalPeriods</B>()</PRE>
+<DL>
+<DD>Get whether the supplied columns are to be processed
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>true if the supplied columns won't be processed</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setDisallowInternalPeriods(boolean)"><!-- --></A><H3>
+setDisallowInternalPeriods</H3>
+<PRE>
+public void <B>setDisallowInternalPeriods</B>(boolean&nbsp;disallow)</PRE>
+<DL>
+<DD>Set whether selected columns should be processed. If true the 
+ selected columns won't be processed.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="attributeIndicesTipText()"><!-- --></A><H3>
+attributeIndicesTipText</H3>
+<PRE>
+public java.lang.String <B>attributeIndicesTipText</B>()</PRE>
+<DL>
+<DD>Returns the tip text for this property
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>tip text for this property suitable for
+ displaying in the explorer/experimenter gui</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="getAttributeIndices()"><!-- --></A><H3>
+getAttributeIndices</H3>
+<PRE>
+public java.lang.String <B>getAttributeIndices</B>()</PRE>
+<DL>
+<DD>Get the current range selection.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>a string containing a comma separated list of ranges</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setAttributeIndices(java.lang.String)"><!-- --></A><H3>
+setAttributeIndices</H3>
+<PRE>
+public void <B>setAttributeIndices</B>(java.lang.String&nbsp;rangeList)</PRE>
+<DL>
+<DD>Set which attributes are to be processed
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>rangeList</CODE> - a string representing the list of attributes.  Since
+ the string will typically come from a user, attributes are indexed from
+ 1. <br>
+ eg: first-3,5,6-last</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setAttributeIndicesArray(int[])"><!-- --></A><H3>
+setAttributeIndicesArray</H3>
+<PRE>
+public void <B>setAttributeIndicesArray</B>(int[]&nbsp;attributes)</PRE>
+<DL>
+<DD>Set which attributes are to be processed
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>attributes</CODE> - an array containing indexes of attributes to select.
+ Since the array will typically come from a program, attributes are indexed
+ from 0.</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="KEAModelBuilder.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="LovinsStemmer.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="KEAPhraseFilter.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#field_summary">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;<A HREF="#field_detail">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/LovinsStemmer.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/LovinsStemmer.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/LovinsStemmer.html	(revision 8815)
@@ -0,0 +1,289 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:50 NZDT 2004 -->
+<TITLE>
+LovinsStemmer
+</TITLE>
+<META NAME="keywords" CONTENT="LovinsStemmer,LovinsStemmer class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="LovinsStemmer";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="KEAPhraseFilter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="NumbersFilter.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="LovinsStemmer.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class LovinsStemmer</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<A HREF="Stemmer.html">Stemmer</A>
+        |
+        +--<B>LovinsStemmer</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.io.Serializable</DD>
+</DL>
+<DL>
+<DT><B>Direct Known Subclasses:</B> <DD><A HREF="IteratedLovinsStemmer.html">IteratedLovinsStemmer</A></DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>LovinsStemmer</B><DT>extends <A HREF="Stemmer.html">Stemmer</A><DT>implements java.io.Serializable</DL>
+
+<P>
+Implements the Lovins stemmer.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="LovinsStemmer">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="LovinsStemmer.html#LovinsStemmer()">LovinsStemmer</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="LovinsStemmer.html#main(java.lang.String[])">main</A></B>(java.lang.String[]&nbsp;ops)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stems text coming into stdin and writes it to stdout.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="LovinsStemmer.html#stem(java.lang.String)">stem</A></B>(java.lang.String&nbsp;word)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns the stemmed version of the given word.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_Stemmer"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class <A HREF="Stemmer.html">Stemmer</A></B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><A HREF="Stemmer.html#stemString(java.lang.String)">stemString</A></CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="LovinsStemmer()"><!-- --></A><H3>
+LovinsStemmer</H3>
+<PRE>
+public <B>LovinsStemmer</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="stem(java.lang.String)"><!-- --></A><H3>
+stem</H3>
+<PRE>
+public java.lang.String <B>stem</B>(java.lang.String&nbsp;word)</PRE>
+<DL>
+<DD>Returns the stemmed version of the given word.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE><A HREF="Stemmer.html#stem(java.lang.String)">stem</A></CODE> in class <CODE><A HREF="Stemmer.html">Stemmer</A></CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>word</CODE> - a string consisting of a single word</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="main(java.lang.String[])"><!-- --></A><H3>
+main</H3>
+<PRE>
+public static void <B>main</B>(java.lang.String[]&nbsp;ops)</PRE>
+<DL>
+<DD>Stems text coming into stdin and writes it to stdout.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="KEAPhraseFilter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="NumbersFilter.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="LovinsStemmer.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/NumbersFilter.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/NumbersFilter.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/NumbersFilter.html	(revision 8815)
@@ -0,0 +1,396 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:50 NZDT 2004 -->
+<TITLE>
+NumbersFilter
+</TITLE>
+<META NAME="keywords" CONTENT="NumbersFilter,NumbersFilter class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="NumbersFilter";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="LovinsStemmer.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="Stemmer.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="NumbersFilter.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_weka.filters.Filter">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class NumbersFilter</H2>
+<PRE>
+java.lang.Object
+  |
+  +--weka.filters.Filter
+        |
+        +--<B>NumbersFilter</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.io.Serializable</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>NumbersFilter</B><DT>extends weka.filters.Filter</DL>
+
+<P>
+Removes all numbers from all the string attributes in the given
+ dataset. Assumes that words are separated by whitespace.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="NumbersFilter">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+<A NAME="field_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Field Summary</B></FONT></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="fields_inherited_from_class_weka.filters.Filter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Fields inherited from class weka.filters.Filter</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>m_NewBatch</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="NumbersFilter.html#NumbersFilter()">NumbersFilter</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="NumbersFilter.html#batchFinished()">batchFinished</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Signify that this batch of input to the filter is finished.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="NumbersFilter.html#globalInfo()">globalInfo</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns a string describing this filter</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="NumbersFilter.html#input(weka.core.Instance)">input</A></B>(weka.core.Instance&nbsp;instance)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Input an instance for filtering.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>static&nbsp;void</CODE></FONT></TD>
+<TD><CODE><B><A HREF="NumbersFilter.html#main(java.lang.String[])">main</A></B>(java.lang.String[]&nbsp;argv)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Main method for testing this class.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="NumbersFilter.html#setInputFormat(weka.core.Instances)">setInputFormat</A></B>(weka.core.Instances&nbsp;instanceInfo)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Sets the format of the input instances.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_weka.filters.Filter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class weka.filters.Filter</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>batchFilterFile, bufferInput, copyStringValues, copyStringValues, filterFile, flushInput, getInputFormat, getInputStringIndex, getOutputFormat, getOutputStringIndex, getStringIndices, inputFormat, isOutputFormatDefined, numPendingOutput, output, outputFormat, outputFormatPeek, outputPeek, push, resetQueue, setOutputFormat, useFilter</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="NumbersFilter()"><!-- --></A><H3>
+NumbersFilter</H3>
+<PRE>
+public <B>NumbersFilter</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="globalInfo()"><!-- --></A><H3>
+globalInfo</H3>
+<PRE>
+public java.lang.String <B>globalInfo</B>()</PRE>
+<DL>
+<DD>Returns a string describing this filter
+<P>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>a description of the filter suitable for
+ displaying in the explorer/experimenter gui</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="batchFinished()"><!-- --></A><H3>
+batchFinished</H3>
+<PRE>
+public boolean <B>batchFinished</B>()
+                      throws java.lang.Exception</PRE>
+<DL>
+<DD>Signify that this batch of input to the filter is finished. If
+ the filter requires all instances prior to filtering, output()
+ may now be called to retrieve the filtered instances. Any
+ subsequent instances filtered should be filtered based on setting
+ obtained from the first batch (unless the inputFormat has been
+ re-assigned or new options have been set). This default
+ implementation assumes all instance processing occurs during
+ inputFormat() and input().
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>batchFinished</CODE> in class <CODE>weka.filters.Filter</CODE></DL>
+</DD>
+<DD><DL>
+
+<DT><B>Returns:</B><DD>true if there are instances pending output
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.NullPointerException</CODE> - if no input structure has been defined,
+<DD><CODE>java.lang.Exception</CODE> - if there was a problem finishing the batch.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="setInputFormat(weka.core.Instances)"><!-- --></A><H3>
+setInputFormat</H3>
+<PRE>
+public boolean <B>setInputFormat</B>(weka.core.Instances&nbsp;instanceInfo)
+                       throws java.lang.Exception</PRE>
+<DL>
+<DD>Sets the format of the input instances.
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>setInputFormat</CODE> in class <CODE>weka.filters.Filter</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>instanceInfo</CODE> - an Instances object containing the input
+ instance structure (any instances contained in the object are
+ ignored - only the structure is required).
+<DT><B>Returns:</B><DD>true if the outputFormat may be collected immediately
+<DD><CODE>java.lang.Exception</CODE></DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="input(weka.core.Instance)"><!-- --></A><H3>
+input</H3>
+<PRE>
+public boolean <B>input</B>(weka.core.Instance&nbsp;instance)
+              throws java.lang.Exception</PRE>
+<DL>
+<DD>Input an instance for filtering. Ordinarily the instance is processed
+ and made available for output immediately. Some filters require all
+ instances be read before producing output.
+<P>
+<DD><DL>
+<DT><B>Overrides:</B><DD><CODE>input</CODE> in class <CODE>weka.filters.Filter</CODE></DL>
+</DD>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>instance</CODE> - the input instance
+<DT><B>Returns:</B><DD>true if the filtered instance may now be
+ collected with output().
+<DT><B>Throws:</B>
+<DD><CODE>java.lang.Exception</CODE> - if the input instance was not of the correct 
+ format or if there was a problem with the filtering.</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="main(java.lang.String[])"><!-- --></A><H3>
+main</H3>
+<PRE>
+public static void <B>main</B>(java.lang.String[]&nbsp;argv)</PRE>
+<DL>
+<DD>Main method for testing this class.
+<P>
+<DD><DL>
+<DT><B>Parameters:</B><DD><CODE>argv</CODE> - should contain arguments to the filter: use -h for help</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="LovinsStemmer.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="Stemmer.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="NumbersFilter.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;<A HREF="#fields_inherited_from_class_weka.filters.Filter">FIELD</A>&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/Stemmer.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/Stemmer.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/Stemmer.html	(revision 8815)
@@ -0,0 +1,278 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:50 NZDT 2004 -->
+<TITLE>
+Stemmer
+</TITLE>
+<META NAME="keywords" CONTENT="Stemmer,Stemmer class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Stemmer";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="NumbersFilter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="Stopwords.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="Stemmer.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class Stemmer</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<B>Stemmer</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.io.Serializable</DD>
+</DL>
+<DL>
+<DT><B>Direct Known Subclasses:</B> <DD><A HREF="GermanStemmer.html">GermanStemmer</A>, <A HREF="LovinsStemmer.html">LovinsStemmer</A></DD>
+</DL>
+<HR>
+<DL>
+<DT>public abstract class <B>Stemmer</B><DT>extends java.lang.Object<DT>implements java.io.Serializable</DL>
+
+<P>
+Abstract class for stemmers.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="Stemmer">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="Stemmer.html#Stemmer()">Stemmer</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>abstract &nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="Stemmer.html#stem(java.lang.String)">stem</A></B>(java.lang.String&nbsp;str)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterated stemming of the given word.</TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;java.lang.String</CODE></FONT></TD>
+<TD><CODE><B><A HREF="Stemmer.html#stemString(java.lang.String)">stemString</A></B>(java.lang.String&nbsp;str)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Stems everything in the given string.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="Stemmer()"><!-- --></A><H3>
+Stemmer</H3>
+<PRE>
+public <B>Stemmer</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="stem(java.lang.String)"><!-- --></A><H3>
+stem</H3>
+<PRE>
+public abstract java.lang.String <B>stem</B>(java.lang.String&nbsp;str)</PRE>
+<DL>
+<DD>Iterated stemming of the given word.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<HR>
+
+<A NAME="stemString(java.lang.String)"><!-- --></A><H3>
+stemString</H3>
+<PRE>
+public java.lang.String <B>stemString</B>(java.lang.String&nbsp;str)</PRE>
+<DL>
+<DD>Stems everything in the given string.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="NumbersFilter.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="Stopwords.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="Stemmer.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/Stopwords.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/Stopwords.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/Stopwords.html	(revision 8815)
@@ -0,0 +1,255 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:50 NZDT 2004 -->
+<TITLE>
+Stopwords
+</TITLE>
+<META NAME="keywords" CONTENT="Stopwords,Stopwords class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Stopwords";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="Stemmer.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="StopwordsEnglish.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="Stopwords.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class Stopwords</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<B>Stopwords</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.io.Serializable</DD>
+</DL>
+<DL>
+<DT><B>Direct Known Subclasses:</B> <DD><A HREF="StopwordsEnglish.html">StopwordsEnglish</A>, <A HREF="StopwordsGerman.html">StopwordsGerman</A></DD>
+</DL>
+<HR>
+<DL>
+<DT>public abstract class <B>Stopwords</B><DT>extends java.lang.Object<DT>implements java.io.Serializable</DL>
+
+<P>
+Class that can test whether a given string is a stop word.
+ Lowercases all words before the test.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="Stopwords">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="Stopwords.html#Stopwords()">Stopwords</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>abstract &nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="Stopwords.html#isStopword(java.lang.String)">isStopword</A></B>(java.lang.String&nbsp;str)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns true if the given string is a stop word.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="Stopwords()"><!-- --></A><H3>
+Stopwords</H3>
+<PRE>
+public <B>Stopwords</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="isStopword(java.lang.String)"><!-- --></A><H3>
+isStopword</H3>
+<PRE>
+public abstract boolean <B>isStopword</B>(java.lang.String&nbsp;str)</PRE>
+<DL>
+<DD>Returns true if the given string is a stop word.
+<P>
+<DD><DL>
+</DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="Stemmer.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="StopwordsEnglish.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="Stopwords.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/StopwordsEnglish.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/StopwordsEnglish.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/StopwordsEnglish.html	(revision 8815)
@@ -0,0 +1,254 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:50 NZDT 2004 -->
+<TITLE>
+StopwordsEnglish
+</TITLE>
+<META NAME="keywords" CONTENT="StopwordsEnglish,StopwordsEnglish class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="StopwordsEnglish";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="Stopwords.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="StopwordsGerman.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="StopwordsEnglish.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class StopwordsEnglish</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<A HREF="Stopwords.html">Stopwords</A>
+        |
+        +--<B>StopwordsEnglish</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.io.Serializable</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>StopwordsEnglish</B><DT>extends <A HREF="Stopwords.html">Stopwords</A></DL>
+
+<P>
+Class that can test whether a given string is a stop word.
+ Lowercases all words before the test.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="StopwordsEnglish">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="StopwordsEnglish.html#StopwordsEnglish()">StopwordsEnglish</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="StopwordsEnglish.html#isStopword(java.lang.String)">isStopword</A></B>(java.lang.String&nbsp;str)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns true if the given string is a stop word.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="StopwordsEnglish()"><!-- --></A><H3>
+StopwordsEnglish</H3>
+<PRE>
+public <B>StopwordsEnglish</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="isStopword(java.lang.String)"><!-- --></A><H3>
+isStopword</H3>
+<PRE>
+public boolean <B>isStopword</B>(java.lang.String&nbsp;str)</PRE>
+<DL>
+<DD>Returns true if the given string is a stop word.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE><A HREF="Stopwords.html#isStopword(java.lang.String)">isStopword</A></CODE> in class <CODE><A HREF="Stopwords.html">Stopwords</A></CODE></DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="Stopwords.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;<A HREF="StopwordsGerman.html"><B>NEXT CLASS</B></A></FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="StopwordsEnglish.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/StopwordsGerman.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/StopwordsGerman.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/StopwordsGerman.html	(revision 8815)
@@ -0,0 +1,259 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:50 NZDT 2004 -->
+<TITLE>
+StopwordsGerman
+</TITLE>
+<META NAME="keywords" CONTENT="StopwordsGerman,StopwordsGerman class">
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="StopwordsGerman";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="StopwordsEnglish.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;NEXT CLASS</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="StopwordsGerman.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<!-- ======== START OF CLASS DATA ======== -->
+<H2>
+Class StopwordsGerman</H2>
+<PRE>
+java.lang.Object
+  |
+  +--<A HREF="Stopwords.html">Stopwords</A>
+        |
+        +--<B>StopwordsGerman</B>
+</PRE>
+<DL>
+<DT><B>All Implemented Interfaces:</B> <DD>java.io.Serializable</DD>
+</DL>
+<HR>
+<DL>
+<DT>public class <B>StopwordsGerman</B><DT>extends <A HREF="Stopwords.html">Stopwords</A></DL>
+
+<P>
+Class that can test whether a given string is a stop word.
+ Lowercases all words before the test.
+
+ This list of German stop words has been obtained from
+ http://snowball.tartarus.org/german/stop.txt
+
+ But I have deleted/changed some words that I haven't seen before.
+<P>
+
+<P>
+<DL>
+<DT><B>See Also:</B><DD><A HREF="serialized-form.html" TARGET="StopwordsGerman">Serialized Form</A></DL>
+<HR>
+
+<P>
+<!-- ======== NESTED CLASS SUMMARY ======== -->
+
+
+<!-- =========== FIELD SUMMARY =========== -->
+
+
+<!-- ======== CONSTRUCTOR SUMMARY ======== -->
+
+<A NAME="constructor_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Constructor Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE><B><A HREF="StopwordsGerman.html#StopwordsGerman()">StopwordsGerman</A></B>()</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</TD>
+</TR>
+</TABLE>
+&nbsp;
+<!-- ========== METHOD SUMMARY =========== -->
+
+<A NAME="method_summary"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Method Summary</B></FONT></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD ALIGN="right" VALIGN="top" WIDTH="1%"><FONT SIZE="-1">
+<CODE>&nbsp;boolean</CODE></FONT></TD>
+<TD><CODE><B><A HREF="StopwordsGerman.html#isStopword(java.lang.String)">isStopword</A></B>(java.lang.String&nbsp;str)</CODE>
+
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Returns true if the given string is a stop word.</TD>
+</TR>
+</TABLE>
+&nbsp;<A NAME="methods_inherited_from_class_java.lang.Object"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#EEEEFF" CLASS="TableSubHeadingColor">
+<TD><B>Methods inherited from class java.lang.Object</B></TD>
+</TR>
+<TR BGCOLOR="white" CLASS="TableRowColor">
+<TD><CODE>clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait</CODE></TD>
+</TR>
+</TABLE>
+&nbsp;
+<P>
+
+<!-- ============ FIELD DETAIL =========== -->
+
+
+<!-- ========= CONSTRUCTOR DETAIL ======== -->
+
+<A NAME="constructor_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Constructor Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="StopwordsGerman()"><!-- --></A><H3>
+StopwordsGerman</H3>
+<PRE>
+public <B>StopwordsGerman</B>()</PRE>
+<DL>
+</DL>
+
+<!-- ============ METHOD DETAIL ========== -->
+
+<A NAME="method_detail"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Method Detail</B></FONT></TD>
+</TR>
+</TABLE>
+
+<A NAME="isStopword(java.lang.String)"><!-- --></A><H3>
+isStopword</H3>
+<PRE>
+public boolean <B>isStopword</B>(java.lang.String&nbsp;str)</PRE>
+<DL>
+<DD>Returns true if the given string is a stop word.
+<P>
+<DD><DL>
+<DT><B>Specified by:</B><DD><CODE><A HREF="Stopwords.html#isStopword(java.lang.String)">isStopword</A></CODE> in class <CODE><A HREF="Stopwords.html">Stopwords</A></CODE></DL>
+</DD>
+<DD><DL>
+</DL>
+</DD>
+</DL>
+<!-- ========= END OF CLASS DATA ========= -->
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">      <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Class</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;<A HREF="StopwordsEnglish.html"><B>PREV CLASS</B></A>&nbsp;
+&nbsp;NEXT CLASS</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="StopwordsGerman.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+<TR>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+  SUMMARY:&nbsp;NESTED&nbsp;|&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_summary">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_summary">METHOD</A></FONT></TD>
+<TD VALIGN="top" CLASS="NavBarCell3"><FONT SIZE="-2">
+DETAIL:&nbsp;FIELD&nbsp;|&nbsp;<A HREF="#constructor_detail">CONSTR</A>&nbsp;|&nbsp;<A HREF="#method_detail">METHOD</A></FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/allclasses-frame.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/allclasses-frame.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/allclasses-frame.html	(revision 8815)
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:48 NZDT 2004 -->
+<TITLE>
+All Classes
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="All Classes";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+<FONT size="+1" CLASS="FrameHeadingFont">
+<B>All Classes</B></FONT>
+<BR>
+
+<TABLE BORDER="0" WIDTH="100%">
+<TR>
+<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="Counter.html" TARGET="classFrame">Counter</A>
+<BR>
+<A HREF="GermanStemmer.html" TARGET="classFrame">GermanStemmer</A>
+<BR>
+<A HREF="IteratedLovinsStemmer.html" TARGET="classFrame">IteratedLovinsStemmer</A>
+<BR>
+<A HREF="KEAFilter.html" TARGET="classFrame">KEAFilter</A>
+<BR>
+<A HREF="KEAKeyphraseExtractor.html" TARGET="classFrame">KEAKeyphraseExtractor</A>
+<BR>
+<A HREF="KEAModelBuilder.html" TARGET="classFrame">KEAModelBuilder</A>
+<BR>
+<A HREF="KEAPhraseFilter.html" TARGET="classFrame">KEAPhraseFilter</A>
+<BR>
+<A HREF="LovinsStemmer.html" TARGET="classFrame">LovinsStemmer</A>
+<BR>
+<A HREF="NumbersFilter.html" TARGET="classFrame">NumbersFilter</A>
+<BR>
+<A HREF="Stemmer.html" TARGET="classFrame">Stemmer</A>
+<BR>
+<A HREF="Stopwords.html" TARGET="classFrame">Stopwords</A>
+<BR>
+<A HREF="StopwordsEnglish.html" TARGET="classFrame">StopwordsEnglish</A>
+<BR>
+<A HREF="StopwordsGerman.html" TARGET="classFrame">StopwordsGerman</A>
+<BR>
+</FONT></TD>
+</TR>
+</TABLE>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/allclasses-noframe.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/allclasses-noframe.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/allclasses-noframe.html	(revision 8815)
@@ -0,0 +1,55 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:48 NZDT 2004 -->
+<TITLE>
+All Classes
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="All Classes";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+<FONT size="+1" CLASS="FrameHeadingFont">
+<B>All Classes</B></FONT>
+<BR>
+
+<TABLE BORDER="0" WIDTH="100%">
+<TR>
+<TD NOWRAP><FONT CLASS="FrameItemFont"><A HREF="Counter.html" TARGET="">Counter</A>
+<BR>
+<A HREF="GermanStemmer.html" TARGET="">GermanStemmer</A>
+<BR>
+<A HREF="IteratedLovinsStemmer.html" TARGET="">IteratedLovinsStemmer</A>
+<BR>
+<A HREF="KEAFilter.html" TARGET="">KEAFilter</A>
+<BR>
+<A HREF="KEAKeyphraseExtractor.html" TARGET="">KEAKeyphraseExtractor</A>
+<BR>
+<A HREF="KEAModelBuilder.html" TARGET="">KEAModelBuilder</A>
+<BR>
+<A HREF="KEAPhraseFilter.html" TARGET="">KEAPhraseFilter</A>
+<BR>
+<A HREF="LovinsStemmer.html" TARGET="">LovinsStemmer</A>
+<BR>
+<A HREF="NumbersFilter.html" TARGET="">NumbersFilter</A>
+<BR>
+<A HREF="Stemmer.html" TARGET="">Stemmer</A>
+<BR>
+<A HREF="Stopwords.html" TARGET="">Stopwords</A>
+<BR>
+<A HREF="StopwordsEnglish.html" TARGET="">StopwordsEnglish</A>
+<BR>
+<A HREF="StopwordsGerman.html" TARGET="">StopwordsGerman</A>
+<BR>
+</FONT></TD>
+</TR>
+</TABLE>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/constant-values.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/constant-values.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/constant-values.html	(revision 8815)
@@ -0,0 +1,123 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:47 NZDT 2004 -->
+<TITLE>
+Constant Field Values
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Constant Field Values";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="constant-values.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H1>
+Constant Field Values</H1>
+</CENTER>
+<HR SIZE="4" NOSHADE>
+<B>Contents</B><UL>
+</UL>
+
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="constant-values.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/deprecated-list.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/deprecated-list.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/deprecated-list.html	(revision 8815)
@@ -0,0 +1,119 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:48 NZDT 2004 -->
+<TITLE>
+Deprecated List
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Deprecated List";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Deprecated</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="deprecated-list.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H2>
+<B>Deprecated API</B></H2>
+</CENTER>
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Deprecated</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="deprecated-list.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/help-doc.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/help-doc.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/help-doc.html	(revision 8815)
@@ -0,0 +1,168 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:50 NZDT 2004 -->
+<TITLE>
+API Help
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="API Help";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="help-doc.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H1>
+How This API Document Is Organized</H1>
+</CENTER>
+This API (Application Programming Interface) document has pages corresponding to the items in the navigation bar, described as follows.<H3>
+Package</H3>
+<BLOCKQUOTE>
+
+<P>
+Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:<UL>
+<LI>Interfaces (italic)<LI>Classes<LI>Exceptions<LI>Errors</UL>
+</BLOCKQUOTE>
+<H3>
+Class/Interface</H3>
+<BLOCKQUOTE>
+
+<P>
+Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:<UL>
+<LI>Class inheritance diagram<LI>Direct Subclasses<LI>All Known Subinterfaces<LI>All Known Implementing Classes<LI>Class/interface declaration<LI>Class/interface description
+<P>
+<LI>Nested Class Summary<LI>Field Summary<LI>Constructor Summary<LI>Method Summary
+<P>
+<LI>Field Detail<LI>Constructor Detail<LI>Method Detail</UL>
+Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.</BLOCKQUOTE>
+<H3>
+Tree (Class Hierarchy)</H3>
+<BLOCKQUOTE>
+There is a <A HREF="overview-tree.html">Class Hierarchy</A> page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with <code>java.lang.Object</code>. The interfaces do not inherit from <code>java.lang.Object</code>.<UL>
+<LI>When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.<LI>When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.</UL>
+</BLOCKQUOTE>
+<H3>
+Deprecated API</H3>
+<BLOCKQUOTE>
+The <A HREF="deprecated-list.html">Deprecated API</A> page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.</BLOCKQUOTE>
+<H3>
+Index</H3>
+<BLOCKQUOTE>
+The <A HREF="index-all.html">Index</A> contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.</BLOCKQUOTE>
+<H3>
+Prev/Next</H3>
+These links take you to the next or previous class, interface, package, or related page.<H3>
+Frames/No Frames</H3>
+These links show and hide the HTML frames.  All pages are available with or without frames.
+<P>
+<H3>
+Serialized Form</H3>
+Each serializable or externalizable class has a description of its serialization fields and methods. This information is of interest to re-implementors, not to developers using the API. While there is no link in the navigation bar, you can get to this information by going to any serialized class and clicking "Serialized Form" in the "See also" section of the class description.
+<P>
+<FONT SIZE="-1">
+<EM>
+This help file applies to API documentation generated using the standard doclet.</EM>
+</FONT>
+<BR>
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Help</B></FONT>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="help-doc.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/index-all.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/index-all.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/index-all.html	(revision 8815)
@@ -0,0 +1,596 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:48 NZDT 2004 -->
+<TITLE>
+Index
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Index";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Index</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="index-all.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<A HREF="#_A_">A</A> <A HREF="#_B_">B</A> <A HREF="#_C_">C</A> <A HREF="#_D_">D</A> <A HREF="#_E_">E</A> <A HREF="#_G_">G</A> <A HREF="#_I_">I</A> <A HREF="#_K_">K</A> <A HREF="#_L_">L</A> <A HREF="#_M_">M</A> <A HREF="#_N_">N</A> <A HREF="#_S_">S</A> <A HREF="#_T_">T</A> <A HREF="#_V_">V</A> <HR>
+<A NAME="_A_"><!-- --></A><H2>
+<B>A</B></H2>
+<DL>
+<DT><A HREF="KEAPhraseFilter.html#attributeIndicesTipText()"><B>attributeIndicesTipText()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Returns the tip text for this property
+</DL>
+<HR>
+<A NAME="_B_"><!-- --></A><H2>
+<B>B</B></H2>
+<DL>
+<DT><A HREF="KEAFilter.html#batchFinished()"><B>batchFinished()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Signify that this batch of input to the filter is finished.
+<DT><A HREF="KEAPhraseFilter.html#batchFinished()"><B>batchFinished()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Signify that this batch of input to the filter is finished.
+<DT><A HREF="NumbersFilter.html#batchFinished()"><B>batchFinished()</B></A> - 
+Method in class <A HREF="NumbersFilter.html">NumbersFilter</A>
+<DD>Signify that this batch of input to the filter is finished.
+<DT><A HREF="KEAModelBuilder.html#buildModel(java.util.Hashtable)"><B>buildModel(Hashtable)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Builds the model from the files
+</DL>
+<HR>
+<A NAME="_C_"><!-- --></A><H2>
+<B>C</B></H2>
+<DL>
+<DT><A HREF="KEAKeyphraseExtractor.html#collectStems()"><B>collectStems()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Collects the stems of the file names.
+<DT><A HREF="KEAModelBuilder.html#collectStems()"><B>collectStems()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Collects the stems of the file names.
+<DT><A HREF="Counter.html"><B>Counter</B></A> - class <A HREF="Counter.html">Counter</A>.<DD>Class that implements a simple counter.<DT><A HREF="Counter.html#Counter()"><B>Counter()</B></A> - 
+Constructor for class <A HREF="Counter.html">Counter</A>
+<DD>Initializes the counter to 1
+<DT><A HREF="Counter.html#Counter(int)"><B>Counter(int)</B></A> - 
+Constructor for class <A HREF="Counter.html">Counter</A>
+<DD>Initializes the counter to the given value
+</DL>
+<HR>
+<A NAME="_D_"><!-- --></A><H2>
+<B>D</B></H2>
+<DL>
+<DT><A HREF="KEAPhraseFilter.html#disallowInternalPeriodsTipText()"><B>disallowInternalPeriodsTipText()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Returns the tip text for this property
+</DL>
+<HR>
+<A NAME="_E_"><!-- --></A><H2>
+<B>E</B></H2>
+<DL>
+<DT><A HREF="KEAKeyphraseExtractor.html#extractKeyphrases(java.util.Hashtable)"><B>extractKeyphrases(Hashtable)</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Builds the model from the files
+</DL>
+<HR>
+<A NAME="_G_"><!-- --></A><H2>
+<B>G</B></H2>
+<DL>
+<DT><A HREF="GermanStemmer.html"><B>GermanStemmer</B></A> - class <A HREF="GermanStemmer.html">GermanStemmer</A>.<DD>A stemmer for German words.<DT><A HREF="GermanStemmer.html#GermanStemmer()"><B>GermanStemmer()</B></A> - 
+Constructor for class <A HREF="GermanStemmer.html">GermanStemmer</A>
+<DD>&nbsp;
+<DT><A HREF="KEAKeyphraseExtractor.html#getAdditionalInfo()"><B>getAdditionalInfo()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Get the value of AdditionalInfo.
+<DT><A HREF="KEAPhraseFilter.html#getAttributeIndices()"><B>getAttributeIndices()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Get the current range selection.
+<DT><A HREF="KEAFilter.html#getCheckForProperNouns()"><B>getCheckForProperNouns()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get the M_CheckProperNouns value.
+<DT><A HREF="KEAModelBuilder.html#getCheckForProperNouns()"><B>getCheckForProperNouns()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the M_CheckProperNouns value.
+<DT><A HREF="KEAFilter.html#getDebug()"><B>getDebug()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get the value of Debug.
+<DT><A HREF="KEAKeyphraseExtractor.html#getDebug()"><B>getDebug()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Get the value of debug.
+<DT><A HREF="KEAModelBuilder.html#getDebug()"><B>getDebug()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the value of debug.
+<DT><A HREF="KEAKeyphraseExtractor.html#getDirName()"><B>getDirName()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Get the value of dirName.
+<DT><A HREF="KEAModelBuilder.html#getDirName()"><B>getDirName()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the value of dirName.
+<DT><A HREF="KEAFilter.html#getDisallowInternalPeriods()"><B>getDisallowInternalPeriods()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get whether the supplied columns are to be processed
+<DT><A HREF="KEAPhraseFilter.html#getDisallowInternalPeriods()"><B>getDisallowInternalPeriods()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Get whether the supplied columns are to be processed
+<DT><A HREF="KEAModelBuilder.html#getDisallowIPeriods()"><B>getDisallowIPeriods()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the value of disallowIPeriods.
+<DT><A HREF="KEAFilter.html#getDocumentAtt()"><B>getDocumentAtt()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get the value of DocumentAtt.
+<DT><A HREF="KEAKeyphraseExtractor.html#getEncoding()"><B>getEncoding()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Get the value of encoding.
+<DT><A HREF="KEAModelBuilder.html#getEncoding()"><B>getEncoding()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the value of encoding.
+<DT><A HREF="KEAPhraseFilter.html#getInvertSelection()"><B>getInvertSelection()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Get whether the supplied columns are to be processed
+<DT><A HREF="KEAFilter.html#getKeyphrasesAtt()"><B>getKeyphrasesAtt()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get the value of KeyphraseAtt.
+<DT><A HREF="KEAFilter.html#getKFused()"><B>getKFused()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Gets whether keyphrase frequency attribute is used.
+<DT><A HREF="KEAFilter.html#getMaxPhraseLength()"><B>getMaxPhraseLength()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get the value of MaxPhraseLength.
+<DT><A HREF="KEAModelBuilder.html#getMaxPhraseLength()"><B>getMaxPhraseLength()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the value of MaxPhraseLength.
+<DT><A HREF="KEAFilter.html#getMinNumOccur()"><B>getMinNumOccur()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get the value of MinNumOccur.
+<DT><A HREF="KEAModelBuilder.html#getMinNumOccur()"><B>getMinNumOccur()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the value of MinNumOccur.
+<DT><A HREF="KEAFilter.html#getMinPhraseLength()"><B>getMinPhraseLength()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get the value of MinPhraseLength.
+<DT><A HREF="KEAModelBuilder.html#getMinPhraseLength()"><B>getMinPhraseLength()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the value of MinPhraseLength.
+<DT><A HREF="KEAKeyphraseExtractor.html#getModelName()"><B>getModelName()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Get the value of modelName.
+<DT><A HREF="KEAModelBuilder.html#getModelName()"><B>getModelName()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the value of modelName.
+<DT><A HREF="KEAKeyphraseExtractor.html#getNumPhrases()"><B>getNumPhrases()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Get the value of numPhrases.
+<DT><A HREF="KEAFilter.html#getOptions()"><B>getOptions()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Gets the current settings of the filter.
+<DT><A HREF="KEAKeyphraseExtractor.html#getOptions()"><B>getOptions()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Gets the current option settings.
+<DT><A HREF="KEAModelBuilder.html#getOptions()"><B>getOptions()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Gets the current option settings.
+<DT><A HREF="KEAPhraseFilter.html#getOptions()"><B>getOptions()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Gets the current settings of the filter.
+<DT><A HREF="KEAFilter.html#getProbabilityIndex()"><B>getProbabilityIndex()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Returns the index of the phrases' probabilities in the output ARFF file.
+<DT><A HREF="KEAFilter.html#getRankIndex()"><B>getRankIndex()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Returns the index of the phrases' ranks in the output ARFF file.
+<DT><A HREF="KEAFilter.html#getStemmedPhraseIndex()"><B>getStemmedPhraseIndex()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Returns the index of the stemmed phrases in the output ARFF file.
+<DT><A HREF="KEAFilter.html#getStemmer()"><B>getStemmer()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get the Stemmer value.
+<DT><A HREF="KEAModelBuilder.html#getStemmer()"><B>getStemmer()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the Stemmer value.
+<DT><A HREF="KEAFilter.html#getStopwords()"><B>getStopwords()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Get the M_Stopwords value.
+<DT><A HREF="KEAModelBuilder.html#getStopwords()"><B>getStopwords()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the M_Stopwords value.
+<DT><A HREF="KEAFilter.html#getUnstemmedPhraseIndex()"><B>getUnstemmedPhraseIndex()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Returns the index of the unstemmed phrases in the output ARFF file.
+<DT><A HREF="KEAModelBuilder.html#getUseKFrequency()"><B>getUseKFrequency()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Get the value of useKFrequency.
+<DT><A HREF="KEAFilter.html#globalInfo()"><B>globalInfo()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Returns a string describing this filter
+<DT><A HREF="KEAPhraseFilter.html#globalInfo()"><B>globalInfo()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Returns a string describing this filter
+<DT><A HREF="NumbersFilter.html#globalInfo()"><B>globalInfo()</B></A> - 
+Method in class <A HREF="NumbersFilter.html">NumbersFilter</A>
+<DD>Returns a string describing this filter
+</DL>
+<HR>
+<A NAME="_I_"><!-- --></A><H2>
+<B>I</B></H2>
+<DL>
+<DT><A HREF="Counter.html#increment()"><B>increment()</B></A> - 
+Method in class <A HREF="Counter.html">Counter</A>
+<DD>Increments the counter.
+<DT><A HREF="KEAFilter.html#input(weka.core.Instance)"><B>input(Instance)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Input an instance for filtering.
+<DT><A HREF="KEAPhraseFilter.html#input(weka.core.Instance)"><B>input(Instance)</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Input an instance for filtering.
+<DT><A HREF="NumbersFilter.html#input(weka.core.Instance)"><B>input(Instance)</B></A> - 
+Method in class <A HREF="NumbersFilter.html">NumbersFilter</A>
+<DD>Input an instance for filtering.
+<DT><A HREF="KEAPhraseFilter.html#invertSelectionTipText()"><B>invertSelectionTipText()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Returns the tip text for this property
+<DT><A HREF="Stopwords.html#isStopword(java.lang.String)"><B>isStopword(String)</B></A> - 
+Method in class <A HREF="Stopwords.html">Stopwords</A>
+<DD>Returns true if the given string is a stop word.
+<DT><A HREF="StopwordsEnglish.html#isStopword(java.lang.String)"><B>isStopword(String)</B></A> - 
+Method in class <A HREF="StopwordsEnglish.html">StopwordsEnglish</A>
+<DD>Returns true if the given string is a stop word.
+<DT><A HREF="StopwordsGerman.html#isStopword(java.lang.String)"><B>isStopword(String)</B></A> - 
+Method in class <A HREF="StopwordsGerman.html">StopwordsGerman</A>
+<DD>Returns true if the given string is a stop word.
+<DT><A HREF="IteratedLovinsStemmer.html"><B>IteratedLovinsStemmer</B></A> - class <A HREF="IteratedLovinsStemmer.html">IteratedLovinsStemmer</A>.<DD>Implements the iterated version of the Lovins stemmer.<DT><A HREF="IteratedLovinsStemmer.html#IteratedLovinsStemmer()"><B>IteratedLovinsStemmer()</B></A> - 
+Constructor for class <A HREF="IteratedLovinsStemmer.html">IteratedLovinsStemmer</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_K_"><!-- --></A><H2>
+<B>K</B></H2>
+<DL>
+<DT><A HREF="KEAFilter.html"><B>KEAFilter</B></A> - class <A HREF="KEAFilter.html">KEAFilter</A>.<DD>This filter converts the incoming data into data appropriate for
+ keyphrase classification.<DT><A HREF="KEAFilter.html#KEAFilter()"><B>KEAFilter()</B></A> - 
+Constructor for class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>&nbsp;
+<DT><A HREF="KEAKeyphraseExtractor.html"><B>KEAKeyphraseExtractor</B></A> - class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>.<DD>Extracts keyphrases from the documents in a given directory.<DT><A HREF="KEAKeyphraseExtractor.html#KEAKeyphraseExtractor()"><B>KEAKeyphraseExtractor()</B></A> - 
+Constructor for class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>&nbsp;
+<DT><A HREF="KEAModelBuilder.html"><B>KEAModelBuilder</B></A> - class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>.<DD>Builds a keyphrase extraction model from the documents in a given
+ directory.<DT><A HREF="KEAModelBuilder.html#KEAModelBuilder()"><B>KEAModelBuilder()</B></A> - 
+Constructor for class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>&nbsp;
+<DT><A HREF="KEAPhraseFilter.html"><B>KEAPhraseFilter</B></A> - class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>.<DD>This filter splits the text in selected string
+ attributes into phrases.<DT><A HREF="KEAPhraseFilter.html#KEAPhraseFilter()"><B>KEAPhraseFilter()</B></A> - 
+Constructor for class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_L_"><!-- --></A><H2>
+<B>L</B></H2>
+<DL>
+<DT><A HREF="KEAFilter.html#listOptions()"><B>listOptions()</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Returns an enumeration describing the available options
+<DT><A HREF="KEAKeyphraseExtractor.html#listOptions()"><B>listOptions()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Returns an enumeration describing the available options.
+<DT><A HREF="KEAModelBuilder.html#listOptions()"><B>listOptions()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Returns an enumeration describing the available options.
+<DT><A HREF="KEAPhraseFilter.html#listOptions()"><B>listOptions()</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Returns an enumeration describing the available options
+<DT><A HREF="KEAKeyphraseExtractor.html#loadModel()"><B>loadModel()</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Loads the extraction model from the file.
+<DT><A HREF="LovinsStemmer.html"><B>LovinsStemmer</B></A> - class <A HREF="LovinsStemmer.html">LovinsStemmer</A>.<DD>Implements the Lovins stemmer.<DT><A HREF="LovinsStemmer.html#LovinsStemmer()"><B>LovinsStemmer()</B></A> - 
+Constructor for class <A HREF="LovinsStemmer.html">LovinsStemmer</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_M_"><!-- --></A><H2>
+<B>M</B></H2>
+<DL>
+<DT><A HREF="KEAPhraseFilter.html#m_DisallowInternalPeriods"><B>m_DisallowInternalPeriods</B></A> - 
+Variable in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Determines whether internal periods are allowed
+<DT><A HREF="KEAPhraseFilter.html#m_SelectCols"><B>m_SelectCols</B></A> - 
+Variable in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Stores which columns to select as a funky range
+<DT><A HREF="IteratedLovinsStemmer.html#main(java.lang.String[])"><B>main(String[])</B></A> - 
+Static method in class <A HREF="IteratedLovinsStemmer.html">IteratedLovinsStemmer</A>
+<DD>Stems text coming into stdin and writes it to stdout.
+<DT><A HREF="KEAFilter.html#main(java.lang.String[])"><B>main(String[])</B></A> - 
+Static method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Main method for testing this class.
+<DT><A HREF="KEAKeyphraseExtractor.html#main(java.lang.String[])"><B>main(String[])</B></A> - 
+Static method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>The main method.
+<DT><A HREF="KEAModelBuilder.html#main(java.lang.String[])"><B>main(String[])</B></A> - 
+Static method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>The main method.
+<DT><A HREF="KEAPhraseFilter.html#main(java.lang.String[])"><B>main(String[])</B></A> - 
+Static method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Main method for testing this class.
+<DT><A HREF="LovinsStemmer.html#main(java.lang.String[])"><B>main(String[])</B></A> - 
+Static method in class <A HREF="LovinsStemmer.html">LovinsStemmer</A>
+<DD>Stems text coming into stdin and writes it to stdout.
+<DT><A HREF="NumbersFilter.html#main(java.lang.String[])"><B>main(String[])</B></A> - 
+Static method in class <A HREF="NumbersFilter.html">NumbersFilter</A>
+<DD>Main method for testing this class.
+</DL>
+<HR>
+<A NAME="_N_"><!-- --></A><H2>
+<B>N</B></H2>
+<DL>
+<DT><A HREF="NumbersFilter.html"><B>NumbersFilter</B></A> - class <A HREF="NumbersFilter.html">NumbersFilter</A>.<DD>Removes all numbers from all the string attributes in the given
+ dataset.<DT><A HREF="NumbersFilter.html#NumbersFilter()"><B>NumbersFilter()</B></A> - 
+Constructor for class <A HREF="NumbersFilter.html">NumbersFilter</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_S_"><!-- --></A><H2>
+<B>S</B></H2>
+<DL>
+<DT><A HREF="KEAModelBuilder.html#saveModel()"><B>saveModel()</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Saves the extraction model to the file.
+<DT><A HREF="KEAKeyphraseExtractor.html#setAdditionalInfo(boolean)"><B>setAdditionalInfo(boolean)</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Set the value of AdditionalInfo.
+<DT><A HREF="KEAPhraseFilter.html#setAttributeIndices(java.lang.String)"><B>setAttributeIndices(String)</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Set which attributes are to be processed
+<DT><A HREF="KEAPhraseFilter.html#setAttributeIndicesArray(int[])"><B>setAttributeIndicesArray(int[])</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Set which attributes are to be processed
+<DT><A HREF="KEAFilter.html#setCheckForProperNouns(boolean)"><B>setCheckForProperNouns(boolean)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set the M_CheckProperNouns value.
+<DT><A HREF="KEAModelBuilder.html#setCheckForProperNouns(boolean)"><B>setCheckForProperNouns(boolean)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the M_CheckProperNouns value.
+<DT><A HREF="KEAFilter.html#setDebug(boolean)"><B>setDebug(boolean)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set the value of Debug.
+<DT><A HREF="KEAKeyphraseExtractor.html#setDebug(boolean)"><B>setDebug(boolean)</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Set the value of debug.
+<DT><A HREF="KEAModelBuilder.html#setDebug(boolean)"><B>setDebug(boolean)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the value of debug.
+<DT><A HREF="KEAKeyphraseExtractor.html#setDirName(java.lang.String)"><B>setDirName(String)</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Set the value of dirName.
+<DT><A HREF="KEAModelBuilder.html#setDirName(java.lang.String)"><B>setDirName(String)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the value of dirName.
+<DT><A HREF="KEAFilter.html#setDisallowInternalPeriods(boolean)"><B>setDisallowInternalPeriods(boolean)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set whether selected columns should be processed.
+<DT><A HREF="KEAPhraseFilter.html#setDisallowInternalPeriods(boolean)"><B>setDisallowInternalPeriods(boolean)</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Set whether selected columns should be processed.
+<DT><A HREF="KEAModelBuilder.html#setDisallowIPeriods(boolean)"><B>setDisallowIPeriods(boolean)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the value of disallowIPeriods.
+<DT><A HREF="KEAFilter.html#setDocumentAtt(int)"><B>setDocumentAtt(int)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set the value of DocumentAtt.
+<DT><A HREF="KEAKeyphraseExtractor.html#setEncoding(java.lang.String)"><B>setEncoding(String)</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Set the value of encoding.
+<DT><A HREF="KEAModelBuilder.html#setEncoding(java.lang.String)"><B>setEncoding(String)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the value of encoding.
+<DT><A HREF="KEAFilter.html#setInputFormat(weka.core.Instances)"><B>setInputFormat(Instances)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Sets the format of the input instances.
+<DT><A HREF="KEAPhraseFilter.html#setInputFormat(weka.core.Instances)"><B>setInputFormat(Instances)</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Sets the format of the input instances.
+<DT><A HREF="NumbersFilter.html#setInputFormat(weka.core.Instances)"><B>setInputFormat(Instances)</B></A> - 
+Method in class <A HREF="NumbersFilter.html">NumbersFilter</A>
+<DD>Sets the format of the input instances.
+<DT><A HREF="KEAPhraseFilter.html#setInvertSelection(boolean)"><B>setInvertSelection(boolean)</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Set whether selected columns should be processed.
+<DT><A HREF="KEAFilter.html#setKeyphrasesAtt(int)"><B>setKeyphrasesAtt(int)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set the value of KeyphrasesAtt.
+<DT><A HREF="KEAFilter.html#setKFused(boolean)"><B>setKFused(boolean)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Sets whether keyphrase frequency attribute is used.
+<DT><A HREF="KEAFilter.html#setMaxPhraseLength(int)"><B>setMaxPhraseLength(int)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set the value of MaxPhraseLength.
+<DT><A HREF="KEAModelBuilder.html#setMaxPhraseLength(int)"><B>setMaxPhraseLength(int)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the value of MaxPhraseLength.
+<DT><A HREF="KEAFilter.html#setMinNumOccur(int)"><B>setMinNumOccur(int)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set the value of MinNumOccur.
+<DT><A HREF="KEAModelBuilder.html#setMinNumOccur(int)"><B>setMinNumOccur(int)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the value of MinNumOccur.
+<DT><A HREF="KEAFilter.html#setMinPhraseLength(int)"><B>setMinPhraseLength(int)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set the value of MinPhraseLength.
+<DT><A HREF="KEAModelBuilder.html#setMinPhraseLength(int)"><B>setMinPhraseLength(int)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the value of MinPhraseLength.
+<DT><A HREF="KEAKeyphraseExtractor.html#setModelName(java.lang.String)"><B>setModelName(String)</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Set the value of modelName.
+<DT><A HREF="KEAModelBuilder.html#setModelName(java.lang.String)"><B>setModelName(String)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the value of modelName.
+<DT><A HREF="KEAKeyphraseExtractor.html#setNumPhrases(int)"><B>setNumPhrases(int)</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Set the value of numPhrases.
+<DT><A HREF="KEAFilter.html#setOptions(java.lang.String[])"><B>setOptions(String[])</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Parses a given list of options controlling the behaviour of this object.
+<DT><A HREF="KEAKeyphraseExtractor.html#setOptions(java.lang.String[])"><B>setOptions(String[])</B></A> - 
+Method in class <A HREF="KEAKeyphraseExtractor.html">KEAKeyphraseExtractor</A>
+<DD>Parses a given list of options controlling the behaviour of this object.
+<DT><A HREF="KEAModelBuilder.html#setOptions(java.lang.String[])"><B>setOptions(String[])</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Parses a given list of options controlling the behaviour of this object.
+<DT><A HREF="KEAPhraseFilter.html#setOptions(java.lang.String[])"><B>setOptions(String[])</B></A> - 
+Method in class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A>
+<DD>Parses a given list of options controlling the behaviour of this object.
+<DT><A HREF="KEAFilter.html#setStemmer(Stemmer)"><B>setStemmer(Stemmer)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set the Stemmer value.
+<DT><A HREF="KEAModelBuilder.html#setStemmer(Stemmer)"><B>setStemmer(Stemmer)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the Stemmer value.
+<DT><A HREF="KEAFilter.html#setStopwords(Stopwords)"><B>setStopwords(Stopwords)</B></A> - 
+Method in class <A HREF="KEAFilter.html">KEAFilter</A>
+<DD>Set the M_Stopwords value.
+<DT><A HREF="KEAModelBuilder.html#setStopwords(Stopwords)"><B>setStopwords(Stopwords)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the M_Stopwords value.
+<DT><A HREF="KEAModelBuilder.html#setUseKFrequency(boolean)"><B>setUseKFrequency(boolean)</B></A> - 
+Method in class <A HREF="KEAModelBuilder.html">KEAModelBuilder</A>
+<DD>Set the value of useKFrequency.
+<DT><A HREF="GermanStemmer.html#stem(java.lang.String)"><B>stem(String)</B></A> - 
+Method in class <A HREF="GermanStemmer.html">GermanStemmer</A>
+<DD>Stemms the given term to an unique <tt>discriminator</tt>.
+<DT><A HREF="IteratedLovinsStemmer.html#stem(java.lang.String)"><B>stem(String)</B></A> - 
+Method in class <A HREF="IteratedLovinsStemmer.html">IteratedLovinsStemmer</A>
+<DD>Iterated stemming of the given word.
+<DT><A HREF="LovinsStemmer.html#stem(java.lang.String)"><B>stem(String)</B></A> - 
+Method in class <A HREF="LovinsStemmer.html">LovinsStemmer</A>
+<DD>Returns the stemmed version of the given word.
+<DT><A HREF="Stemmer.html#stem(java.lang.String)"><B>stem(String)</B></A> - 
+Method in class <A HREF="Stemmer.html">Stemmer</A>
+<DD>Iterated stemming of the given word.
+<DT><A HREF="Stemmer.html"><B>Stemmer</B></A> - class <A HREF="Stemmer.html">Stemmer</A>.<DD>Abstract class for stemmers.<DT><A HREF="Stemmer.html#Stemmer()"><B>Stemmer()</B></A> - 
+Constructor for class <A HREF="Stemmer.html">Stemmer</A>
+<DD>&nbsp;
+<DT><A HREF="Stemmer.html#stemString(java.lang.String)"><B>stemString(String)</B></A> - 
+Method in class <A HREF="Stemmer.html">Stemmer</A>
+<DD>Stems everything in the given string.
+<DT><A HREF="Stopwords.html"><B>Stopwords</B></A> - class <A HREF="Stopwords.html">Stopwords</A>.<DD>Class that can test whether a given string is a stop word.<DT><A HREF="Stopwords.html#Stopwords()"><B>Stopwords()</B></A> - 
+Constructor for class <A HREF="Stopwords.html">Stopwords</A>
+<DD>&nbsp;
+<DT><A HREF="StopwordsEnglish.html"><B>StopwordsEnglish</B></A> - class <A HREF="StopwordsEnglish.html">StopwordsEnglish</A>.<DD>Class that can test whether a given string is a stop word.<DT><A HREF="StopwordsEnglish.html#StopwordsEnglish()"><B>StopwordsEnglish()</B></A> - 
+Constructor for class <A HREF="StopwordsEnglish.html">StopwordsEnglish</A>
+<DD>&nbsp;
+<DT><A HREF="StopwordsGerman.html"><B>StopwordsGerman</B></A> - class <A HREF="StopwordsGerman.html">StopwordsGerman</A>.<DD>Class that can test whether a given string is a stop word.<DT><A HREF="StopwordsGerman.html#StopwordsGerman()"><B>StopwordsGerman()</B></A> - 
+Constructor for class <A HREF="StopwordsGerman.html">StopwordsGerman</A>
+<DD>&nbsp;
+</DL>
+<HR>
+<A NAME="_T_"><!-- --></A><H2>
+<B>T</B></H2>
+<DL>
+<DT><A HREF="Counter.html#toString()"><B>toString()</B></A> - 
+Method in class <A HREF="Counter.html">Counter</A>
+<DD>Returns string containing value.
+</DL>
+<HR>
+<A NAME="_V_"><!-- --></A><H2>
+<B>V</B></H2>
+<DL>
+<DT><A HREF="Counter.html#value()"><B>value()</B></A> - 
+Method in class <A HREF="Counter.html">Counter</A>
+<DD>Gets the value.
+</DL>
+<HR>
+<A HREF="#_A_">A</A> <A HREF="#_B_">B</A> <A HREF="#_C_">C</A> <A HREF="#_D_">D</A> <A HREF="#_E_">E</A> <A HREF="#_G_">G</A> <A HREF="#_I_">I</A> <A HREF="#_K_">K</A> <A HREF="#_L_">L</A> <A HREF="#_M_">M</A> <A HREF="#_N_">N</A> <A HREF="#_S_">S</A> <A HREF="#_T_">T</A> <A HREF="#_V_">V</A> 
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Index</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="index-all.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/index.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/index.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/index.html	(revision 8815)
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:48 NZDT 2004-->
+<TITLE>
+Generated Documentation (Untitled)
+</TITLE>
+</HEAD>
+<FRAMESET cols="20%,80%">
+<FRAME src="allclasses-frame.html" name="packageFrame">
+<FRAME src="Counter.html" name="classFrame">
+</FRAMESET>
+<NOFRAMES>
+<H2>
+Frame Alert</H2>
+
+<P>
+This document is designed to be viewed using the frames feature. If you see this message, you are using a non-frame-capable web client.
+<BR>
+Link to<A HREF="Counter.html">Non-frame version.</A></NOFRAMES>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/overview-tree.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/overview-tree.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/overview-tree.html	(revision 8815)
@@ -0,0 +1,143 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:48 NZDT 2004 -->
+<TITLE>
+Class Hierarchy
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Class Hierarchy";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="overview-tree.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H2>
+Hierarchy For All Packages</H2>
+</CENTER>
+<H2>
+Class Hierarchy
+</H2>
+<UL>
+<LI TYPE="circle">class java.lang.Object<UL>
+<LI TYPE="circle">class <A HREF="Counter.html"><B>Counter</B></A> (implements java.io.Serializable)
+<LI TYPE="circle">class weka.filters.Filter (implements java.io.Serializable)
+<UL>
+<LI TYPE="circle">class <A HREF="KEAFilter.html"><B>KEAFilter</B></A> (implements weka.core.OptionHandler)
+<LI TYPE="circle">class <A HREF="KEAPhraseFilter.html"><B>KEAPhraseFilter</B></A> (implements weka.core.OptionHandler)
+<LI TYPE="circle">class <A HREF="NumbersFilter.html"><B>NumbersFilter</B></A></UL>
+<LI TYPE="circle">class <A HREF="KEAKeyphraseExtractor.html"><B>KEAKeyphraseExtractor</B></A> (implements weka.core.OptionHandler)
+<LI TYPE="circle">class <A HREF="KEAModelBuilder.html"><B>KEAModelBuilder</B></A> (implements weka.core.OptionHandler)
+<LI TYPE="circle">class <A HREF="Stemmer.html"><B>Stemmer</B></A> (implements java.io.Serializable)
+<UL>
+<LI TYPE="circle">class <A HREF="GermanStemmer.html"><B>GermanStemmer</B></A><LI TYPE="circle">class <A HREF="LovinsStemmer.html"><B>LovinsStemmer</B></A> (implements java.io.Serializable)
+<UL>
+<LI TYPE="circle">class <A HREF="IteratedLovinsStemmer.html"><B>IteratedLovinsStemmer</B></A></UL>
+</UL>
+<LI TYPE="circle">class <A HREF="Stopwords.html"><B>Stopwords</B></A> (implements java.io.Serializable)
+<UL>
+<LI TYPE="circle">class <A HREF="StopwordsEnglish.html"><B>StopwordsEnglish</B></A><LI TYPE="circle">class <A HREF="StopwordsGerman.html"><B>StopwordsGerman</B></A></UL>
+</UL>
+</UL>
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#FFFFFF" CLASS="NavBarCell1Rev"> &nbsp;<FONT CLASS="NavBarFont1Rev"><B>Tree</B></FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="overview-tree.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/package-list
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/package-list	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/package-list	(revision 8815)
@@ -0,0 +1,1 @@
+
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/packages.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/packages.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/packages.html	(revision 8815)
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:48 NZDT 2004 -->
+<TITLE>
+
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<BODY BGCOLOR="white">
+
+<BR>
+
+<BR>
+
+<BR>
+<CENTER>
+The front page has been relocated.Please see:
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="index.html">Frame version</A>
+<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<A HREF="Counter.html">Non-frame version.</A></CENTER>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/serialized-form.html
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/serialized-form.html	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/serialized-form.html	(revision 8815)
@@ -0,0 +1,604 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN""http://www.w3.org/TR/REC-html40/loose.dtd">
+<!--NewPage-->
+<HTML>
+<HEAD>
+<!-- Generated by javadoc on Fri Mar 19 17:50:50 NZDT 2004 -->
+<TITLE>
+Serialized Form
+</TITLE>
+<LINK REL ="stylesheet" TYPE="text/css" HREF="stylesheet.css" TITLE="Style">
+</HEAD>
+<SCRIPT>
+function asd()
+{
+parent.document.title="Serialized Form";
+}
+</SCRIPT>
+<BODY BGCOLOR="white" onload="asd();">
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_top"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_top_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="serialized-form.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+<CENTER>
+<H1>
+Serialized Form</H1>
+</CENTER>
+<A NAME="Counter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="Counter.html">Counter</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+<A NAME="serializedForm"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Serialized Fields</B></FONT></TD>
+</TR>
+</TABLE>
+
+<H3>
+m_val</H3>
+<PRE>
+int <B>m_val</B></PRE>
+<DL>
+<DD>Integer value stored
+<P>
+<DL>
+</DL>
+</DL>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="GermanStemmer"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="GermanStemmer.html">GermanStemmer</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+<A NAME="serializedForm"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Serialized Fields</B></FONT></TD>
+</TR>
+</TABLE>
+
+<H3>
+sb</H3>
+<PRE>
+java.lang.StringBuffer <B>sb</B></PRE>
+<DL>
+<DD>Buffer for the terms while stemming them.
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+uppercase</H3>
+<PRE>
+boolean <B>uppercase</B></PRE>
+<DL>
+<DD>Indicates if a term is handled as a noun.
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+substCount</H3>
+<PRE>
+int <B>substCount</B></PRE>
+<DL>
+<DD>Amount of characters that are removed with <tt>substitute()</tt> while stemming.
+<P>
+<DL>
+</DL>
+</DL>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="IteratedLovinsStemmer"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="IteratedLovinsStemmer.html">IteratedLovinsStemmer</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="KEAFilter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="KEAFilter.html">KEAFilter</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+<A NAME="serializedForm"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Serialized Fields</B></FONT></TD>
+</TR>
+</TABLE>
+
+<H3>
+m_DocumentAtt</H3>
+<PRE>
+int <B>m_DocumentAtt</B></PRE>
+<DL>
+<DD>Index of attribute containing the documents
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_KeyphrasesAtt</H3>
+<PRE>
+int <B>m_KeyphrasesAtt</B></PRE>
+<DL>
+<DD>Index of attribute containing the keyphrases
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_MaxPhraseLength</H3>
+<PRE>
+int <B>m_MaxPhraseLength</B></PRE>
+<DL>
+<DD>The maximum length of phrases
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_MinPhraseLength</H3>
+<PRE>
+int <B>m_MinPhraseLength</B></PRE>
+<DL>
+<DD>The minimum length of phrases
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_KFused</H3>
+<PRE>
+boolean <B>m_KFused</B></PRE>
+<DL>
+<DD>Is keyphrase frequency attribute being used?
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_Debug</H3>
+<PRE>
+boolean <B>m_Debug</B></PRE>
+<DL>
+<DD>Flag for debugging mode
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_DisallowInternalPeriods</H3>
+<PRE>
+boolean <B>m_DisallowInternalPeriods</B></PRE>
+<DL>
+<DD>Determines whether internal periods are allowed
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_MinNumOccur</H3>
+<PRE>
+int <B>m_MinNumOccur</B></PRE>
+<DL>
+<DD>The minimum number of occurences of a phrase
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_NumFeatures</H3>
+<PRE>
+int <B>m_NumFeatures</B></PRE>
+<DL>
+<DD>The number of features describing a phrase
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_TfidfIndex</H3>
+<PRE>
+int <B>m_TfidfIndex</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_FirstOccurIndex</H3>
+<PRE>
+int <B>m_FirstOccurIndex</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_KeyFreqIndex</H3>
+<PRE>
+int <B>m_KeyFreqIndex</B></PRE>
+<DL>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_PunctFilter</H3>
+<PRE>
+KEAPhraseFilter <B>m_PunctFilter</B></PRE>
+<DL>
+<DD>The punctuation filter used by this filter
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_NumbersFilter</H3>
+<PRE>
+NumbersFilter <B>m_NumbersFilter</B></PRE>
+<DL>
+<DD>The numbers filter used by this filter
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_Classifier</H3>
+<PRE>
+weka.classifiers.DistributionClassifier <B>m_Classifier</B></PRE>
+<DL>
+<DD>The actual classifier used to compute probabilities
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_Dictionary</H3>
+<PRE>
+java.util.HashMap <B>m_Dictionary</B></PRE>
+<DL>
+<DD>The dictionary containing the document frequencies
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_KeyphraseDictionary</H3>
+<PRE>
+java.util.HashMap <B>m_KeyphraseDictionary</B></PRE>
+<DL>
+<DD>The dictionary containing the keyphrases
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_NumDocs</H3>
+<PRE>
+int <B>m_NumDocs</B></PRE>
+<DL>
+<DD>The number of documents in the global frequencies corpus
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_ClassifierData</H3>
+<PRE>
+weka.core.Instances <B>m_ClassifierData</B></PRE>
+<DL>
+<DD>Template for the classifier data
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_Stemmer</H3>
+<PRE>
+Stemmer <B>m_Stemmer</B></PRE>
+<DL>
+<DD>The stemmer to be used
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_Stopwords</H3>
+<PRE>
+Stopwords <B>m_Stopwords</B></PRE>
+<DL>
+<DD>The list of stop words to be used
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_CheckForProperNouns</H3>
+<PRE>
+boolean <B>m_CheckForProperNouns</B></PRE>
+<DL>
+<DD>Determines whether check for proper nouns is performed
+<P>
+<DL>
+</DL>
+</DL>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="KEAPhraseFilter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="KEAPhraseFilter.html">KEAPhraseFilter</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+<A NAME="serializedForm"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableHeadingColor">
+<TD COLSPAN=1><FONT SIZE="+2">
+<B>Serialized Fields</B></FONT></TD>
+</TR>
+</TABLE>
+
+<H3>
+m_SelectCols</H3>
+<PRE>
+weka.core.Range <B>m_SelectCols</B></PRE>
+<DL>
+<DD>Stores which columns to select as a funky range
+<P>
+<DL>
+</DL>
+</DL>
+<HR>
+
+<H3>
+m_DisallowInternalPeriods</H3>
+<PRE>
+boolean <B>m_DisallowInternalPeriods</B></PRE>
+<DL>
+<DD>Determines whether internal periods are allowed
+<P>
+<DL>
+</DL>
+</DL>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="LovinsStemmer"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="LovinsStemmer.html">LovinsStemmer</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="NumbersFilter"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="NumbersFilter.html">NumbersFilter</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="Stemmer"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="Stemmer.html">Stemmer</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="Stopwords"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="Stopwords.html">Stopwords</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="StopwordsEnglish"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="StopwordsEnglish.html">StopwordsEnglish</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+
+<P>
+<HR SIZE="4" NOSHADE>
+<A NAME="StopwordsGerman"><!-- --></A>
+<TABLE BORDER="1" CELLPADDING="3" CELLSPACING="0" WIDTH="100%">
+<TR BGCOLOR="#CCCCFF" CLASS="TableSubHeadingColor">
+<TD COLSPAN=2><FONT SIZE="+2">
+<B>Class <A HREF="StopwordsGerman.html">StopwordsGerman</A> implements Serializable</B></FONT></TD>
+</TR>
+</TABLE>
+
+<P>
+
+<P>
+<HR>
+
+<!-- ========== START OF NAVBAR ========== -->
+<A NAME="navbar_bottom"><!-- --></A>
+<TABLE BORDER="0" WIDTH="100%" CELLPADDING="1" CELLSPACING="0">
+<TR>
+<TD COLSPAN=3 BGCOLOR="#EEEEFF" CLASS="NavBarCell1">
+<A NAME="navbar_bottom_firstrow"><!-- --></A>
+<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">
+  <TR ALIGN="center" VALIGN="top">
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Package</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <FONT CLASS="NavBarFont1">Class</FONT>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="overview-tree.html"><FONT CLASS="NavBarFont1"><B>Tree</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="deprecated-list.html"><FONT CLASS="NavBarFont1"><B>Deprecated</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="index-all.html"><FONT CLASS="NavBarFont1"><B>Index</B></FONT></A>&nbsp;</TD>
+  <TD BGCOLOR="#EEEEFF" CLASS="NavBarCell1">    <A HREF="help-doc.html"><FONT CLASS="NavBarFont1"><B>Help</B></FONT></A>&nbsp;</TD>
+  </TR>
+</TABLE>
+</TD>
+<TD ALIGN="right" VALIGN="top" ROWSPAN=3><EM>
+</EM>
+</TD>
+</TR>
+
+<TR>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+&nbsp;PREV&nbsp;
+&nbsp;NEXT</FONT></TD>
+<TD BGCOLOR="white" CLASS="NavBarCell2"><FONT SIZE="-2">
+  <A HREF="index.html" TARGET="_top"><B>FRAMES</B></A>  &nbsp;
+&nbsp;<A HREF="serialized-form.html" TARGET="_top"><B>NO FRAMES</B></A>  &nbsp;
+&nbsp;
+<SCRIPT>
+  <!--
+  if(window==top) {
+    document.writeln('<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>');
+  }
+  //-->
+</SCRIPT>
+<NOSCRIPT>
+<A HREF="allclasses-noframe.html" TARGET=""><B>All Classes</B></A>
+</NOSCRIPT>
+</FONT></TD>
+</TR>
+</TABLE>
+<!-- =========== END OF NAVBAR =========== -->
+
+<HR>
+
+</BODY>
+</HTML>
Index: /trunk/gsdl/packages/kea/kea-3.0/doc/stylesheet.css
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/doc/stylesheet.css	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/doc/stylesheet.css	(revision 8815)
@@ -0,0 +1,29 @@
+/* Javadoc style sheet */
+
+/* Define colors, fonts and other style attributes here to override the defaults */
+
+/* Page background color */
+body { background-color: #FFFFFF }
+
+/* Table colors */
+.TableHeadingColor     { background: #CCCCFF } /* Dark mauve */
+.TableSubHeadingColor  { background: #EEEEFF } /* Light mauve */
+.TableRowColor         { background: #FFFFFF } /* White */
+
+/* Font used in left-hand frame lists */
+.FrameTitleFont   { font-size: 10pts; font-family: Helvetica, Arial, san-serif }
+.FrameHeadingFont { font-size: 10pts; font-family: Helvetica, Arial, san-serif }
+.FrameItemFont    { font-size: 10pts; font-family: Helvetica, Arial, san-serif }
+
+/* Example of smaller, sans-serif font in frames */
+/* .FrameItemFont  { font-size: 10pt; font-family: Helvetica, Arial, sans-serif } */
+
+/* Navigation bar fonts and colors */
+.NavBarCell1    { background-color:#EEEEFF;}/* Light mauve */
+.NavBarCell1Rev { background-color:#00008B;}/* Dark Blue */
+.NavBarFont1    { font-family: Arial, Helvetica, sans-serif; color:#000000;}
+.NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;}
+
+.NavBarCell2    { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}
+.NavBarCell3    { font-family: Arial, Helvetica, sans-serif; background-color:#FFFFFF;}
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/Classifier.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/Classifier.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/Classifier.java	(revision 8815)
@@ -0,0 +1,115 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Classifier.java
+ *    Copyright (C) 1999 Eibe Frank, Len Trigg
+ *
+ */
+
+package weka.classifiers;
+
+import java.io.Serializable;
+import weka.core.Instance;
+import weka.core.Instances;
+import weka.core.SerializedObject;
+import weka.core.Utils;
+
+
+/** 
+ * Abstract classifier. All schemes for numeric or nominal prediction in
+ * Weka extend this class.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public abstract class Classifier implements Cloneable, Serializable {
+ 
+  /**
+   * Generates a classifier. Must initialize all fields of the classifier
+   * that are not being set via options (ie. multiple calls of buildClassifier
+   * must always lead to the same result). Must not change the dataset
+   * in any way.
+   *
+   * @param data set of instances serving as training data 
+   * @exception Exception if the classifier has not been 
+   * generated successfully
+   */
+  public abstract void buildClassifier(Instances data) throws Exception;
+
+  /**
+   * Classifies a given instance.
+   *
+   * @param instance the instance to be classified
+   * @return index of the predicted class as a double
+   * if the class is nominal, otherwise the predicted value
+   * @exception Exception if instance could not be classified
+   * successfully
+   */
+  public abstract double classifyInstance(Instance instance) throws Exception; 
+
+
+  
+  /**
+   * Creates a new instance of a classifier given it's class name and
+   * (optional) arguments to pass to it's setOptions method. If the
+   * classifier implements OptionHandler and the options parameter is
+   * non-null, the classifier will have it's options set.
+   *
+   * @param classifierName the fully qualified class name of the classifier
+   * @param options an array of options suitable for passing to setOptions. May
+   * be null.
+   * @return the newly created classifier, ready for use.
+   * @exception Exception if the classifier name is invalid, or the options
+   * supplied are not acceptable to the classifier
+   */
+  public static Classifier forName(String classifierName,
+				   String [] options) throws Exception {
+
+    return (Classifier)Utils.forName(Classifier.class,
+				     classifierName,
+				     options);
+  }
+
+  /**
+   * Creates copies of the current classifier, which can then
+   * be used for boosting etc. Note that this method now uses
+   * Serialization to perform a deep copy, so the Classifier
+   * object must be fully Serializable. Any currently built model
+   * will now be copied as well.
+   *
+   * @param model an example classifier to copy
+   * @param num the number of classifiers copies to create.
+   * @return an array of classifiers.
+   * @exception Exception if an error occurs
+   */
+  public static Classifier [] makeCopies(Classifier model,
+					 int num) throws Exception {
+
+    if (model == null) {
+      throw new Exception("No model classifier set");
+    }
+    Classifier [] classifiers = new Classifier [num];
+    SerializedObject so = new SerializedObject(model);
+    for(int i = 0; i < classifiers.length; i++) {
+      classifiers[i] = (Classifier) so.getObject();
+    }
+    return classifiers;
+  }
+
+}
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/DistributionClassifier.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/DistributionClassifier.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/DistributionClassifier.java	(revision 8815)
@@ -0,0 +1,92 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    DistributionClassifier.java
+ *    Copyright (C) 1999 Eibe Frank, Len Trigg
+ *
+ */
+
+package weka.classifiers;
+
+import weka.core.*;
+
+/** 
+ * Abstract classification model that produces (for each test instance)
+ * an estimate of the membership in each class 
+ * (ie. a probability distribution).
+ *
+ * @author   Eibe Frank (trigg@cs.waikato.ac.nz)
+ * @author   Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public abstract class DistributionClassifier extends Classifier {
+
+  /**
+   * Predicts the class memberships for a given instance. If
+   * an instance is unclassified, the returned array elements
+   * must be all zero. If the class is numeric, the array
+   * must consist of only one element, which contains the
+   * predicted value.
+   *
+   * @param instance the instance to be classified
+   * @return an array containing the estimated membership 
+   * probabilities of the test instance in each class (this 
+   * should sum to at most 1)
+   * @exception Exception if distribution could not be 
+   * computed successfully
+   */
+  public abstract double[] distributionForInstance(Instance instance) 
+       throws Exception;
+
+  /**
+   * Classifies the given test instance. The instance has to belong to a
+   * dataset when it's being classified.
+   *
+   * @param instance the instance to be classified
+   * @return the predicted most likely class for the instance or 
+   * Instance.missingValue() if no prediction is made
+   * @exception Exception if an error occurred during the prediction
+   */
+  public double classifyInstance(Instance instance) throws Exception {
+
+    double [] dist = distributionForInstance(instance);
+    if (dist == null) {
+      throw new Exception("Null distribution predicted");
+    }
+    switch (instance.classAttribute().type()) {
+    case Attribute.NOMINAL:
+      double max = 0;
+      int maxIndex = 0;
+      
+      for (int i = 0; i < dist.length; i++) {
+	if (dist[i] > max) {
+	  maxIndex = i;
+	  max = dist[i];
+	}
+      }
+      if (max > 0) {
+	return maxIndex;
+      } else {
+	return Instance.missingValue();
+      }
+    case Attribute.NUMERIC:
+      return dist[0];
+    default:
+      return Instance.missingValue();
+    }
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/FilteredClassifier.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/FilteredClassifier.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/FilteredClassifier.java	(revision 8815)
@@ -0,0 +1,374 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    FilteredClassifier.java
+ *    Copyright (C) 1999 Len Trigg
+ *
+ */
+
+package weka.classifiers;
+
+import java.util.Enumeration;
+import java.util.Vector;
+import weka.core.Instance;
+import weka.core.Instances;
+import weka.core.Option;
+import weka.core.OptionHandler;
+import weka.core.Utils;
+import weka.filters.Filter;
+import weka.core.Attribute;
+
+
+/**
+ * Class for running an arbitrary classifier on data that has been passed
+ * through an arbitrary filter.<p>
+ *
+ * Valid options from the command line are:<p>
+ *
+ * -B classifierstring <br>
+ * Classifierstring should contain the full class name of a classifier
+ * followed by options to the classifier.
+ * (required).<p>
+ *
+ * -F filterstring <br>
+ * Filterstring should contain the full class name of a filter
+ * followed by options to the filter.
+ * (required).<p>
+ *
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class FilteredClassifier extends DistributionClassifier
+  implements OptionHandler {
+
+  /** The classifier */
+  protected Classifier m_Classifier = new weka.classifiers.NaiveBayesSimple();
+
+  /** The filter */
+  protected Filter m_Filter = new weka.filters.DiscretizeFilter();
+
+  /** The instance structure of the filtered instances */
+  protected Instances m_FilteredInstances;
+  
+  /**
+   * Default constructor specifying NaiveBayesSimple as the classifier and
+   * DiscretizeFilter as the filter. Both of these are just placeholders
+   * for more useful selections.
+   */
+  public FilteredClassifier() {
+
+    this(new weka.classifiers.NaiveBayesSimple(), 
+	 new weka.filters.DiscretizeFilter());
+  }
+
+  /**
+   * Constructor that specifies the subclassifier and filter to use.
+   *
+   * @param classifier the Classifier to receive filtered instances.
+   * @param filter the Filter that will process instances before
+   * passing to the Classifier.
+   */
+  public FilteredClassifier(Classifier classifier, Filter filter) {
+
+    m_Classifier = classifier;
+    m_Filter = filter;
+  }
+
+  /**
+   * Returns an enumeration describing the available options
+   *
+   * @return an enumeration of all the available options
+   */
+  public Enumeration listOptions() {
+
+    Vector newVector = new Vector(2);
+
+    newVector.addElement(new Option(
+	      "\tFull class name of classifier to use, followed\n"
+	      + "\tby scheme options. (required)\n"
+	      + "\teg: \"weka.classifiers.NaiveBayes -D\"",
+	      "B", 1, "-B <classifier specification>"));
+    newVector.addElement(new Option(
+	      "\tFull class name of filter to use, followed\n"
+	      + "\tby filter options. (required)\n"
+	      + "\teg: \"weka.filters.AttributeFilter -V -R 1,2\"",
+	      "F", 1, "-F <filter specification>"));
+    return newVector.elements();
+  }
+
+  /**
+   * Parses a given list of options. Valid options are:<p>
+   *
+   * -B classifierstring <br>
+   * Classifierstring should contain the full class name of a classifier
+   * followed by options to the classifier.
+   * (required).<p>
+   *
+   * -F filterstring <br>
+   * Filterstring should contain the full class name of a filter
+   * followed by options to the filter.
+   * (required).<p>
+   *
+   * @param options the list of options as an array of strings
+   * @exception Exception if an option is not supported
+   */
+  public void setOptions(String[] options) throws Exception {
+
+    String classifierString = Utils.getOption('B', options);
+    if (classifierString.length() == 0) {
+      throw new Exception("A classifier must be specified"
+			  + " with the -B option.");
+    }
+    String [] classifierSpec = Utils.splitOptions(classifierString);
+    if (classifierSpec.length == 0) {
+      throw new Exception("Invalid classifier specification string");
+    }
+    String classifierName = classifierSpec[0];
+    classifierSpec[0] = "";
+    setClassifier(Classifier.forName(classifierName, classifierSpec));
+    
+    // Same for filter
+    String filterString = Utils.getOption('F', options);
+    if (filterString.length() == 0) {
+      throw new Exception("A filter must be specified"
+			  + " with the -F option.");
+    }
+    String [] filterSpec = Utils.splitOptions(filterString);
+    if (filterSpec.length == 0) {
+      throw new Exception("Invalid filter specification string");
+    }
+    String filterName = filterSpec[0];
+    filterSpec[0] = "";
+    setFilter((Filter) Utils.forName(Filter.class, filterName, filterSpec));
+  }
+
+  /**
+   * Gets the current settings of the Classifier.
+   *
+   * @return an array of strings suitable for passing to setOptions
+   */
+  public String [] getOptions() {
+
+    String [] options = new String [4];
+    int current = 0;
+
+    options[current++] = "-B";
+    options[current++] = "" + getClassifierSpec();
+
+    // Same for filter
+    options[current++] = "-F";
+    options[current++] = "" + getFilterSpec();
+    
+    while (current < options.length) {
+      options[current++] = "";
+    }
+    return options;
+  }
+
+  /**
+   * Sets the classifier
+   *
+   * @param classifier the classifier with all options set.
+   */
+  public void setClassifier(Classifier classifier) {
+
+    m_Classifier = classifier;
+  }
+
+  /**
+   * Gets the classifier used.
+   *
+   * @return the classifier
+   */
+  public Classifier getClassifier() {
+
+    return m_Classifier;
+  }
+  
+  /**
+   * Gets the classifier specification string, which contains the class name of
+   * the classifier and any options to the classifier
+   *
+   * @return the classifier string.
+   */
+  protected String getClassifierSpec() {
+    
+    Classifier c = getClassifier();
+    if (c instanceof OptionHandler) {
+      return c.getClass().getName() + " "
+	+ Utils.joinOptions(((OptionHandler)c).getOptions());
+    }
+    return c.getClass().getName();
+  }
+
+  /**
+   * Sets the filter
+   *
+   * @param filter the filter with all options set.
+   */
+  public void setFilter(Filter filter) {
+
+    m_Filter = filter;
+  }
+
+  /**
+   * Gets the filter used.
+   *
+   * @return the filter
+   */
+  public Filter getFilter() {
+
+    return m_Filter;
+  }
+  
+  /**
+   * Gets the filter specification string, which contains the class name of
+   * the filter and any options to the filter
+   *
+   * @return the filter string.
+   */
+  protected String getFilterSpec() {
+    
+    Filter c = getFilter();
+    if (c instanceof OptionHandler) {
+      return c.getClass().getName() + " "
+	+ Utils.joinOptions(((OptionHandler)c).getOptions());
+    }
+    return c.getClass().getName();
+  }
+
+  /**
+   * Build the classifier on the filtered data.
+   *
+   * @param data the training data
+   * @exception Exception if the classifier could not be built successfully
+   */
+  public void buildClassifier(Instances data) throws Exception {
+
+    if (m_Classifier == null) {
+      throw new Exception("No base classifiers have been set!");
+    }
+    /*
+    String fname = m_Filter.getClass().getName();
+    fname = fname.substring(fname.lastIndexOf('.') + 1);
+    util.Timer t = util.Timer.getTimer("FilteredClassifier::" + fname);
+    t.start();
+    */
+    m_Filter.setInputFormat(data);
+    data = Filter.useFilter(data, m_Filter);
+    //t.stop();
+    m_FilteredInstances = data.stringFreeStructure();
+    m_Classifier.buildClassifier(data);
+  }
+
+  /**
+   * Classifies a given instance after filtering.
+   *
+   * @param instance the instance to be classified
+   * @exception Exception if instance could not be classified
+   * successfully
+   */
+  public double [] distributionForInstance(Instance instance)
+    throws Exception {
+
+    /*
+      System.err.println("FilteredClassifier:: " 
+                         + m_Filter.getClass().getName()
+                         + " in: " + instance);
+    */
+    if (m_Filter.numPendingOutput() > 0) {
+      throw new Exception("Filter output queue not empty!");
+    }
+    /*
+    String fname = m_Filter.getClass().getName();
+    fname = fname.substring(fname.lastIndexOf('.') + 1);
+    util.Timer t = util.Timer.getTimer("FilteredClassifier::" + fname);
+    t.start();
+    */
+    if (!m_Filter.input(instance)) {
+      throw new Exception("Filter didn't make the test instance"
+			  + " immediately available!");
+    }
+    m_Filter.batchFinished();
+    Instance newInstance = m_Filter.output();
+    //t.stop();
+    /*
+    System.err.println("FilteredClassifier:: " 
+                       + m_Filter.getClass().getName()
+                       + " out: " + newInstance);
+    */
+    if (m_Classifier instanceof DistributionClassifier) {
+      return ((DistributionClassifier)m_Classifier)
+	.distributionForInstance(newInstance);
+    }
+    double pred = m_Classifier.classifyInstance(newInstance);
+    double [] result = new double [m_FilteredInstances.numClasses()];
+    if (Instance.isMissingValue(pred)) {
+      return result;
+    }
+    switch (instance.classAttribute().type()) {
+    case Attribute.NOMINAL:
+      result[(int) pred] = 1.0;
+      break;
+    case Attribute.NUMERIC:
+      result[0] = pred;
+      break;
+    default:
+      throw new Exception("Unknown class type");
+    }
+    return result;
+  }
+
+  /**
+   * Output a representation of this classifier
+   */
+  public String toString() {
+
+    if (m_FilteredInstances == null) {
+      return "FilteredClassifier: No model built yet.";
+    }
+
+    String result = "FilteredClassifier using "
+      + getClassifierSpec()
+      + " on data filtered through "
+      + getFilterSpec()
+      + "\n\nFiltered Header\n"
+      + m_FilteredInstances.toString()
+      + "\n\nClassifier Model\n"
+      + m_Classifier.toString();
+    return result;
+  }
+
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param argv should contain the following arguments:
+   * -t training file [-T test file] [-c class index]
+   */
+  public static void main(String [] argv) {
+
+    try {
+      System.out.println("Evaluation disabled!");
+      //System.out.println(Evaluation.evaluateModel(new FilteredClassifier(),
+      //					  argv));
+    } catch (Exception e) {
+      System.err.println(e.getMessage());
+    }
+  }
+
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/NaiveBayesSimple.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/NaiveBayesSimple.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/classifiers/NaiveBayesSimple.java	(revision 8815)
@@ -0,0 +1,331 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    NaiveBayesSimple.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.classifiers;
+
+import java.io.*;
+import java.util.*;
+import weka.core.*;
+
+/**
+ * Class for building and using a simple Naive Bayes classifier.
+ * Numeric attributes are modelled by a normal distribution. For more
+ * information, see<p>
+ *
+ * Richard Duda and Peter Hart (1973).<i>Pattern
+ * Classification and Scene Analysis</i>. Wiley, New York.
+
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$ 
+*/
+public class NaiveBayesSimple extends DistributionClassifier {
+
+  /** All the counts for nominal attributes. */
+  private double [][][] m_Counts;
+  
+  /** The means for numeric attributes. */
+  private double [][] m_Means;
+
+  /** The standard deviations for numeric attributes. */
+  private double [][] m_Devs;
+
+  /** The prior probabilities of the classes. */
+  private double [] m_Priors;
+
+  /** The instances used for training. */
+  private Instances m_Instances;
+
+  /** Constant for normal distribution. */
+  private static double NORM_CONST = Math.sqrt(2 * Math.PI);
+
+  /**
+   * Generates the classifier.
+   *
+   * @param instances set of instances serving as training data 
+   * @exception Exception if the classifier has not been generated successfully
+   */
+  public void buildClassifier(Instances instances) throws Exception {
+
+    int attIndex = 0;
+    double sum;
+    
+    if (instances.checkForStringAttributes()) {
+      throw new Exception("Can't handle string attributes!");
+    }
+    if (instances.classAttribute().isNumeric()) {
+      throw new Exception("Naive Bayes: Class is numeric!");
+    }
+    
+    m_Instances = new Instances(instances, 0);
+    
+    // Reserve space
+    m_Counts = new double[instances.numClasses()]
+      [instances.numAttributes() - 1][0];
+    m_Means = new double[instances.numClasses()]
+      [instances.numAttributes() - 1];
+    m_Devs = new double[instances.numClasses()]
+      [instances.numAttributes() - 1];
+    m_Priors = new double[instances.numClasses()];
+    Enumeration enum = instances.enumerateAttributes();
+    while (enum.hasMoreElements()) {
+      Attribute attribute = (Attribute) enum.nextElement();
+      if (attribute.isNominal()) {
+	for (int j = 0; j < instances.numClasses(); j++) {
+	  m_Counts[j][attIndex] = new double[attribute.numValues()];
+	}
+      } else {
+	for (int j = 0; j < instances.numClasses(); j++) {
+	  m_Counts[j][attIndex] = new double[1];
+	}
+      }
+      attIndex++;
+    }
+    
+    // Compute counts and sums
+    Enumeration enumInsts = instances.enumerateInstances();
+    while (enumInsts.hasMoreElements()) {
+      Instance instance = (Instance) enumInsts.nextElement();
+      if (!instance.classIsMissing()) {
+	Enumeration enumAtts = instances.enumerateAttributes();
+	attIndex = 0;
+	while (enumAtts.hasMoreElements()) {
+	  Attribute attribute = (Attribute) enumAtts.nextElement();
+	  if (!instance.isMissing(attribute)) {
+	    if (attribute.isNominal()) {
+	      m_Counts[(int)instance.classValue()][attIndex]
+		[(int)instance.value(attribute)]++;
+	    } else {
+	      m_Means[(int)instance.classValue()][attIndex] +=
+		instance.value(attribute);
+	      m_Counts[(int)instance.classValue()][attIndex][0]++;
+	    }
+	  }
+	  attIndex++;
+	}
+	m_Priors[(int)instance.classValue()]++;
+      }
+    }
+    
+    // Compute means
+    Enumeration enumAtts = instances.enumerateAttributes();
+    attIndex = 0;
+    while (enumAtts.hasMoreElements()) {
+      Attribute attribute = (Attribute) enumAtts.nextElement();
+      if (attribute.isNumeric()) {
+	for (int j = 0; j < instances.numClasses(); j++) {
+	  if (m_Counts[j][attIndex][0] < 2) {
+	    throw new Exception("attribute " + attribute.name() +
+				": less than two values for class " +
+				instances.classAttribute().value(j));
+	  }
+	  m_Means[j][attIndex] /= m_Counts[j][attIndex][0];
+	}
+      }
+      attIndex++;
+    }    
+    
+    // Compute standard deviations
+    enumInsts = instances.enumerateInstances();
+    while (enumInsts.hasMoreElements()) {
+      Instance instance = 
+	(Instance) enumInsts.nextElement();
+      if (!instance.classIsMissing()) {
+	enumAtts = instances.enumerateAttributes();
+	attIndex = 0;
+	while (enumAtts.hasMoreElements()) {
+	  Attribute attribute = (Attribute) enumAtts.nextElement();
+	  if (!instance.isMissing(attribute)) {
+	    if (attribute.isNumeric()) {
+	      m_Devs[(int)instance.classValue()][attIndex] +=
+		(m_Means[(int)instance.classValue()][attIndex]-
+		 instance.value(attribute))*
+		(m_Means[(int)instance.classValue()][attIndex]-
+		 instance.value(attribute));
+	    }
+	  }
+	  attIndex++;
+	}
+      }
+    }
+    enumAtts = instances.enumerateAttributes();
+    attIndex = 0;
+    while (enumAtts.hasMoreElements()) {
+      Attribute attribute = (Attribute) enumAtts.nextElement();
+      if (attribute.isNumeric()) {
+	for (int j = 0; j < instances.numClasses(); j++) {
+	  if (m_Devs[j][attIndex] <= 0) {
+	    throw new Exception("attribute " + attribute.name() +
+				": standard deviation is 0 for class " +
+				instances.classAttribute().value(j));
+	  }
+	  else {
+	    m_Devs[j][attIndex] /= m_Counts[j][attIndex][0] - 1;
+	    m_Devs[j][attIndex] = Math.sqrt(m_Devs[j][attIndex]);
+	  }
+	}
+      }
+      attIndex++;
+    } 
+    
+    // Normalize counts
+    enumAtts = instances.enumerateAttributes();
+    attIndex = 0;
+    while (enumAtts.hasMoreElements()) {
+      Attribute attribute = (Attribute) enumAtts.nextElement();
+      if (attribute.isNominal()) {
+	for (int j = 0; j < instances.numClasses(); j++) {
+	  sum = Utils.sum(m_Counts[j][attIndex]);
+	  for (int i = 0; i < attribute.numValues(); i++) {
+	    m_Counts[j][attIndex][i] =
+	      (m_Counts[j][attIndex][i] + 1) 
+	      / (sum + (double)attribute.numValues());
+	  }
+	}
+      }
+      attIndex++;
+    }
+    
+    // Normalize priors
+    sum = Utils.sum(m_Priors);
+    for (int j = 0; j < instances.numClasses(); j++)
+      m_Priors[j] = (m_Priors[j] + 1) 
+	/ (sum + (double)instances.numClasses());
+  }
+
+  /**
+   * Calculates the class membership probabilities for the given test instance.
+   *
+   * @param instance the instance to be classified
+   * @return predicted class probability distribution
+   * @exception Exception if distribution can't be computed
+   */
+  public double[] distributionForInstance(Instance instance) throws Exception {
+    
+    double [] probs = new double[instance.numClasses()];
+    int attIndex;
+    
+    for (int j = 0; j < instance.numClasses(); j++) {
+      probs[j] = 1;
+      Enumeration enumAtts = instance.enumerateAttributes();
+      attIndex = 0;
+      while (enumAtts.hasMoreElements()) {
+	Attribute attribute = (Attribute) enumAtts.nextElement();
+	if (!instance.isMissing(attribute)) {
+	  if (attribute.isNominal()) {
+	    probs[j] *= m_Counts[j][attIndex][(int)instance.value(attribute)];
+	  } else {
+	    probs[j] *= normalDens(instance.value(attribute),
+				   m_Means[j][attIndex],
+				   m_Devs[j][attIndex]);}
+	}
+	attIndex++;
+      }
+      probs[j] *= m_Priors[j];
+    }
+    
+    // Normalize probabilities
+    Utils.normalize(probs);
+
+    return probs;
+  }
+
+  /**
+   * Returns a description of the classifier.
+   *
+   * @return a description of the classifier as a string.
+   */
+  public String toString() {
+
+    if (m_Instances == null) {
+      return "Naive Bayes (simple): No model built yet.";
+    }
+    try {
+      StringBuffer text = new StringBuffer("Naive Bayes (simple)");
+      int attIndex;
+      
+      for (int i = 0; i < m_Instances.numClasses(); i++) {
+	text.append("\n\nClass " + m_Instances.classAttribute().value(i) 
+		    + ": P(C) = " 
+		    + Utils.doubleToString(m_Priors[i], 10, 8)
+		    + "\n\n");
+	Enumeration enumAtts = m_Instances.enumerateAttributes();
+	attIndex = 0;
+	while (enumAtts.hasMoreElements()) {
+	  Attribute attribute = (Attribute) enumAtts.nextElement();
+	  text.append("Attribute " + attribute.name() + "\n");
+	  if (attribute.isNominal()) {
+	    for (int j = 0; j < attribute.numValues(); j++) {
+	      text.append(attribute.value(j) + "\t");
+	    }
+	    text.append("\n");
+	    for (int j = 0; j < attribute.numValues(); j++)
+	      text.append(Utils.
+			  doubleToString(m_Counts[i][attIndex][j], 10, 8)
+			  + "\t");
+	  } else {
+	    text.append("Mean: " + Utils.
+			doubleToString(m_Means[i][attIndex], 10, 8) + "\t");
+	    text.append("Standard Deviation: " 
+			+ Utils.doubleToString(m_Devs[i][attIndex], 10, 8));
+	  }
+	  text.append("\n\n");
+	  attIndex++;
+	}
+      }
+      
+      return text.toString();
+    } catch (Exception e) {
+      return "Can't print Naive Bayes classifier!";
+    }
+  }
+
+  /**
+   * Density function of normal distribution.
+   */
+  private double normalDens(double x, double mean, double stdDev) {
+    
+    double diff = x - mean;
+    
+    return (1 / (NORM_CONST * stdDev)) 
+      * Math.exp(-(diff * diff / (2 * stdDev * stdDev)));
+  }
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param argv the options
+   */
+  public static void main(String [] argv) {
+
+    Classifier scheme;
+
+    try {
+      scheme = new NaiveBayesSimple();
+      System.out.println("Evaluation disabled!");
+      //System.out.println(Evaluation.evaluateModel(scheme, argv));
+    } catch (Exception e) {
+      System.err.println(e.getMessage());
+    }
+  }
+}
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/Attribute.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/Attribute.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/Attribute.java	(revision 8815)
@@ -0,0 +1,682 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Attribute.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+import java.io.*;
+import java.util.*;
+
+/** 
+ * Class for handling an attribute. Once an attribute has been created,
+ * it can't be changed. <p>
+ *
+ * Three attribute types are supported:
+ * <ul>
+ *    <li> numeric: <ul>
+ *         This type of attribute represents a floating-point number.
+ *    </ul>
+ *    <li> nominal: <ul>
+ *         This type of attribute represents a fixed set of nominal values.
+ *    </ul>
+ *    <li> string: <ul>
+ *         This type of attribute represents a dynamically expanding set of
+ *         nominal values. String attributes are not used by the learning
+ *         schemes in Weka. They can be used, for example,  to store an 
+ *         identifier with each instance in a dataset.
+ *    </ul>
+ * </ul>
+ * Typical usage (code from the main() method of this class): <p>
+ *
+ * <code>
+ * ... <br>
+ *
+ * // Create numeric attributes "length" and "weight" <br>
+ * Attribute length = new Attribute("length"); <br>
+ * Attribute weight = new Attribute("weight"); <br><br>
+ * 
+ * // Create vector to hold nominal values "first", "second", "third" <br>
+ * FastVector my_nominal_values = new FastVector(3); <br>
+ * my_nominal_values.addElement("first"); <br>
+ * my_nominal_values.addElement("second"); <br>
+ * my_nominal_values.addElement("third"); <br><br>
+ *
+ * // Create nominal attribute "position" <br>
+ * Attribute position = new Attribute("position", my_nominal_values);<br>
+ *
+ * ... <br>
+ * </code><p>
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class Attribute implements Copyable, Serializable {
+
+  /** Constant set for numeric attributes. */
+  public final static int NUMERIC = 0;
+
+  /** Constant set for nominal attributes. */
+  public final static int NOMINAL = 1;
+
+  /** Constant set for attributes with string values. */
+  public final static int STRING = 2;
+
+  /** Strings longer than this will be stored compressed. */
+  private final static int STRING_COMPRESS_THRESHOLD = 200;
+  //private final static int STRING_COMPRESS_THRESHOLD = Integer.MAX_VALUE;
+
+  /** The attribute's name. */
+  private String m_Name;
+
+  /** The attribute's type. */
+  private int m_Type;
+
+  /** The attribute's values (if nominal or string). */
+  private FastVector m_Values;
+
+  /** Mapping of values to indices (if nominal or string). */
+  private Hashtable m_Hashtable;
+
+  /** The attribute's index. */
+  private int m_Index;
+
+  /**
+   * Constructor for a numeric attribute.
+   *
+   * @param attributeName the name for the attribute
+   */
+  public Attribute(String attributeName) {
+
+    m_Name = attributeName;
+    m_Index = -1;
+    m_Values = null;
+    m_Hashtable = null;
+    m_Type = NUMERIC;
+  }
+
+  /**
+   * Constructor for nominal attributes and string attributes.
+   * If a null vector of attribute values is passed to the method,
+   * the attribute is assumed to be a string.
+   *
+   * @param attributeName the name for the attribute
+   * @param attributeValues a vector of strings denoting the 
+   * attribute values. Null if the attribute is a string attribute.
+   */
+  public Attribute(String attributeName, 
+		   FastVector attributeValues) {
+
+    m_Name = attributeName;
+    m_Index = -1;
+    if (attributeValues == null) {
+      m_Values = new FastVector();
+      m_Hashtable = new Hashtable();
+      m_Type = STRING;
+    } else {
+      m_Values = (FastVector) attributeValues.copy();
+      m_Hashtable = new Hashtable(m_Values.size());
+      for (int i = 0; i < m_Values.size(); i++) {
+	m_Hashtable.put(m_Values.elementAt(i), new Integer(i));
+      }
+      m_Type = NOMINAL;
+    }
+  }
+
+  /**
+   * Produces a shallow copy of this attribute.
+   *
+   * @return a copy of this attribute with the same index
+   */
+  public Object copy() {
+
+    Attribute copy = new Attribute(m_Name);
+
+    copy.m_Index = m_Index;
+    if (!isNominal() && !isString())
+      return copy;
+    copy.m_Type = m_Type;
+    copy.m_Values = m_Values;
+    copy.m_Hashtable = m_Hashtable;
+ 
+    return copy;
+  }
+
+  /**
+   * Returns an enumeration of all the attribute's values if
+   * the attribute is nominal or a string, null otherwise. 
+   *
+   * @return enumeration of all the attribute's values
+   */
+  public final Enumeration enumerateValues() {
+
+    if (isNominal() || isString()) {
+      final Enumeration ee = m_Values.elements();
+      return new Enumeration () {
+          public boolean hasMoreElements() {
+            return ee.hasMoreElements();
+          }
+          public Object nextElement() {
+            Object oo = ee.nextElement();
+            if (oo instanceof SerializedObject) {
+              return ((SerializedObject)oo).getObject();
+            } else {
+              return oo;
+            }
+          }
+        };
+    }
+    return null;
+  }
+
+  /**
+   * Tests if given attribute is equal to this attribute.
+   *
+   * @param other the Object to be compared to this attribute
+   * @return true if the given attribute is equal to this attribute
+   */
+  public final boolean equals(Object other) {
+
+    if ((other == null) || !(other.getClass().equals(this.getClass()))) {
+      return false;
+    }
+    Attribute att = (Attribute) other;
+    if (!m_Name.equals(att.m_Name)) {
+      return false;
+    }
+    if (isNumeric() && att.isNumeric()) {
+      return true;
+    }
+    if (isNumeric() || att.isNumeric()) {
+      return false;
+    }
+    if (m_Values.size() != att.m_Values.size()) {
+      return false;
+    }
+    for (int i = 0; i < m_Values.size(); i++) {
+      if (!m_Values.elementAt(i).equals(att.m_Values.elementAt(i))) {
+	return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Returns the index of this attribute.
+   *
+   * @return the index of this attribute
+   */
+  public final int index() {
+
+    return m_Index;
+  }
+
+  /**
+   * Returns the index of a given attribute value. (The index of
+   * the first occurence of this value.)
+   *
+   * @param value the value for which the index is to be returned
+   * @return the index of the given attribute value if attribute
+   * is nominal or a string, -1 if it is numeric or the value 
+   * can't be found
+   */
+  public final int indexOfValue(String value) {
+
+    if (!isNominal() && !isString())
+      return -1;
+    Object store = value;
+    if (value.length() > STRING_COMPRESS_THRESHOLD) {
+      try {
+        store = new SerializedObject(value, true);
+      } catch (Exception ex) {
+        System.err.println("Couldn't compress string attribute value -"
+                           + " searching uncompressed.");
+      }
+    }
+    Integer val = (Integer)m_Hashtable.get(store);
+    if (val == null) {
+      throw new IllegalArgumentException("Value \"" + value + 
+					 "\" not found in attribute " +
+					 "declaration!");
+    } else {
+      return val.intValue();
+    }
+  }
+
+  /**
+   * Test if the attribute is nominal.
+   *
+   * @return true if the attribute is nominal
+   */
+  public final boolean isNominal() {
+
+    return (m_Type == NOMINAL);
+  }
+
+  /**
+   * Tests if the attribute is numeric.
+   *
+   * @return true if the attribute is numeric
+   */
+  public final boolean isNumeric() {
+
+    return (m_Type == NUMERIC);
+  }
+
+  /**
+   * Tests if the attribute is a string.
+   *
+   * @return true if the attribute is a string
+   */
+  public final boolean isString() {
+
+    return (m_Type == STRING);
+  }
+
+  /**
+   * Returns the attribute's name.
+   *
+   * @return the attribute's name as a string
+   */
+  public final String name() {
+
+    return m_Name;
+  }
+  
+  /**
+   * Returns the number of attribute values. Returns 0 for numeric attributes.
+   *
+   * @return the number of attribute values
+   */
+  public final int numValues() {
+
+    if (!isNominal() && !isString()) {
+      return 0;
+    } else {
+      return m_Values.size();
+    }
+  }
+
+  /**
+   * Returns a description of this attribute in ARFF format. Quotes
+   * strings if they contain whitespace characters, or if they
+   * are a question mark.
+   *
+   * @return a description of this attribute as a string
+   */
+  public final String toString() {
+    
+    StringBuffer text = new StringBuffer();
+    
+    text.append("@attribute " + Utils.quote(m_Name) + " ");
+    if (isNominal()) {
+      text.append('{');
+      Enumeration enum = enumerateValues();
+      while (enum.hasMoreElements()) {
+	text.append(Utils.quote((String) enum.nextElement()));
+	if (enum.hasMoreElements())
+	  text.append(',');
+      }
+      text.append('}');
+    } else {
+      if (isNumeric()) {
+	text.append("numeric");
+      } else {
+	text.append("string");
+      }
+    }
+    return text.toString();
+  }
+
+  /**
+   * Returns the attribute's type as an integer.
+   *
+   * @returns the attribute's type.
+   */
+  public final int type() {
+
+    return m_Type;
+  }
+
+  /**
+   * Returns a value of a nominal or string attribute. 
+   * Returns an empty string if the attribute is neither
+   * nominal nor a string attribute.
+   *
+   * @param valIndex the value's index
+   * @return the attribute's value as a string
+   */
+  public final String value(int valIndex) {
+    
+    if (!isNominal() && !isString()) {
+      return "";
+    } else {
+      Object val = m_Values.elementAt(valIndex);
+      
+      // If we're storing strings compressed, uncompress it.
+      if (val instanceof SerializedObject) {
+        val = ((SerializedObject)val).getObject();
+      }
+      return (String) val;
+    }
+  }
+
+  /**
+   * Constructor for a numeric attribute with a particular index.
+   *
+   * @param attributeName the name for the attribute
+   * @param index the attribute's index
+   */
+  Attribute(String attributeName, int index) {
+
+    this(attributeName);
+
+    m_Index = index;
+  }
+
+  /**
+   * Constructor for nominal attributes and string attributes with
+   * a particular index.
+   * If a null vector of attribute values is passed to the method,
+   * the attribute is assumed to be a string.
+   *
+   * @param attributeName the name for the attribute
+   * @param attributeValues a vector of strings denoting the attribute values.
+   * Null if the attribute is a string attribute.
+   * @param index the attribute's index
+   */
+  Attribute(String attributeName, FastVector attributeValues, 
+	    int index) {
+
+    this(attributeName, attributeValues);
+
+    m_Index = index;
+  }
+
+  /**
+   * Adds a string value to the list of valid strings for attributes
+   * of type STRING and returns the index of the string.
+   *
+   * @param value The string value to add
+   * @return the index assigned to the string, or -1 if the attribute is not
+   * of type Attribute.STRING 
+   */
+  public int addStringValue(String value) {
+
+    if (!isString()) {
+      return -1;
+    }
+    Object store = value;
+
+    if (value.length() > STRING_COMPRESS_THRESHOLD) {
+      try {
+        store = new SerializedObject(value, true);
+      } catch (Exception ex) {
+        System.err.println("Couldn't compress string attribute value -"
+                           + " storing uncompressed.");
+      }
+    }
+    Integer index = (Integer)m_Hashtable.get(store);
+    if (index != null) {
+      return index.intValue();
+    } else {
+      int intIndex = m_Values.size();
+      m_Values.addElement(store);
+      m_Hashtable.put(store, new Integer(intIndex));
+      return intIndex;
+    }
+  }
+
+  /**
+   * Adds a string value to the list of valid strings for attributes
+   * of type STRING and returns the index of the string. This method is
+   * more efficient than addStringValue(String) for long strings.
+   *
+   * @param src The Attribute containing the string value to add.
+   * @param int index the index of the string value in the source attribute.
+   * @return the index assigned to the string, or -1 if the attribute is not
+   * of type Attribute.STRING 
+   */
+  public int addStringValue(Attribute src, int index) {
+
+    if (!isString()) {
+      return -1;
+    }
+    Object store = src.m_Values.elementAt(index);
+    Integer oldIndex = (Integer)m_Hashtable.get(store);
+    if (oldIndex != null) {
+      return oldIndex.intValue();
+    } else {
+      int intIndex = m_Values.size();
+      m_Values.addElement(store);
+      m_Hashtable.put(store, new Integer(intIndex));
+      return intIndex;
+    }
+  }
+
+  /**
+   * Adds an attribute value. Creates a fresh list of attribute
+   * values before adding it.
+   *
+   * @param value the attribute value
+   */
+  final void addValue(String value) {
+
+    m_Values = (FastVector)m_Values.copy();
+    m_Hashtable = (Hashtable)m_Hashtable.clone();
+    forceAddValue(value);
+  }
+
+  /**
+   * Produces a shallow copy of this attribute with a new name.
+   *
+   * @param newName the name of the new attribute
+   * @return a copy of this attribute with the same index
+   */
+  final Attribute copy(String newName) {
+
+    Attribute copy = new Attribute(newName);
+
+    copy.m_Index = m_Index;
+    if (!isNominal() && !isString())
+      return copy;
+    copy.m_Type = m_Type;
+    copy.m_Values = m_Values;
+    copy.m_Hashtable = m_Hashtable;
+ 
+    return copy;
+  }
+
+  /**
+   * Removes a value of a nominal or string attribute. Creates a 
+   * fresh list of attribute values before removing it.
+   *
+   * @param index the value's index
+   * @exception IllegalArgumentException if the attribute is not nominal
+   */
+  final void delete(int index) {
+    
+    if (!isNominal() && !isString()) 
+      throw new IllegalArgumentException("Can only remove value of" +
+                                         "nominal or string attribute!");
+    else {
+      m_Values = (FastVector)m_Values.copy();
+      m_Values.removeElementAt(index);
+      Hashtable hash = new Hashtable(m_Hashtable.size());
+      Enumeration enum = hash.keys();
+      while (enum.hasMoreElements()) {
+	String string = (String)enum.nextElement();
+	Integer valIndexObject = (Integer)m_Hashtable.get(string);
+	int valIndex = valIndexObject.intValue();
+	if (valIndex > index) {
+	  hash.put(string, new Integer(valIndex - 1));
+	} else if (valIndex < index) {
+	  hash.put(string, valIndexObject);
+	}
+      }
+      m_Hashtable = hash;
+    }
+  }
+
+  /**
+   * Adds an attribute value.
+   *
+   * @param value the attribute value
+   */
+  final void forceAddValue(String value) {
+
+    Object store = value;
+    if (value.length() > STRING_COMPRESS_THRESHOLD) {
+      try {
+        store = new SerializedObject(value, true);
+      } catch (Exception ex) {
+        System.err.println("Couldn't compress string attribute value -"
+                           + " storing uncompressed.");
+      }
+    }
+    m_Values.addElement(store);
+    m_Hashtable.put(store, new Integer(m_Values.size() - 1));
+  }
+
+  /**
+   * Sets the index of this attribute.
+   *
+   * @param the index of this attribute
+   */
+  final void setIndex(int index) {
+
+    m_Index = index;
+  }
+
+  /**
+   * Sets a value of a nominal attribute or string attribute.
+   * Creates a fresh list of attribute values before it is set.
+   *
+   * @param index the value's index
+   * @param string the value
+   * @exception IllegalArgumentException if the attribute is not nominal or 
+   * string.
+   */
+  final void setValue(int index, String string) {
+
+    if (!isNominal() && !isString()) {
+      throw new IllegalArgumentException("Can only set value of nominal"+
+                                         "or string attribute!");
+    } else {
+      m_Values = (FastVector)m_Values.copy();
+      m_Hashtable = (Hashtable)m_Hashtable.clone();
+      Object store = string;
+      if (string.length() > STRING_COMPRESS_THRESHOLD) {
+        try {
+          store = new SerializedObject(string, true);
+        } catch (Exception ex) {
+          System.err.println("Couldn't compress string attribute value -"
+                             + " storing uncompressed.");
+        }
+      }
+      m_Hashtable.remove(m_Values.elementAt(index));
+      m_Values.setElementAt(store, index);
+      m_Hashtable.put(store, new Integer(index));
+    }
+  }
+
+  /**
+   * Simple main method for testing this class.
+   */
+  public static void main(String[] ops) {
+
+    try {
+      
+      // Create numeric attributes "length" and "weight"
+      Attribute length = new Attribute("length");
+      Attribute weight = new Attribute("weight");
+      
+      // Create vector to hold nominal values "first", "second", "third" 
+      FastVector my_nominal_values = new FastVector(3); 
+      my_nominal_values.addElement("first"); 
+      my_nominal_values.addElement("second"); 
+      my_nominal_values.addElement("third"); 
+      
+      // Create nominal attribute "position" 
+      Attribute position = new Attribute("position", my_nominal_values);
+
+      // Print the name of "position"
+      System.out.println("Name of \"position\": " + position.name());
+
+      // Print the values of "position"
+      Enumeration attValues = position.enumerateValues();
+      while (attValues.hasMoreElements()) {
+	String string = (String)attValues.nextElement();
+	System.out.println("Value of \"position\": " + string);
+      }
+
+      // Shallow copy attribute "position"
+      Attribute copy = (Attribute) position.copy();
+
+      // Test if attributes are the same
+      System.out.println("Copy is the same as original: " + copy.equals(position));
+
+      // Print index of attribute "weight" (should be unset: -1)
+      System.out.println("Index of attribute \"weight\" (should be -1): " + 
+			 weight.index());
+
+      // Print index of value "first" of attribute "position"
+      System.out.println("Index of value \"first\" of \"position\" (should be 0): " +
+			 position.indexOfValue("first"));
+
+      // Tests type of attribute "position"
+      System.out.println("\"position\" is numeric: " + position.isNumeric());
+      System.out.println("\"position\" is nominal: " + position.isNominal());
+      System.out.println("\"position\" is string: " + position.isString());
+
+      // Prints name of attribute "position"
+      System.out.println("Name of \"position\": " + position.name());
+    
+      // Prints number of values of attribute "position"
+      System.out.println("Number of values for \"position\": " + position.numValues());
+
+      // Prints the values (againg)
+      for (int i = 0; i < position.numValues(); i++) {
+	System.out.println("Value " + i + ": " + position.value(i));
+      }
+
+      // Prints the attribute "position" in ARFF format
+      System.out.println(position);
+
+      // Checks type of attribute "position" using constants
+      switch (position.type()) {
+      case Attribute.NUMERIC:
+	System.out.println("\"position\" is numeric");
+	break;
+      case Attribute.NOMINAL:
+	System.out.println("\"position\" is nominal");
+	break;
+      case Attribute.STRING:
+	System.out.println("\"position\" is string");
+	break;
+      default:
+	System.out.println("\"position\" has unknown type");
+      }
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
+  
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/AttributeStats.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/AttributeStats.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/AttributeStats.java	(revision 8815)
@@ -0,0 +1,136 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    AttributeStats.java
+ *    Copyright (C) 1999 Len Trigg
+ *
+ */
+
+package weka.core;
+
+/**
+ * A Utility class that contains summary information on an
+ * the values that appear in a dataset for a particular attribute.
+ *
+ * @author <a href="mailto:len@webmind.com">Len Trigg</a>
+ * @version $Revision$
+ */
+public class AttributeStats {    
+  
+  /** The number of int-like values */
+  public int intCount = 0;
+  
+  /** The number of real-like values (i.e. have a fractional part) */
+  public int realCount = 0;
+  
+  /** The number of missing values */
+  public int missingCount = 0;
+  
+  /** The number of distinct values */
+  public int distinctCount = 0;
+  
+  /** The number of values that only appear once */
+  public int uniqueCount = 0;
+  
+  /** The total number of values (i.e. number of instances) */
+  public int totalCount = 0;
+  
+  /** Stats on numeric value distributions */
+  // perhaps Stats should be moved from weka.experiment to weka.core
+  public weka.experiment.Stats numericStats;
+  
+  /** Counts of each nominal value */
+  public int [] nominalCounts;
+    
+  /**
+   * Updates the counters for one more observed distinct value.
+   *
+   * @param value the value that has just been seen
+   * @param count the number of times the value appeared
+   */
+  protected void addDistinct(double value, int count) {
+    
+    if (count > 0) {
+      if (count == 1) {
+	uniqueCount++;
+	}
+      if (Utils.eq(value, (double)((int)value))) {
+	intCount += count;
+      } else {
+	realCount += count;
+      }
+      if (nominalCounts != null) {
+	nominalCounts[(int)value] = count;
+      }
+      if (numericStats != null) {
+	  numericStats.add(value, count);
+	  numericStats.calculateDerived();
+      }
+    }
+    distinctCount++;
+  }
+
+  /**
+   * Returns a human readable representation of this AttributeStats instance.
+   *
+   * @return a String represtinging these AttributeStats.
+   */
+  public String toString() {
+
+    StringBuffer sb = new StringBuffer();
+    sb.append(Utils.padLeft("Type", 4)).append(Utils.padLeft("Nom", 5));
+    sb.append(Utils.padLeft("Int", 5)).append(Utils.padLeft("Real", 5));
+    sb.append(Utils.padLeft("Missing", 12));
+    sb.append(Utils.padLeft("Unique", 12));
+    sb.append(Utils.padLeft("Dist", 6));
+    if (nominalCounts != null) {
+      sb.append(' ');
+      for (int i = 0; i < nominalCounts.length; i++) {
+        sb.append(Utils.padLeft("C[" + i + "]", 5));
+      }
+    }
+    sb.append('\n');
+
+    long percent;
+    percent = Math.round(100.0 * intCount / totalCount);
+    if (nominalCounts != null) {
+      sb.append(Utils.padLeft("Nom", 4)).append(' ');
+      sb.append(Utils.padLeft("" + percent, 3)).append("% ");
+      sb.append(Utils.padLeft("" + 0, 3)).append("% ");
+    } else {
+      sb.append(Utils.padLeft("Num", 4)).append(' ');
+      sb.append(Utils.padLeft("" + 0, 3)).append("% ");
+      sb.append(Utils.padLeft("" + percent, 3)).append("% ");
+    }
+    percent = Math.round(100.0 * realCount / totalCount);
+    sb.append(Utils.padLeft("" + percent, 3)).append("% ");
+    sb.append(Utils.padLeft("" + missingCount, 5)).append(" /");
+    percent = Math.round(100.0 * missingCount / totalCount);
+    sb.append(Utils.padLeft("" + percent, 3)).append("% ");
+    sb.append(Utils.padLeft("" + uniqueCount, 5)).append(" /");
+    percent = Math.round(100.0 * uniqueCount / totalCount);
+    sb.append(Utils.padLeft("" + percent, 3)).append("% ");
+    sb.append(Utils.padLeft("" + distinctCount, 5)).append(' ');
+    if (nominalCounts != null) {
+      for (int i = 0; i < nominalCounts.length; i++) {
+        sb.append(Utils.padLeft("" + nominalCounts[i], 5));
+      }
+    }
+    sb.append('\n');
+    return sb.toString();
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/ContingencyTables.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/ContingencyTables.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/ContingencyTables.java	(revision 8815)
@@ -0,0 +1,635 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    ContingencyTables.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+/**
+ * Class implementing some statistical routines for contingency tables.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class ContingencyTables {
+
+  /** The natural logarithm of 2 */
+  private static double log2 = Math.log(2);
+
+  /**
+   * Returns chi-squared probability for a given matrix.
+   *
+   * @param matrix the contigency table
+   * @param yates is Yates' correction to be used?
+   * @return the chi-squared probability
+   */
+
+  public static double chiSquared(double [][] matrix, boolean yates) {
+
+    int df = (matrix.length - 1) * (matrix[0].length - 1);
+
+    return Statistics.chiSquaredProbability(chiVal(matrix, yates), df);
+  }
+
+  /**
+   * Computes chi-squared statistic for a contingency table.
+   *
+   * @param matrix the contigency table
+   * @param yates is Yates' correction to be used?
+   * @return the value of the chi-squared statistic
+   */
+  public static double chiVal(double [][] matrix, boolean useYates) {
+    
+    int df, nrows, ncols, row, col;
+    double[] rtotal, ctotal;
+    double expect = 0, chival = 0, n = 0;
+    boolean yates = true;
+    
+    nrows = matrix.length;
+    ncols = matrix[0].length;
+    rtotal = new double [nrows];
+    ctotal = new double [ncols];
+    for (row = 0; row < nrows; row++) {
+      for (col = 0; col < ncols; col++) {
+	rtotal[row] += matrix[row][col];
+	ctotal[col] += matrix[row][col];
+	n += matrix[row][col];
+      }
+    }
+    df = (nrows - 1)*(ncols - 1);
+    if ((df > 1) || (!useYates)) {
+      yates = false;
+    } else if (df <= 0) {
+      return 0;
+    }
+    chival = 0.0;
+    for (row = 0; row < nrows; row++) {
+      if (Utils.gr(rtotal[row], 0)) {
+	for (col = 0; col < ncols; col++) {
+	  if (Utils.gr(ctotal[col], 0)) {
+	    expect = (ctotal[col] * rtotal[row]) / n;
+	    chival += chiCell (matrix[row][col], expect, yates);
+	  }
+	}
+      }
+    }
+    return chival;
+  }
+
+  /**
+   * Tests if Cochran's criterion is fullfilled for the given
+   * contingency table. Rows and columns with all zeros are not considered
+   * relevant.
+   *
+   * @param matrix the contigency table to be tested
+   * @return true if contingency table is ok, false if not
+   */
+  public static boolean cochransCriterion(double[][] matrix) {
+
+    double[] rtotal, ctotal;
+    double n = 0, expect, smallfreq = 5;
+    int smallcount = 0, nonZeroRows = 0, nonZeroColumns = 0, nrows, ncols, 
+      row, col;
+
+    nrows = matrix.length;
+    ncols = matrix[0].length;
+
+    rtotal = new double [nrows];
+    ctotal = new double [ncols];
+    for (row = 0; row < nrows; row++) {
+      for (col = 0; col < ncols; col++) {
+	rtotal[row] += matrix[row][col];
+	ctotal[col] += matrix[row][col];
+	n += matrix[row][col];
+      }
+    }
+    for (row = 0; row < nrows; row++) {
+      if (Utils.gr(rtotal[row], 0)) {
+	nonZeroRows++;
+      }
+    }
+    for (col = 0; col < ncols; col++) {
+      if (Utils.gr(ctotal[col], 0)) {
+	nonZeroColumns++;
+      }
+    }
+    for (row = 0; row < nrows; row++) {
+      if (Utils.gr(rtotal[row], 0)) {
+	for (col = 0; col < ncols; col++) {
+	  if (Utils.gr(ctotal[col], 0)) {
+	    expect = (ctotal[col] * rtotal[row]) / n;
+	    if (Utils.sm(expect, smallfreq)) {
+	      if (Utils.sm(expect, 1)) {
+		return false;
+	      } else {
+		smallcount++;
+		if (smallcount > (nonZeroRows * nonZeroColumns) / smallfreq) {
+		  return false;
+		}
+	      }
+	    }
+	  }
+	}
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Computes Cramer's V for a contingency table.
+   *
+   * @param matrix the contingency table
+   * @return Cramer's V
+   */
+  public static double CramersV(double [][] matrix) {
+
+    int row, col, nrows,ncols, min;
+    double n = 0;
+    
+    nrows = matrix.length;
+    ncols = matrix[0].length;
+    for (row = 0; row < nrows; row++) {
+      for (col = 0; col < ncols; col++) {
+	n += matrix[row][col];
+      }
+    }
+    min = nrows < ncols ? nrows-1 : ncols-1;
+    if ((min == 0) || Utils.eq(n, 0))
+      return 0;
+    return Math.sqrt(chiVal(matrix, false) / (n * (double)min)); 
+  } 
+
+  /**
+   * Computes the entropy of the given array.
+   *
+   * @param array the array
+   * @return the entropy
+   */
+  public static double entropy(double[] array) {
+
+    double returnValue = 0, sum = 0;
+
+    for (int i = 0; i < array.length; i++) {
+      returnValue -= lnFunc(array[i]);
+      sum += array[i];
+    }
+    if (Utils.eq(sum, 0)) {
+      return 0;
+    } else {
+      return (returnValue + lnFunc(sum)) / (sum * log2);
+    }
+  }
+
+  /**
+   * Computes conditional entropy of the rows given
+   * the columns.
+   *
+   * @param matrix the contingency table
+   * @return the conditional entropy of the rows given the columns
+   */
+  public static double entropyConditionedOnColumns(double[][] matrix) {
+    
+    double returnValue = 0, sumForColumn, total = 0;
+
+    for (int j = 0; j < matrix[0].length; j++) {
+      sumForColumn = 0;
+      for (int i = 0; i < matrix.length; i++) {
+	returnValue = returnValue + lnFunc(matrix[i][j]);
+	sumForColumn += matrix[i][j];
+      }
+      returnValue = returnValue - lnFunc(sumForColumn);
+      total += sumForColumn;
+    }
+    if (Utils.eq(total, 0)) {
+      return 0;
+    }
+    return -returnValue / (total * log2);
+  }
+
+  /**
+   * Computes conditional entropy of the columns given
+   * the rows.
+   *
+   * @param matrix the contingency table
+   * @return the conditional entropy of the columns given the rows
+   */
+  public static double entropyConditionedOnRows(double[][] matrix) {
+    
+    double returnValue = 0, sumForRow, total = 0;
+
+    for (int i = 0; i < matrix.length; i++) {
+      sumForRow = 0;
+      for (int j = 0; j < matrix[0].length; j++) {
+	returnValue = returnValue + lnFunc(matrix[i][j]);
+	sumForRow += matrix[i][j];
+      }
+      returnValue = returnValue - lnFunc(sumForRow);
+      total += sumForRow;
+    }
+    if (Utils.eq(total, 0)) {
+      return 0;
+    }
+    return -returnValue / (total * log2);
+  }
+
+  /**
+   * Computes conditional entropy of the columns given the rows
+   * of the test matrix with respect to the train matrix. Uses a
+   * Laplace prior. Does NOT normalize the entropy.
+   *
+   * @param train the train matrix 
+   * @param test the test matrix
+   * @param the number of symbols for Laplace
+   * @return the entropy
+   */
+  public static double entropyConditionedOnRows(double[][] train, 
+						double[][] test,
+						double numClasses) {
+    
+    double returnValue = 0, trainSumForRow, testSumForRow, testSum = 0;
+
+    for (int i = 0; i < test.length; i++) {
+      trainSumForRow = 0;
+      testSumForRow = 0;
+      for (int j = 0; j < test[0].length; j++) {
+	returnValue -= test[i][j] * Math.log(train[i][j] + 1);
+	trainSumForRow += train[i][j];
+	testSumForRow += test[i][j];
+      }
+      testSum = testSumForRow;
+      returnValue += testSumForRow * Math.log(trainSumForRow + 
+					     numClasses);
+    }
+    return returnValue / (testSum * log2);
+  }
+
+  /**
+   * Computes the rows' entropy for the given contingency table.
+   *
+   * @param matrix the contingency table
+   * @return the rows' entropy
+   */
+  public static double entropyOverRows(double[][] matrix) {
+    
+    double returnValue = 0, sumForRow, total = 0;
+
+    for (int i = 0; i < matrix.length; i++) {
+      sumForRow = 0;
+      for (int j = 0; j < matrix[0].length; j++) {
+	sumForRow += matrix[i][j];
+      }
+      returnValue = returnValue - lnFunc(sumForRow);
+      total += sumForRow;
+    }
+    if (Utils.eq(total, 0)) {
+      return 0;
+    }
+    return (returnValue + lnFunc(total)) / (total * log2);
+  }
+
+  /**
+   * Computes the columns' entropy for the given contingency table.
+   *
+   * @param matrix the contingency table
+   * @return the columns' entropy
+   */
+  public static double entropyOverColumns(double[][] matrix){
+    
+    double returnValue = 0, sumForColumn, total = 0;
+
+    for (int j = 0; j < matrix[0].length; j++){
+      sumForColumn = 0;
+      for (int i = 0; i < matrix.length; i++) {
+	sumForColumn += matrix[i][j];
+      }
+      returnValue = returnValue - lnFunc(sumForColumn);
+      total += sumForColumn;
+    }
+    if (Utils.eq(total, 0)) {
+      return 0;
+    }
+    return (returnValue + lnFunc(total)) / (total * log2);
+  }
+
+  /**
+   * Computes gain ratio for contingency table (split on rows).
+   * Returns Double.MAX_VALUE if the split entropy is 0.
+   *
+   * @param matrix the contingency table
+   * @return the gain ratio
+   */
+  public static double gainRatio(double[][] matrix){
+    
+    double preSplit = 0, postSplit = 0, splitEnt = 0,
+      sumForRow, sumForColumn, total = 0, infoGain;
+
+    // Compute entropy before split
+    for (int i = 0; i < matrix[0].length; i++) {
+      sumForColumn = 0;
+      for (int j = 0; j < matrix.length; j++) 
+	sumForColumn += matrix[j][i];
+      preSplit += lnFunc(sumForColumn);
+      total += sumForColumn;
+    }
+    preSplit -= lnFunc(total);
+
+    // Compute entropy after split and split entropy
+    for (int i = 0; i < matrix.length; i++) {
+      sumForRow = 0;
+      for (int j = 0; j < matrix[0].length; j++) {
+	postSplit += lnFunc(matrix[i][j]);
+	sumForRow += matrix[i][j];
+      }
+      splitEnt += lnFunc(sumForRow);
+    }
+    postSplit -= splitEnt;
+    splitEnt -= lnFunc(total);
+
+    infoGain = preSplit - postSplit;
+    if (Utils.eq(splitEnt, 0))
+      return 0;
+    return infoGain / splitEnt;
+  }
+
+  /**
+   * Returns negative base 2 logarithm of multiple hypergeometric
+   * probability for a contingency table.
+   *
+   * @param matrix the contingency table
+   * @return the log of the hypergeometric probability of the contingency table 
+   */
+  public static double log2MultipleHypergeometric(double[][] matrix) {
+
+    double sum = 0, sumForRow, sumForColumn, total = 0;
+
+    for (int i = 0; i < matrix.length; i++) {
+      sumForRow = 0;
+      for (int j = 0; j < matrix[i].length; j++) {
+	sumForRow += matrix[i][j];
+      }
+      sum += SpecialFunctions.lnFactorial(sumForRow);
+      total += sumForRow;
+    }
+    for (int j = 0; j < matrix[0].length; j++) {
+      sumForColumn = 0;
+      for (int i = 0; i < matrix.length; i++) {
+	sumForColumn += matrix [i][j];
+      }
+      sum += SpecialFunctions.lnFactorial(sumForColumn);
+    }
+    for (int i = 0; i < matrix.length; i++) {
+      for (int j = 0; j < matrix[i].length; j++) {
+	sum -= SpecialFunctions.lnFactorial(matrix[i][j]);
+      }
+    }
+    sum -= SpecialFunctions.lnFactorial(total);
+    return -sum / log2;
+  }
+
+  /**
+   * Reduces a matrix by deleting all zero rows and columns.
+   *
+   * @param matrix the matrix to be reduced
+   * @param the matrix with all zero rows and columns deleted
+   */
+  public static double[][] reduceMatrix(double[][] matrix) {
+
+    int row, col, currCol, currRow, nrows, ncols, 
+      nonZeroRows = 0, nonZeroColumns = 0;
+    double[] rtotal, ctotal;
+    double[][] newMatrix;
+
+    nrows = matrix.length;
+    ncols = matrix[0].length;
+    rtotal = new double [nrows];
+    ctotal = new double [ncols];
+    for (row = 0; row < nrows; row++) {
+      for (col = 0; col < ncols; col++) {
+	rtotal[row] += matrix[row][col];
+	ctotal[col] += matrix[row][col];
+      }
+    }
+    for (row = 0; row < nrows; row++) {
+      if (Utils.gr(rtotal[row],0)) {
+	nonZeroRows++;
+      }
+    }
+    for (col = 0; col < ncols; col++) {
+      if (Utils.gr(ctotal[col],0)) {
+	nonZeroColumns++;
+      }
+    }
+    newMatrix = new double[nonZeroRows][nonZeroColumns];
+    currRow = 0;
+    for (row = 0; row < nrows; row++) {
+      if (Utils.gr(rtotal[row],0)) {
+	currCol = 0;
+	for (col = 0; col < ncols; col++) {
+	  if (Utils.gr(ctotal[col],0)) {
+	    newMatrix[currRow][currCol] = matrix[row][col];
+	    currCol++;
+	  }
+	}
+	currRow++;
+      }
+    }
+    return newMatrix;
+  }
+    
+   /**
+    * Calculates the symmetrical uncertainty for base 2.
+    *
+    * @param matrix the contingency table
+    * @return the calculated symmetrical uncertainty
+    *
+    */
+  public static double symmetricalUncertainty(double matrix[][]) {
+
+    double sumForColumn, sumForRow, total = 0, columnEntropy = 0, 
+      rowEntropy = 0, entropyConditionedOnRows = 0, infoGain = 0;
+
+    // Compute entropy for columns
+    for (int i = 0; i < matrix[0].length; i++) {
+      sumForColumn = 0;
+      for (int j = 0; j < matrix.length; j++) {
+	sumForColumn += matrix[j][i];
+      }
+      columnEntropy += lnFunc(sumForColumn);
+      total += sumForColumn;
+    }
+    columnEntropy -= lnFunc(total);
+
+    // Compute entropy for rows and conditional entropy
+    for (int i = 0; i < matrix.length; i++) {
+      sumForRow = 0;
+      for (int j = 0; j < matrix[0].length; j++) { 
+	sumForRow += matrix[i][j];
+	entropyConditionedOnRows += lnFunc(matrix[i][j]);
+      }
+      rowEntropy += lnFunc(sumForRow);
+    }
+    entropyConditionedOnRows -= rowEntropy;
+    rowEntropy -= lnFunc(total);
+    infoGain = columnEntropy - entropyConditionedOnRows;
+    if (Utils.eq(columnEntropy, 0) || Utils.eq(rowEntropy, 0))
+      return 0;
+    return 2.0 * (infoGain / (columnEntropy + rowEntropy));
+  }
+
+  /**
+   * Computes Goodman and Kruskal's tau-value for a contingency table.
+   *
+   * @param matrix the contingency table
+   * @param Goodman and Kruskal's tau-value
+   */
+  public static double tauVal(double[][] matrix) {
+    
+    int nrows, ncols, row, col;
+    double [] ctotal;
+    double maxcol = 0, max, maxtotal = 0, n = 0;
+    
+    nrows = matrix.length;
+    ncols = matrix[0].length;
+    ctotal = new double [ncols];
+    for (row = 0; row < nrows; row++) {
+      max = 0;
+      for (col = 0; col < ncols; col++) {
+	if (Utils.gr(matrix[row][col], max)) 
+	  max = matrix[row][col];
+	ctotal[col] += matrix[row][col];
+	n += matrix[row][col];
+      }
+      maxtotal += max;
+    }
+    if (Utils.eq(n, 0)) {
+      return 0;
+    }
+    maxcol = ctotal[Utils.maxIndex(ctotal)];
+    return (maxtotal - maxcol)/(n - maxcol);
+  }
+
+  /**
+   * Help method for computing entropy.
+   */
+  private static double lnFunc(double num){
+    
+    // Constant hard coded for efficiency reasons
+    if (num < 1e-6) {
+      return 0;
+    } else {
+      return num * Math.log(num);
+    }
+  }
+  
+  /**
+   * Computes chi-value for one cell in matrix.
+   * From Gary Perlman's unixstat.
+   */
+  private static double chiCell(double freq, double expect, boolean yates){
+
+    double  diff = freq - expect;
+       
+    if (yates) {
+      diff = Math.abs (diff) - 0.5;
+      if (diff < 0.0) { // over-correction
+	diff = 0.0;
+      }
+    }
+    if (Math.abs(expect) < 10e-10) {
+      return (0.0);
+    } else {
+      return (diff * diff / expect);
+    }
+  }
+
+  /**
+   * Main method for testing this class.
+   */
+  public static void main(String[] ops) {
+
+    double[] firstRow = {10, 5, 20};
+    double[] secondRow = {2, 10, 6};
+    double[] thirdRow = {5, 10, 10};
+    double[][] matrix = new double[3][0];
+
+    matrix[0] = firstRow; matrix[1] = secondRow; matrix[2] = thirdRow;
+    for (int i = 0; i < matrix.length; i++) {
+      for (int j = 0; j < matrix[i].length; j++) {
+	System.out.print(matrix[i][j] + " ");
+      }
+      System.out.println();
+    }
+    System.out.println("Chi-squared probability: " +
+		       ContingencyTables.chiSquared(matrix, false));
+    System.out.println("Chi-squared value: " +
+		       ContingencyTables.chiVal(matrix, false));
+    System.out.println("Cochran's criterion fullfilled: " +
+		       ContingencyTables.cochransCriterion(matrix));
+    System.out.println("Cramer's V: " +
+		       ContingencyTables.CramersV(matrix));
+    System.out.println("Entropy of first row: " +
+		       ContingencyTables.entropy(firstRow));
+    System.out.println("Entropy conditioned on columns: " +
+		       ContingencyTables.entropyConditionedOnColumns(matrix));
+    System.out.println("Entropy conditioned on rows: " +
+		       ContingencyTables.entropyConditionedOnRows(matrix));
+    System.out.println("Entropy conditioned on rows (with Laplace): " +
+		       ContingencyTables.entropyConditionedOnRows(matrix, matrix, 3));
+    System.out.println("Entropy of rows: " +
+		       ContingencyTables.entropyOverRows(matrix));
+    System.out.println("Entropy of columns: " +
+		       ContingencyTables.entropyOverColumns(matrix));
+    System.out.println("Gain ratio: " +
+		       ContingencyTables.gainRatio(matrix));
+    System.out.println("Negative log2 of multiple hypergeometric probability: " +
+		       ContingencyTables.log2MultipleHypergeometric(matrix));
+    System.out.println("Symmetrical uncertainty: " +
+		       ContingencyTables.symmetricalUncertainty(matrix));
+    System.out.println("Tau value: " +
+		       ContingencyTables.tauVal(matrix));
+    double[][] newMatrix = new double[3][3];
+    newMatrix[0][0] = 1; newMatrix[0][1] = 0; newMatrix[0][2] = 1;
+    newMatrix[1][0] = 0; newMatrix[1][1] = 0; newMatrix[1][2] = 0;
+    newMatrix[2][0] = 1; newMatrix[2][1] = 0; newMatrix[2][2] = 1;
+    System.out.println("Matrix with empty row and column: ");
+    for (int i = 0; i < newMatrix.length; i++) {
+      for (int j = 0; j < newMatrix[i].length; j++) {
+	System.out.print(newMatrix[i][j] + " ");
+      }
+      System.out.println();
+    }
+    System.out.println("Reduced matrix: ");
+    newMatrix = ContingencyTables.reduceMatrix(newMatrix);
+    for (int i = 0; i < newMatrix.length; i++) {
+      for (int j = 0; j < newMatrix[i].length; j++) {
+	System.out.print(newMatrix[i][j] + " ");
+      }
+      System.out.println();
+    }
+  }
+}
+
+
+
+
+
+
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/Copyable.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/Copyable.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/Copyable.java	(revision 8815)
@@ -0,0 +1,41 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Copyable.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+/**
+ * Interface implemented by classes that can produce "shallow" copies
+ * of their objects. (As opposed to clone(), which is supposed to
+ * produce a "deep" copy.)
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public interface Copyable {
+
+  /**
+   * This method produces a shallow copy of an object.
+   * It does the same as the clone() method in Object, which also produces
+   * a shallow copy.
+   */
+  public Object copy();
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/FastVector.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/FastVector.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/FastVector.java	(revision 8815)
@@ -0,0 +1,432 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    FastVector.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Implements a fast vector class without synchronized
+ * methods. Replaces java.util.Vector. (Synchronized methods tend to
+ * be slow.)
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$ */
+public class FastVector implements Copyable, Serializable {
+
+  /**
+   * Class for enumerating the vector's elements.
+   */
+  public class FastVectorEnumeration implements Enumeration {
+
+    /** The counter. */
+    private int m_Counter;
+
+    /** The vector. */
+    private FastVector m_Vector;
+
+    /** Special element. Skipped during enumeration. */
+    private int m_SpecialElement;
+
+    /**
+     * Constructs an enumeration.
+     *
+     * @param vector the vector which is to be enumerated
+     */
+    public FastVectorEnumeration(FastVector vector) {
+
+      m_Counter = 0;
+      m_Vector = vector;
+      m_SpecialElement = -1;
+    }
+
+    /**
+     * Constructs an enumeration with a special element.
+     * The special element is skipped during the enumeration.
+     *
+     * @param vector the vector which is to be enumerated
+     * @param special the index of the special element
+     */
+    public FastVectorEnumeration(FastVector vector, int special) {
+
+      m_Vector = vector;
+      m_SpecialElement = special;
+      if (special == 0) {
+	m_Counter = 1;
+      } else {
+	m_Counter = 0;
+      }
+    }
+
+
+    /**
+     * Tests if there are any more elements to enumerate.
+     *
+     * @return true if there are some elements left
+     */
+    public final boolean hasMoreElements() {
+
+      if (m_Counter < m_Vector.size()) {
+	return true;
+      }
+      return false;
+    }
+
+    /**
+     * Returns the next element.
+     *
+     * @return the next element to be enumerated
+     */
+    public final Object nextElement() {
+  
+      Object result = m_Vector.elementAt(m_Counter);
+
+      m_Counter++;
+      if (m_Counter == m_SpecialElement) {
+	m_Counter++;
+      }
+      return result;
+    }
+  }
+
+  /** The array of objects. */
+  private Object[] m_Objects;
+
+  /** The current size; */
+  private int m_Size;
+
+  /** The capacity increment */
+  private int m_CapacityIncrement;
+  
+  /** The capacity multiplier. */
+  private double m_CapacityMultiplier;
+
+  /**
+   * Constructs an empty vector with initial
+   * capacity zero.
+   */
+  public FastVector() {
+  
+    m_Objects = new Object[0];
+    m_Size = 0;
+    m_CapacityIncrement = 1;
+    m_CapacityMultiplier = 2;
+  }
+
+  /**
+   * Constructs a vector with the given capacity.
+   *
+   * @param capacity the vector's initial capacity
+   */
+  public FastVector(int capacity) {
+
+    m_Objects = new Object[capacity];
+    m_Size = 0;
+    m_CapacityIncrement = 1;
+    m_CapacityMultiplier = 2;
+  }
+
+  /**
+   * Constructs a vector with the given capacity, capacity 
+   * increment and capacity mulitplier.
+   *
+   * @param capacity the vector's initial capacity
+   */
+  public FastVector(int capacity, int capIncrement, 
+		    double capMultiplier) {
+
+    m_Objects = new Object[capacity];
+    m_Size = 0;
+    m_CapacityIncrement = capIncrement;
+    m_CapacityMultiplier = capMultiplier;
+  }
+
+  /**
+   * Adds an element to this vector. Increases its
+   * capacity if its not large enough.
+   *
+   * @param element the element to add
+   */
+  public final void addElement(Object element) {
+
+    Object[] newObjects;
+
+    if (m_Size == m_Objects.length) {
+      newObjects = new Object[(int)m_CapacityMultiplier *
+			     (m_Objects.length +
+			      m_CapacityIncrement)];
+      System.arraycopy(m_Objects, 0, newObjects, 0, m_Size);
+      m_Objects = newObjects;
+    }
+    m_Objects[m_Size] = element;
+    m_Size++;
+  }
+
+  /**
+   * Returns the capacity of the vector.
+   *
+   * @return the capacity of the vector
+   */
+  public final int capacity() {
+  
+    return m_Objects.length;
+  }
+
+  /**
+   * Produces a shallow copy of this vector.
+   *
+   * @return the new vector
+   */
+  public final Object copy() {
+
+    FastVector copy = new FastVector(m_Objects.length, 
+				     m_CapacityIncrement,
+				     m_CapacityMultiplier);
+    copy.m_Size = m_Size;
+    System.arraycopy(m_Objects, 0, copy.m_Objects, 0, m_Size);
+    return copy;
+  }
+
+  /**
+   * Clones the vector and shallow copies all its elements.
+   * The elements have to implement the Copyable interface.
+   * 
+   * @return the new vector
+   */
+  public final Object copyElements() {
+
+    FastVector copy = new FastVector(m_Objects.length, 
+				     m_CapacityIncrement,
+				     m_CapacityMultiplier);
+    copy.m_Size = m_Size;
+    for (int i = 0; i < m_Size; i++) {
+      copy.m_Objects[i] = ((Copyable)m_Objects[i]).copy();
+    }
+    return copy;
+  }
+
+  /**
+   * Returns the element at the given position.
+   *
+   * @param index the element's index
+   * @return the element with the given index
+   */
+  public final Object elementAt(int index) {
+
+    return m_Objects[index];
+  }
+
+  /**
+   * Returns an enumeration of this vector.
+   *
+   * @return an enumeration of this vector
+   */
+  public final Enumeration elements() {
+  
+    return new FastVectorEnumeration(this);
+  }
+
+  /**
+   * Returns an enumeration of this vector, skipping the
+   * element with the given index.
+   *
+   * @param index the element to skip
+   * @return an enumeration of this vector
+   */
+  public final Enumeration elements(int index) {
+  
+    return new FastVectorEnumeration(this, index);
+  }
+
+  /**
+   * Returns the first element of the vector.
+   *
+   * @return the first element of the vector
+   */
+  public final Object firstElement() {
+
+    return m_Objects[0];
+  }
+
+  /**
+   * Searches for the first occurence of the given argument, 
+   * testing for equality using the equals method. 
+   *
+   * @param element the element to be found
+   * @return the index of the first occurrence of the argument 
+   * in this vector; returns -1 if the object is not found
+   */
+  public final int indexOf(Object element) {
+
+    for (int i = 0; i < m_Size; i++) {
+      if (element.equals(m_Objects[i])) {
+	return i;
+      }
+    }
+    return -1;
+  }
+
+  /**
+   * Inserts an element at the given position.
+   *
+   * @param element the element to be inserted
+   * @param index the element's index
+   */
+  public final void insertElementAt(Object element, int index) {
+
+    Object[] newObjects;
+
+    if (m_Size < m_Objects.length) {
+      System.arraycopy(m_Objects, index, m_Objects, index + 1, 
+                       m_Size - index);
+      m_Objects[index] = element;
+    } else {
+      newObjects = new Object[(int)m_CapacityMultiplier *
+			     (m_Objects.length +
+			      m_CapacityIncrement)];
+      System.arraycopy(m_Objects, 0, newObjects, 0, index);
+      newObjects[index] = element;
+      System.arraycopy(m_Objects, index, newObjects, index + 1,
+		       m_Size - index);
+      m_Objects = newObjects;
+    }
+    m_Size++;
+  }
+
+  /**
+   * Returns the last element of the vector.
+   *
+   * @return the last element of the vector
+   */
+  public final Object lastElement() {
+
+    return m_Objects[m_Size - 1];
+  }
+
+  /**
+   * Deletes an element from this vector.
+   *
+   * @param index the index of the element to be deleted
+   */
+  public final void removeElementAt(int index) {
+
+    System.arraycopy(m_Objects, index + 1, m_Objects, index, 
+                     m_Size - index - 1);
+    m_Size--;
+  }
+
+  /**
+   * Removes all components from this vector and sets its 
+   * size to zero. 
+   */
+  public final void removeAllElements() {
+
+    m_Objects = new Object[m_Objects.length];
+    m_Size = 0;
+  }
+
+  /**
+   * Appends all elements of the supplied vector to this vector.
+   *
+   * @param toAppend the FastVector containing elements to append.
+   */
+  public final void appendElements(FastVector toAppend) {
+
+    setCapacity(size() + toAppend.size());
+    System.arraycopy(toAppend.m_Objects, 0, m_Objects, size(), toAppend.size());
+    m_Size = m_Objects.length;
+  }
+
+  /** 
+   * Returns all the elements of this vector as an array
+   *
+   * @param an array containing all the elements of this vector
+   */
+  public final Object [] toArray() {
+
+    Object [] newObjects = new Object[size()];
+    System.arraycopy(m_Objects, 0, newObjects, 0, size());
+    return newObjects;
+  }
+
+  /**
+   * Sets the vector's capacity to the given value.
+   *
+   * @param capacity the new capacity
+   */
+  public final void setCapacity(int capacity) {
+
+    Object[] newObjects = new Object[capacity];
+   
+    System.arraycopy(m_Objects, 0, newObjects, 0, Math.min(capacity, m_Size));
+    m_Objects = newObjects;
+    if (m_Objects.length < m_Size)
+      m_Size = m_Objects.length;
+  }
+
+  /**
+   * Sets the element at the given index.
+   *
+   * @param element the element to be put into the vector
+   * @param index the index at which the element is to be placed
+   */
+  public final void setElementAt(Object element, int index) {
+
+    m_Objects[index] = element;
+  }
+
+  /**
+   * Returns the vector's current size.
+   *
+   * @return the vector's current size
+   */
+  public final int size() {
+
+    return m_Size;
+  }
+
+  /**
+   * Swaps two elements in the vector.
+   *
+   * @param first index of the first element
+   * @param second index of the second element
+   */
+  public final void swap(int first, int second) {
+
+    Object help = m_Objects[first];
+
+    m_Objects[first] = m_Objects[second];
+    m_Objects[second] = help;
+  }
+
+  /**
+   * Sets the vector's capacity to its size.
+   */
+  public final void trimToSize() {
+
+    Object[] newObjects = new Object[m_Size];
+    
+    System.arraycopy(m_Objects, 0, newObjects, 0, m_Size);
+    m_Objects = newObjects;
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/Instance.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/Instance.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/Instance.java	(revision 8815)
@@ -0,0 +1,1064 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Instance.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Class for handling an instance. All values (numeric, nominal, or
+ * string) are internally stored as floating-point numbers. If an
+ * attribute is nominal (or a string), the stored value is the index
+ * of the corresponding nominal (or string) value in the attribute's
+ * definition. We have chosen this approach in favor of a more elegant
+ * object-oriented approach because it is much faster. <p>
+ *
+ * Typical usage (code from the main() method of this class): <p>
+ *
+ * <code>
+ * ... <br>
+ *      
+ * // Create empty instance with three attribute values <br>
+ * Instance inst = new Instance(3); <br><br>
+ *     
+ * // Set instance's values for the attributes "length", "weight", and "position"<br>
+ * inst.setValue(length, 5.3); <br>
+ * inst.setValue(weight, 300); <br>
+ * inst.setValue(position, "first"); <br><br>
+ *   
+ * // Set instance's dataset to be the dataset "race" <br>
+ * inst.setDataset(race); <br><br>
+ *   
+ * // Print the instance <br>
+ * System.out.println("The instance: " + inst); <br>
+ *
+ * ... <br>
+ * </code><p>
+ *
+ * All methods that change an instance are safe, ie. a change of an
+ * instance does not affect any other instances. All methods that
+ * change an instance's attribute values clone the attribute value
+ * vector before it is changed. If your application heavily modifies
+ * instance values, it may be faster to create a new instance from scratch.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$ 
+ */
+public class Instance implements Copyable, Serializable {
+  
+  /** Constant representing a missing value. */
+  protected final static double MISSING_VALUE = Double.NaN;
+
+  /** 
+   * The dataset the instance has access to.  Null if the instance
+   * doesn't have access to any dataset.  Only if an instance has
+   * access to a dataset, it knows about the actual attribute types.  
+   */
+  protected Instances m_Dataset;
+
+  /** The instance's attribute values. */
+  protected double[] m_AttValues;
+
+  /** The instance's weight. */
+  protected double m_Weight;
+
+  /**
+   * Constructor that copies the attribute values and the weight from
+   * the given instance. Reference to the dataset is set to null.
+   * (ie. the instance doesn't have access to information about the
+   * attribute types)
+   *
+   * @param instance the instance from which the attribute
+   * values and the weight are to be copied 
+   */
+  public Instance(Instance instance) {
+    
+    m_AttValues = instance.m_AttValues;
+    m_Weight = instance.m_Weight;
+    m_Dataset = null;
+  }
+
+  /**
+   * Constructor that inititalizes instance variable with given
+   * values. Reference to the dataset is set to null. (ie. the instance
+   * doesn't have access to information about the attribute types)
+   *
+   * @param weight the instance's weight
+   * @param attValues a vector of attribute values 
+   */
+  public Instance(double weight, double[] attValues){
+    
+    m_AttValues = attValues;
+    m_Weight = weight;
+    m_Dataset = null;
+  }
+
+  /**
+   * Constructor of an instance that sets weight to one, all values to
+   * be missing, and the reference to the dataset to null. (ie. the instance
+   * doesn't have access to information about the attribute types)
+   *
+   * @param numAttributes the size of the instance 
+   */
+  public Instance(int numAttributes) {
+    
+    m_AttValues = new double[numAttributes];
+    for (int i = 0; i < m_AttValues.length; i++) {
+      m_AttValues[i] = MISSING_VALUE;
+    }
+    m_Weight = 1;
+    m_Dataset = null;
+  }
+
+  /**
+   * Returns the attribute with the given index.
+   *
+   * @param index the attribute's index
+   * @return the attribute at the given position
+   * @exception UnassignedDatasetException if instance doesn't have access to a
+   * dataset
+   */ 
+  public Attribute attribute(int index) {
+   
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    }
+    return m_Dataset.attribute(index);
+  }
+
+  /**
+   * Returns the attribute with the given index. Does the same
+   * thing as attribute().
+   *
+   * @param indexOfIndex the index of the attribute's index 
+   * @return the attribute at the given position
+   * @exception UnassignedDatasetException if instance doesn't have access to a
+   * dataset
+   */ 
+  public Attribute attributeSparse(int indexOfIndex) {
+   
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    }
+    return m_Dataset.attribute(indexOfIndex);
+  }
+
+  /**
+   * Returns class attribute.
+   *
+   * @return the class attribute
+   * @exception UnassignedDatasetException if the class is not set or the
+   * instance doesn't have access to a dataset
+   */
+  public Attribute classAttribute() {
+
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    }
+    return m_Dataset.classAttribute();
+  }
+
+  /**
+   * Returns the class attribute's index.
+   *
+   * @return the class index as an integer 
+   * @exception UnassignedDatasetException if instance doesn't have access to a dataset 
+   */
+  public int classIndex() {
+    
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    }
+    return m_Dataset.classIndex();
+  }
+
+  /**
+   * Tests if an instance's class is missing.
+   *
+   * @return true if the instance's class is missing
+   * @exception UnassignedClassException if the class is not set or the instance doesn't
+   * have access to a dataset
+   */
+  public boolean classIsMissing() {
+
+    if (classIndex() < 0) {
+      throw new UnassignedClassException("Class is not set!");
+    }
+    return isMissing(classIndex());
+  }
+
+  /**
+   * Returns an instance's class value in internal format. (ie. as a
+   * floating-point number)
+   *
+   * @return the corresponding value as a double (If the 
+   * corresponding attribute is nominal (or a string) then it returns the 
+   * value's index as a double).
+   * @exception UnassignedClassException if the class is not set or the instance doesn't
+   * have access to a dataset 
+   */
+  public double classValue() {
+    
+    if (classIndex() < 0) {
+      throw new UnassignedClassException("Class is not set!");
+    }
+    return value(classIndex());
+  }
+
+  /**
+   * Produces a shallow copy of this instance. The copy has
+   * access to the same dataset. (if you want to make a copy
+   * that doesn't have access to the dataset, use 
+   * <code>new Instance(instance)</code>
+   *
+   * @return the shallow copy
+   */
+  public Object copy() {
+
+    Instance result = new Instance(this);
+    result.m_Dataset = m_Dataset;
+    return result;
+  }
+
+  /**
+   * Returns the dataset this instance has access to. (ie. obtains
+   * information about attribute types from) Null if the instance
+   * doesn't have access to a dataset.
+   *
+   * @return the dataset the instance has accesss to
+   */
+  public Instances dataset() {
+
+    return m_Dataset;
+  }
+
+  /**
+   * Deletes an attribute at the given position (0 to 
+   * numAttributes() - 1). Only succeeds if the instance does not
+   * have access to any dataset because otherwise inconsistencies
+   * could be introduced.
+   *
+   * @param pos the attribute's position
+   * @exception RuntimeException if the instance has access to a
+   * dataset 
+   */
+  public void deleteAttributeAt(int position) {
+
+    if (m_Dataset != null) {
+      throw new RuntimeException("Instance has access to a dataset!");
+    }
+    forceDeleteAttributeAt(position);
+  }
+
+  /**
+   * Returns an enumeration of all the attributes.
+   *
+   * @return enumeration of all the attributes
+   * @exception UnassignedDatasetException if the instance doesn't
+   * have access to a dataset 
+   */
+  public Enumeration enumerateAttributes() {
+
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    }
+    return m_Dataset.enumerateAttributes();
+  }
+
+  /**
+   * Tests if the headers of two instances are equivalent.
+   *
+   * @param instance another instance
+   * @return true if the header of the given instance is 
+   * equivalent to this instance's header
+   * @exception UnassignedDatasetException if instance doesn't have access to any
+   * dataset
+   */
+  public boolean equalHeaders(Instance inst) {
+
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    }
+    return m_Dataset.equalHeaders(inst.m_Dataset);
+  }
+
+  /**
+   * Returns the index of the attribute stored at the given position.
+   * Just returns the given value.
+   *
+   * @param position the position 
+   * @return the index of the attribute stored at the given position
+   */
+  public int index(int position) {
+
+    return position;
+  }
+
+  /**
+   * Inserts an attribute at the given position (0 to 
+   * numAttributes()). Only succeeds if the instance does not
+   * have access to any dataset because otherwise inconsistencies
+   * could be introduced.
+   *
+   * @param pos the attribute's position
+   * @exception RuntimeException if the instance has accesss to a
+   * dataset
+   * @exception IllegalArgumentException if the position is out of range
+   */
+  public void insertAttributeAt(int position) {
+
+    if (m_Dataset != null) {
+      throw new RuntimeException("Instance has accesss to a dataset!");
+    }
+    if ((position < 0) ||
+	(position > numAttributes())) {
+      throw new IllegalArgumentException("Can't insert attribute: index out "+
+                                         "of range");
+    }
+    forceInsertAttributeAt(position);
+  }
+
+  /**
+   * Tests if a specific value is "missing".
+   *
+   * @param attIndex the attribute's index
+   */
+  public boolean isMissing(int attIndex) {
+
+    if (Double.isNaN(m_AttValues[attIndex])) {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Tests if a specific value is "missing". Does
+   * the same thing as isMissing() if applied to an Instance.
+   *
+   * @param indexOfIndex the index of the attribute's index 
+   */
+  public boolean isMissingSparse(int indexOfIndex) {
+
+    if (Double.isNaN(m_AttValues[indexOfIndex])) {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Tests if a specific value is "missing".
+   * The given attribute has to belong to a dataset.
+   *
+   * @param att the attribute
+   */
+  public boolean isMissing(Attribute att) {
+
+    return isMissing(att.index());
+  }
+
+  /**
+   * Tests if the given value codes "missing".
+   *
+   * @param val the value to be tested
+   * @return true if val codes "missing"
+   */
+  public static boolean isMissingValue(double val) {
+
+    return Double.isNaN(val);
+  }
+
+  /**
+   * Merges this instance with the given instance and returns
+   * the result. Dataset is set to null.
+   *
+   * @param inst the instance to be merged with this one
+   * @return the merged instances
+   */
+  public Instance mergeInstance(Instance inst) {
+
+    int m = 0;
+    double [] newVals = new double[numAttributes() + inst.numAttributes()];
+    for (int j = 0; j < numAttributes(); j++, m++) {
+      newVals[m] = value(j);
+    }
+    for (int j = 0; j < inst.numAttributes(); j++, m++) {
+      newVals[m] = inst.value(j);
+    }
+    return new Instance(1.0, newVals);
+  }
+
+  /**
+   * Returns the double that codes "missing".
+   *
+   * @return the double that codes "missing"
+   */
+  public static double missingValue() {
+
+    return MISSING_VALUE;
+  }
+
+  /**
+   * Returns the number of attributes.
+   *
+   * @return the number of attributes as an integer
+   */
+  public int numAttributes() {
+
+    return m_AttValues.length;
+  }
+
+  /**
+   * Returns the number of class labels.
+   *
+   * @return the number of class labels as an integer if the 
+   * class attribute is nominal, 1 otherwise.
+   * @exception UnassignedDatasetException if instance doesn't have access to any
+   * dataset
+   */
+  public int numClasses() {
+    
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    }
+    return m_Dataset.numClasses();
+  }
+
+  /**
+   * Returns the number of values present. Always the same as numAttributes().
+   *
+   * @return the number of values
+   */
+  public int numValues() {
+
+    return m_AttValues.length;
+  }
+
+  /** 
+   * Replaces all missing values in the instance with the
+   * values contained in the given array. A deep copy of
+   * the vector of attribute values is performed before the
+   * values are replaced.
+   *
+   * @param array containing the means and modes
+   * @exception IllegalArgumentException if numbers of attributes are unequal
+   */
+  public void replaceMissingValues(double[] array) {
+	 
+    if ((array == null) || 
+	(array.length != m_AttValues.length)) {
+      throw new IllegalArgumentException("Unequal number of attributes!");
+    }
+    freshAttributeVector();
+    for (int i = 0; i < m_AttValues.length; i++) {
+      if (isMissing(i)) {
+	m_AttValues[i] = array[i];
+      }
+    }
+  }
+
+  /**
+   * Sets the class value of an instance to be "missing". A deep copy of
+   * the vector of attribute values is performed before the
+   * value is set to be missing.
+   *
+   * @exception UnassignedClassException if the class is not set
+   * @exception UnassignedDatasetException if the instance doesn't
+   * have access to a dataset
+   */
+  public void setClassMissing() {
+
+    if (classIndex() < 0) {
+      throw new UnassignedClassException("Class is not set!");
+    }
+    setMissing(classIndex());
+  }
+
+  /**
+   * Sets the class value of an instance to the given value (internal
+   * floating-point format).  A deep copy of the vector of attribute
+   * values is performed before the value is set.
+   *
+   * @param value the new attribute value (If the corresponding
+   * attribute is nominal (or a string) then this is the new value's
+   * index as a double).  
+   * @exception UnassignedClassException if the class is not set
+   * @exception UnaddignedDatasetException if the instance doesn't
+   * have access to a dataset 
+   */
+  public void setClassValue(double value) {
+
+    if (classIndex() < 0) {
+      throw new UnassignedClassException("Class is not set!");
+    }
+    setValue(classIndex(), value);
+  }
+
+  /**
+   * Sets the class value of an instance to the given value. A deep
+   * copy of the vector of attribute values is performed before the
+   * value is set.
+   *
+   * @param value the new class value (If the class
+   * is a string attribute and the value can't be found,
+   * the value is added to the attribute).
+   * @exception UnassignedClassException if the class is not set
+   * @exception UnassignedDatasetException if the dataset is not set
+   * @exception IllegalArgumentException if the attribute is not
+   * nominal or a string, or the value couldn't be found for a nominal
+   * attribute 
+   */
+  public final void setClassValue(String value) {
+
+    if (classIndex() < 0) {
+      throw new UnassignedClassException("Class is not set!");
+    }
+    setValue(classIndex(), value);
+  }
+
+  /**
+   * Sets the reference to the dataset. Does not check if the instance
+   * is compatible with the dataset. Note: the dataset does not know
+   * about this instance. If the structure of the dataset's header
+   * gets changed, this instance will not be adjusted automatically.
+   *
+   * @param instances the reference to the dataset 
+   */
+  public final void setDataset(Instances instances) {
+    
+    m_Dataset = instances;
+  }
+
+  /**
+   * Sets a specific value to be "missing". Performs a deep copy
+   * of the vector of attribute values before the value is set to
+   * be missing.
+   *
+   * @param attIndex the attribute's index
+   */
+  public final void setMissing(int attIndex) {
+
+    setValue(attIndex, MISSING_VALUE);
+  }
+
+  /**
+   * Sets a specific value to be "missing". Performs a deep copy
+   * of the vector of attribute values before the value is set to
+   * be missing. The given attribute has to belong to a dataset.
+   *
+   * @param att the attribute
+   */
+  public final void setMissing(Attribute att) {
+
+    setMissing(att.index());
+  }
+
+  /**
+   * Sets a specific value in the instance to the given value 
+   * (internal floating-point format). Performs a deep copy
+   * of the vector of attribute values before the value is set.
+   *
+   * @param attIndex the attribute's index 
+   * @param value the new attribute value (If the corresponding
+   * attribute is nominal (or a string) then this is the new value's
+   * index as a double).  
+   */
+  public void setValue(int attIndex, double value) {
+    
+    freshAttributeVector();
+    m_AttValues[attIndex] = value;
+  }
+
+  /**
+   * Sets a specific value in the instance to the given value 
+   * (internal floating-point format). Performs a deep copy
+   * of the vector of attribute values before the value is set.
+   * Does exactly the same thing as setValue().
+   *
+   * @param indexOfIndex the index of the attribute's index 
+   * @param value the new attribute value (If the corresponding
+   * attribute is nominal (or a string) then this is the new value's
+   * index as a double).  
+   */
+  public void setValueSparse(int indexOfIndex, double value) {
+    
+    freshAttributeVector();
+    m_AttValues[indexOfIndex] = value;
+  }
+
+  /**
+   * Sets a value of a nominal or string attribute to the given
+   * value. Performs a deep copy of the vector of attribute values
+   * before the value is set.
+   *
+   * @param attIndex the attribute's index
+   * @param value the new attribute value (If the attribute
+   * is a string attribute and the value can't be found,
+   * the value is added to the attribute).
+   * @exception UnassignedDatasetException if the dataset is not set
+   * @exception IllegalArgumentException if the selected
+   * attribute is not nominal or a string, or the supplied value couldn't 
+   * be found for a nominal attribute 
+   */
+  public final void setValue(int attIndex, String value) {
+    
+    int valIndex;
+
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    }
+    if (!attribute(attIndex).isNominal() &&
+	!attribute(attIndex).isString()) {
+      throw new IllegalArgumentException("Attribute neither nominal nor string!");
+    }
+    valIndex = attribute(attIndex).indexOfValue(value);
+    if (valIndex == -1) {
+      if (attribute(attIndex).isNominal()) {
+	throw new IllegalArgumentException("Value not defined for given nominal attribute!");
+      } else {
+	attribute(attIndex).forceAddValue(value);
+	valIndex = attribute(attIndex).indexOfValue(value);
+      }
+    }
+    setValue(attIndex, (double)valIndex); 
+  }
+
+  /**
+   * Sets a specific value in the instance to the given value
+   * (internal floating-point format). Performs a deep copy of the
+   * vector of attribute values before the value is set, so if you are
+   * planning on calling setValue many times it may be faster to
+   * create a new instance using toDoubleArray.  The given attribute
+   * has to belong to a dataset.
+   *
+   * @param att the attribute 
+   * @param value the new attribute value (If the corresponding
+   * attribute is nominal (or a string) then this is the new value's
+   * index as a double).  
+   */
+  public final void setValue(Attribute att, double value) {
+
+    setValue(att.index(), value);
+  }
+
+  /**
+   * Sets a value of an nominal or string attribute to the given
+   * value. Performs a deep copy of the vector of attribute values
+   * before the value is set, so if you are planning on calling setValue many
+   * times it may be faster to create a new instance using toDoubleArray.
+   * The given attribute has to belong to a dataset.
+   *
+   * @param att the attribute
+   * @param value the new attribute value (If the attribute
+   * is a string attribute and the value can't be found,
+   * the value is added to the attribute).
+   * @exception IllegalArgumentException if the the attribute is not
+   * nominal or a string, or the value couldn't be found for a nominal
+   * attribute 
+   */
+  public final void setValue(Attribute att, String value) {
+
+    if (!att.isNominal() &&
+	!att.isString()) {
+      throw new IllegalArgumentException("Attribute neither nominal nor string!");
+    }
+    int valIndex = att.indexOfValue(value);
+    if (valIndex == -1) {
+      if (att.isNominal()) {
+	throw new IllegalArgumentException("Value not defined for given nominal attribute!");
+      } else {
+	att.forceAddValue(value);
+	valIndex = att.indexOfValue(value);
+      }
+    }
+    setValue(att.index(), (double)valIndex);
+  }
+
+  /**
+   * Sets the weight of an instance.
+   *
+   * @param weight the weight
+   */
+  public final void setWeight(double weight) {
+
+    m_Weight = weight;
+  }
+
+  /** 
+   * Returns the value of a nominal (or string) attribute
+   * for the instance.
+   *
+   * @param attIndex the attribute's index
+   * @return the value as a string
+   * @exception IllegalArgumentException if the attribute is not a nominal
+   * (or string) attribute.
+   * @exception UnassignedDatasetException if the instance doesn't belong
+   * to a dataset.
+   */
+  public final String stringValue(int attIndex) {
+
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    } 
+    if (!m_Dataset.attribute(attIndex).isNominal() &&
+	!m_Dataset.attribute(attIndex).isString()) {
+      throw new IllegalArgumentException("Attribute neither nominal nor string!");
+    }
+    return m_Dataset.attribute(attIndex).
+      value((int) value(attIndex));
+  }
+
+  /** 
+   * Returns the value of a nominal (or string) attribute
+   * for the instance.
+   *
+   * @param att the attribute
+   * @return the value as a string
+   * @exception IllegalArgumentException if the attribute is not a nominal
+   * (or string) attribute.
+   * @exception UnassignedDatasetException if the instance doesn't belong
+   * to a dataset.
+   */
+  public final String stringValue(Attribute att) {
+
+    return stringValue(att.index());
+  }
+
+  /**
+   * Returns the values of each attribute as an array of doubles.
+   *
+   * @return an array containing all the instance attribute values
+   */
+  public double[] toDoubleArray() {
+
+    double[] newValues = new double[m_AttValues.length];
+    System.arraycopy(m_AttValues, 0, newValues, 0, 
+		     m_AttValues.length);
+    return newValues;
+  }
+
+  /**
+   * Returns the description of one instance. If the instance
+   * doesn't have access to a dataset, it returns the internal
+   * floating-point values. Quotes string
+   * values that contain whitespace characters.
+   *
+   * @return the instance's description as a string
+   */
+  public String toString() {
+
+    StringBuffer text = new StringBuffer();
+    
+    for (int i = 0; i < m_AttValues.length; i++) {
+      if (i > 0) text.append(",");
+      text.append(toString(i));
+    }
+
+    return text.toString();
+  }
+
+  /**
+   * Returns the description of one value of the instance as a 
+   * string. If the instance doesn't have access to a dataset, it 
+   * returns the internal floating-point value. Quotes string
+   * values that contain whitespace characters, or if they
+   * are a question mark.
+   *
+   * @param attIndex the attribute's index
+   * @return the value's description as a string
+   */
+  public final String toString(int attIndex) {
+
+   StringBuffer text = new StringBuffer();
+   
+   if (isMissing(attIndex)) {
+     text.append("?");
+   } else {
+     if (m_Dataset == null) {
+       text.append(Utils.doubleToString(m_AttValues[attIndex],6));
+     } else {
+       if (m_Dataset.attribute(attIndex).isNominal() || 
+	   m_Dataset.attribute(attIndex).isString()) {
+         text.append(Utils.quote(stringValue(attIndex)));
+       } else {
+	 text.append(Utils.doubleToString(value(attIndex),6));
+       }
+     }
+   }
+   return text.toString();
+  }
+
+  /**
+   * Returns the description of one value of the instance as a 
+   * string. If the instance doesn't have access to a dataset it 
+   * returns the internal floating-point value. Quotes string
+   * values that contain whitespace characters, or if they
+   * are a question mark.
+   * The given attribute has to belong to a dataset.
+   *
+   * @param att the attribute
+   * @return the value's description as a string
+   */
+  public final String toString(Attribute att) {
+   
+   return toString(att.index());
+  }
+
+  /**
+   * Returns an instance's attribute value in internal format.
+   *
+   * @param attIndex the attribute's index
+   * @return the specified value as a double (If the corresponding
+   * attribute is nominal (or a string) then it returns the value's index as a 
+   * double).
+   */
+  public double value(int attIndex) {
+
+    return m_AttValues[attIndex];
+  }
+
+  /**
+   * Returns an instance's attribute value in internal format.
+   * Does exactly the same thing as value() if applied to an Instance.
+   *
+   * @param indexOfIndex the index of the attribute's index
+   * @return the specified value as a double (If the corresponding
+   * attribute is nominal (or a string) then it returns the value's index as a 
+   * double).
+   */
+  public double valueSparse(int indexOfIndex) {
+
+    return m_AttValues[indexOfIndex];
+  }  
+
+  /**
+   * Returns an instance's attribute value in internal format.
+   * The given attribute has to belong to a dataset.
+   *
+   * @param att the attribute
+   * @return the specified value as a double (If the corresponding
+   * attribute is nominal (or a string) then it returns the value's index as a
+   * double).
+   */
+  public double value(Attribute att) {
+
+    return value(att.index());
+  }
+
+  /**
+   * Returns the instance's weight.
+   *
+   * @return the instance's weight as a double
+   */
+  public final double weight() {
+
+    return m_Weight;
+  }
+
+  /**
+   * Deletes an attribute at the given position (0 to 
+   * numAttributes() - 1).
+   *
+   * @param pos the attribute's position
+   */
+
+  void forceDeleteAttributeAt(int position) {
+
+    double[] newValues = new double[m_AttValues.length - 1];
+
+    System.arraycopy(m_AttValues, 0, newValues, 0, position);
+    if (position < m_AttValues.length - 1) {
+      System.arraycopy(m_AttValues, position + 1, 
+		       newValues, position, 
+		       m_AttValues.length - (position + 1));
+    }
+    m_AttValues = newValues;
+  }
+
+  /**
+   * Inserts an attribute at the given position
+   * (0 to numAttributes()) and sets its value to be missing. 
+   *
+   * @param pos the attribute's position
+   */
+  void forceInsertAttributeAt(int position)  {
+
+    double[] newValues = new double[m_AttValues.length + 1];
+
+    System.arraycopy(m_AttValues, 0, newValues, 0, position);
+    newValues[position] = MISSING_VALUE;
+    System.arraycopy(m_AttValues, position, newValues, 
+		     position + 1, m_AttValues.length - position);
+    m_AttValues = newValues;
+  }
+
+  /**
+   * Private constructor for subclasses. Does nothing.
+   */
+  protected Instance() {
+  }
+
+  /**
+   * Clones the attribute vector of the instance and
+   * overwrites it with the clone.
+   */
+  private void freshAttributeVector() {
+
+    m_AttValues = toDoubleArray();
+  }
+
+  /**
+   * Main method for testing this class.
+   */
+  public static void main(String[] options) {
+
+    try {
+
+      // Create numeric attributes "length" and "weight"
+      Attribute length = new Attribute("length");
+      Attribute weight = new Attribute("weight");
+      
+      // Create vector to hold nominal values "first", "second", "third" 
+      FastVector my_nominal_values = new FastVector(3); 
+      my_nominal_values.addElement("first"); 
+      my_nominal_values.addElement("second"); 
+      my_nominal_values.addElement("third"); 
+      
+      // Create nominal attribute "position" 
+      Attribute position = new Attribute("position", my_nominal_values);
+      
+      // Create vector of the above attributes 
+      FastVector attributes = new FastVector(3);
+      attributes.addElement(length);
+      attributes.addElement(weight);
+      attributes.addElement(position);
+      
+      // Create the empty dataset "race" with above attributes
+      Instances race = new Instances("race", attributes, 0);
+      
+      // Make position the class attribute
+      race.setClassIndex(position.index());
+      
+      // Create empty instance with three attribute values
+      Instance inst = new Instance(3);
+      
+      // Set instance's values for the attributes "length", "weight", and "position"
+      inst.setValue(length, 5.3);
+      inst.setValue(weight, 300);
+      inst.setValue(position, "first");
+      
+      // Set instance's dataset to be the dataset "race"
+      inst.setDataset(race);
+      
+      // Print the instance
+      System.out.println("The instance: " + inst);
+      
+      // Print the first attribute
+      System.out.println("First attribute: " + inst.attribute(0));
+      
+      // Print the class attribute
+      System.out.println("Class attribute: " + inst.classAttribute());
+      
+      // Print the class index
+      System.out.println("Class index: " + inst.classIndex());
+      
+      // Say if class is missing
+      System.out.println("Class is missing: " + inst.classIsMissing());
+      
+      // Print the instance's class value in internal format
+      System.out.println("Class value (internal format): " + inst.classValue());
+      
+      // Print a shallow copy of this instance
+      Instance copy = (Instance) inst.copy();
+      System.out.println("Shallow copy: " + copy);
+      
+      // Set dataset for shallow copy
+      copy.setDataset(inst.dataset());
+      System.out.println("Shallow copy with dataset set: " + copy);
+      
+      // Unset dataset for copy, delete first attribute, and insert it again
+      copy.setDataset(null);
+      copy.deleteAttributeAt(0);
+      copy.insertAttributeAt(0);
+      copy.setDataset(inst.dataset());
+      System.out.println("Copy with first attribute deleted and inserted: " + copy); 
+      
+      // Enumerate attributes (leaving out the class attribute)
+      System.out.println("Enumerating attributes (leaving out class):");
+      Enumeration enum = inst.enumerateAttributes();
+      while (enum.hasMoreElements()) {
+	Attribute att = (Attribute) enum.nextElement();
+	System.out.println(att);
+      }
+      
+      // Headers are equivalent?
+      System.out.println("Header of original and copy equivalent: " +
+			 inst.equalHeaders(copy));
+
+      // Test for missing values
+      System.out.println("Length of copy missing: " + copy.isMissing(length));
+      System.out.println("Weight of copy missing: " + copy.isMissing(weight.index()));
+      System.out.println("Length of copy missing: " + 
+			 Instance.isMissingValue(copy.value(length)));
+      System.out.println("Missing value coded as: " + Instance.missingValue());
+
+      // Prints number of attributes and classes
+      System.out.println("Number of attributes: " + copy.numAttributes());
+      System.out.println("Number of classes: " + copy.numClasses());
+
+      // Replace missing values
+      double[] meansAndModes = {2, 3, 0};
+      copy.replaceMissingValues(meansAndModes);
+      System.out.println("Copy with missing value replaced: " + copy);
+
+      // Setting and getting values and weights
+      copy.setClassMissing();
+      System.out.println("Copy with missing class: " + copy);
+      copy.setClassValue(0);
+      System.out.println("Copy with class value set to first value: " + copy);
+      copy.setClassValue("third");
+      System.out.println("Copy with class value set to \"third\": " + copy);
+      copy.setMissing(1);
+      System.out.println("Copy with second attribute set to be missing: " + copy);
+      copy.setMissing(length);
+      System.out.println("Copy with length set to be missing: " + copy);
+      copy.setValue(0, 0);
+      System.out.println("Copy with first attribute set to 0: " + copy);
+      copy.setValue(weight, 1);
+      System.out.println("Copy with weight attribute set to 1: " + copy);
+      copy.setValue(position, "second");
+      System.out.println("Copy with position set to \"second\": " + copy);
+      copy.setValue(2, "first");
+      System.out.println("Copy with last attribute set to \"first\": " + copy);
+      System.out.println("Current weight of instance copy: " + copy.weight());
+      copy.setWeight(2);
+      System.out.println("Current weight of instance copy (set to 2): " + copy.weight());
+      System.out.println("Last value of copy: " + copy.toString(2));
+      System.out.println("Value of position for copy: " + copy.toString(position));
+      System.out.println("Last value of copy (internal format): " + copy.value(2));
+      System.out.println("Value of position for copy (internal format): " + 
+			 copy.value(position));
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/Instances.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/Instances.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/Instances.java	(revision 8815)
@@ -0,0 +1,2150 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Instances.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Class for handling an ordered set of weighted instances. <p>
+ *
+ * Typical usage (code from the main() method of this class): <p>
+ *
+ * <code>
+ * ... <br>
+ * 
+ * // Read all the instances in the file <br>
+ * reader = new FileReader(filename); <br>
+ * instances = new Instances(reader); <br><br>
+ *
+ * // Make the last attribute be the class <br>
+ * instances.setClassIndex(instances.numAttributes() - 1); <br><br>
+ * 
+ * // Print header and instances. <br>
+ * System.out.println("\nDataset:\n"); <br> 
+ * System.out.println(instances); <br><br>
+ *
+ * ... <br>
+ * </code><p>
+ *
+ * All methods that change a set of instances are safe, ie. a change
+ * of a set of instances does not affect any other sets of
+ * instances. All methods that change a datasets's attribute
+ * information clone the dataset before it is changed.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$ 
+ */
+public class Instances implements Serializable {
+ 
+  /** The filename extension that should be used for arff files */
+  public static String FILE_EXTENSION = ".arff";
+
+  /** The dataset's name. */
+  protected String m_RelationName;         
+
+  /** The attribute information. */
+  protected FastVector m_Attributes;
+
+  /** The instances. */
+  protected FastVector m_Instances;
+
+  /** The class attribute's index */
+  protected int m_ClassIndex;
+
+  /** Buffer of values for sparse instance */
+  protected double[] m_ValueBuffer;
+
+  /** Buffer of indices for sparse instance */
+  protected int[] m_IndicesBuffer;
+
+  /**
+   * Reads an ARFF file from a reader, and assigns a weight of
+   * one to each instance. Lets the index of the class 
+   * attribute be undefined (negative).
+   *
+   * @param reader the reader
+   * @exception IOException if the ARFF file is not read 
+   * successfully
+   */
+  public Instances(Reader reader) throws IOException {
+
+    StreamTokenizer tokenizer;
+
+    tokenizer = new StreamTokenizer(reader);
+    initTokenizer(tokenizer);
+    readHeader(tokenizer);
+    m_ClassIndex = -1;
+    m_Instances = new FastVector(1000);
+    while (getInstance(tokenizer, true)) {};
+    compactify();
+  }
+ 
+  /**
+   * Reads the header of an ARFF file from a reader and 
+   * reserves space for the given number of instances. Lets
+   * the class index be undefined (negative).
+   *
+   * @param reader the reader
+   * @param capacity the capacity
+   * @exception IllegalArgumentException if the header is not read successfully
+   * or the capacity is negative.
+   * @exception IOException if there is a problem with the reader.
+   */
+   public Instances(Reader reader, int capacity) throws IOException {
+
+    StreamTokenizer tokenizer;
+
+    if (capacity < 0) {
+      throw new IllegalArgumentException("Capacity has to be positive!");
+    }
+    tokenizer = new StreamTokenizer(reader); 
+    initTokenizer(tokenizer);
+    readHeader(tokenizer);
+    m_ClassIndex = -1;
+    m_Instances = new FastVector(capacity);
+  }
+
+  /**
+   * Constructor copying all instances and references to
+   * the header information from the given set of instances.
+   *
+   * @param instances the set to be copied
+   */
+  public Instances(Instances dataset) {
+
+    this(dataset, dataset.numInstances());
+
+    dataset.copyInstances(0, this, dataset.numInstances());
+  }
+
+  /**
+   * Constructor creating an empty set of instances. Copies references
+   * to the header information from the given set of instances. Sets
+   * the capacity of the set of instances to 0 if its negative.
+   *
+   * @param instances the instances from which the header 
+   * information is to be taken
+   * @param capacity the capacity of the new dataset 
+   */
+  public Instances(Instances dataset, int capacity) {
+    
+    if (capacity < 0) {
+      capacity = 0;
+    }
+    
+    // Strings only have to be "shallow" copied because
+    // they can't be modified.
+    m_ClassIndex = dataset.m_ClassIndex;
+    m_RelationName = dataset.m_RelationName;
+    m_Attributes = dataset.m_Attributes;
+    m_Instances = new FastVector(capacity);
+  }
+
+  /**
+   * Creates a new set of instances by copying a 
+   * subset of another set.
+   *
+   * @param source the set of instances from which a subset 
+   * is to be created
+   * @param first the index of the first instance to be copied
+   * @param toCopy the number of instances to be copied
+   * @exception IllegalArgumentException if first and toCopy are out of range
+   */
+  public Instances(Instances source, int first, int toCopy) {
+    
+    this(source, toCopy);
+
+    if ((first < 0) || ((first + toCopy) > source.numInstances())) {
+      throw new IllegalArgumentException("Parameters first and/or toCopy out "+
+                                         "of range");
+    }
+    source.copyInstances(first, this, toCopy);
+  }
+
+  /**
+   * Creates an empty set of instances. Uses the given
+   * attribute information. Sets the capacity of the set of 
+   * instances to 0 if its negative. Given attribute information
+   * must not be changed after this constructor has been used.
+   *
+   * @param name the name of the relation
+   * @param attInfo the attribute information
+   * @param capacity the capacity of the set
+   */
+  public Instances(String name, FastVector attInfo, int capacity) {
+
+    m_RelationName = name;
+    m_ClassIndex = -1;
+    m_Attributes = attInfo;
+    for (int i = 0; i < numAttributes(); i++) {
+      attribute(i).setIndex(i);
+    }
+    m_Instances = new FastVector(capacity);
+  }
+ 
+  /**
+   * Create a copy of the structure, but "cleanse" string types (i.e.
+   * doesn't contain references to the strings seen in the past).
+   *
+   * @return a copy of the instance structure.
+   */
+  public Instances stringFreeStructure() {
+
+    FastVector atts = (FastVector)m_Attributes.copy();
+    for (int i = 0 ; i < atts.size(); i++) {
+      Attribute att = (Attribute)atts.elementAt(i);
+      if (att.type() == Attribute.STRING) {
+        atts.setElementAt(new Attribute(att.name(), null), i);
+      }
+    }
+    Instances result = new Instances(relationName(), atts, 0);
+    result.m_ClassIndex = m_ClassIndex;
+    return result;
+  }
+
+  /**
+   * Adds one instance to the end of the set. 
+   * Shallow copies instance before it is added. Increases the
+   * size of the dataset if it is not large enough. Does not
+   * check if the instance is compatible with the dataset.
+   *
+   * @param instance the instance to be added
+   */
+  public final void add(Instance instance) {
+
+    Instance newInstance = (Instance)instance.copy();
+
+    newInstance.setDataset(this);
+    m_Instances.addElement(newInstance);
+  }
+
+  /**
+   * Returns an attribute.
+   *
+   * @param index the attribute's index
+   * @return the attribute at the given position
+   */ 
+  public final Attribute attribute(int index) {
+    
+    return (Attribute) m_Attributes.elementAt(index);
+  }
+
+  /**
+   * Returns an attribute given its name. If there is more than
+   * one attribute with the same name, it returns the first one.
+   * Returns null if the attribute can't be found.
+   *
+   * @param name the attribute's name
+   * @return the attribute with the given name, null if the
+   * attribute can't be found
+   */ 
+  public final Attribute attribute(String name) {
+    
+    for (int i = 0; i < numAttributes(); i++) {
+      if (attribute(i).name().equals(name)) {
+	return attribute(i);
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Checks for string attributes in the dataset
+   *
+   * @return true if string attributes are present, false otherwise
+   */
+  public boolean checkForStringAttributes() {
+
+    int i = 0;
+   
+    while (i < m_Attributes.size()) {
+      if (attribute(i++).isString()) {
+	return true;
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Checks if the given instance is compatible
+   * with this dataset. Only looks at the size of
+   * the instance and the ranges of the values for 
+   * nominal and string attributes.
+   *
+   * @return true if the instance is compatible with the dataset 
+   */
+  public final boolean checkInstance(Instance instance) {
+
+    if (instance.numAttributes() != numAttributes()) {
+      return false;
+    }
+    for (int i = 0; i < numAttributes(); i++) {
+      if (instance.isMissing(i)) {
+	continue;
+      } else if (attribute(i).isNominal() ||
+		 attribute(i).isString()) {
+	if (!(Utils.eq(instance.value(i),
+		       (double)(int)instance.value(i)))) {
+	  return false;
+	} else if (Utils.sm(instance.value(i), 0) ||
+		   Utils.gr(instance.value(i),
+			    attribute(i).numValues())) {
+	  return false;
+	}
+      }
+    }
+    return true;
+  }
+	
+  /**
+   * Returns the class attribute.
+   *
+   * @return the class attribute
+   * @exception UnassignedClassException if the class is not set
+   */
+  public final Attribute classAttribute() {
+
+    if (m_ClassIndex < 0) {
+      throw new UnassignedClassException("Class index is negative (not set)!");
+    }
+    return attribute(m_ClassIndex);
+  }
+
+  /**
+   * Returns the class attribute's index. Returns negative number
+   * if it's undefined.
+   *
+   * @return the class index as an integer
+   */
+  public final int classIndex() {
+    
+    return m_ClassIndex;
+  }
+ 
+  /**
+   * Compactifies the set of instances. Decreases the capacity of
+   * the set so that it matches the number of instances in the set.
+   */
+  public final void compactify() {
+
+    m_Instances.trimToSize();
+  }
+
+  /**
+   * Removes all instances from the set.
+   */
+  public final void delete() {
+    
+    m_Instances = new FastVector();
+  }
+
+  /**
+   * Removes an instance at the given position from the set.
+   *
+   * @param index the instance's position
+   */
+  public final void delete(int index) {
+    
+    m_Instances.removeElementAt(index);
+  }
+
+  /**
+   * Deletes an attribute at the given position 
+   * (0 to numAttributes() - 1). A deep copy of the attribute
+   * information is performed before the attribute is deleted.
+   *
+   * @param pos the attribute's position
+   * @exception IllegalArgumentException if the given index is out of range or the
+   * class attribute is being deleted
+   */
+  public void deleteAttributeAt(int position) {
+	 
+    if ((position < 0) || (position >= m_Attributes.size())) {
+      throw new IllegalArgumentException("Index out of range");
+    }
+    if (position == m_ClassIndex) {
+      throw new IllegalArgumentException("Can't delete class attribute");
+    }
+    freshAttributeInfo();
+    if (m_ClassIndex > position) {
+      m_ClassIndex--;
+    }
+    m_Attributes.removeElementAt(position);
+    for (int i = position; i < m_Attributes.size(); i++) {
+      Attribute current = (Attribute)m_Attributes.elementAt(i);
+      current.setIndex(current.index() - 1);
+    }
+    for (int i = 0; i < numInstances(); i++) {
+      instance(i).forceDeleteAttributeAt(position); 
+    }
+  }
+
+  /**
+   * Deletes all string attributes in the dataset. A deep copy of the attribute
+   * information is performed before an attribute is deleted.
+   *
+   * @exception IllegalArgumentException if string attribute couldn't be 
+   * successfully deleted (probably because it is the class attribute).
+   */
+  public void deleteStringAttributes() {
+
+    int i = 0;
+    while (i < m_Attributes.size()) {
+      if (attribute(i).isString()) {
+	deleteAttributeAt(i);
+      } else {
+	i++;
+      }
+    }
+  }
+
+  /**
+   * Removes all instances with missing values for a particular
+   * attribute from the dataset.
+   *
+   * @param attIndex the attribute's index
+   */
+  public final void deleteWithMissing(int attIndex) {
+
+    FastVector newInstances = new FastVector(numInstances());
+
+    for (int i = 0; i < numInstances(); i++) {
+      if (!instance(i).isMissing(attIndex)) {
+	newInstances.addElement(instance(i));
+      }
+    }
+    m_Instances = newInstances;
+  }
+
+  /**
+   * Removes all instances with missing values for a particular
+   * attribute from the dataset.
+   *
+   * @param att the attribute
+   */
+  public final void deleteWithMissing(Attribute att) {
+
+    deleteWithMissing(att.index());
+  }
+
+  /**
+   * Removes all instances with a missing class value
+   * from the dataset.
+   *
+   * @exception UnassignedClassException if class is not set
+   */
+  public final void deleteWithMissingClass() {
+
+    if (m_ClassIndex < 0) {
+      throw new UnassignedClassException("Class index is negative (not set)!");
+    }
+    deleteWithMissing(m_ClassIndex);
+  }
+
+  /**
+   * Returns an enumeration of all the attributes.
+   *
+   * @return enumeration of all the attributes.
+   */
+  public Enumeration enumerateAttributes() {
+
+    return m_Attributes.elements(m_ClassIndex);
+  }
+
+  /**
+   * Returns an enumeration of all instances in the dataset.
+   *
+   * @return enumeration of all instances in the dataset
+   */
+  public final Enumeration enumerateInstances() {
+
+    return m_Instances.elements();
+  }
+
+  /**
+   * Checks if two headers are equivalent.
+   *
+   * @param dataset another dataset
+   * @return true if the header of the given dataset is equivalent 
+   * to this header
+   */
+  public final boolean equalHeaders(Instances dataset){
+
+    // Check class and all attributes
+    if (m_ClassIndex != dataset.m_ClassIndex) {
+      return false;
+    }
+    if (m_Attributes.size() != dataset.m_Attributes.size()) {
+      return false;
+    }
+    for (int i = 0; i < m_Attributes.size(); i++) {
+      if (!(attribute(i).equals(dataset.attribute(i)))) {
+	return false;
+      }
+    }
+    return true;
+  }
+ 
+  /**
+   * Returns the first instance in the set.
+   *
+   * @return the first instance in the set
+   */
+  public final Instance firstInstance() {
+    
+    return (Instance)m_Instances.firstElement();
+  }
+ 
+  /**
+   * Inserts an attribute at the given position (0 to 
+   * numAttributes()) and sets all values to be missing.
+   * Shallow copies the attribute before it is inserted, and performs
+   * a deep copy of the existing attribute information.
+   *
+   * @param att the attribute to be inserted
+   * @param pos the attribute's position
+   * @exception IllegalArgumentException if the given index is out of range
+   */
+  public void insertAttributeAt(Attribute att, int position) {
+	 
+    if ((position < 0) ||
+	(position > m_Attributes.size())) {
+      throw new IllegalArgumentException("Index out of range");
+    }
+    att = (Attribute)att.copy();
+    freshAttributeInfo();
+    att.setIndex(position);
+    m_Attributes.insertElementAt(att, position);
+    for (int i = position + 1; i < m_Attributes.size(); i++) {
+      Attribute current = (Attribute)m_Attributes.elementAt(i);
+      current.setIndex(current.index() + 1);
+    }
+    for (int i = 0; i < numInstances(); i++) {
+      instance(i).forceInsertAttributeAt(position);
+    }
+    if (m_ClassIndex >= position) {
+      m_ClassIndex++;
+    }
+  }
+
+  /**
+   * Returns the instance at the given position.
+   *
+   * @param index the instance's index
+   * @return the instance at the given position
+   */
+  public final Instance instance(int index) {
+
+    return (Instance)m_Instances.elementAt(index);
+  }
+
+  /**
+   * Returns the last instance in the set.
+   *
+   * @return the last instance in the set
+   */
+  public final Instance lastInstance() {
+    
+    return (Instance)m_Instances.lastElement();
+  }
+
+  /**
+   * Returns the mean (mode) for a numeric (nominal) attribute as
+   * a floating-point value. Returns 0 if the attribute is neither nominal nor 
+   * numeric. If all values are missing it returns zero.
+   *
+   * @param attIndex the attribute's index
+   * @return the mean or the mode
+   */
+  public final double meanOrMode(int attIndex) {
+
+    double result, found;
+    int [] counts;
+
+    if (attribute(attIndex).isNumeric()) {
+      result = found = 0;
+      for (int j = 0; j < numInstances(); j++) {
+	if (!instance(j).isMissing(attIndex)) {
+	  found += instance(j).weight();
+	  result += instance(j).weight()*instance(j).value(attIndex);
+	}
+      }
+      if (Utils.eq(found, 0)) {
+	return 0;
+      } else {
+	return result / found;
+      }
+    } else if (attribute(attIndex).isNominal()) {
+      counts = new int[attribute(attIndex).numValues()];
+      for (int j = 0; j < numInstances(); j++) {
+	if (!instance(j).isMissing(attIndex)) {
+	  counts[(int) instance(j).value(attIndex)] += instance(j).weight();
+	}
+      }
+      return (double)Utils.maxIndex(counts);
+    } else {
+      return 0;
+    }
+  }
+
+  /**
+   * Returns the mean (mode) for a numeric (nominal) attribute as a
+   * floating-point value.  Returns 0 if the attribute is neither
+   * nominal nor numeric.  If all values are missing it returns zero.
+   *
+   * @param att the attribute
+   * @return the mean or the mode 
+   */
+  public final double meanOrMode(Attribute att) {
+
+    return meanOrMode(att.index());
+  }
+
+  /**
+   * Returns the number of attributes.
+   *
+   * @return the number of attributes as an integer
+   */
+  public final int numAttributes() {
+
+    return m_Attributes.size();
+  }
+
+  /**
+   * Returns the number of class labels.
+   *
+   * @return the number of class labels as an integer if the class 
+   * attribute is nominal, 1 otherwise.
+   * @exception UnassignedClassException if the class is not set
+   */
+  public final int numClasses() {
+    
+    if (m_ClassIndex < 0) {
+      throw new UnassignedClassException("Class index is negative (not set)!");
+    }
+    if (!classAttribute().isNominal()) {
+      return 1;
+    } else {
+      return classAttribute().numValues();
+    }
+  }
+
+  /**
+   * Returns the number of distinct values of a given attribute.
+   * Returns the number of instances if the attribute is a
+   * string attribute. The value 'missing' is not counted.
+   *
+   * @param attIndex the attribute
+   * @return the number of distinct values of a given attribute
+   */
+  public final int numDistinctValues(int attIndex) {
+
+    if (attribute(attIndex).isNumeric()) {
+      double [] attVals = attributeToDoubleArray(attIndex);
+      int [] sorted = Utils.sort(attVals);
+      double prev = 0;
+      int counter = 0;
+      for (int i = 0; i < sorted.length; i++) {
+	Instance current = instance(sorted[i]);
+	if (current.isMissing(attIndex)) {
+	  break;
+	}
+	if ((i == 0) || 
+	    Utils.gr(current.value(attIndex), prev)) {
+	  prev = current.value(attIndex);
+	  counter++;
+	}
+      }
+      return counter;
+    } else {
+      return attribute(attIndex).numValues();
+    }
+  }
+
+  /**
+   * Returns the number of distinct values of a given attribute.
+   * Returns the number of instances if the attribute is a
+   * string attribute. The value 'missing' is not counted.
+   *
+   * @param att the attribute
+   * @return the number of distinct values of a given attribute
+   */
+  public final int numDistinctValues(Attribute att) {
+
+    return numDistinctValues(att.index());
+  }
+  
+  /**
+   * Returns the number of instances in the dataset.
+   *
+   * @return the number of instances in the dataset as an integer
+   */
+  public final int numInstances() {
+
+    return m_Instances.size();
+  }
+
+  /**
+   * Shuffles the instances in the set so that they are ordered 
+   * randomly.
+   *
+   * @param random a random number generator
+   */
+  public final void randomize(Random random) {
+
+    for (int j = numInstances() - 1; j > 0; j--)
+      swap(j,(int)(random.nextDouble()*(double)j));
+  }
+
+  /**
+   * Reads a single instance from the reader and appends it
+   * to the dataset.  Automatically expands the dataset if it
+   * is not large enough to hold the instance. This method does
+   * not check for carriage return at the end of the line.
+   *
+   * @param reader the reader 
+   * @return false if end of file has been reached
+   * @exception IOException if the information is not read 
+   * successfully
+   */ 
+  public final boolean readInstance(Reader reader) 
+       throws IOException {
+
+    StreamTokenizer tokenizer = new StreamTokenizer(reader);
+    
+    initTokenizer(tokenizer);
+    return getInstance(tokenizer, false);
+  }    
+
+  /**
+   * Returns the relation's name.
+   *
+   * @return the relation's name as a string
+   */
+  public final String relationName() {
+
+    return m_RelationName;
+  }
+
+  /**
+   * Renames an attribute. This change only affects this
+   * dataset.
+   *
+   * @param att the attribute's index
+   * @param name the new name
+   */
+  public final void renameAttribute(int att, String name) {
+
+    Attribute newAtt = attribute(att).copy(name);
+    FastVector newVec = new FastVector(numAttributes());
+
+    for (int i = 0; i < numAttributes(); i++) {
+      if (i == att) {
+	newVec.addElement(newAtt);
+      } else {
+	newVec.addElement(attribute(i));
+      }
+    }
+    m_Attributes = newVec;
+  }
+
+  /**
+   * Renames an attribute. This change only affects this
+   * dataset.
+   *
+   * @param att the attribute
+   * @param name the new name
+   */
+  public final void renameAttribute(Attribute att, String name) {
+
+    renameAttribute(att.index(), name);
+  }
+
+  /**
+   * Renames the value of a nominal (or string) attribute value. This
+   * change only affects this dataset.
+   *
+   * @param att the attribute's index
+   * @param val the value's index
+   * @param name the new name 
+   */
+  public final void renameAttributeValue(int att, int val, String name) {
+
+    Attribute newAtt = (Attribute)attribute(att).copy();
+    FastVector newVec = new FastVector(numAttributes());
+
+    newAtt.setValue(val, name);
+    for (int i = 0; i < numAttributes(); i++) {
+      if (i == att) {
+	newVec.addElement(newAtt);
+      } else {
+	newVec.addElement(attribute(i));
+      }
+    }
+    m_Attributes = newVec;
+  }
+
+  /**
+   * Renames the value of a nominal (or string) attribute value. This
+   * change only affects this dataset.
+   *
+   * @param att the attribute
+   * @param val the value
+   * @param name the new name
+   */
+  public final void renameAttributeValue(Attribute att, String val, 
+                                         String name) {
+
+    renameAttributeValue(att.index(), att.indexOfValue(val), name);
+  }
+
+  /**
+   * Creates a new dataset of the same size using random sampling
+   * with replacement.
+   *
+   * @param random a random number generator
+   * @return the new dataset
+   */
+  public final Instances resample(Random random) {
+
+    Instances newData = new Instances(this, numInstances());
+    while (newData.numInstances() < numInstances()) {
+      int i = (int) (random.nextDouble() * (double) numInstances());
+      newData.add(instance(i));
+    }
+    return newData;
+  }
+
+  /**
+   * Creates a new dataset of the same size using random sampling
+   * with replacement according to the current instance weights. The
+   * weights of the instances in the new dataset are set to one.
+   *
+   * @param random a random number generator
+   * @return the new dataset
+   */
+  public final Instances resampleWithWeights(Random random) {
+
+    double [] weights = new double[numInstances()];
+    boolean foundOne = false;
+    for (int i = 0; i < weights.length; i++) {
+      weights[i] = instance(i).weight();
+      if (!Utils.eq(weights[i], weights[0])) {
+        foundOne = true;
+      }
+    }
+    if (foundOne) {
+      return resampleWithWeights(random, weights);
+    } else {
+      return new Instances(this);
+    }
+  }
+
+
+  /**
+   * Creates a new dataset of the same size using random sampling
+   * with replacement according to the given weight vector. The
+   * weights of the instances in the new dataset are set to one.
+   * The length of the weight vector has to be the same as the
+   * number of instances in the dataset, and all weights have to
+   * be positive.
+   *
+   * @param random a random number generator
+   * @param weights the weight vector
+   * @return the new dataset
+   * @exception IllegalArgumentException if the weights array is of the wrong
+   * length or contains negative weights.
+   */
+  public final Instances resampleWithWeights(Random random, 
+					     double[] weights) {
+
+    if (weights.length != numInstances()) {
+      throw new IllegalArgumentException("weights.length != numInstances.");
+    }
+    Instances newData = new Instances(this, numInstances());
+    double[] probabilities = new double[numInstances()];
+    double sumProbs = 0, sumOfWeights = Utils.sum(weights);
+    for (int i = 0; i < numInstances(); i++) {
+      sumProbs += random.nextDouble();
+      probabilities[i] = sumProbs;
+    }
+    Utils.normalize(probabilities, sumProbs / sumOfWeights);
+
+    // Make sure that rounding errors don't mess things up
+    probabilities[numInstances() - 1] = sumOfWeights;
+    int k = 0; int l = 0;
+    sumProbs = 0;
+    while ((k < numInstances() && (l < numInstances()))) {
+      if (weights[l] < 0) {
+	throw new IllegalArgumentException("Weights have to be positive.");
+      }
+      sumProbs += weights[l];
+      while ((k < numInstances()) &&
+	     (probabilities[k] <= sumProbs)) { 
+	newData.add(instance(l));
+	newData.instance(k).setWeight(1);
+	k++;
+      }
+      l++;
+    }
+    return newData;
+  }
+
+  /** 
+   * Sets the class attribute.
+   *
+   * @param att attribute to be the class
+   */
+  public final void setClass(Attribute att) {
+
+    m_ClassIndex = att.index();
+  }
+
+  /** 
+   * Sets the class index of the set.
+   * If the class index is negative there is assumed to be no class.
+   * (ie. it is undefined)
+   *
+   * @param classIndex the new class index
+   * @exception IllegalArgumentException if the class index is too big or < 0
+   */
+  public final void setClassIndex(int classIndex) {
+
+    if (classIndex >= numAttributes()) {
+      throw new IllegalArgumentException("Invalid class index: " + classIndex);
+    }
+    m_ClassIndex = classIndex;
+  }
+
+  /**
+   * Sets the relation's name.
+   *
+   * @param newName the new relation name.
+   */
+  public final void setRelationName(String newName) {
+    
+    m_RelationName = newName;
+  }
+
+  /**
+   * Sorts the instances based on an attribute. For numeric attributes, 
+   * instances are sorted in ascending order. For nominal attributes, 
+   * instances are sorted based on the attribute label ordering 
+   * specified in the header. Instances with missing values for the 
+   * attribute are placed at the end of the dataset.
+   *
+   * @param attIndex the attribute's index
+   */
+  public final void sort(int attIndex) {
+
+    int i,j;
+
+    // move all instances with missing values to end
+    j = numInstances() - 1;
+    i = 0;
+    while (i <= j) {
+      if (instance(j).isMissing(attIndex)) {
+	j--;
+      } else {
+	if (instance(i).isMissing(attIndex)) {
+	  swap(i,j);
+	  j--;
+	}
+	i++;
+      }
+    }
+    quickSort(attIndex, 0, j);
+  }
+
+  /**
+   * Sorts the instances based on an attribute. For numeric attributes, 
+   * instances are sorted into ascending order. For nominal attributes, 
+   * instances are sorted based on the attribute label ordering 
+   * specified in the header. Instances with missing values for the 
+   * attribute are placed at the end of the dataset.
+   *
+   * @param att the attribute
+   */
+  public final void sort(Attribute att) {
+
+    sort(att.index());
+  }
+
+  /**
+   * Stratifies a set of instances according to its class values 
+   * if the class attribute is nominal (so that afterwards a 
+   * stratified cross-validation can be performed).
+   *
+   * @param numFolds the number of folds in the cross-validation
+   * @exception UnassignedClassException if the class is not set
+   */
+  public final void stratify(int numFolds) {
+    
+    if (numFolds <= 0) {
+      throw new IllegalArgumentException("Number of folds must be greater than 1");
+    }
+    if (m_ClassIndex < 0) {
+      throw new UnassignedClassException("Class index is negative (not set)!");
+    }
+    if (classAttribute().isNominal()) {
+
+      // sort by class
+      int index = 1;
+      while (index < numInstances()) {
+	Instance instance1 = instance(index - 1);
+	for (int j = index; j < numInstances(); j++) {
+	  Instance instance2 = instance(j);
+	  if ((instance1.classValue() == instance2.classValue()) ||
+	      (instance1.classIsMissing() && 
+	       instance2.classIsMissing())) {
+	    swap(index,j);
+	    index++;
+	  }
+	}
+	index++;
+      }
+      stratStep(numFolds);
+    }
+  }
+ 
+  /**
+   * Computes the sum of all the instances' weights.
+   *
+   * @return the sum of all the instances' weights as a double
+   */
+  public final double sumOfWeights() {
+    
+    double sum = 0;
+
+    for (int i = 0; i < numInstances(); i++) {
+      sum += instance(i).weight();
+    }
+    return sum;
+  }
+
+  /**
+   * Creates the test set for one fold of a cross-validation on 
+   * the dataset.
+   *
+   * @param numFolds the number of folds in the cross-validation. Must
+   * be greater than 1.
+   * @param numFold 0 for the first fold, 1 for the second, ...
+   * @return the test set as a set of weighted instances
+   * @exception IllegalArgumentException if the number of folds is less than 2
+   * or greater than the number of instances.
+   */
+  public Instances testCV(int numFolds, int numFold) {
+
+    int numInstForFold, first, offset;
+    Instances test;
+    
+    if (numFolds < 2) {
+      throw new IllegalArgumentException("Number of folds must be at least 2!");
+    }
+    if (numFolds > numInstances()) {
+      throw new IllegalArgumentException("Can't have more folds than instances!");
+    }
+    numInstForFold = numInstances() / numFolds;
+    if (numFold < numInstances() % numFolds){
+      numInstForFold++;
+      offset = numFold;
+    }else
+      offset = numInstances() % numFolds;
+    test = new Instances(this, numInstForFold);
+    first = numFold * (numInstances() / numFolds) + offset;
+    copyInstances(first, test, numInstForFold);
+    return test;
+  }
+ 
+  /**
+   * Returns the dataset as a string in ARFF format. Strings
+   * are quoted if they contain whitespace characters, or if they
+   * are a question mark.
+   *
+   * @return the dataset in ARFF format as a string
+   */
+  public final String toString() {
+    
+    StringBuffer text = new StringBuffer();
+    
+    text.append("@relation " + Utils.quote(m_RelationName) + "\n\n");
+    for (int i = 0; i < numAttributes(); i++) {
+      text.append(attribute(i) + "\n");
+    }
+    text.append("\n@data\n");
+    for (int i = 0; i < numInstances(); i++) {
+      text.append(instance(i));
+      if (i < numInstances() - 1) {
+	text.append('\n');
+      }
+    }
+    return text.toString();
+  }
+
+  /**
+   * Creates the training set for one fold of a cross-validation 
+   * on the dataset.
+   *
+   * @param numFolds the number of folds in the cross-validation. Must
+   * be greater than 1.
+   * @param numFold 0 for the first fold, 1 for the second, ...
+   * @return the training set as a set of weighted 
+   * instances
+   * @exception IllegalArgumentException if the number of folds is less than 2
+   * or greater than the number of instances.
+   */
+  public Instances trainCV(int numFolds, int numFold) {
+
+    int numInstForFold, first, offset;
+    Instances train;
+ 
+    if (numFolds < 2) {
+      throw new IllegalArgumentException("Number of folds must be at least 2!");
+    }
+    if (numFolds > numInstances()) {
+      throw new IllegalArgumentException("Can't have more folds than instances!");
+    }
+    numInstForFold = numInstances() / numFolds;
+    if (numFold < numInstances() % numFolds) {
+      numInstForFold++;
+      offset = numFold;
+    }else
+      offset = numInstances() % numFolds;
+    train = new Instances(this, numInstances() - numInstForFold);
+    first = numFold * (numInstances() / numFolds) + offset;
+    copyInstances(0, train, first);
+    copyInstances(first + numInstForFold, train,
+		  numInstances() - first - numInstForFold);
+
+    return train;
+  }
+
+  /**
+   * Computes the variance for a numeric attribute.
+   *
+   * @param attIndex the numeric attribute
+   * @return the variance if the attribute is numeric
+   * @exception IllegalArgumentException if the attribute is not numeric
+   */
+  public final double variance(int attIndex) {
+  
+    double sum = 0, sumSquared = 0, sumOfWeights = 0;
+
+    if (!attribute(attIndex).isNumeric()) {
+      throw new IllegalArgumentException("Can't compute variance because attribute is " +
+			  "not numeric!");
+    }
+    for (int i = 0; i < numInstances(); i++) {
+      if (!instance(i).isMissing(attIndex)) {
+	sum += instance(i).weight() * 
+	  instance(i).value(attIndex);
+	sumSquared += instance(i).weight() * 
+	  instance(i).value(attIndex) *
+	  instance(i).value(attIndex);
+	sumOfWeights += instance(i).weight();
+      }
+    }
+    if (Utils.smOrEq(sumOfWeights, 1)) {
+      return 0;
+    }
+    return (sumSquared - (sum * sum / sumOfWeights)) / 
+      (sumOfWeights - 1);
+  }
+
+  /**
+   * Computes the variance for a numeric attribute.
+   *
+   * @param att the numeric attribute
+   * @return the variance if the attribute is numeric
+   * @exception IllegalArgumentException if the attribute is not numeric
+   */
+  public final double variance(Attribute att) {
+    
+    return variance(att.index());
+  }
+  
+  /**
+   * Calculates summary statistics on the values that appear in this
+   * set of instances for a specified attribute.
+   *
+   * @param index the index of the attribute to summarize.
+   * @return an AttributeStats object with it's fields calculated.
+   */
+  public AttributeStats attributeStats(int index) {
+
+    AttributeStats result = new AttributeStats();
+    if (attribute(index).isNominal()) {
+      result.nominalCounts = new int [attribute(index).numValues()];
+    }
+    if (attribute(index).isNumeric()) {
+      result.numericStats = new weka.experiment.Stats();
+    }
+    result.totalCount = numInstances();
+
+    double [] attVals = attributeToDoubleArray(index);
+    int [] sorted = Utils.sort(attVals);
+    int currentCount = 0;
+    double prev = Instance.missingValue();
+    for (int j = 0; j < numInstances(); j++) {
+      Instance current = instance(sorted[j]);
+      if (current.isMissing(index)) {
+	result.missingCount = numInstances() - j;
+	break;
+      }
+      if (Utils.eq(current.value(index), prev)) {
+	currentCount++;
+      } else {
+	result.addDistinct(prev, currentCount);
+	currentCount = 1;
+	prev = current.value(index);
+      }
+    }
+    result.addDistinct(prev, currentCount);
+    result.distinctCount--; // So we don't count "missing" as a value 
+    return result;
+  }
+  
+  /**
+   * Gets the value of all instances in this dataset for a particular
+   * attribute. Useful in conjunction with Utils.sort to allow iterating
+   * through the dataset in sorted order for some attribute.
+   *
+   * @param index the index of the attribute.
+   * @return an array containing the value of the desired attribute for
+   * each instance in the dataset. 
+   */
+  public double [] attributeToDoubleArray(int index) {
+
+    double [] result = new double[numInstances()];
+    for (int i = 0; i < result.length; i++) {
+      result[i] = instance(i).value(index);
+    }
+    return result;
+  }
+
+  /**
+   * Generates a string summarizing the set of instances. Gives a breakdown
+   * for each attribute indicating the number of missing/discrete/unique
+   * values and other information.
+   *
+   * @return a string summarizing the dataset
+   */
+  public String toSummaryString() {
+
+    StringBuffer result = new StringBuffer();
+    result.append("Relation Name:  ").append(relationName()).append('\n');
+    result.append("Num Instances:  ").append(numInstances()).append('\n');
+    result.append("Num Attributes: ").append(numAttributes()).append('\n');
+    result.append('\n');
+
+    result.append(Utils.padLeft("", 5)).append(Utils.padRight("Name", 25));
+    result.append(Utils.padLeft("Type", 5)).append(Utils.padLeft("Nom", 5));
+    result.append(Utils.padLeft("Int", 5)).append(Utils.padLeft("Real", 5));
+    result.append(Utils.padLeft("Missing", 12));
+    result.append(Utils.padLeft("Unique", 12));
+    result.append(Utils.padLeft("Dist", 6)).append('\n');
+    for (int i = 0; i < numAttributes(); i++) {
+      Attribute a = attribute(i);
+      AttributeStats as = attributeStats(i);
+      result.append(Utils.padLeft("" + (i + 1), 4)).append(' ');
+      result.append(Utils.padRight(a.name(), 25)).append(' ');
+      long percent;
+      switch (a.type()) {
+      case Attribute.NOMINAL:
+	result.append(Utils.padLeft("Nom", 4)).append(' ');
+	percent = Math.round(100.0 * as.intCount / as.totalCount);
+	result.append(Utils.padLeft("" + percent, 3)).append("% ");
+	result.append(Utils.padLeft("" + 0, 3)).append("% ");
+	percent = Math.round(100.0 * as.realCount / as.totalCount);
+	result.append(Utils.padLeft("" + percent, 3)).append("% ");
+	break;
+      case Attribute.NUMERIC:
+	result.append(Utils.padLeft("Num", 4)).append(' ');
+	result.append(Utils.padLeft("" + 0, 3)).append("% ");
+	percent = Math.round(100.0 * as.intCount / as.totalCount);
+	result.append(Utils.padLeft("" + percent, 3)).append("% ");
+	percent = Math.round(100.0 * as.realCount / as.totalCount);
+	result.append(Utils.padLeft("" + percent, 3)).append("% ");
+	break;
+      case Attribute.STRING:
+	result.append(Utils.padLeft("Str", 4)).append(' ');
+	percent = Math.round(100.0 * as.intCount / as.totalCount);
+	result.append(Utils.padLeft("" + percent, 3)).append("% ");
+	result.append(Utils.padLeft("" + 0, 3)).append("% ");
+	percent = Math.round(100.0 * as.realCount / as.totalCount);
+	result.append(Utils.padLeft("" + percent, 3)).append("% ");
+	break;
+      default:
+	result.append(Utils.padLeft("???", 4)).append(' ');
+	result.append(Utils.padLeft("" + 0, 3)).append("% ");
+	percent = Math.round(100.0 * as.intCount / as.totalCount);
+	result.append(Utils.padLeft("" + percent, 3)).append("% ");
+	percent = Math.round(100.0 * as.realCount / as.totalCount);
+	result.append(Utils.padLeft("" + percent, 3)).append("% ");
+	break;
+      }
+      result.append(Utils.padLeft("" + as.missingCount, 5)).append(" /");
+      percent = Math.round(100.0 * as.missingCount / as.totalCount);
+      result.append(Utils.padLeft("" + percent, 3)).append("% ");
+      result.append(Utils.padLeft("" + as.uniqueCount, 5)).append(" /");
+      percent = Math.round(100.0 * as.uniqueCount / as.totalCount);
+      result.append(Utils.padLeft("" + percent, 3)).append("% ");
+      result.append(Utils.padLeft("" + as.distinctCount, 5)).append(' ');
+      result.append('\n');
+    }
+    return result.toString();
+  }
+  
+  /**
+   * Reads a single instance using the tokenizer and appends it
+   * to the dataset. Automatically expands the dataset if it
+   * is not large enough to hold the instance.
+   *
+   * @param tokenizer the tokenizer to be used
+   * @param flag if method should test for carriage return after 
+   * each instance
+   * @return false if end of file has been reached
+   * @exception IOException if the information is not read 
+   * successfully
+   */ 
+  protected boolean getInstance(StreamTokenizer tokenizer, 
+				boolean flag) 
+       throws IOException {
+    
+    // Check if any attributes have been declared.
+    if (m_Attributes.size() == 0) {
+      errms(tokenizer,"no header information available");
+    }
+
+    // Check if end of file reached.
+    getFirstToken(tokenizer);
+    if (tokenizer.ttype == StreamTokenizer.TT_EOF) {
+      return false;
+    }
+    
+    // Parse instance
+    if (tokenizer.ttype == '{') {
+      return getInstanceSparse(tokenizer, flag);
+    } else {
+      return getInstanceFull(tokenizer, flag);
+    }
+  }
+
+  /**
+   * Reads a single instance using the tokenizer and appends it
+   * to the dataset. Automatically expands the dataset if it
+   * is not large enough to hold the instance.
+   *
+   * @param tokenizer the tokenizer to be used
+   * @param flag if method should test for carriage return after 
+   * each instance
+   * @return false if end of file has been reached
+   * @exception IOException if the information is not read 
+   * successfully
+   */ 
+  protected boolean getInstanceSparse(StreamTokenizer tokenizer, 
+				      boolean flag) 
+       throws IOException {
+
+    int valIndex, numValues = 0, maxIndex = -1;
+    
+    // Get values
+    do {
+      
+      // Get index
+      getIndex(tokenizer);
+      if (tokenizer.ttype == '}') {
+	break;
+      }
+       
+      // Is index valid?
+      try{
+	m_IndicesBuffer[numValues] = Integer.valueOf(tokenizer.sval).intValue();
+      } catch (NumberFormatException e) {
+	errms(tokenizer,"index number expected");
+      }
+      if (m_IndicesBuffer[numValues] <= maxIndex) {
+	errms(tokenizer,"indices have to be ordered");
+      }
+      if ((m_IndicesBuffer[numValues] < 0) || 
+	  (m_IndicesBuffer[numValues] >= numAttributes())) {
+	errms(tokenizer,"index out of bounds");
+      }
+      maxIndex = m_IndicesBuffer[numValues];
+
+      // Get value;
+      getNextToken(tokenizer);
+
+      // Check if value is missing.
+      if  (tokenizer.ttype == '?') {
+	m_ValueBuffer[numValues] = Instance.missingValue();
+      } else {
+
+	// Check if token is valid.
+	if (tokenizer.ttype != StreamTokenizer.TT_WORD) {
+	  errms(tokenizer,"not a valid value");
+	}
+	if (attribute(m_IndicesBuffer[numValues]).isNominal()) {
+	  
+	  // Check if value appears in header.
+	  valIndex = 
+	    attribute(m_IndicesBuffer[numValues]).indexOfValue(tokenizer.sval);
+	  if (valIndex == -1) {
+	    errms(tokenizer,"nominal value not declared in header");
+	  }
+	  m_ValueBuffer[numValues] = (double)valIndex;
+	} else if (attribute(m_IndicesBuffer[numValues]).isNumeric()) {
+	  
+	  // Check if value is really a number.
+	  try{
+	    m_ValueBuffer[numValues] = Double.valueOf(tokenizer.sval).
+	      doubleValue();
+	  } catch (NumberFormatException e) {
+	    errms(tokenizer,"number expected");
+	  }
+	} else { 
+	  m_ValueBuffer[numValues] = 
+	    attribute(m_IndicesBuffer[numValues]).addStringValue(tokenizer.sval);
+	}
+      }
+      numValues++;
+    } while (true);
+    if (flag) {
+      getLastToken(tokenizer,true);
+    }
+      
+    // Add instance to dataset
+    double[] tempValues = new double[numValues];
+    int[] tempIndices = new int[numValues];
+    System.arraycopy(m_ValueBuffer, 0, tempValues, 0, numValues);
+    System.arraycopy(m_IndicesBuffer, 0, tempIndices, 0, numValues);
+    add(new SparseInstance(1, tempValues, tempIndices, numAttributes()));
+    return true;
+  }
+
+  /**
+   * Reads a single instance using the tokenizer and appends it
+   * to the dataset. Automatically expands the dataset if it
+   * is not large enough to hold the instance.
+   *
+   * @param tokenizer the tokenizer to be used
+   * @param flag if method should test for carriage return after 
+   * each instance
+   * @return false if end of file has been reached
+   * @exception IOException if the information is not read 
+   * successfully
+   */ 
+  protected boolean getInstanceFull(StreamTokenizer tokenizer, 
+				    boolean flag) 
+       throws IOException {
+
+    double[] instance = new double[numAttributes()];
+    int index;
+    
+    // Get values for all attributes.
+    for (int i = 0; i < numAttributes(); i++){
+      
+      // Get next token
+      if (i > 0) {
+	getNextToken(tokenizer);
+      }
+            
+      // Check if value is missing.
+      if  (tokenizer.ttype == '?') {
+	instance[i] = Instance.missingValue();
+      } else {
+
+	// Check if token is valid.
+	if (tokenizer.ttype != StreamTokenizer.TT_WORD) {
+	  errms(tokenizer,"not a valid value");
+	}
+	if (attribute(i).isNominal()) {
+	  
+	  // Check if value appears in header.
+	  index = attribute(i).indexOfValue(tokenizer.sval);
+	  if (index == -1) {
+	    errms(tokenizer,"nominal value not declared in header");
+	  }
+	  instance[i] = (double)index;
+	} else if (attribute(i).isNumeric()) {
+	  
+	  // Check if value is really a number.
+	  try{
+	    instance[i] = Double.valueOf(tokenizer.sval).
+	      doubleValue();
+	  } catch (NumberFormatException e) {
+	    errms(tokenizer,"number expected");
+	  }
+	} else { 
+	  instance[i] = attribute(i).addStringValue(tokenizer.sval);
+	}
+      }
+    }
+    if (flag) {
+      getLastToken(tokenizer,true);
+    }
+      
+    // Add instance to dataset
+    add(new Instance(1, instance));
+    return true;
+  }
+
+  /**
+   * Reads and stores header of an ARFF file.
+   *
+   * @param tokenizer the stream tokenizer
+   * @exception IOException if the information is not read 
+   * successfully
+   */ 
+  protected void readHeader(StreamTokenizer tokenizer) 
+     throws IOException{
+    
+    String attributeName;
+    FastVector attributeValues;
+    int i;
+
+    // Get name of relation.
+    getFirstToken(tokenizer);
+    if (tokenizer.ttype == StreamTokenizer.TT_EOF) {
+      errms(tokenizer,"premature end of file");
+    }
+    if (tokenizer.sval.equalsIgnoreCase("@relation")){
+      getNextToken(tokenizer);
+      m_RelationName = tokenizer.sval;
+      getLastToken(tokenizer,false);
+    } else {
+      errms(tokenizer,"keyword @relation expected");
+    }
+
+    // Create vectors to hold information temporarily.
+    m_Attributes = new FastVector();
+ 
+    // Get attribute declarations.
+    getFirstToken(tokenizer);
+    if (tokenizer.ttype == StreamTokenizer.TT_EOF) {
+      errms(tokenizer,"premature end of file");
+    }
+    while (tokenizer.sval.equalsIgnoreCase("@attribute")) {
+
+      // Get attribute name.
+      getNextToken(tokenizer);
+      attributeName = tokenizer.sval;
+      getNextToken(tokenizer);
+
+      // Check if attribute is nominal.
+      if (tokenizer.ttype == StreamTokenizer.TT_WORD) {
+
+	// Attribute is real, integer, or string.
+	if (tokenizer.sval.equalsIgnoreCase("real") ||
+	    tokenizer.sval.equalsIgnoreCase("integer") ||
+	    tokenizer.sval.equalsIgnoreCase("numeric")) {
+	  m_Attributes.addElement(new Attribute(attributeName,
+						 numAttributes()));
+	  readTillEOL(tokenizer);
+	} else if (tokenizer.sval.equalsIgnoreCase("string")) {
+	  m_Attributes.
+	    addElement(new Attribute(attributeName, null,
+				     numAttributes()));
+	  readTillEOL(tokenizer);
+	} else {
+	  errms(tokenizer,"no valid attribute type or invalid "+
+		"enumeration");
+	}
+      } else {
+
+	// Attribute is nominal.
+	attributeValues = new FastVector();
+	tokenizer.pushBack();
+	
+	// Get values for nominal attribute.
+	if (tokenizer.nextToken() != '{') {
+	  errms(tokenizer,"{ expected at beginning of enumeration");
+	}
+	while (tokenizer.nextToken() != '}') {
+	  if (tokenizer.ttype == StreamTokenizer.TT_EOL) {
+	    errms(tokenizer,"} expected at end of enumeration");
+	  } else {
+	    attributeValues.addElement(tokenizer.sval);
+	  }
+	}
+	if (attributeValues.size() == 0) {
+	  errms(tokenizer,"no nominal values found");
+	}
+	m_Attributes.
+	  addElement(new Attribute(attributeName, attributeValues,
+				   numAttributes()));
+      }
+      getLastToken(tokenizer,false);
+      getFirstToken(tokenizer);
+      if (tokenizer.ttype == StreamTokenizer.TT_EOF)
+	errms(tokenizer,"premature end of file");
+    }
+
+    // Check if data part follows. We can't easily check for EOL.
+    if (!tokenizer.sval.equalsIgnoreCase("@data")) {
+      errms(tokenizer,"keyword @data expected");
+    }
+    
+    // Check if any attributes have been declared.
+    if (m_Attributes.size() == 0) {
+      errms(tokenizer,"no attributes declared");
+    }
+
+    // Allocate buffers in case sparse instances have to be read
+    m_ValueBuffer = new double[numAttributes()];
+    m_IndicesBuffer = new int[numAttributes()];
+  }
+
+  /**
+   * Copies instances from one set to the end of another 
+   * one.
+   *
+   * @param source the source of the instances
+   * @param from the position of the first instance to be copied
+   * @param dest the destination for the instances
+   * @param num the number of instances to be copied
+   */
+  private void copyInstances(int from, Instances dest, int num) {
+    
+    for (int i = 0; i < num; i++) {
+      dest.add(instance(from + i));
+    }
+  }
+  
+  /**
+   * Throws error message with line number and last token read.
+   *
+   * @param theMsg the error message to be thrown
+   * @param tokenizer the stream tokenizer
+   * @throws IOExcpetion containing the error message
+   */
+  private void errms(StreamTokenizer tokenizer, String theMsg) 
+       throws IOException {
+    
+    throw new IOException(theMsg + ", read " + tokenizer.toString());
+  }
+  
+  /**
+   * Replaces the attribute information by a clone of
+   * itself.
+   */
+  private void freshAttributeInfo() {
+
+    m_Attributes = (FastVector) m_Attributes.copyElements();
+  }
+
+  /**
+   * Gets next token, skipping empty lines.
+   *
+   * @param tokenizer the stream tokenizer
+   * @exception IOException if reading the next token fails
+   */
+  private void getFirstToken(StreamTokenizer tokenizer) 
+    throws IOException{
+    
+    while (tokenizer.nextToken() == StreamTokenizer.TT_EOL){};
+    if ((tokenizer.ttype == '\'') ||
+	(tokenizer.ttype == '"')) {
+      tokenizer.ttype = StreamTokenizer.TT_WORD;
+    } else if ((tokenizer.ttype == StreamTokenizer.TT_WORD) &&
+	       (tokenizer.sval.equals("?"))){
+      tokenizer.ttype = '?';
+    }
+  }
+
+  /**
+   * Gets index, checking for a premature and of line.
+   *
+   * @param tokenizer the stream tokenizer
+   * @exception IOException if it finds a premature end of line
+   */
+  private void getIndex(StreamTokenizer tokenizer) throws IOException{
+    
+    if (tokenizer.nextToken() == StreamTokenizer.TT_EOL) {
+      errms(tokenizer,"premature end of line");
+    }
+    if (tokenizer.ttype == StreamTokenizer.TT_EOF) {
+      errms(tokenizer,"premature end of file");
+    }
+  }
+  
+  /**
+   * Gets token and checks if its end of line.
+   *
+   * @param tokenizer the stream tokenizer
+   * @exception IOException if it doesn't find an end of line
+   */
+  private void getLastToken(StreamTokenizer tokenizer, boolean endOfFileOk) 
+       throws IOException{
+
+    if ((tokenizer.nextToken() != StreamTokenizer.TT_EOL) &&
+	((tokenizer.nextToken() != StreamTokenizer.TT_EOF) || !endOfFileOk)) {
+      errms(tokenizer,"end of line expected");
+    }
+  }
+
+  /**
+   * Gets next token, checking for a premature and of line.
+   *
+   * @param tokenizer the stream tokenizer
+   * @exception IOException if it finds a premature end of line
+   */
+  private void getNextToken(StreamTokenizer tokenizer) 
+       throws IOException{
+    
+    if (tokenizer.nextToken() == StreamTokenizer.TT_EOL) {
+      errms(tokenizer,"premature end of line");
+    }
+    if (tokenizer.ttype == StreamTokenizer.TT_EOF) {
+      errms(tokenizer,"premature end of file");
+    } else if ((tokenizer.ttype == '\'') ||
+	       (tokenizer.ttype == '"')) {
+      tokenizer.ttype = StreamTokenizer.TT_WORD;
+    } else if ((tokenizer.ttype == StreamTokenizer.TT_WORD) &&
+	       (tokenizer.sval.equals("?"))){
+      tokenizer.ttype = '?';
+    }
+  }
+	
+  /**
+   * Initializes the StreamTokenizer used for reading the ARFF file.
+   *
+   * @param tokenizer the stream tokenizer
+   */
+  private void initTokenizer(StreamTokenizer tokenizer){
+
+    tokenizer.resetSyntax();         
+    tokenizer.whitespaceChars(0, ' ');    
+    tokenizer.wordChars(' '+1,'\u00FF');
+    tokenizer.whitespaceChars(',',',');
+    tokenizer.commentChar('%');
+    tokenizer.quoteChar('"');
+    tokenizer.quoteChar('\'');
+    tokenizer.ordinaryChar('{');
+    tokenizer.ordinaryChar('}');
+    tokenizer.eolIsSignificant(true);
+  }
+ 
+  /**
+   * Returns string including all instances, their weights and
+   * their indices in the original dataset.
+   *
+   * @return description of instance and its weight as a string
+   */
+  private String instancesAndWeights(){
+
+    StringBuffer text = new StringBuffer();
+
+    for (int i = 0; i < numInstances(); i++) {
+      text.append(instance(i) + " " + instance(i).weight());
+      if (i < numInstances() - 1) {
+	text.append("\n");
+      }
+    }
+    return text.toString();
+  }
+  
+  /**
+   * Implements quicksort.
+   *
+   * @param attIndex the attribute's index
+   * @param lo0 the first index of the subset to be sorted
+   * @param hi0 the last index of the subset to be sorted
+   */
+  private void quickSort(int attIndex, int lo0, int hi0) {
+    
+    int lo = lo0, hi = hi0;
+    double mid, midPlus, midMinus;
+    
+    if (hi0 > lo0) {
+      
+      // Arbitrarily establishing partition element as the 
+      // midpoint of the array.
+      mid = instance((lo0 + hi0) / 2).value(attIndex);
+      midPlus = mid + 1e-6;
+      midMinus = mid - 1e-6;
+
+      // loop through the array until indices cross
+      while(lo <= hi) {
+	
+	// find the first element that is greater than or equal to 
+	// the partition element starting from the left Index.
+	while ((instance(lo).value(attIndex) < 
+		midMinus) && (lo < hi0)) {
+	  ++lo;
+	}
+	
+	// find an element that is smaller than or equal to
+	// the partition element starting from the right Index.
+	while ((instance(hi).value(attIndex)  > 
+		midPlus) && (hi > lo0)) {
+	  --hi;
+	}
+	
+	// if the indexes have not crossed, swap
+	if(lo <= hi) {
+	  swap(lo,hi);
+	  ++lo;
+	  --hi;
+	}
+      }
+      
+      // If the right index has not reached the left side of array
+      // must now sort the left partition.
+      if(lo0 < hi) {
+	quickSort(attIndex,lo0,hi);
+      }
+      
+      // If the left index has not reached the right side of array
+      // must now sort the right partition.
+      if(lo < hi0) {
+	quickSort(attIndex,lo,hi0);
+      }
+    }
+  }
+
+  /**
+   * Reads and skips all tokens before next end of line token.
+   *
+   * @param tokenizer the stream tokenizer
+   */
+  private void readTillEOL(StreamTokenizer tokenizer) 
+       throws IOException{
+    
+    while (tokenizer.nextToken() != StreamTokenizer.TT_EOL) {};
+    tokenizer.pushBack();
+  }
+
+  /**
+   * Help function needed for stratification of set.
+   *
+   * @param numFolds the number of folds for the stratification
+   */
+  private void stratStep (int numFolds){
+    
+    FastVector newVec = new FastVector(m_Instances.capacity());
+    int start = 0, j;
+
+    // create stratified batch
+    while (newVec.size() < numInstances()) {
+      j = start;
+      while (j < numInstances()) {
+	newVec.addElement(instance(j));
+	j = j + numFolds;
+      }
+      start++;
+    }
+    m_Instances = newVec;
+  }
+  
+  /**
+   * Swaps two instances in the set.
+   *
+   * @param i the first instance's index
+   * @param j the second instance's index
+   */
+  private void swap(int i, int j){
+    
+    m_Instances.swap(i, j);
+  }
+
+  /**
+   * Merges two sets of Instances together. The resulting set will have
+   * all the attributes of the first set plus all the attributes of the 
+   * second set. The number of instances in both sets must be the same.
+   *
+   * @param first the first set of Instances
+   * @param second the second set of Instances
+   * @return the merged set of Instances
+   * @exception IllegalArgumentException if the datasets are not the same size
+   */
+  public static Instances mergeInstances(Instances first, Instances second) {
+
+    if (first.numInstances() != second.numInstances()) {
+      throw new IllegalArgumentException("Instance sets must be of the same size");
+    }
+
+    // Create the vector of merged attributes
+    FastVector newAttributes = new FastVector();
+    for (int i = 0; i < first.numAttributes(); i++) {
+      newAttributes.addElement(first.attribute(i));
+    }
+    for (int i = 0; i < second.numAttributes(); i++) {
+      newAttributes.addElement(second.attribute(i));
+    }
+    
+    // Create the set of Instances
+    Instances merged = new Instances(first.relationName() + '_'
+				     + second.relationName(), 
+				     newAttributes, 
+				     first.numInstances());
+    // Merge each instance
+    for (int i = 0; i < first.numInstances(); i++) {
+      merged.add(first.instance(i).mergeInstance(second.instance(i)));
+    }
+    return merged;
+  }
+
+  /**
+   * Method for testing this class.
+   *
+   * @param argv should contain one element: the name of an ARFF file
+   */
+  public static void test(String [] argv) {
+
+    Instances instances, secondInstances, train, test, transformed, empty;
+    Instance instance;
+    Random random = new Random(2);
+    Reader reader;
+    int start, num;
+    double newWeight;
+    FastVector testAtts, testVals;
+    int i,j;
+    
+    try{
+      if (argv.length > 1) {
+	throw (new Exception("Usage: Instances [<filename>]"));
+      }
+      
+      // Creating set of instances from scratch
+      testVals = new FastVector(2);
+      testVals.addElement("first_value");
+      testVals.addElement("second_value");
+      testAtts = new FastVector(2);
+      testAtts.addElement(new Attribute("nominal_attribute", testVals));
+      testAtts.addElement(new Attribute("numeric_attribute"));
+      instances = new Instances("test_set", testAtts, 10);
+      instances.add(new Instance(instances.numAttributes()));
+      instances.add(new Instance(instances.numAttributes()));
+      instances.add(new Instance(instances.numAttributes()));
+      instances.setClassIndex(0);
+      System.out.println("\nSet of instances created from scratch:\n");
+      System.out.println(instances);
+      
+      if (argv.length == 1) {
+	String filename = argv[0];
+	reader = new FileReader(filename);
+	
+	// Read first five instances and print them
+	System.out.println("\nFirst five instances from file:\n");
+	instances = new Instances(reader, 1);
+	instances.setClassIndex(instances.numAttributes() - 1);
+	i = 0;
+	while ((i < 5) && (instances.readInstance(reader))) {
+	  i++;
+	}
+	System.out.println(instances);
+
+	// Read all the instances in the file
+	reader = new FileReader(filename);
+	instances = new Instances(reader);
+
+	// Make the last attribute be the class 
+	instances.setClassIndex(instances.numAttributes() - 1);
+	
+	// Print header and instances.
+	System.out.println("\nDataset:\n");
+	System.out.println(instances);
+	System.out.println("\nClass index: "+instances.classIndex());
+      }
+      
+      // Test basic methods based on class index.
+      System.out.println("\nClass name: "+instances.classAttribute().name());
+      System.out.println("\nClass index: "+instances.classIndex());
+      System.out.println("\nClass is nominal: " +
+			 instances.classAttribute().isNominal());
+      System.out.println("\nClass is numeric: " +
+			 instances.classAttribute().isNumeric());
+      System.out.println("\nClasses:\n");
+      for (i = 0; i < instances.numClasses(); i++) {
+	System.out.println(instances.classAttribute().value(i));
+      }
+      System.out.println("\nClass values and labels of instances:\n");
+      for (i = 0; i < instances.numInstances(); i++) {
+	Instance inst = instances.instance(i);
+	System.out.print(inst.classValue() + "\t");
+	System.out.print(inst.toString(inst.classIndex()));
+	if (instances.instance(i).classIsMissing()) {
+	  System.out.println("\tis missing");
+	} else {
+	  System.out.println();
+	}
+      }
+      
+      // Create random weights.
+      System.out.println("\nCreating random weights for instances.");
+      for (i = 0; i < instances.numInstances(); i++) {
+	instances.instance(i).setWeight(random.nextDouble()); 
+      }
+      
+      // Print all instances and their weights (and the sum of weights).
+      System.out.println("\nInstances and their weights:\n");
+      System.out.println(instances.instancesAndWeights());
+      System.out.print("\nSum of weights: ");
+      System.out.println(instances.sumOfWeights());
+      
+      // Insert an attribute
+      secondInstances = new Instances(instances);
+      Attribute testAtt = new Attribute("Inserted");
+      secondInstances.insertAttributeAt(testAtt, 0);
+      System.out.println("\nSet with inserted attribute:\n");
+      System.out.println(secondInstances);
+      System.out.println("\nClass name: "
+			 + secondInstances.classAttribute().name());
+      
+      // Delete the attribute
+      secondInstances.deleteAttributeAt(0);
+      System.out.println("\nSet with attribute deleted:\n");
+      System.out.println(secondInstances);
+      System.out.println("\nClass name: "
+			 + secondInstances.classAttribute().name());
+      
+      // Test if headers are equal
+      System.out.println("\nHeaders equal: "+
+			 instances.equalHeaders(secondInstances) + "\n");
+      
+      // Print data in internal format.
+      System.out.println("\nData (internal values):\n");
+      for (i = 0; i < instances.numInstances(); i++) {
+	for (j = 0; j < instances.numAttributes(); j++) {
+	  if (instances.instance(i).isMissing(j)) {
+	    System.out.print("? ");
+	  } else {
+	    System.out.print(instances.instance(i).value(j) + " ");
+	  }
+	}
+	System.out.println();
+      }
+      
+      // Just print header
+      System.out.println("\nEmpty dataset:\n");
+      empty = new Instances(instances, 0);
+      System.out.println(empty);
+      System.out.println("\nClass name: "+empty.classAttribute().name());
+
+      // Create copy and rename an attribute and a value (if possible)
+      if (empty.classAttribute().isNominal()) {
+	Instances copy = new Instances(empty, 0);
+	copy.renameAttribute(copy.classAttribute(), "new_name");
+	copy.renameAttributeValue(copy.classAttribute(), 
+				  copy.classAttribute().value(0), 
+				  "new_val_name");
+	System.out.println("\nDataset with names changed:\n" + copy);
+	System.out.println("\nOriginal dataset:\n" + empty);
+      }
+
+      // Create and prints subset of instances.
+      start = instances.numInstances() / 4;
+      num = instances.numInstances() / 2;
+      System.out.print("\nSubset of dataset: ");
+      System.out.println(num + " instances from " + (start + 1) 
+			 + ". instance");
+      secondInstances = new Instances(instances, start, num);
+      System.out.println("\nClass name: "
+			 + secondInstances.classAttribute().name());
+
+      // Print all instances and their weights (and the sum of weights).
+      System.out.println("\nInstances and their weights:\n");
+      System.out.println(secondInstances.instancesAndWeights());
+      System.out.print("\nSum of weights: ");
+      System.out.println(secondInstances.sumOfWeights());
+      
+      // Create and print training and test sets for 3-fold
+      // cross-validation.
+      System.out.println("\nTrain and test folds for 3-fold CV:");
+      if (instances.classAttribute().isNominal()) {
+	instances.stratify(3);
+      }
+      for (j = 0; j < 3; j++) {
+        train = instances.trainCV(3,j);
+	test = instances.testCV(3,j);
+                      
+	// Print all instances and their weights (and the sum of weights).
+	System.out.println("\nTrain: ");
+	System.out.println("\nInstances and their weights:\n");
+	System.out.println(train.instancesAndWeights());
+	System.out.print("\nSum of weights: ");
+	System.out.println(train.sumOfWeights());
+	System.out.println("\nClass name: "+train.classAttribute().name());
+	System.out.println("\nTest: ");
+	System.out.println("\nInstances and their weights:\n");
+	System.out.println(test.instancesAndWeights());
+	System.out.print("\nSum of weights: ");
+	System.out.println(test.sumOfWeights());
+	System.out.println("\nClass name: "+test.classAttribute().name());
+      }
+
+      // Randomize instances and print them.
+      System.out.println("\nRandomized dataset:");
+      instances.randomize(random);
+      
+      // Print all instances and their weights (and the sum of weights).
+      System.out.println("\nInstances and their weights:\n");
+      System.out.println(instances.instancesAndWeights());
+      System.out.print("\nSum of weights: ");
+      System.out.println(instances.sumOfWeights());
+
+      // Sort instances according to first attribute and
+      // print them.
+      System.out.print("\nInstances sorted according to first attribute:\n ");
+      instances.sort(0);
+        
+      // Print all instances and their weights (and the sum of weights).
+      System.out.println("\nInstances and their weights:\n");
+      System.out.println(instances.instancesAndWeights());
+      System.out.print("\nSum of weights: ");
+      System.out.println(instances.sumOfWeights());
+    } catch (Exception e) {
+      e.printStackTrace(); 
+    }
+  }
+
+  /**
+   * Main method for this class -- just prints a summary of a set
+   * of instances.
+   *
+   * @param argv should contain one element: the name of an ARFF file
+   */
+  public static void main(String [] args) {
+
+    try {
+      Reader r = null;
+      if (args.length > 1) {
+	throw (new Exception("Usage: Instances <filename>"));
+      } else if (args.length == 0) {
+        r = new BufferedReader(new InputStreamReader(System.in));
+      } else {
+        r = new BufferedReader(new FileReader(args[0]));
+      }
+      Instances i = new Instances(r);
+      System.out.println(i.toSummaryString());
+    } catch (Exception ex) {
+      System.err.println(ex.getMessage());
+    }
+  }
+}
+
+     
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/Option.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/Option.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/Option.java	(revision 8815)
@@ -0,0 +1,105 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Option.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+/** 
+ * Class to store information about an option. <p>
+ *
+ * Typical usage: <p>
+ *
+ * <code>Option myOption = new Option("Uses extended mode.", "E", 0, "-E")); </code><p>
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class Option {
+
+  /** What does this option do? */
+  private String m_Description;
+
+  /** The synopsis. */
+  private String m_Synopsis;
+
+  /** What's the option's name? */
+  private String m_Name;
+
+  /** How many arguments does it take? */
+  private int m_NumArguments;
+
+  /**
+   * Creates new option with the given parameters.
+   *
+   * @String description the option's description
+   * @String name the option's name
+   * @String numArguments the number of arguments
+   */
+  public Option(String description, String name, 
+		int numArguments, String synopsis) {
+  
+    m_Description = description;
+    m_Name = name;
+    m_NumArguments = numArguments;
+    m_Synopsis = synopsis;
+  }
+
+  /**
+   * Returns the option's description.
+   *
+   * @return the option's description
+   */
+  public String description() {
+  
+    return m_Description;
+  }
+
+  /**
+   * Returns the option's name.
+   *
+   * @return the option's name
+   */
+  public String name() {
+
+    return m_Name;
+  }
+
+  /**
+   * Returns the option's number of arguments.
+   *
+   * @return the option's number of arguments
+   */
+  public int numArguments() {
+  
+    return m_NumArguments;
+  }
+
+  /**
+   * Returns the option's synopsis.
+   *
+   * @return the option's synopsis
+   */
+  public String synopsis() {
+  
+    return m_Synopsis;
+  }
+}
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/OptionHandler.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/OptionHandler.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/OptionHandler.java	(revision 8815)
@@ -0,0 +1,67 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    OptionHandler.java
+ *    Copyright (C) 1999 Eibe Frank,Len Trigg
+ *
+ */
+
+package weka.core;
+
+import java.util.*;
+
+/** 
+ * Interface to something that understands options.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public interface OptionHandler {
+
+  /**
+   * Returns an enumeration of all the available options.
+   *
+   * @return an enumeration of all available options
+   */
+  public Enumeration listOptions();
+
+  /**
+   * Sets the OptionHandler's options using the given list. All options
+   * will be set (or reset) during this call (i.e. incremental setting
+   * of options is not possible).
+   *
+   * @param options the list of options as an array of strings
+   * @exception Exception if an option is not supported
+   */
+  public void setOptions(String[] options) throws Exception;
+
+  /**
+   * Gets the current option settings for the OptionHandler.
+   *
+   * @return the list of current option settings as an array of strings
+   */
+  public String[] getOptions();
+}
+
+
+
+
+
+
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/Queue.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/Queue.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/Queue.java	(revision 8815)
@@ -0,0 +1,229 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Queue.java
+ *    Copyright (C) 1999 Len Trigg
+ *
+ */
+
+package weka.core;
+
+import java.io.*;
+
+/** 
+ * Class representing a FIFO queue.
+ *
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class Queue extends Object implements Serializable {
+
+  /**
+   * Represents one node in the queue.
+   */
+  protected class QueueNode implements Serializable {
+
+    /** The next node in the queue */
+    protected QueueNode m_Next;
+
+    /** The nodes contents */
+    protected Object m_Contents;
+
+    /** 
+     * Creates a queue node with the given contents 
+     */
+    public QueueNode(Object contents) {
+
+      m_Contents = contents;
+      next(null);
+    }
+
+    /**
+     * Sets the next node in the queue, and returns it.
+     */
+    public QueueNode next(QueueNode next) {
+
+      return m_Next = next;
+    }
+
+    /**
+     * Gets the next node in the queue. 
+     */
+    public QueueNode next() {
+
+      return m_Next;
+    }
+
+    /**
+     * Sets the contents of the node.
+     */
+    public Object contents(Object contents) {
+
+      return m_Contents = contents;
+    }
+
+    /**
+     * Returns the contents in the node.
+     */
+    public Object contents() {
+
+      return m_Contents;
+    }
+  }
+
+  /** Store a reference to the head of the queue */
+  protected QueueNode m_Head = null;
+
+  /** Store a reference to the tail of the queue */
+  protected QueueNode m_Tail = null;
+
+  /** Store the current number of elements in the queue */
+  protected int m_Size = 0;
+
+  /**
+   * Removes all objects from the queue.
+   */
+  public final synchronized void removeAllElements() {
+
+    m_Size = 0;
+    m_Head = null;
+    m_Tail = null;
+  }
+
+  /**
+   * Appends an object to the back of the queue.
+   *
+   * @param item the object to be appended
+   * @return the object appended
+   */
+  public synchronized Object push(Object item) {
+
+    QueueNode newNode = new QueueNode(item);
+    if (m_Head == null) {
+      m_Head = m_Tail = newNode;
+    } else {
+      m_Tail = m_Tail.next(newNode);
+    }
+    m_Size++;
+    return item;
+  }
+
+  /**
+   * Pops an object from the front of the queue.
+   *
+   * @return the object at the front of the queue
+   * @exception RuntimeException if the queue is empty
+   */
+  public synchronized Object pop() {
+
+    if (m_Head == null) {
+      throw new RuntimeException("Queue is empty");
+    }
+    Object retval = m_Head.contents();
+    m_Size--;
+    m_Head = m_Head.next();
+    if (m_Head == null) {
+      m_Tail = null;
+    }
+    return retval;
+  }
+
+  /**
+   * Gets object from the front of the queue.
+   *
+   * @return the object at the front of the queue
+   * @exception RuntimeException if the queue is empty
+   */
+  public synchronized Object peek() {
+    
+    if (m_Head == null) {
+      throw new RuntimeException("Queue is empty");
+    }
+    return m_Head.contents();
+  }
+
+  /**
+   * Checks if queue is empty.
+   * 
+   * @return true if queue is empty
+   */
+  public boolean empty() {
+
+    return (m_Head == null);
+  }
+
+  /** 
+   * Gets queue's size.
+   *
+   * @return size of queue
+   */
+  public int size() {
+
+    return m_Size;
+  }
+
+  /**
+   * Produces textual description of queue.
+   *
+   * @return textual description of queue
+   */
+  public String toString() {
+
+    String retval = "Queue Contents "+m_Size+" elements\n";
+    QueueNode current = m_Head;
+    if (current == null) {
+      return retval + "Empty\n";
+    } else {
+      while (current != null) {
+	retval += current.contents().toString()+"\n";
+	current = current.next();
+      }
+    }
+    return retval;
+  }
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param argv a set of strings that are pushed on a test queue
+   */
+  public static void main(String [] argv) {
+
+    try {
+      Queue queue = new Queue();
+      for(int i = 0; i < argv.length; i++) {
+	queue.push(argv[i]);
+      }
+      System.out.println("After Pushing");
+      System.out.println(queue.toString());
+      System.out.println("Popping...");
+      while (!queue.empty()) {
+	System.out.println(queue.pop().toString());
+      }
+    } catch (Exception ex) {
+      System.out.println(ex.getMessage());
+    }
+  }
+}
+
+
+
+
+
+
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/Range.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/Range.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/Range.java	(revision 8815)
@@ -0,0 +1,439 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Range.java
+ *    Copyright (C) 1999 Len Trigg
+ *
+ */
+
+package weka.core;
+
+import java.io.*;
+import java.util.*;
+
+/** 
+ * Class representing a range of cardinal numbers. The range is set by a 
+ * string representation such as: <P>
+ *
+ * <code>
+ *   all
+ *   first-last
+ *   1,2,3,4
+ * </code> <P>
+ * or combinations thereof. The range is internally converted from
+ * 1-based to 0-based (so methods that set or get numbers not in string
+ * format should use 0-based numbers).
+ *
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class Range implements Serializable {
+
+  /** Record the string representations of the columns to delete */
+  Vector m_RangeStrings = new Vector();
+
+  /** Whether matching should be inverted */
+  boolean m_Invert;
+
+  /** The array of flags for whether an column is selected */
+  boolean [] m_SelectFlags;
+
+  /** Store the maximum value permitted in the range. -1 indicates that
+      no upper value has been set */
+  int m_Upper = -1;
+
+  /** Default constructor. */
+  public Range() {
+  }
+
+  /**
+   * Constructor to set initial range.
+   *
+   * @param rangeList the initial range
+   * @exception IllegalArgumentException if the range list is invalid
+   */
+  public Range(String rangeList) {
+
+    setRanges(rangeList);
+  }
+
+  /**
+   * Sets the value of "last".
+   *
+   * @param newUpper the value of "last"
+   */
+  public void setUpper(int newUpper) {
+
+    if (newUpper >= 0) {
+      m_Upper = newUpper;
+      setFlags();
+    }
+  }
+  
+  /**
+   * Gets whether the range sense is inverted, i.e. all <i>except</i>
+   * the values included by the range string are selected.
+   * 
+   * @return whether the matching sense is inverted
+   */
+  public boolean getInvert() {
+
+    return m_Invert;
+  }
+
+  /**
+   * Sets whether the range sense is inverted, i.e. all <i>except</i>
+   * the values included by the range string are selected.
+   * 
+   * @param newSetting true if the matching sense is inverted
+   */
+  public void setInvert(boolean newSetting) {
+
+    m_Invert = newSetting;
+  }
+
+  /**
+   * Gets the string representing the selected range of values
+   *
+   * @return the range selection string
+   */
+  public String getRanges() {
+
+    String result = null;
+    Enumeration enum = m_RangeStrings.elements();
+    while (enum.hasMoreElements()) {
+      if (result == null) {
+	result = (String)enum.nextElement();
+      } else {
+	result += ',' + (String)enum.nextElement();
+      }
+    }
+    return (result == null) ? "" : result;
+  }
+
+  /**
+   * Sets the ranges from a string representation.
+   *
+   * @param rangeList the comma separated list of ranges. The empty
+   * string sets the range to empty.
+   * @exception IllegalArgumentException if the rangeList was not well formed
+   */
+  public void setRanges(String rangeList) {
+
+    Vector ranges = new Vector (10);
+
+    // Split the rangeList up into the vector
+    while (!rangeList.equals("")) {
+      String range = rangeList.trim();
+      int commaLoc = rangeList.indexOf(',');
+      if (commaLoc != -1) {
+	range = rangeList.substring(0, commaLoc).trim();
+	rangeList = rangeList.substring(commaLoc + 1).trim();
+      } else {
+	rangeList = "";
+      }
+      if (!range.equals("")) {
+	if (isValidRange(range)) {
+	  ranges.addElement(range);
+	} else {
+	  throw new IllegalArgumentException("Invalid range list at " + range
+                                             + rangeList);
+	}
+      }
+    }
+    m_RangeStrings = ranges;
+    
+    if (m_Upper >= 0) {
+      setFlags();
+    }
+  }
+
+  /**
+   * Gets whether the supplied cardinal number is included in the current
+   * range.
+   *
+   * @param index the number of interest
+   * @return true if index is in the current range
+   * @exception RuntimeException if the upper limit of the range hasn't been defined
+   */
+  public boolean isInRange(int index) {
+
+    if (m_Upper == -1) {
+      throw new RuntimeException("No upper limit has been specified for range");
+    }
+    if (m_Invert) {
+      return !m_SelectFlags[index];
+    } else {
+      return m_SelectFlags[index];
+    }
+  }
+
+  /**
+   * Constructs a representation of the current range. Being a string
+   * representation, the numbers are based from 1.
+   * 
+   * @return the string representation of the current range
+   */
+  public String toString() {
+
+    if (m_RangeStrings.size() == 0) {
+      return "Empty";
+    }
+    String result ="Strings: ";
+    Enumeration enum = m_RangeStrings.elements();
+    while (enum.hasMoreElements()) {
+      result += (String)enum.nextElement() + " ";
+    }
+    result += "\n";
+
+    result += "Invert: " + m_Invert + "\n";
+
+    try {
+      if (m_Upper == -1) {
+	throw new RuntimeException("Upper limit has not been specified");
+      }
+      String cols = null;
+      for (int i = 0; i < m_SelectFlags.length; i++) {
+	if (isInRange(i)) {
+	  if (cols == null) {
+	    cols = "Cols: " + (i + 1);
+	  } else {
+	    cols += "," + (i + 1);
+	  }
+	}
+      }
+      if (cols != null) {
+	result += cols + "\n";
+      }
+    } catch (Exception ex) {
+      result += ex.getMessage();
+    }
+    return result;
+  }
+
+  /**
+   * Gets an array containing all the selected values, in the order
+   * that they were selected (or ascending order if range inversion is on)
+   *
+   * @return the array of selected values
+   * @exception RuntimeException if the upper limit of the range hasn't been defined
+   */
+  public int [] getSelection() {
+
+    if (m_Upper == -1) {
+      throw new RuntimeException("No upper limit has been specified for range");
+    }
+    int [] selectIndices = new int [m_Upper + 1];
+    int numSelected = 0;
+    if (m_Invert)
+    {
+      for (int i = 0; i <= m_Upper; i++) {
+	if (!m_SelectFlags[i]) {
+	  selectIndices[numSelected++] = i;
+	}
+      }
+    }
+    else
+    {
+      Enumeration enum = m_RangeStrings.elements();
+      while (enum.hasMoreElements()) {
+	String currentRange = (String)enum.nextElement();
+	int start = rangeLower(currentRange);
+	int end = rangeUpper(currentRange);
+	for (int i = start; (i <= m_Upper) && (i <= end); i++) {
+	  if (m_SelectFlags[i]) {
+	    selectIndices[numSelected++] = i;
+	  }
+	}
+      }
+    }
+    int [] result = new int [numSelected];
+    System.arraycopy(selectIndices, 0, result, 0, numSelected);
+    return result;
+  }
+
+  /**
+   * Creates a string representation of the indices in the supplied array.
+   *
+   * @param indices an array containing indices to select.
+   * Since the array will typically come from a program, indices are assumed
+   * from 0, and thus will have 1 added in the String representation.
+   */
+  public static String indicesToRangeList(int []indices) {
+
+    StringBuffer rl = new StringBuffer();
+    int last = -2;
+    boolean range = false;
+    for(int i = 0; i < indices.length; i++) {
+      if (i == 0) {
+	rl.append(indices[i] + 1);
+      } else if (indices[i] == last) {
+        range = true;
+      } else {
+        if (range) {
+          rl.append('-').append(last);
+          range = false;
+        }
+	rl.append(',').append(indices[i] + 1);
+      }
+      last = indices[i] + 1;
+    }
+    if (range) {
+      rl.append('-').append(last);
+    }
+    return rl.toString();
+  }
+
+  /** Sets the flags array. */
+  protected void setFlags() {
+
+    m_SelectFlags = new boolean [m_Upper + 1];
+    Enumeration enum = m_RangeStrings.elements();
+    while (enum.hasMoreElements()) {
+      String currentRange = (String)enum.nextElement();
+      int start = rangeLower(currentRange);
+      int end = rangeUpper(currentRange);
+      for (int i = start; (i <= m_Upper) && (i <= end); i++) {
+	m_SelectFlags[i] = true;
+      }
+    }
+  }
+
+
+  /**
+   * Translates a single string selection into it's internal 0-based equivalent
+   *
+   * @param single the string representing the selection (eg: 1 first last)
+   * @return the number corresponding to the selected value
+   */
+  protected int rangeSingle(String single) {
+
+    if (single.toLowerCase().equals("first")) {
+      return 0;
+    }
+    if (single.toLowerCase().equals("last")) {
+      return m_Upper;
+    }
+    int index = Integer.parseInt(single) - 1;
+    if (index < 0) {
+      index = 0;
+    }
+    if (index > m_Upper) {
+      index = m_Upper;
+    }
+    return index;
+  }
+
+  /**
+   * Translates a range into it's lower index.
+   *
+   * @param range the string representation of the range
+   * @return the lower index of the range
+   */
+  protected int rangeLower(String range) {
+
+    int hyphenIndex;
+    if ((hyphenIndex = range.indexOf('-')) >= 0) {
+      return Math.min(rangeLower(range.substring(0, hyphenIndex)),
+		       rangeLower(range.substring(hyphenIndex + 1)));
+    }
+    return rangeSingle(range);
+  }
+
+  /**
+   * Translates a range into it's upper index. Must only be called once
+   * setUpper has been called.
+   *
+   * @param range the string representation of the range
+   * @return the upper index of the range
+   */
+  protected int rangeUpper(String range) {
+
+    int hyphenIndex;
+    if ((hyphenIndex = range.indexOf('-')) >= 0) {
+      return Math.max(rangeUpper(range.substring(0, hyphenIndex)),
+		       rangeUpper(range.substring(hyphenIndex + 1)));
+    }
+    return rangeSingle(range);
+  }
+
+  /**
+   * Determines if a string represents a valid index or simple range.
+   * Examples: <code>first  last   2   first-last  first-4  4-last</code>
+   * Doesn't check that a < b for a-b
+   *
+   * @param range
+   * @return true if the range is valid
+   */
+  protected boolean isValidRange(String range) {
+
+    if (range == null) {
+      return false;
+    }
+    int hyphenIndex;
+    if ((hyphenIndex = range.indexOf('-')) >= 0) {
+      if (isValidRange(range.substring(0, hyphenIndex)) &&
+	  isValidRange(range.substring(hyphenIndex + 1))) {
+	return true;
+      }
+      return false;
+    }
+    if (range.toLowerCase().equals("first")) {
+      return true;
+    }
+    if (range.toLowerCase().equals("last")) {
+      return true;
+    }
+    try {
+      int index = Integer.parseInt(range);
+      if (index > 0) {
+	return true;
+      }
+      return false;
+    } catch (NumberFormatException ex) {
+      return false;
+    }
+  }
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param argv one parameter: a test range specification
+   */
+  public static void main(String [] argv) {
+
+    try {
+      if (argv.length == 0) {
+	throw new Exception("Usage: Range <rangespec>");
+      }
+      Range range = new Range();
+      range.setRanges(argv[0]);
+      range.setUpper(9);
+      range.setInvert(false);
+      System.out.println("Input: " + argv[0] + "\n"
+			 + range.toString());
+      int [] rangeIndices = range.getSelection();
+      for (int i = 0; i < rangeIndices.length; i++)
+	System.out.print(" " + (rangeIndices[i] + 1));
+      System.out.println("");
+    } catch (Exception ex) {
+      System.out.println(ex.getMessage());
+    }
+  }
+}
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/SerializedObject.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/SerializedObject.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/SerializedObject.java	(revision 8815)
@@ -0,0 +1,249 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    SerializedObject.java
+ *    Copyright (C) 2000 Webmind Inc.
+ *
+ */
+
+package weka.core;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+
+/**
+ * This class stores an object serialized in memory. It allows compression,
+ * to be used to conserve memory (for example, when storing large strings
+ * in memory), or can be used as a mechanism for deep copying objects.
+ *
+ * @author Len Trigg (len@intelligenesis.net)
+ * @version $Revision$
+ */
+public class SerializedObject implements Serializable {
+
+  /** Stores the serialized object */
+  private byte [] m_Serialized;
+
+  /** True if the object has been compressed during storage */
+  private boolean m_Compressed;
+
+  /**
+   * Serializes the supplied object into a byte array without compression.
+   *
+   * @param obj the Object to serialize.
+   * @exception Exception if the object is not Serializable.
+   */
+  public SerializedObject(Object obj) throws Exception {
+
+    this(obj, false);
+  }
+
+  /**
+   * Serializes the supplied object into a byte array.
+   *
+   * @param obj the Object to serialize.
+   * @param compress true if the object should be stored compressed.
+   * @exception Exception if the object is not Serializable.
+   */
+  public SerializedObject(Object obj, boolean compress) throws Exception {
+
+    //System.err.print("."); System.err.flush();
+    m_Compressed = compress;
+    m_Serialized = toByteArray(obj, m_Compressed);
+  }
+
+  /**
+   * Serializes the supplied object to a byte array.
+   *
+   * @param obj the Object to serialize
+   * @param compress true if the object should be compressed.
+   * @return the byte array containing the serialized object.
+   * @exception Exception if the object is not Serializable.
+   */
+  protected static byte [] toByteArray(Object obj, boolean compress) 
+    throws Exception {
+
+    ByteArrayOutputStream bo = new ByteArrayOutputStream();
+    OutputStream os = bo;
+    if (compress) {
+      os = new GZIPOutputStream(os);
+    }
+    os = new BufferedOutputStream(os);
+    ObjectOutputStream oo = new ObjectOutputStream(os);
+    oo.writeObject(obj);
+    oo.close();
+    return bo.toByteArray();
+  }
+
+  /**
+   * Gets the object stored in this SerializedObject. The object returned
+   * will be a deep copy of the original stored object.
+   *
+   * @return the deserialized Object.
+   */
+  public Object getObject() {
+    try {
+      InputStream is = new ByteArrayInputStream(m_Serialized);
+      if (m_Compressed) {
+        is = new GZIPInputStream(is);
+      }
+      is = new BufferedInputStream(is);
+      ObjectInputStream oi = new ObjectInputStream(is);
+      Object result = oi.readObject();
+      oi.close();
+      return result;
+    } catch (Exception ex) {
+      ex.printStackTrace();
+    }
+    return null;
+  }
+
+  /**
+   * Compares this object with another for equality.
+   *
+   * @param other the other Object.
+   * @return true if the objects are equal.
+   */
+  public final boolean equals(Object other) {
+
+    // Check class type
+    if ((other == null) || !(other.getClass().equals(this.getClass()))) {
+      return false;
+    }
+    // Check serialized length
+    byte [] os = ((SerializedObject)other).m_Serialized;
+    if (os.length != m_Serialized.length) {
+      return false;
+    }
+    // Check serialized contents
+    for (int i = 0; i < m_Serialized.length; i++) {
+      if (m_Serialized[i] != os[i]) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Returns a hashcode for this object.
+   *
+   * @return the hashcode for this object.
+   */
+  public final int hashCode() {
+    
+    return m_Serialized.length;
+  }
+
+  /**
+   * Returns a text representation of the state of this object.
+   *
+   * @return a String representing this object.
+   */
+  public String toString() {
+    
+    return (m_Compressed ? "Compressed object: " : "Uncompressed object: ")
+      + m_Serialized.length + " bytes";
+  }
+
+  /**
+   * Test routine, reads text from stdin and measures memory usage
+   */
+  public static void main2(String []args) {
+
+    try {
+      Runtime r = Runtime.getRuntime();
+      r.gc();
+      java.io.LineNumberReader lnr = new java.io.LineNumberReader(new java.io.InputStreamReader(System.in));
+      StringBuffer sb = new StringBuffer();
+      String line;
+      while ((line = lnr.readLine()) != null) {
+        sb.append(line).append('\n');
+      }
+      String text = sb.toString();
+      //System.err.println("TEXT:");
+      //System.err.println(text);
+      r.gc();
+
+      System.err.print("TOTAL: " + r.totalMemory());
+      System.err.println("\tFREE: " + r.freeMemory());
+      long used = r.totalMemory() - r.freeMemory();
+      
+      // convert to a compressedobject
+      SerializedObject co = new SerializedObject(text, true);
+
+      System.err.print("TOTAL: " + r.totalMemory());
+      System.err.println("\tFREE: " + r.freeMemory());
+      r.gc();
+      long used1 = r.totalMemory() - r.freeMemory();
+      long csize = used1 - used;
+      System.err.println("CompressedSize = " + csize);
+
+      String newstr = (String)co.getObject();
+      r.gc();
+      System.err.print("TOTAL: " + r.totalMemory());
+      System.err.println("\tFREE: " + r.freeMemory());
+      long used2 = r.totalMemory() - r.freeMemory();
+      long usize = used2 - used1;
+      System.err.println("UncompressedSize = " + usize);
+
+      // A couple of references to the original objects
+      // so they don't get freed prematurely and muck up the
+      // measurements.
+      newstr = newstr.toLowerCase();
+      text = text.toLowerCase();
+      System.err.println("Byte array: " + co.toString());
+      System.err.println("Length of text: " + text.length());
+    } catch (Exception ex) {
+      ex.printStackTrace();
+    }
+  }
+
+
+  /**
+   * Test routine, reads an arff file from stdin and measures memory usage
+   * (the arff file should have long string attribute values)
+   */
+  public static void main(String []args) {
+
+    try {
+      Runtime r = Runtime.getRuntime();
+      r.gc();
+      System.err.print("TOTAL: " + r.totalMemory());
+      System.err.println("\tFREE: " + r.freeMemory());
+      long used = r.totalMemory() - r.freeMemory();
+      Instances inst = new Instances(new java.io.BufferedReader(new java.io.InputStreamReader(System.in)));
+      r.gc();
+      long used1 = r.totalMemory() - r.freeMemory();
+      long csize = used1 - used;
+      System.err.print("\nTOTAL: " + r.totalMemory());
+      System.err.println("\tFREE: " + r.freeMemory());
+      System.err.println("size = " + csize);
+      int blah = inst.numAttributes();
+    } catch (Exception ex) {
+      ex.printStackTrace();
+    }
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/SparseInstance.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/SparseInstance.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/SparseInstance.java	(revision 8815)
@@ -0,0 +1,773 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    SparseInstance.java
+ *    Copyright (C) 2000 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+import java.util.*;
+import java.io.*;
+
+/**
+ * Class for storing an instance as a sparse vector. A sparse instance
+ * only requires storage for those attribute values that are non-zero.
+ * Since the objective is to reduce storage requirements for datasets
+ * with large numbers of default values, this also includes nominal
+ * attributes -- the first nominal value (i.e. that which has index 0)
+ * will not require explicit storage, so rearrange your nominal attribute
+ * value orderings if necessary. Missing values will be stored
+ * explicitly.
+ */
+public class SparseInstance extends Instance {
+
+  /** The index of the attribute associated with each stored value. */
+  protected int[] m_Indices;
+
+  /** The maximum number of values that can be stored. */
+  protected int m_NumAttributes;
+
+  protected SparseInstance() {
+
+  }
+
+  /**
+   * Constructor that generates a sparse instance from the given
+   * instance. Reference to the dataset is set to null.
+   * (ie. the instance doesn't have access to information about the
+   * attribute types)
+   *
+   * @param instance the instance from which the attribute values
+   * and the weight are to be copied
+   */
+  public SparseInstance(Instance instance) {
+    
+    m_Weight = instance.m_Weight;
+    m_Dataset = null;
+    m_NumAttributes = instance.numAttributes();
+    if (instance instanceof SparseInstance) {
+      m_AttValues = ((SparseInstance)instance).m_AttValues;
+      m_Indices = ((SparseInstance)instance).m_Indices;
+    } else {
+      double[] tempValues = new double[instance.numAttributes()];
+      int[] tempIndices = new int[instance.numAttributes()];
+      int vals = 0;
+      for (int i = 0; i < instance.numAttributes(); i++) {
+	if (instance.value(i) != 0) {
+	  tempValues[vals] = instance.value(i);
+	  tempIndices[vals] = i;
+	  vals++;
+	}
+      }
+      m_AttValues = new double[vals];
+      m_Indices = new int[vals];
+      System.arraycopy(tempValues, 0, m_AttValues, 0, vals);
+      System.arraycopy(tempIndices, 0, m_Indices, 0, vals);
+    }
+  }
+
+  /**
+   * Constructor that copies the info from the given instance. 
+   * Reference to the dataset is set to null.
+   * (ie. the instance doesn't have access to information about the
+   * attribute types)
+   *
+   * @param instance the instance from which the attribute
+   * info is to be copied 
+   */
+  public SparseInstance(SparseInstance instance) {
+    
+    m_AttValues = instance.m_AttValues;
+    m_Indices = instance.m_Indices;
+    m_Weight = instance.m_Weight;
+    m_NumAttributes = instance.m_NumAttributes;
+    m_Dataset = null;
+  }
+
+  /**
+   * Constructor that generates a sparse instance from the given
+   * parameters. Reference to the dataset is set to null.
+   * (ie. the instance doesn't have access to information about the
+   * attribute types)
+   *
+   * @param weight the instance's weight
+   * @param attValues a vector of attribute values 
+   */
+  public SparseInstance(double weight, double[] attValues) {
+    
+    m_Weight = weight;
+    m_Dataset = null;
+    m_NumAttributes = attValues.length;
+    double[] tempValues = new double[m_NumAttributes];
+    int[] tempIndices = new int[m_NumAttributes];
+    int vals = 0;
+    for (int i = 0; i < m_NumAttributes; i++) {
+      if (attValues[i] != 0) {
+	tempValues[vals] = attValues[i];
+	tempIndices[vals] = i;
+	vals++;
+      }
+    }
+    m_AttValues = new double[vals];
+    m_Indices = new int[vals];
+    System.arraycopy(tempValues, 0, m_AttValues, 0, vals);
+    System.arraycopy(tempIndices, 0, m_Indices, 0, vals);
+  }
+  
+  /**
+   * Constructor that inititalizes instance variable with given
+   * values. Reference to the dataset is set to null. (ie. the instance
+   * doesn't have access to information about the attribute types)
+   *
+   * @param weight the instance's weight
+   * @param attValues a vector of attribute values (just the ones to be stored)
+   * @param indices the indices of the given values in the full vector
+   * @param maxNumValues the maximium number of values that can be stored
+   */
+  public SparseInstance(double weight, double[] attValues,
+			int[] indices, int maxNumValues){
+    
+    int vals = 0; 
+    m_AttValues = new double [attValues.length];
+    m_Indices = new int [indices.length];
+    for (int i = 0; i < attValues.length; i++) {
+      if (attValues[i] != 0) {
+        m_AttValues[vals] = attValues[i];
+        m_Indices[vals] = indices[i];
+        vals++;
+      }
+    }
+    if (vals != attValues.length) {
+      // Need to truncate.
+      double [] newVals = new double[vals];
+      System.arraycopy(m_AttValues, 0, newVals, 0, vals);
+      m_AttValues = newVals;
+      int [] newIndices = new int[vals];
+      System.arraycopy(m_Indices, 0, newIndices, 0, vals);
+      m_Indices = newIndices;
+    }
+    m_Weight = weight;
+    m_NumAttributes = maxNumValues;
+    m_Dataset = null;
+  }
+
+  /**
+   * Constructor of an instance that sets weight to one, all values to
+   * be missing, and the reference to the dataset to null. (ie. the instance
+   * doesn't have access to information about the attribute types)
+   *
+   * @param numAttributes the size of the instance 
+   */
+  public SparseInstance(int numAttributes) {
+    
+    m_AttValues = new double[numAttributes];
+    m_NumAttributes = numAttributes;
+    m_Indices = new int[numAttributes];
+    for (int i = 0; i < m_AttValues.length; i++) {
+      m_AttValues[i] = MISSING_VALUE;
+      m_Indices[i] = i;
+    }
+    m_Weight = 1;
+    m_Dataset = null;
+  }
+
+  /**
+   * Returns the attribute associated with the internal index. 
+   *
+   * @param indexOfIndex the index of the attribute's index 
+   * @return the attribute at the given position
+   * @exception UnassignedDatasetException if instance doesn't have access to a
+   * dataset
+   */ 
+  public Attribute attributeSparse(int indexOfIndex) {
+   
+    if (m_Dataset == null) {
+      throw new UnassignedDatasetException("Instance doesn't have access to a dataset!");
+    }
+    return m_Dataset.attribute(m_Indices[indexOfIndex]);
+  }
+
+  /**
+   * Produces a shallow copy of this instance. The copy has
+   * access to the same dataset. (if you want to make a copy
+   * that doesn't have access to the dataset, use 
+   * <code>new SparseInstance(instance)</code>
+   *
+   * @return the shallow copy
+   */
+  public Object copy() {
+
+    Instance result = new SparseInstance(this);
+    result.m_Dataset = m_Dataset;
+    return result;
+  }
+
+  /**
+   * Returns the index of the attribute stored at the given position.
+   *
+   * @param position the position 
+   * @return the index of the attribute stored at the given position
+   */
+  public int index(int position) {
+
+    return m_Indices[position];
+  }
+
+  /**
+   * Tests if a specific value is "missing".
+   *
+   * @param attIndex the attribute's index
+   */
+  public boolean isMissing(int attIndex) {
+
+    if (Double.isNaN(value(attIndex))) {
+      return true;
+    }
+    return false;
+  }
+
+  /**
+   * Locates the greatest index that is not greater than the
+   * given index.
+   *
+   * @return the internal index of the attribute index. Returns
+   * -1 if no index with this property couldn't be found
+   */
+  public int locateIndex(int index) {
+
+    int min = 0, max = m_Indices.length - 1;
+
+    // Binary search
+    while (max >= min) {
+      int current = (max + min) / 2;
+      if (m_Indices[current] > index) {
+	max = current - 1;
+      } else if (m_Indices[current] < index) {
+	min = current + 1;
+      } else {
+	return current;
+      }
+    }
+    return max;
+  }
+
+  /**
+   * Merges this instance with the given instance and returns
+   * the result. Dataset is set to null.
+   *
+   * @param inst the instance to be merged with this one
+   * @return the merged instances
+   */
+  public Instance mergeInstance(Instance inst) {
+
+    double[] values = new double[numValues() + inst.numValues()];
+    int[] indices = new int[numValues() + inst.numValues()];
+
+    int m = 0;
+    for (int j = 0; j < numValues(); j++, m++) {
+      values[m] = valueSparse(j);
+      indices[m] = index(j);
+    }
+    for (int j = 0; j < inst.numValues(); j++, m++) {
+      values[m] = inst.valueSparse(j);
+      indices[m] = inst.index(j) + inst.numAttributes();
+    }
+    
+    return new SparseInstance(1.0, values, indices, numAttributes() +
+			      inst.numAttributes());
+  }
+
+  /**
+   * Returns the number of attributes.
+   *
+   * @return the number of attributes as an integer
+   */
+  public int numAttributes() {
+
+    return m_NumAttributes;
+  }
+
+  /**
+   * Returns the number of values in the sparse vector.
+   *
+   * @return the number of values
+   */
+  public int numValues() {
+
+    return m_Indices.length;
+  }
+
+  /** 
+   * Replaces all missing values in the instance with the 
+   * values contained in the given array. A deep copy of
+   * the vector of attribute values is performed before the
+   * values are replaced.
+   *
+   * @param array containing the means and modes
+   * @exception IllegalArgumentException if numbers of attributes are unequal
+   */
+  public void replaceMissingValues(double[] array) {
+	 
+    if ((array == null) || (array.length != m_NumAttributes)) {
+      throw new IllegalArgumentException("Unequal number of attributes!");
+    }
+    double[] tempValues = new double[m_AttValues.length];
+    int[] tempIndices = new int[m_AttValues.length];
+    int vals = 0;
+    for (int i = 0; i < m_AttValues.length; i++) {
+      if (isMissingValue(m_AttValues[i])) {
+	if (array[m_Indices[i]] != 0) {
+	  tempValues[vals] = array[m_Indices[i]];
+	  tempIndices[vals] = m_Indices[i];
+	  vals++;
+	} 
+      } else {
+	tempValues[vals] = m_AttValues[i];
+	tempIndices[vals] = m_Indices[i];
+	vals++;
+      }
+    }
+    m_AttValues = new double[vals];
+    m_Indices = new int[vals];
+    System.arraycopy(tempValues, 0, m_AttValues, 0, vals);
+    System.arraycopy(tempIndices, 0, m_Indices, 0, vals);
+  }
+
+  /**
+   * Sets a specific value in the instance to the given value 
+   * (internal floating-point format). Performs a deep copy
+   * of the vector of attribute values before the value is set.
+   *
+   * @param attIndex the attribute's index 
+   * @param value the new attribute value (If the corresponding
+   * attribute is nominal (or a string) then this is the new value's
+   * index as a double).  
+   */
+  public void setValue(int attIndex, double value) {
+
+    int index = locateIndex(attIndex);
+    
+    if ((index >= 0) && (m_Indices[index] == attIndex)) {
+      if (value != 0) {
+	double[] tempValues = new double[m_AttValues.length];
+	System.arraycopy(m_AttValues, 0, tempValues, 0, m_AttValues.length);
+	tempValues[index] = value;
+	m_AttValues = tempValues;
+      } else {
+	double[] tempValues = new double[m_AttValues.length - 1];
+	int[] tempIndices = new int[m_Indices.length - 1];
+	System.arraycopy(m_AttValues, 0, tempValues, 0, index);
+	System.arraycopy(m_Indices, 0, tempIndices, 0, index);
+	System.arraycopy(m_AttValues, index + 1, tempValues, index, 
+			 m_AttValues.length - index - 1);
+	System.arraycopy(m_Indices, index + 1, tempIndices, index, 
+			 m_Indices.length - index - 1);
+	m_AttValues = tempValues;
+	m_Indices = tempIndices;
+      }
+    } else {
+      if (value != 0) {
+	double[] tempValues = new double[m_AttValues.length + 1];
+	int[] tempIndices = new int[m_Indices.length + 1];
+	System.arraycopy(m_AttValues, 0, tempValues, 0, index + 1);
+	System.arraycopy(m_Indices, 0, tempIndices, 0, index + 1);
+	tempIndices[index + 1] = attIndex;
+	tempValues[index + 1] = value;
+	System.arraycopy(m_AttValues, index + 1, tempValues, index + 2, 
+			 m_AttValues.length - index - 1);
+	System.arraycopy(m_Indices, index + 1, tempIndices, index + 2, 
+			 m_Indices.length - index - 1);
+	m_AttValues = tempValues;
+	m_Indices = tempIndices;
+      }
+    }
+  }
+
+  /**
+   * Sets a specific value in the instance to the given value 
+   * (internal floating-point format). Performs a deep copy
+   * of the vector of attribute values before the value is set.
+   *
+   * @param indexOfIndex the index of the attribute's index 
+   * @param value the new attribute value (If the corresponding
+   * attribute is nominal (or a string) then this is the new value's
+   * index as a double).  
+   */
+  public void setValueSparse(int indexOfIndex, double value) {
+
+    if (value != 0) {
+      double[] tempValues = new double[m_AttValues.length];
+      System.arraycopy(m_AttValues, 0, tempValues, 0, m_AttValues.length);
+      m_AttValues = tempValues;
+      m_AttValues[indexOfIndex] = value;
+    } else {
+      double[] tempValues = new double[m_AttValues.length - 1];
+      int[] tempIndices = new int[m_Indices.length - 1];
+      System.arraycopy(m_AttValues, 0, tempValues, 0, indexOfIndex);
+      System.arraycopy(m_Indices, 0, tempIndices, 0, indexOfIndex);
+      System.arraycopy(m_AttValues, indexOfIndex + 1, tempValues, indexOfIndex, 
+		       m_AttValues.length - indexOfIndex - 1);
+      System.arraycopy(m_Indices, indexOfIndex + 1, tempIndices, indexOfIndex, 
+		       m_Indices.length - indexOfIndex - 1);
+      m_AttValues = tempValues;
+      m_Indices = tempIndices;
+    }
+  }
+
+  /**
+   * Returns the values of each attribute as an array of doubles.
+   *
+   * @return an array containing all the instance attribute values
+   */
+  public double[] toDoubleArray() {
+
+    double[] newValues = new double[m_NumAttributes];
+    for (int i = 0; i < m_AttValues.length; i++) {
+      newValues[m_Indices[i]] = m_AttValues[i];
+    }
+    return newValues;
+  }
+
+  /**
+   * Returns the description of one instance in sparse format. 
+   * If the instance doesn't have access to a dataset, it returns the 
+   * internal floating-point values. Quotes string values that contain 
+   * whitespace characters.
+   *
+   * @return the instance's description as a string
+   */
+  public String toString() {
+
+    StringBuffer text = new StringBuffer();
+    
+    text.append('{');
+    for (int i = 0; i < m_Indices.length; i++) {
+      if (i > 0) text.append(",");
+      if (isMissingValue(m_AttValues[i])) {
+	text.append(m_Indices[i] + " ?");
+      } else {
+	if (m_Dataset == null) {
+	  text.append(m_Indices[i] + " " + 
+		      Utils.doubleToString(m_AttValues[i],6));
+	} else {
+	  if (m_Dataset.attribute(m_Indices[i]).isNominal() || 
+	      m_Dataset.attribute(m_Indices[i]).isString()) {
+	    try {
+	      text.append(m_Indices[i] + " " +
+			  Utils.quote(m_Dataset.attribute(m_Indices[i]).
+				      value((int)valueSparse(i))));
+	    } catch (Exception e) {
+              e.printStackTrace();
+              System.err.println(new Instances(m_Dataset, 0));
+              System.err.println("Att:" + m_Indices[i] + " Val:" + valueSparse(i));
+	      throw new Error("This should never happen!");
+	    }
+	  } else {
+	    text.append(m_Indices[i] + " " +
+			Utils.doubleToString(m_AttValues[i],6));
+	  }
+	}
+      }
+    }
+    text.append('}');
+    return text.toString();
+  }
+
+  /**
+   * Returns an instance's attribute value in internal format.
+   *
+   * @param attIndex the attribute's index
+   * @return the specified value as a double (If the corresponding
+   * attribute is nominal (or a string) then it returns the value's index as a 
+   * double).
+   */
+  public double value(int attIndex) {
+
+    int index = locateIndex(attIndex);
+    if ((index >= 0) && (m_Indices[index] == attIndex)) {
+      return m_AttValues[index];
+    } else {
+      return 0.0;
+    }
+  }  
+
+  /**
+   * Deletes an attribute at the given position (0 to 
+   * numAttributes() - 1).
+   *
+   * @param pos the attribute's position
+   */
+  void forceDeleteAttributeAt(int position) {
+
+    int index = locateIndex(position);
+
+    m_NumAttributes--;
+    if ((index >= 0) && (m_Indices[index] == position)) {
+      int[] tempIndices = new int[m_Indices.length - 1];
+      double[] tempValues = new double[m_AttValues.length - 1];
+      System.arraycopy(m_Indices, 0, tempIndices, 0, index);
+      System.arraycopy(m_AttValues, 0, tempValues, 0, index);
+      for (int i = index; i < m_Indices.length - 1; i++) {
+	tempIndices[i] = m_Indices[i + 1] - 1;
+	tempValues[i] = m_AttValues[i + 1];
+      }
+      m_Indices = tempIndices;
+      m_AttValues = tempValues;
+    } else {
+      int[] tempIndices = new int[m_Indices.length];
+      double[] tempValues = new double[m_AttValues.length];
+      System.arraycopy(m_Indices, 0, tempIndices, 0, index + 1);
+      System.arraycopy(m_AttValues, 0, tempValues, 0, index + 1);
+      for (int i = index + 1; i < m_Indices.length - 1; i++) {
+	tempIndices[i] = m_Indices[i] - 1;
+	tempValues[i] = m_AttValues[i];
+      }
+      m_Indices = tempIndices;
+      m_AttValues = tempValues;
+    }
+  }
+
+  /**
+   * Inserts an attribute at the given position
+   * (0 to numAttributes()) and sets its value to be missing. 
+   *
+   * @param pos the attribute's position
+   */
+  void forceInsertAttributeAt(int position)  {
+
+    int index = locateIndex(position);
+
+    m_NumAttributes++;
+    if ((index >= 0) && (m_Indices[index] == position)) {
+      int[] tempIndices = new int[m_Indices.length + 1];
+      double[] tempValues = new double[m_AttValues.length + 1];
+      System.arraycopy(m_Indices, 0, tempIndices, 0, index);
+      System.arraycopy(m_AttValues, 0, tempValues, 0, index);
+      tempIndices[index] = position;
+      tempValues[index] = MISSING_VALUE;
+      for (int i = index; i < m_Indices.length; i++) {
+	tempIndices[i + 1] = m_Indices[i] + 1;
+	tempValues[i + 1] = m_AttValues[i];
+      }
+      m_Indices = tempIndices;
+      m_AttValues = tempValues;
+    } else {
+      int[] tempIndices = new int[m_Indices.length + 1];
+      double[] tempValues = new double[m_AttValues.length + 1];
+      System.arraycopy(m_Indices, 0, tempIndices, 0, index + 1);
+      System.arraycopy(m_AttValues, 0, tempValues, 0, index + 1);
+      tempIndices[index + 1] = position;
+      tempValues[index + 1] = MISSING_VALUE;
+      for (int i = index + 1; i < m_Indices.length; i++) {
+	tempIndices[i + 1] = m_Indices[i] + 1;
+	tempValues[i + 1] = m_AttValues[i];
+      }
+      m_Indices = tempIndices;
+      m_AttValues = tempValues;
+    }
+  }
+
+  /**
+   * Main method for testing this class.
+   */
+  public static void main(String[] options) {
+
+    try {
+
+      // Create numeric attributes "length" and "weight"
+      Attribute length = new Attribute("length");
+      Attribute weight = new Attribute("weight");
+      
+      // Create vector to hold nominal values "first", "second", "third" 
+      FastVector my_nominal_values = new FastVector(3); 
+      my_nominal_values.addElement("first"); 
+      my_nominal_values.addElement("second"); 
+      my_nominal_values.addElement("third"); 
+      
+      // Create nominal attribute "position" 
+      Attribute position = new Attribute("position", my_nominal_values);
+      
+      // Create vector of the above attributes 
+      FastVector attributes = new FastVector(3);
+      attributes.addElement(length);
+      attributes.addElement(weight);
+      attributes.addElement(position);
+      
+      // Create the empty dataset "race" with above attributes
+      Instances race = new Instances("race", attributes, 0);
+      
+      // Make position the class attribute
+      race.setClassIndex(position.index());
+      
+      // Create empty instance with three attribute values
+      SparseInstance inst = new SparseInstance(3);
+      
+      // Set instance's values for the attributes "length", "weight", and "position"
+      inst.setValue(length, 5.3);
+      inst.setValue(weight, 300);
+      inst.setValue(position, "first");
+      
+      // Set instance's dataset to be the dataset "race"
+      inst.setDataset(race);
+      
+      // Print the instance
+      System.out.println("The instance: " + inst);
+      
+      // Print the first attribute
+      System.out.println("First attribute: " + inst.attribute(0));
+      
+      // Print the class attribute
+      System.out.println("Class attribute: " + inst.classAttribute());
+      
+      // Print the class index
+      System.out.println("Class index: " + inst.classIndex());
+      
+      // Say if class is missing
+      System.out.println("Class is missing: " + inst.classIsMissing());
+      
+      // Print the instance's class value in internal format
+      System.out.println("Class value (internal format): " + inst.classValue());
+      
+      // Print a shallow copy of this instance
+      SparseInstance copy = (SparseInstance) inst.copy();
+      System.out.println("Shallow copy: " + copy);
+      
+      // Set dataset for shallow copy
+      copy.setDataset(inst.dataset());
+      System.out.println("Shallow copy with dataset set: " + copy);
+
+      // Print out all values in internal format
+      System.out.print("All stored values in internal format: ");
+      for (int i = 0; i < inst.numValues(); i++) {
+	if (i > 0) {
+	  System.out.print(",");
+	}
+	System.out.print(inst.valueSparse(i));
+      }
+      System.out.println();
+
+      // Set all values to zero
+      System.out.print("All values set to zero: ");
+      while (inst.numValues() > 0) {
+	inst.setValueSparse(0, 0);
+      }
+      for (int i = 0; i < inst.numValues(); i++) {
+	if (i > 0) {
+	  System.out.print(",");
+	}
+	System.out.print(inst.valueSparse(i));
+      }
+      System.out.println();
+
+      // Set all values to one
+      System.out.print("All values set to one: ");
+      for (int i = 0; i < inst.numAttributes(); i++) {
+	inst.setValue(i, 1);
+      }
+      for (int i = 0; i < inst.numValues(); i++) {
+	if (i > 0) {
+	  System.out.print(",");
+	}
+	System.out.print(inst.valueSparse(i));
+      }
+      System.out.println();
+
+      // Unset dataset for copy, delete first attribute, and insert it again
+      copy.setDataset(null);
+      copy.deleteAttributeAt(0);
+      copy.insertAttributeAt(0);
+      copy.setDataset(inst.dataset());
+      System.out.println("Copy with first attribute deleted and inserted: " + copy); 
+
+      // Same for second attribute
+      copy.setDataset(null);
+      copy.deleteAttributeAt(1);
+      copy.insertAttributeAt(1);
+      copy.setDataset(inst.dataset());
+      System.out.println("Copy with second attribute deleted and inserted: " + copy); 
+
+      // Same for last attribute
+      copy.setDataset(null);
+      copy.deleteAttributeAt(2);
+      copy.insertAttributeAt(2);
+      copy.setDataset(inst.dataset());
+      System.out.println("Copy with third attribute deleted and inserted: " + copy); 
+      
+      // Enumerate attributes (leaving out the class attribute)
+      System.out.println("Enumerating attributes (leaving out class):");
+      Enumeration enum = inst.enumerateAttributes();
+      while (enum.hasMoreElements()) {
+	Attribute att = (Attribute) enum.nextElement();
+	System.out.println(att);
+      }
+      
+      // Headers are equivalent?
+      System.out.println("Header of original and copy equivalent: " +
+			 inst.equalHeaders(copy));
+
+      // Test for missing values
+      System.out.println("Length of copy missing: " + copy.isMissing(length));
+      System.out.println("Weight of copy missing: " + copy.isMissing(weight.index()));
+      System.out.println("Length of copy missing: " + 
+			 Instance.isMissingValue(copy.value(length)));
+      System.out.println("Missing value coded as: " + Instance.missingValue());
+
+      // Prints number of attributes and classes
+      System.out.println("Number of attributes: " + copy.numAttributes());
+      System.out.println("Number of classes: " + copy.numClasses());
+
+      // Replace missing values
+      double[] meansAndModes = {2, 3, 0};
+      copy.replaceMissingValues(meansAndModes);
+      System.out.println("Copy with missing value replaced: " + copy);
+
+      // Setting and getting values and weights
+      copy.setClassMissing();
+      System.out.println("Copy with missing class: " + copy);
+      copy.setClassValue(0);
+      System.out.println("Copy with class value set to first value: " + copy);
+      copy.setClassValue("third");
+      System.out.println("Copy with class value set to \"third\": " + copy);
+      copy.setMissing(1);
+      System.out.println("Copy with second attribute set to be missing: " + copy);
+      copy.setMissing(length);
+      System.out.println("Copy with length set to be missing: " + copy);
+      copy.setValue(0, 0);
+      System.out.println("Copy with first attribute set to 0: " + copy);
+      copy.setValue(weight, 1);
+      System.out.println("Copy with weight attribute set to 1: " + copy);
+      copy.setValue(position, "second");
+      System.out.println("Copy with position set to \"second\": " + copy);
+      copy.setValue(2, "first");
+      System.out.println("Copy with last attribute set to \"first\": " + copy);
+      System.out.println("Current weight of instance copy: " + copy.weight());
+      copy.setWeight(2);
+      System.out.println("Current weight of instance copy (set to 2): " + copy.weight());
+      System.out.println("Last value of copy: " + copy.toString(2));
+      System.out.println("Value of position for copy: " + copy.toString(position));
+      System.out.println("Last value of copy (internal format): " + copy.value(2));
+      System.out.println("Value of position for copy (internal format): " + 
+			 copy.value(position));
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/SpecialFunctions.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/SpecialFunctions.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/SpecialFunctions.java	(revision 8815)
@@ -0,0 +1,127 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    SpecialFunctions.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+import java.lang.Math;
+
+/**
+ * Class implementing some mathematical functions.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public final class SpecialFunctions {
+
+  /** Some constants */
+  private static double log2 = Math.log(2);
+  private static double[] cofLogGamma = {76.18009172947146,-86.50532032941677,
+					 24.01409824083091,-1.231739572450155,
+					 0.1208650973866179e-2,-0.5395239384953e-5};
+
+  /**
+   * Returns natural logarithm of factorial using gamma function.
+   *
+   * @param x the value
+   * @return natural logarithm of factorial
+   */
+  public static double lnFactorial(double x){
+
+    return lnGamma(x+1);
+  }
+
+  /**
+   * Returns natural logarithm of gamma function. Converted to java
+   * from Numerical Recipes in C.
+   *
+   * @param x the value
+   * @return natural logarithm of gamma function
+   */
+  public static double lnGamma(double x){
+    
+    double y,tmp,ser;
+    int j;
+    
+    y=x;
+    tmp=x+5.5;
+    tmp -= (x+0.5)*Math.log(tmp);
+    ser=1.000000000190015;
+    for (j=0;j<=5;j++) {
+      ser += cofLogGamma[j]/++y;
+    }
+    return -tmp+Math.log(2.5066282746310005*ser/x);
+  }
+
+  /**
+   * Returns base 2 logarithm of binomial coefficient using gamma function.
+   *
+   * @param a upper part of binomial coefficient
+   * @param b lower part
+   * @return the base 2 logarithm of the binominal coefficient a over b
+   */
+  public static double log2Binomial(double a, double b) throws ArithmeticException{
+    
+    if (Utils.gr(b,a)) {
+      throw new ArithmeticException("Can't compute binomial coefficient.");
+    }
+    return (lnFactorial(a)-lnFactorial(b)-lnFactorial(a-b))/log2;
+  }
+
+  /**
+   * Returns base 2 logarithm of multinomial using gamma function.
+   *
+   * @param a upper part of multinomial coefficient
+   * @param bs lower part
+   * @return multinomial coefficient of a over the bs
+   */
+  public static double log2Multinomial(double a, double[] bs)
+       throws ArithmeticException{
+    
+    double sum = 0;
+    int i;
+    
+    for (i=0;i<bs.length;i++) {
+      if (Utils.gr(bs[i],a)) {
+	throw 
+	  new ArithmeticException("Can't compute multinomial coefficient.");
+      } else {
+	sum = sum+lnFactorial(bs[i]);
+      }
+    }
+    return (lnFactorial(a)-sum)/log2;
+  }
+
+  /**
+   * Main method for testing this class.
+   */
+  public static void main(String[] ops) {
+
+    double[] doubles = {1, 2, 3};
+
+    System.out.println("6!: " + Math.exp(SpecialFunctions.lnFactorial(6)));
+    System.out.println("lnGamma(6): "+ SpecialFunctions.lnGamma(6));
+    System.out.println("Binomial 6 over 2: " +
+		       Math.pow(2, SpecialFunctions.log2Binomial(6, 2)));
+    System.out.println("Multinomial 6 over 1, 2, 3: " +
+		       Math.pow(2, SpecialFunctions.log2Multinomial(6, doubles)));
+  }    
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/Statistics.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/Statistics.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/Statistics.java	(revision 8815)
@@ -0,0 +1,280 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Statistics.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+/**
+ * Class implementing some distributions, tests, etc. Most of the
+ * code is adapted from Gary Perlman's unixstat.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class Statistics {
+
+  /** Some constants */
+  private static double logSqrtPi = Math.log(Math.sqrt(Math.PI));
+  private static double rezSqrtPi = 1/Math.sqrt(Math.PI);
+  private static double bigx = 20.0;
+
+  /**
+   * Computes standard error for observed values of a binomial
+   * random variable.
+   *
+   * @param p the probability of success
+   * @param n the size of the sample
+   * @return the standard error
+   */
+  public static double binomialStandardError(double p, int n) {
+
+    if (n == 0) {
+      return 0; 
+    }
+    return Math.sqrt((p*(1-p))/(double) n);
+  }
+
+  /**
+   * Returns chi-squared probability for given value and degrees
+   * of freedom. (The probability that the chi-squared variate
+   * will be greater than x for the given degrees of freedom.)
+   * Adapted from unixstat by Gary Perlman.
+   *
+   * @param x the value
+   * @param df the number of degrees of freedom
+   */
+  public static double chiSquaredProbability(double x, int df) {
+
+    double a, y = 0, s, e, c, z, val;
+    boolean even;
+   
+    if (x <= 0 || df < 1)
+      return (1);
+    a = 0.5 * x;
+    even = (((int)(2*(df/2))) == df);
+    if (df > 1)
+      y = Math.exp(-a); //((-a < -bigx) ? 0.0 : Math.exp (-a));
+    s = (even ? y : (2.0 * normalProbability(-Math.sqrt (x))));
+    if (df > 2){
+      x = 0.5 * (df - 1.0);
+      z = (even ? 1.0 : 0.5);
+      if (a > bigx){
+	e = (even ? 0.0 : logSqrtPi);
+	c = Math.log (a);
+	while (z <= x){
+	  e = Math.log (z) + e;
+	  val = c*z-a-e;
+	  s += Math.exp (val); //((val < -bigx) ? 0.0 : Math.exp (val));
+	  z += 1.0;
+	}
+	return (s);
+      }else{
+	e = (even ? 1.0 : (rezSqrtPi / Math.sqrt (a)));
+	c = 0.0;
+	while (z <= x){
+	  e = e * (a / z);
+	  c = c + e;
+	  z += 1.0;
+	}
+	return (c * y + s);
+      }
+    }else{
+      return (s);
+    }
+  }
+
+  /**
+   * Critical value for given probability of F-distribution.
+   * Adapted from unixstat by Gary Perlman.
+   *
+   * @param p the probability
+   * @param df1 the first number of degrees of freedom
+   * @param df2 the second number of degrees of freedom
+   * @return the critical value for the given probability
+   */
+  public static double FCriticalValue(double p, int df1, int df2) {
+
+    double  fval;
+    double  maxf = 99999.0;     /* maximum possible F ratio */
+    double  minf = .000001;     /* minimum possible F ratio */
+    
+    if (p <= 0.0 || p >= 1.0)
+      return (0.0);
+    
+    fval = 1.0 / p; /* the smaller the p, the larger the F */
+    
+    while (Math.abs (maxf - minf) > .000001) {
+      if (FProbability(fval, df1, df2) < p) /* F too large */
+	maxf = fval;
+      else /* F too small */
+	minf = fval;
+      fval = (maxf + minf) * 0.5;
+    }
+    
+    return (fval);
+  }
+
+  /**
+   * Computes probability of F-ratio.
+   * Adapted from unixstat by Gary Perlman.
+   * Collected Algorithms of the CACM 
+   * Algorithm 322
+   * Egon Dorrer
+   *
+   * @param F the F-ratio
+   * @param df1 the first number of degrees of freedom
+   * @param df2 the second number of degrees of freedom
+   * @return the probability of the F-ratio.
+   */
+  public static double FProbability(double F, int df1, int df2) {
+
+    int     i, j;
+    int     a, b;
+    double  w, y, z, d, p;
+
+    if ((Math.abs(F) < 10e-10) || df1 <= 0 || df2 <= 0)
+      return (1.0);
+    a = (df1%2 == 1) ? 1 : 2;
+    b = (df2%2 == 1) ? 1 : 2;
+    w = (F * df1) / df2;
+    z = 1.0 / (1.0 + w);
+    if (a == 1)
+      if (b == 1) {
+	p = Math.sqrt (w);
+	y = 1/Math.PI; /* 1 / 3.14159 */
+	d = y * z / p;
+	p = 2.0 * y * Math.atan (p);
+      } else {
+	p = Math.sqrt (w * z);
+	d = 0.5 * p * z / w;
+      } else if (b == 1) {
+	p = Math.sqrt (z);
+	d = 0.5 * z * p;
+	p = 1.0 - p;
+      } else {
+	d = z * z;
+	p = w * z;
+      }
+    y = 2.0 * w / z;
+    for (j = b + 2; j <= df2; j += 2) {
+      d *= (1.0 + a / (j - 2.0)) * z;
+      p = (a == 1 ? p + d * y / (j - 1.0) : (p + w) * z);
+    }
+    y = w * z;
+    z = 2.0 / z;
+    b = df2 - 2;
+    for (i = a + 2; i <= df1; i += 2) {
+      j = i + b;
+      d *= y * j / (i - 2.0);
+      p -= z * d / j;
+    }
+    
+    // correction for approximation errors suggested in certification
+    if (p < 0.0)
+      p = 0.0;
+    else if (p > 1.0)
+      p = 1.0;
+    return (1.0-p);
+  }
+  
+  /**
+   * Returns probability that the standardized normal variate Z (mean = 0, standard
+   * deviation = 1) is less than z.
+   * Adapted from unixstat by Gary Perlman.
+   *
+   * @param the z-value
+   * @return the probability of the z value according to the normal pdf
+   */
+  public static double normalProbability(double z) {
+
+    double  y, x, w;
+    
+    if (z == 0.0)
+      x = 0.0;
+    else{
+      y = 0.5 * Math.abs (z);
+      if (y >= 3.0)
+	x = 1.0;
+      else if (y < 1.0){
+	w = y*y;
+	x = ((((((((0.000124818987 * w
+                   -0.001075204047) * w +0.005198775019) * w
+                   -0.019198292004) * w +0.059054035642) * w
+                   -0.151968751364) * w +0.319152932694) * w
+                   -0.531923007300) * w +0.797884560593) * y * 2.0;
+      }else{
+	y -= 2.0;
+	x = (((((((((((((-0.000045255659 * y
+                         +0.000152529290) * y -0.000019538132) * y
+                         -0.000676904986) * y +0.001390604284) * y
+                         -0.000794620820) * y -0.002034254874) * y
+                         +0.006549791214) * y -0.010557625006) * y
+                         +0.011630447319) * y -0.009279453341) * y
+                         +0.005353579108) * y -0.002141268741) * y
+                         +0.000535310849) * y +0.999936657524;
+      }
+    }
+  
+    return (z > 0.0 ? ((x + 1.0) / 2.0) : ((1.0 - x) / 2.0));
+  }
+
+  /**
+   * Computes absolute size of half of a student-t confidence interval 
+   * for given degrees of freedom, probability, and observed value.
+   *
+   * @param df the number of degrees of freedom
+   * @param p the probability
+   * @param se the observed value
+   * @return absolute size of half of a student-t confidence interval
+   */
+  public static double studentTConfidenceInterval(int df, double p,
+						  double se) {
+
+    return Math.sqrt(FCriticalValue(p, 1, df))*se;
+  }
+
+  /**
+   * Main method for testing this class.
+   */
+  public static void main(String[] ops) {
+
+    System.out.println("Binomial standard error (0.5, 100): " + 
+		       Statistics.binomialStandardError(0.5, 100));
+    System.out.println("Chi-squared probability (2.558, 10): " +
+		       Statistics.chiSquaredProbability(2.558, 10));
+    System.out.println("Normal probability (0.2): " +
+		       Statistics.normalProbability(0.2));
+    System.out.println("F critical value (0.05, 4, 5): " +
+		       Statistics.FCriticalValue(0.05, 4, 5));
+    System.out.println("F probability (5.1922, 4, 5): " +
+		       Statistics.FProbability(5.1922, 4, 5));
+    System.out.println("Student-t confidence interval (9, 0.01, 2): " +
+		       Statistics.studentTConfidenceInterval(9, 0.01, 2));
+  }
+}
+
+
+
+
+
+
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/UnassignedClassException.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/UnassignedClassException.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/UnassignedClassException.java	(revision 8815)
@@ -0,0 +1,52 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    UnassignedClassException.java
+ *    Copyright (C) 2001 Webmind Corp.
+ */
+
+package weka.core;
+
+/**
+ * <code>UnassignedClassException</code> is used when
+ * a method requires access to the Attribute designated as 
+ * the class attribute in a set of Instances, but the Instances does not
+ * have any class attribute assigned (such as by setClassIndex()).
+ *
+ * @author <a href="mailto:len@webmind.com">Len Trigg</a>
+ * @version $Revision$
+ */
+public class UnassignedClassException extends RuntimeException {
+
+  /**
+   * Creates a new <code>UnassignedClassException</code> instance
+   * with no detail message.
+   */
+  public UnassignedClassException() { 
+    super(); 
+  }
+
+  /**
+   * Creates a new <code>UnassignedClassException</code> instance
+   * with a specified message.
+   *
+   * @param messagae a <code>String</code> containing the message.
+   */
+  public UnassignedClassException(String message) { 
+    super(message); 
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/UnassignedDatasetException.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/UnassignedDatasetException.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/UnassignedDatasetException.java	(revision 8815)
@@ -0,0 +1,53 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    UnassignedDatasetException.java
+ *    Copyright (C) 2001 Webmind Corp.
+ */
+
+package weka.core;
+
+/**
+ * <code>UnassignedDatasetException</code> is used when
+ * a method of an Instance is called that requires access to
+ * the Instance structure, but that the Instance does not contain
+ * a reference to any Instances (as set by Instance.setDataset(), or when
+ * an Instance is added to a set of Instances)).
+ *
+ * @author <a href="mailto:len@webmind.com">Len Trigg</a>
+ * @version $Revision$
+ */
+public class UnassignedDatasetException extends RuntimeException {
+
+  /**
+   * Creates a new <code>UnassignedDatasetException</code> instance
+   * with no detail message.
+   */
+  public UnassignedDatasetException() { 
+    super(); 
+  }
+
+  /**
+   * Creates a new <code>UnassignedDatasetException</code> instance
+   * with a specified message.
+   *
+   * @param messagae a <code>String</code> containing the message.
+   */
+  public UnassignedDatasetException(String message) { 
+    super(message); 
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/UnsupportedClassTypeException.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/UnsupportedClassTypeException.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/UnsupportedClassTypeException.java	(revision 8815)
@@ -0,0 +1,51 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    UnsupportedClassTypeException.java
+ *    Copyright (C) 2001 Webmind Corp.
+ */
+
+package weka.core;
+
+/**
+ * <code>UnsupportedClassTypeException</code> is used in situations
+ * where the throwing object is not able to accept Instances with the
+ * supplied structure, because the class Attribute is of the wrong type.
+ *
+ * @author <a href="mailto:len@webmind.com">Len Trigg</a>
+ * @version $Revision$
+ */
+public class UnsupportedClassTypeException extends WekaException {
+
+  /**
+   * Creates a new <code>UnsupportedClassTypeException</code> instance
+   * with no detail message.
+   */
+  public UnsupportedClassTypeException() { 
+    super(); 
+  }
+
+  /**
+   * Creates a new <code>UnsupportedClassTypeException</code> instance
+   * with a specified message.
+   *
+   * @param messagae a <code>String</code> containing the message.
+   */
+  public UnsupportedClassTypeException(String message) { 
+    super(message); 
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/Utils.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/Utils.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/Utils.java	(revision 8815)
@@ -0,0 +1,1384 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Utils.java
+ *    Copyright (C) 1999 Eibe Frank,Len Trigg,Yong Wang
+ *
+ */
+
+package weka.core;
+
+import java.lang.Math;
+import java.util.StringTokenizer;
+import java.util.Properties;
+import java.io.File;
+import java.io.FileInputStream;
+
+/**
+ * Class implementing some simple utility methods.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @author Yong Wang (yongwang@cs.waikato.ac.nz)
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public final class Utils {
+
+  /** The natural logarithm of 2. */
+  public static double log2 = Math.log(2);
+
+  /** The small deviation allowed in double comparisons */
+  public static double SMALL = 1e-6;
+
+  
+  /**
+   * Reads properties that inherit from three locations. Properties
+   * are first defined in the system resource location (i.e. in the
+   * CLASSPATH).  These default properties must exist. Properties
+   * defined in the users home directory (optional) override default
+   * settings. Properties defined in the current directory (optional)
+   * override all these settings.
+   *
+   * @param resourceName the location of the resource that should be
+   * loaded.  e.g.: "weka/core/Utils.props". (The use of hardcoded
+   * forward slashes here is OK - see
+   * jdk1.1/docs/guide/misc/resources.html) This routine will also
+   * look for the file (in this case) "Utils.props" in the users home
+   * directory and the current directory.
+   * @return the Properties
+   * @exception Exception if no default properties are defined, or if
+   * an error occurs reading the properties files.  
+   */
+  public static Properties readProperties(String resourceName)
+    throws Exception{
+
+    Properties defaultProps = new Properties();
+    try {
+      // Apparently hardcoded slashes are OK here
+      // jdk1.1/docs/guide/misc/resources.html
+      defaultProps.load(ClassLoader.getSystemResourceAsStream(resourceName));
+    } catch (Exception ex) {
+/*      throw new Exception("Problem reading default properties: "
+	+ ex.getMessage()); */
+      System.err.println("Warning, unable to load properties file from "
+			 +"system resource (Utils.java)");
+    }
+
+    // Hardcoded slash is OK here
+    // eg: see jdk1.1/docs/guide/misc/resources.html
+    int slInd = resourceName.lastIndexOf('/');
+    if (slInd != -1) {
+      resourceName = resourceName.substring(slInd + 1);
+    }
+
+    // Allow a properties file in the home directory to override
+    Properties userProps = new Properties(defaultProps);    
+    File propFile = new File(System.getProperties().getProperty("user.home")
+                             + File.separatorChar
+                             + resourceName);
+    if (propFile.exists()) {
+      try {
+        userProps.load(new FileInputStream(propFile));
+      } catch (Exception ex) {
+        throw new Exception("Problem reading user properties: " + propFile);
+      }
+    }
+
+    // Allow a properties file in the current directory to override
+    Properties localProps = new Properties(userProps);
+    propFile = new File(resourceName);
+    if (propFile.exists()) {
+      try {
+        localProps.load(new FileInputStream(propFile));
+      } catch (Exception ex) {
+        throw new Exception("Problem reading local properties: " + propFile);
+      }
+    }
+    
+    return localProps;
+  }
+
+  /**
+   * Returns the correlation coefficient of two double vectors.
+   *
+   * @param y1 double vector 1
+   * @param y2 double vector 2
+   * @param n the length of two double vectors
+   * @return the correlation coefficient
+   */
+  public final static double correlation(double y1[],double y2[],int n) {
+
+    int i;
+    double av1 = 0.0, av2 = 0.0, y11 = 0.0, y22 = 0.0, y12 = 0.0, c;
+    
+    if (n <= 1) {
+      return 1.0;
+    }
+    for (i = 0; i < n; i++) {
+      av1 += y1[i];
+      av2 += y2[i];
+    }
+    av1 /= (double) n;
+    av2 /= (double) n;
+    for (i = 0; i < n; i++) {
+      y11 += (y1[i] - av1) * (y1[i] - av1);
+      y22 += (y2[i] - av2) * (y2[i] - av2);
+      y12 += (y1[i] - av1) * (y2[i] - av2);
+    }
+    if (y11 * y22 == 0.0) {
+      c=1.0;
+    } else {
+      c = y12 / Math.sqrt(Math.abs(y11 * y22));
+    }
+    
+    return c;
+  }
+
+  /**
+   * Removes all occurrences of a string from another string.
+   *
+   * @param inString the string to remove substrings from.
+   * @param substring the substring to remove.
+   * @return the input string with occurrences of substring removed.
+   */
+  public static String removeSubstring(String inString, String substring) {
+
+    StringBuffer result = new StringBuffer();
+    int oldLoc = 0, loc = 0;
+    while ((loc = inString.indexOf(substring, oldLoc))!= -1) {
+      result.append(inString.substring(oldLoc, loc));
+      oldLoc = loc + substring.length();
+    }
+    result.append(inString.substring(oldLoc));
+    return result.toString();
+  }
+
+  /**
+   * Replaces with a new string, all occurrences of a string from 
+   * another string.
+   *
+   * @param inString the string to replace substrings in.
+   * @param substring the substring to replace.
+   * @param replaceString the replacement substring
+   * @return the input string with occurrences of substring replaced.
+   */
+  public static String replaceSubstring(String inString, String subString,
+					String replaceString) {
+
+    StringBuffer result = new StringBuffer();
+    int oldLoc = 0, loc = 0;
+    while ((loc = inString.indexOf(subString, oldLoc))!= -1) {
+      result.append(inString.substring(oldLoc, loc));
+      result.append(replaceString);
+      oldLoc = loc + subString.length();
+    }
+    result.append(inString.substring(oldLoc));
+    return result.toString();
+  }
+
+
+  /**
+   * Pads a string to a specified length, inserting spaces on the left
+   * as required. If the string is too long, characters are removed (from
+   * the right).
+   *
+   * @param inString the input string
+   * @param length the desired length of the output string
+   * @return the output string
+   */
+  public static String padLeft(String inString, int length) {
+
+    return fixStringLength(inString, length, false);
+  }
+  
+  /**
+   * Pads a string to a specified length, inserting spaces on the right
+   * as required. If the string is too long, characters are removed (from
+   * the right).
+   *
+   * @param inString the input string
+   * @param length the desired length of the output string
+   * @return the output string
+   */
+  public static String padRight(String inString, int length) {
+
+    return fixStringLength(inString, length, true);
+  }
+  
+  /**
+   * Pads a string to a specified length, inserting spaces as
+   * required. If the string is too long, characters are removed (from
+   * the right).
+   *
+   * @param inString the input string
+   * @param length the desired length of the output string
+   * @param right true if inserted spaces should be added to the right
+   * @return the output string
+   */
+  private static String fixStringLength(String inString, int length,
+					boolean right) {
+
+    if (inString.length() < length) {
+      while (inString.length() < length) {
+	inString = (right ? inString.concat(" ") : " ".concat(inString));
+      }
+    } else if (inString.length() > length) {
+      inString = inString.substring(0, length);
+    }
+    return inString;
+  }
+ 
+  /**
+   * Rounds a double and converts it into String.
+   *
+   * @param value the double value
+   * @param afterDecimalPoint the (maximum) number of digits permitted
+   * after the decimal point
+   * @return the double as a formatted string
+   */
+  public static String doubleToString(double value, int afterDecimalPoint) {
+    
+    StringBuffer stringBuffer;
+    double temp;
+    int i,dotPosition;
+    long precisionValue;
+    
+    temp = value * Math.pow(10.0, afterDecimalPoint);
+    if (Math.abs(temp) < Long.MAX_VALUE) {
+      precisionValue = 	(temp > 0) ? (long)(temp + 0.5) 
+                                   : -(long)(Math.abs(temp) + 0.5);
+      if (precisionValue == 0) {
+	stringBuffer = new StringBuffer(String.valueOf(0));
+      } else {
+	stringBuffer = new StringBuffer(String.valueOf(precisionValue));
+      }
+      if (afterDecimalPoint == 0) {
+	return stringBuffer.toString();
+      }
+      dotPosition = stringBuffer.length() - afterDecimalPoint;
+      while (((precisionValue < 0) && (dotPosition < 1)) ||
+	     (dotPosition < 0)) {
+	if (precisionValue < 0) {
+	  stringBuffer.insert(1, 0);
+	} else {
+	  stringBuffer.insert(0, 0);
+	}
+	dotPosition++;
+      }
+      stringBuffer.insert(dotPosition, '.');
+      if ((precisionValue < 0) && (stringBuffer.charAt(1) == '.')) {
+	stringBuffer.insert(1, 0);
+      } else if (stringBuffer.charAt(0) == '.') {
+	stringBuffer.insert(0, 0);
+      }
+      int currentPos = stringBuffer.length() - 1;
+      while ((currentPos > dotPosition) &&
+	     (stringBuffer.charAt(currentPos) == '0')) {
+	stringBuffer.setCharAt(currentPos--, ' ');
+      }
+      if (stringBuffer.charAt(currentPos) == '.') {
+	stringBuffer.setCharAt(currentPos, ' ');
+      }
+      
+      return stringBuffer.toString().trim();
+    }
+    return new String("" + value);
+  }
+
+  /**
+   * Rounds a double and converts it into a formatted decimal-justified String.
+   * Trailing 0's are replaced with spaces.
+   *
+   * @param value the double value
+   * @param width the width of the string
+   * @param afterDecimalPoint the number of digits after the decimal point
+   * @return the double as a formatted string
+   */
+  public static String doubleToString(double value, int width,
+				      int afterDecimalPoint) {
+    
+    String tempString = doubleToString(value, afterDecimalPoint);
+    char[] result;
+    int dotPosition;
+
+    if ((afterDecimalPoint >= width) 
+        || (tempString.indexOf('E') != -1)) { // Protects sci notation
+      return tempString;
+    }
+
+    // Initialize result
+    result = new char[width];
+    for (int i = 0; i < result.length; i++) {
+      result[i] = ' ';
+    }
+
+    if (afterDecimalPoint > 0) {
+      // Get position of decimal point and insert decimal point
+      dotPosition = tempString.indexOf('.');
+      if (dotPosition == -1) {
+	dotPosition = tempString.length();
+      } else {
+	result[width - afterDecimalPoint - 1] = '.';
+      }
+    } else {
+      dotPosition = tempString.length();
+    }
+    
+
+    int offset = width - afterDecimalPoint - dotPosition;
+    if (afterDecimalPoint > 0) {
+      offset--;
+    }
+
+    // Not enough room to decimal align within the supplied width
+    if (offset < 0) {
+      return tempString;
+    }
+
+    // Copy characters before decimal point
+    for (int i = 0; i < dotPosition; i++) {
+      result[offset + i] = tempString.charAt(i);
+    }
+
+    // Copy characters after decimal point
+    for (int i = dotPosition + 1; i < tempString.length(); i++) {
+      result[offset + i] = tempString.charAt(i);
+    }
+
+    return new String(result);
+  }
+
+  /**
+   * Tests if a is equal to b.
+   *
+   * @param a a double
+   * @param b a double
+   */
+  public static boolean eq(double a, double b){
+    
+    return (a - b < SMALL) && (b - a < SMALL); 
+  }
+
+  /**
+   * Checks if the given array contains any non-empty options.
+   *
+   * @param strings an array of strings
+   * @exception Exception if there are any non-empty options
+   */
+  public static void checkForRemainingOptions(String [] options) 
+    throws Exception {
+    
+    int illegalOptionsFound = 0;
+    StringBuffer text = new StringBuffer();
+
+    if (options == null) {
+      return;
+    }
+    for (int i = 0; i < options.length; i++) {
+      if (options[i].length() > 0) {
+	illegalOptionsFound++;
+	text.append(options[i] + ' ');
+      }
+    }
+    if (illegalOptionsFound > 0) {
+      throw new Exception("Illegal options: " + text);
+    }
+  }
+  
+  /**
+   * Checks if the given array contains the flag "-Char". Stops
+   * searching at the first marker "--". If the flag is found,
+   * it is replaced with the empty string.
+   *
+   * @param flag the character indicating the flag.
+   * @param strings the array of strings containing all the options.
+   * @return true if the flag was found
+   * @exception Exception if an illegal option was found
+   */
+
+  public static boolean getFlag(char flag, String [] options) 
+    throws Exception {
+
+    if (options == null) {
+      return false;
+    }
+    for (int i = 0; i < options.length; i++) {
+      if ((options[i].length() > 1) && (options[i].charAt(0) == '-')) {
+	try {
+	  Double dummy = Double.valueOf(options[i]);
+	} catch (NumberFormatException e) {
+	  if (options[i].length() > 2) {
+	    throw new Exception("Illegal option: " + options[i]);
+	  }
+	  if (options[i].charAt(1) == flag) {
+	    options[i] = "";
+	    return true;
+	  }
+	  if (options[i].charAt(1) == '-') {
+	    return false;
+	  }
+	}
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Gets an option indicated by a flag "-Char" from the given array
+   * of strings. Stops searching at the first marker "--". Replaces 
+   * flag and option with empty strings.
+   *
+   * @param flag the character indicating the option.
+   * @param options the array of strings containing all the options.
+   * @return the indicated option or an empty string
+   * @exception Exception if the option indicated by the flag can't be found
+   */
+  public static String getOption(char flag, String [] options) 
+    throws Exception {
+
+    String newString;
+
+    if (options == null)
+      return "";
+    for (int i = 0; i < options.length; i++) {
+      if ((options[i].length() > 0) && (options[i].charAt(0) == '-')) {
+	
+	// Check if it is a negative number
+	try {
+	  Double dummy = Double.valueOf(options[i]);
+	} catch (NumberFormatException e) {
+	  if (options[i].length() > 2) {
+	    throw new Exception("Illegal option: " + options[i]);
+	  }
+	  if (options[i].charAt(1) == flag) {
+	    if (i + 1 == options.length) {
+	      throw new Exception("No value given for -" + flag + " option.");
+	    }
+	    options[i] = "";
+	    newString = new String(options[i + 1]);
+	    options[i + 1] = "";
+	    return newString;
+	  }
+	  if (options[i].charAt(1) == '-') {
+	    return "";
+	  }
+	}
+      }
+    }
+    return "";
+  }
+
+  /**
+   * Quotes a string if it contains special characters.
+   * 
+   * The following rules are applied:
+   *
+   * A character is backquoted version of it is one 
+   * of <tt>" ' % \ \n \r \t</tt>.
+   *
+   * A string is enclosed within single quotes if a character has been
+   * backquoted using the previous rule above or contains 
+   * <tt>{ }</tt> or is exactly equal to the strings 
+   * <tt>, ? space or ""</tt> (empty string).
+   *
+   * A quoted question mark distinguishes it from the missing value which
+   * is represented as an unquoted question mark in arff files.
+   *
+   * @param string the string to be quoted
+   * @return the string (possibly quoted)
+   */
+  public static String quote(String string) {
+      boolean quote = false;
+
+      // backquote the following characters 
+      if ((string.indexOf('\n') != -1) || (string.indexOf('\r') != -1) || 
+	  (string.indexOf('\'') != -1) || (string.indexOf('"') != -1) || 
+	  (string.indexOf('\\') != -1) || 
+	  (string.indexOf('\t') != -1) || (string.indexOf('%') != -1)) {
+	  string = backQuoteChars(string);
+	  quote = true;
+      }
+
+      // Enclose the string in 's if the string contains a recently added
+      // backquote or contains one of the following characters.
+      if((quote == true) || 
+	 (string.indexOf('{') != -1) || (string.indexOf('}') != -1) ||
+	 (string.indexOf(',') != -1) || (string.equals("?")) ||
+	 (string.indexOf(' ') != -1) || (string.equals(""))) {
+	  string = ("'".concat(string)).concat("'");
+      }
+
+      return string;
+  }
+
+  /**
+   * Converts carriage returns and new lines in a string into \r and \n.
+   * Backquotes the following characters: ` " \ \t and %
+   * @param string the string
+   * @return the converted string
+   */
+  public static String backQuoteChars(String string) {
+
+    int index;
+    StringBuffer newStringBuffer;
+
+    // replace each of the following characters with the backquoted version
+    char   charsFind[] =    {'\\',   '\'',  '\t',  '"',    '%'};
+    String charsReplace[] = {"\\\\", "\\'", "\\t", "\\\"", "\\%"};
+    for(int i = 0; i < charsFind.length; i++) {
+	if (string.indexOf(charsFind[i]) != -1 ) {
+	    newStringBuffer = new StringBuffer();
+	    while ((index = string.indexOf(charsFind[i])) != -1) {
+		if (index > 0) {
+		    newStringBuffer.append(string.substring(0, index));
+		}
+		newStringBuffer.append(charsReplace[i]);
+		if ((index + 1) < string.length()) {
+		    string = string.substring(index + 1);
+		} else {
+		    string = "";
+		}
+	    }
+	    newStringBuffer.append(string);
+	    string = newStringBuffer.toString();
+	}
+    }
+
+    return Utils.convertNewLines(string);
+  }
+
+  /**
+   * Converts carriage returns and new lines in a string into \r and \n.
+   * @param string the string
+   * @return the converted string
+   */
+  public static String convertNewLines(String string) {
+    
+    int index;
+
+    // Replace with \n
+    StringBuffer newStringBuffer = new StringBuffer();
+    while ((index = string.indexOf('\n')) != -1) {
+      if (index > 0) {
+	newStringBuffer.append(string.substring(0, index));
+      }
+      newStringBuffer.append('\\');
+      newStringBuffer.append('n');
+      if ((index + 1) < string.length()) {
+	string = string.substring(index + 1);
+      } else {
+	string = "";
+      }
+    }
+    newStringBuffer.append(string);
+    string = newStringBuffer.toString();
+
+    // Replace with \r
+    newStringBuffer = new StringBuffer();
+    while ((index = string.indexOf('\r')) != -1) {
+      if (index > 0) {
+	newStringBuffer.append(string.substring(0, index));
+      }
+      newStringBuffer.append('\\');
+      newStringBuffer.append('r');
+      if ((index + 1) < string.length()){
+	string = string.substring(index + 1);
+      } else {
+	string = "";
+      }
+    }
+    newStringBuffer.append(string);
+    return newStringBuffer.toString();
+  }
+    
+
+  /**
+   * Returns the secondary set of options (if any) contained in
+   * the supplied options array. The secondary set is defined to
+   * be any options after the first "--". These options are removed from
+   * the original options array.
+   *
+   * @param options the input array of options
+   * @return the array of secondary options
+   */
+  public static String [] partitionOptions(String [] options) {
+
+    for (int i = 0; i < options.length; i++) {
+      if (options[i].equals("--")) {
+	options[i++] = "";
+	String [] result = new String [options.length - i];
+	for (int j = i; j < options.length; j++) {
+	  result[j - i] = options[j];
+	  options[j] = "";
+	}
+	return result;
+      }
+    }
+    return new String [0];
+  }
+
+  /**
+   * Split up a string containing options into an array of strings,
+   * one for each option.
+   *
+   * @param optionString the string containing the options
+   * @return the array of options
+   */
+  public static String [] splitOptions(String optionString) {
+
+    FastVector optionsVec = new FastVector();
+    StringTokenizer st = new StringTokenizer(optionString);
+    while (st.hasMoreTokens())
+      optionsVec.addElement(st.nextToken());
+
+    String [] options = new String[optionsVec.size()];
+    for (int i = 0; i < optionsVec.size(); i++) {
+      options[i] = (String)optionsVec.elementAt(i);
+    }
+    return options;
+  }
+
+  /**
+   * Joins all the options in an option array into a single string,
+   * as might be used on the command line.
+   *
+   * @param optionArray the array of options
+   * @return the string containing all options.
+   */
+  public static String joinOptions(String [] optionArray) {
+
+    String optionString = "";
+    for (int i = 0; i < optionArray.length; i++) {
+      if (optionArray[i].equals("")) {
+	continue;
+      }
+      if (optionArray[i].indexOf(' ') != -1) {
+	optionString += '"' + optionArray[i] + '"';
+      } else {
+	optionString += optionArray[i];
+      }
+      optionString += " ";
+    }
+    return optionString.trim();
+  }
+  
+  /**
+   * Creates a new instance of an object given it's class name and
+   * (optional) arguments to pass to it's setOptions method. If the
+   * object implements OptionHandler and the options parameter is
+   * non-null, the object will have it's options set. Example use:<p>
+   *
+   * <code> <pre>
+   * String classifierName = Utils.getOption('W', options);
+   * Classifier c = (Classifier)Utils.forName(Classifier.class,
+   *                                          classifierName,
+   *                                          options);
+   * setClassifier(c);
+   * </pre></code>
+   *
+   * @param classType the class that the instantiated object should
+   * be assignable to -- an exception is thrown if this is not the case
+   * @param className the fully qualified class name of the object
+   * @param options an array of options suitable for passing to setOptions. May
+   * be null. Any options accepted by the object will be removed from the
+   * array.
+   * @return the newly created object, ready for use.
+   * @exception Exception if the class name is invalid, or if the
+   * class is not assignable to the desired class type, or the options
+   * supplied are not acceptable to the object
+   */
+  public static Object forName(Class classType,
+			       String className,
+			       String [] options) throws Exception {
+
+    Class c = null;
+    try {
+      c = Class.forName(className);
+    } catch (Exception ex) {
+      throw new Exception("Can't find class called: " + className);
+    }
+    if (!classType.isAssignableFrom(c)) {
+      throw new Exception(classType.getName() + " is not assignable from "
+			  + className);
+    }
+    Object o = c.newInstance();
+    if ((o instanceof OptionHandler)
+	&& (options != null)) {
+      ((OptionHandler)o).setOptions(options);
+      Utils.checkForRemainingOptions(options);
+    }
+    return o;
+  }
+
+  /**
+   * Computes entropy for an array of integers.
+   *
+   * @param counts array of counts
+   * @returns - a log2 a - b log2 b - c log2 c + (a+b+c) log2 (a+b+c)
+   * when given array [a b c]
+   */
+  public static double info(int counts[]) {
+    
+    int total = 0; int c;
+    double x = 0;
+    for (int j = 0; j < counts.length; j++) {
+      x -= xlogx(counts[j]);
+      total += counts[j];
+    }
+    return x + xlogx(total);
+  }
+
+  /**
+   * Tests if a is smaller or equal to b.
+   *
+   * @param a a double
+   * @param b a double
+   */
+  public static boolean smOrEq(double a,double b) {
+    
+    return (a-b < SMALL);
+  }
+
+  /**
+   * Tests if a is greater or equal to b.
+   *
+   * @param a a double
+   * @param b a double
+   */
+  public static boolean grOrEq(double a,double b) {
+    
+    return (b-a < SMALL);
+  }
+  
+  /**
+   * Tests if a is smaller than b.
+   *
+   * @param a a double
+   * @param b a double
+   */
+  public static boolean sm(double a,double b) {
+    
+    return (b-a > SMALL);
+  }
+
+  /**
+   * Tests if a is smaller than b.
+   *
+   * @param a a double
+   * @param b a double 
+   */
+  public static boolean gr(double a,double b) {
+    
+    return (a-b > SMALL);
+  }
+
+  /**
+   * Returns the logarithm of a for base 2.
+   *
+   * @param a a double
+   */
+  public static double log2(double a) {
+    
+    return Math.log(a) / log2;
+  }
+
+  /**
+   * Returns index of maximum element in a given
+   * array of doubles. First maximum is returned.
+   *
+   * @param doubles the array of doubles
+   * @return the index of the maximum element
+   */
+  public static int maxIndex(double [] doubles) {
+
+    double maximum = 0;
+    int maxIndex = 0;
+
+    for (int i = 0; i < doubles.length; i++) {
+      if ((i == 0) || (doubles[i] > maximum)) {
+	maxIndex = i;
+	maximum = doubles[i];
+      }
+    }
+
+    return maxIndex;
+  }
+
+  /**
+   * Returns index of maximum element in a given
+   * array of integers. First maximum is returned.
+   *
+   * @param ints the array of integers
+   * @return the index of the maximum element
+   */
+  public static int maxIndex(int [] ints) {
+
+    int maximum = 0;
+    int maxIndex = 0;
+
+    for (int i = 0; i < ints.length; i++) {
+      if ((i == 0) || (ints[i] > maximum)) {
+	maxIndex = i;
+	maximum = ints[i];
+      }
+    }
+
+    return maxIndex;
+  }
+
+  /**
+   * Computes the mean for an array of doubles.
+   *
+   * @param vector the array
+   * @return the mean
+   */
+  public static double mean(double[] vector) {
+  
+    double sum = 0;
+
+    if (vector.length == 0) {
+      return 0;
+    }
+    for (int i = 0; i < vector.length; i++) {
+      sum += vector[i];
+    }
+    return sum / (double) vector.length;
+  }
+
+  /**
+   * Returns index of minimum element in a given
+   * array of integers. First minimum is returned.
+   *
+   * @param ints the array of integers
+   * @return the index of the minimum element
+   */
+  public static int minIndex(int [] ints) {
+
+    int minimum = 0;
+    int minIndex = 0;
+
+    for (int i = 0; i < ints.length; i++) {
+      if ((i == 0) || (ints[i] < minimum)) {
+	minIndex = i;
+	minimum = ints[i];
+      }
+    }
+
+    return minIndex;
+  }
+
+  /**
+   * Returns index of minimum element in a given
+   * array of doubles. First minimum is returned.
+   *
+   * @param doubles the array of doubles
+   * @return the index of the minimum element
+   */
+  public static int minIndex(double [] doubles) {
+
+    double minimum = 0;
+    int minIndex = 0;
+
+    for (int i = 0; i < doubles.length; i++) {
+      if ((i == 0) || (doubles[i] < minimum)) {
+	minIndex = i;
+	minimum = doubles[i];
+      }
+    }
+
+    return minIndex;
+  }
+
+  /**
+   * Normalizes the doubles in the array by their sum.
+   *
+   * @param doubles the array of double
+   * @exception IllegalArgumentException if sum is Zero or NaN
+   */
+  public static void normalize(double[] doubles) {
+
+    double sum = 0;
+    for (int i = 0; i < doubles.length; i++) {
+      sum += doubles[i];
+    }
+    normalize(doubles, sum);
+  }
+
+  /**
+   * Normalizes the doubles in the array using the given value.
+   *
+   * @param doubles the array of double
+   * @param sum the value by which the doubles are to be normalized
+   * @exception IllegalArgumentException if sum is zero or NaN
+   */
+  public static void normalize(double[] doubles, double sum) {
+
+    if (Double.isNaN(sum)) {
+      throw new IllegalArgumentException("Can't normalize array. Sum is NaN.");
+    }
+    if (sum == 0) {
+      // Maybe this should just be a return.
+      throw new IllegalArgumentException("Can't normalize array. Sum is zero.");
+    }
+    for (int i = 0; i < doubles.length; i++) {
+      doubles[i] /= sum;
+    }
+  }
+
+  /**
+   * Rounds a double to the next nearest integer value. The JDK version
+   * of it doesn't work properly.
+   *
+   * @param value the double value
+   * @return the resulting integer value
+   */
+  public static int round(double value) {
+
+    int roundedValue = value > 0
+      ? (int)(value + 0.5)
+      : -(int)(Math.abs(value) + 0.5);
+    
+    return roundedValue;
+  }
+
+  /**
+   * Rounds a double to the given number of decimal places.
+   *
+   * @param value the double value
+   * @param afterDecimalPoint the number of digits after the decimal point
+   * @return the double rounded to the given precision
+   */
+  public static double roundDouble(double value,int afterDecimalPoint) {
+
+    double mask = Math.pow(10.0, (double)afterDecimalPoint);
+
+    return (double)(Math.round(value * mask)) / mask;
+  }
+
+  /**
+   * Sorts a given array of integers in ascending order and returns an 
+   * array of integers with the positions of the elements of the original 
+   * array in the sorted array. The sort is stable. (Equal elements remain
+   * in their original order.)
+   *
+   * @param array this array is not changed by the method!
+   * @return an array of integers with the positions in the sorted
+   * array.
+   */
+  public static int[] sort(int [] array) {
+
+    int [] index = new int[array.length];
+    int [] newIndex = new int[array.length];
+    int [] helpIndex;
+    int numEqual;
+    
+    for (int i = 0; i < index.length; i++) {
+      index[i] = i;
+    }
+    quickSort(array, index, 0, array.length - 1);
+
+    // Make sort stable
+    int i = 0;
+    while (i < index.length) {
+      numEqual = 1;
+      for (int j = i + 1; ((j < index.length)
+			   && (array[index[i]] == array[index[j]]));
+	   j++) {
+	numEqual++;
+      }
+      if (numEqual > 1) {
+	helpIndex = new int[numEqual];
+	for (int j = 0; j < numEqual; j++) {
+	  helpIndex[j] = i + j;
+	}
+	quickSort(index, helpIndex, 0, numEqual - 1);
+	for (int j = 0; j < numEqual; j++) {
+	  newIndex[i + j] = index[helpIndex[j]];
+	}
+	i += numEqual;
+      } else {
+	newIndex[i] = index[i];
+	i++;
+      }
+    }
+    return newIndex;
+  }
+
+  /**
+   * Sorts a given array of doubles in ascending order and returns an
+   * array of integers with the positions of the elements of the
+   * original array in the sorted array. NOTE THESE CHANGES: the sort
+   * is no longer stable and it doesn't use safe floating-point
+   * comparisons anymore. Occurrences of Double.NaN are treated as 
+   * Double.MAX_VALUE
+   *
+   * @param array this array is not changed by the method!
+   * @return an array of integers with the positions in the sorted
+   * array.  
+   */
+  public static int[] sort(double [] array) {
+
+    int [] index = new int[array.length];
+    array = (double [])array.clone();
+    for (int i = 0; i < index.length; i++) {
+      index[i] = i;
+      if (Double.isNaN(array[i])) {
+        array[i] = Double.MAX_VALUE;
+      }
+    }
+    quickSort(array, index, 0, array.length - 1);
+    return index;
+  }
+
+  /**
+   * Sorts a given array of doubles in ascending order and returns an 
+   * array of integers with the positions of the elements of the original 
+   * array in the sorted array. The sort is stable (Equal elements remain
+   * in their original order.) Occurrences of Double.NaN are treated as 
+   * Double.MAX_VALUE
+   *
+   * @param array this array is not changed by the method!
+   * @return an array of integers with the positions in the sorted
+   * array.
+   */
+  public static int[] stableSort(double [] array){
+
+    int [] index = new int[array.length];
+    int [] newIndex = new int[array.length];
+    int [] helpIndex;
+    int numEqual;
+    
+    array = (double [])array.clone();
+    for (int i = 0; i < index.length; i++) {
+      index[i] = i;
+      if (Double.isNaN(array[i])) {
+        array[i] = Double.MAX_VALUE;
+      }
+    }
+    quickSort(array,index,0,array.length-1);
+
+    // Make sort stable
+
+    int i = 0;
+    while (i < index.length) {
+      numEqual = 1;
+      for (int j = i+1; ((j < index.length) && Utils.eq(array[index[i]],
+							array[index[j]])); j++)
+	numEqual++;
+      if (numEqual > 1) {
+	helpIndex = new int[numEqual];
+	for (int j = 0; j < numEqual; j++)
+	  helpIndex[j] = i+j;
+	quickSort(index, helpIndex, 0, numEqual-1);
+	for (int j = 0; j < numEqual; j++) 
+	  newIndex[i+j] = index[helpIndex[j]];
+	i += numEqual;
+      } else {
+	newIndex[i] = index[i];
+	i++;
+      }
+    }
+
+    return newIndex;
+  }
+
+  /**
+   * Computes the variance for an array of doubles.
+   *
+   * @param vector the array
+   * @return the variance
+   */
+  public static double variance(double[] vector) {
+  
+    double sum = 0, sumSquared = 0;
+
+    if (vector.length <= 1) {
+      return 0;
+    }
+    for (int i = 0; i < vector.length; i++) {
+      sum += vector[i];
+      sumSquared += (vector[i] * vector[i]);
+    }
+    return (sumSquared - (sum * sum / (double) vector.length)) / 
+      (double) (vector.length - 1);
+  }
+
+  /**
+   * Computes the sum of the elements of an array of doubles.
+   *
+   * @param doubles the array of double
+   * @returns the sum of the elements
+   */
+  public static double sum(double[] doubles) {
+
+    double sum = 0;
+
+    for (int i = 0; i < doubles.length; i++) {
+      sum += doubles[i];
+    }
+    return sum;
+  }
+
+  /**
+   * Computes the sum of the elements of an array of integers.
+   *
+   * @param ints the array of integers
+   * @returns the sum of the elements
+   */
+  public static int sum(int[] ints) {
+
+    int sum = 0;
+
+    for (int i = 0; i < ints.length; i++) {
+      sum += ints[i];
+    }
+    return sum;
+  }
+
+  /**
+   * Returns c*log2(c) for a given integer value c.
+   *
+   * @param c an integer value
+   * @returns c*log2(c) (but is careful to return 0 if c is 0)
+   */
+  public static double xlogx(int c) {
+    
+    if (c == 0) {
+      return 0.0;
+    }
+    return c * Utils.log2((double) c);
+  }
+
+  /**
+   * Implements quicksort for an array of indices.
+   *
+   * @param array the array of integers to be sorted
+   * @param index the index which should contain the positions in the
+   * sorted array
+   * @param lo0 the first index of the subset to be sorted
+   * @param hi0 the last index of the subset to be sorted
+   */
+  private static void quickSort(int [] array, int [] index,
+				int lo0, int hi0) {
+
+    int lo = lo0;
+    int hi = hi0;
+    int mid;
+    int help;
+    
+    if (hi0 > lo0) {
+      
+      // Arbitrarily establishing partition element as the midpoint of
+      // the array.
+      mid = array[index[(lo0 + hi0) / 2]];
+
+      // loop through the array until indices cross
+      while (lo <= hi) {
+	
+	// find the first element that is greater than or equal to  
+	// the partition element starting from the left Index.
+	while ((array[index[lo]] < mid) && (lo < hi0)) {
+	  ++lo;
+	}
+	
+	// find an element that is smaller than or equal to 
+	// the partition element starting from the right Index.
+	while ((array[index[hi]] > mid) && (hi > lo0)) {
+	  --hi;
+	}
+	
+	// if the indexes have not crossed, swap
+	if (lo <= hi) {
+	  help = index[lo];
+	  index[lo] = index[hi];
+	  index[hi] = help;
+	  ++lo;
+	  --hi;
+	}
+      }
+      
+      // If the right index has not reached the left side of array
+      // must now sort the left partition.
+      if (lo0 < hi) {
+	quickSort(array, index, lo0, hi);
+      }
+      
+      // If the left index has not reached the right side of array
+      // must now sort the right partition.
+      if (lo < hi0) {
+	quickSort(array, index, lo, hi0);
+      }
+    }
+  }
+
+  /**
+   * Implements unsafe quicksort for an array of indices.
+   *
+   * @param array the array of doubles to be sorted
+   * @param index the index which should contain the positions in the
+   * sorted array
+   * @param lo0 the first index of the subset to be sorted
+   * @param hi0 the last index of the subset to be sorted
+   */
+  private static void quickSort(double [] array, int [] index, int lo0, int hi0) {
+
+    int lo = lo0;
+    int hi = hi0;
+    double mid;
+    int help;
+    
+    if (hi0 > lo0) {
+      
+      // Arbitrarily establishing partition element as the midpoint of
+      // the array.
+      mid = array[index[(lo0 + hi0) / 2]];
+
+      // loop through the array until indices cross
+      while (lo <= hi) {
+	
+	// find the first element that is greater than or equal to  
+	// the partition element starting from the left Index.
+	while ((array[index[lo]] < mid) && (lo < hi0)) {
+	  ++lo;
+	}
+	
+	// find an element that is smaller than or equal to 
+	// the partition element starting from the right Index.
+	while ((array[index[hi]] > mid) && (hi > lo0)) {
+	  --hi;
+	}
+	
+	// if the indexes have not crossed, swap
+	if (lo <= hi) {
+	  help = index[lo];
+	  index[lo] = index[hi];
+	  index[hi] = help;
+	  ++lo;
+	  --hi;
+	}
+      }
+      
+      // If the right index has not reached the left side of array
+      // must now sort the left partition.
+      if (lo0 < hi) {
+	quickSort(array, index, lo0, hi);
+      }
+      
+      // If the left index has not reached the right side of array
+      // must now sort the right partition.
+      if (lo < hi0) {
+	quickSort(array, index, lo, hi0);
+      }
+    }
+  }
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param ops some dummy options
+   */
+  public static void main(String[] ops) {
+
+    double[] doubles = {4.5, 6.7, Double.NaN, 3.4, 4.8, 1.2, 3.4};
+    int[] ints = {12, 6, 2, 18, 16, 6, 7, 5};
+
+    try {
+
+      // Option handling
+      System.out.println("First option split up:");
+      if (ops.length > 0) {
+	String[] firstOptionSplitUp = Utils.splitOptions(ops[0]);
+	for (int i = 0; i < firstOptionSplitUp.length; i ++) {
+	  System.out.println(firstOptionSplitUp[i]);
+	}
+      }					       
+      System.out.println("Partitioned options: ");
+      String[] partitionedOptions = Utils.partitionOptions(ops);
+      for (int i  = 0; i < partitionedOptions.length; i++) {
+	System.out.println(partitionedOptions[i]);
+      }
+      System.out.println("Get flag -f: " + Utils.getFlag('f', ops));
+      System.out.println("Get option -o: " + Utils.getOption('o', ops));
+      System.out.println("Checking for remaining options... ");
+      Utils.checkForRemainingOptions(ops);
+      
+      // Statistics
+      System.out.println("Original array (doubles): ");
+      for (int i = 0; i < doubles.length; i++) {
+	System.out.print(doubles[i] + " ");
+      }
+      System.out.println();
+      System.out.println("Original array (ints): ");
+      for (int i = 0; i < ints.length; i++) {
+	System.out.print(ints[i] + " ");
+      }
+      System.out.println();
+      System.out.println("Correlation: " + Utils.correlation(doubles, doubles, 
+							     doubles.length));
+      System.out.println("Mean: " + Utils.mean(doubles));
+      System.out.println("Variance: " + Utils.variance(doubles));
+      System.out.println("Sum (doubles): " + Utils.sum(doubles));
+      System.out.println("Sum (ints): " + Utils.sum(ints));
+      System.out.println("Max index (doubles): " + Utils.maxIndex(doubles));
+      System.out.println("Max index (ints): " + Utils.maxIndex(ints));
+      System.out.println("Min index (doubles): " + Utils.minIndex(doubles));
+      System.out.println("Min index (ints): " + Utils.minIndex(ints));
+      
+      // Sorting and normalizing
+      System.out.println("Sorted array (doubles): ");
+      int[] sorted = Utils.sort(doubles);
+      for (int i = 0; i < doubles.length; i++) {
+	System.out.print(doubles[sorted[i]] + " ");
+      }
+      System.out.println();
+      System.out.println("Normalized array (doubles): ");
+      Utils.normalize(doubles);
+      for (int i = 0; i < doubles.length; i++) {
+	System.out.print(doubles[i] + " ");
+      }
+      System.out.println();
+      System.out.println("Normalized again (doubles): ");
+      Utils.normalize(doubles, Utils.sum(doubles));
+      for (int i = 0; i < doubles.length; i++) {
+	System.out.print(doubles[i] + " ");
+      }
+      System.out.println();
+      
+      // Pretty-printing
+      System.out.println("-4.58: " + Utils.doubleToString(-4.57826535, 2));
+      System.out.println("-6.78: " + Utils.doubleToString(-6.78214234, 6,2));
+      
+      // Comparisons
+      System.out.println("5.70001 == 5.7 ? " + Utils.eq(5.70001, 5.7));
+      System.out.println("5.70001 > 5.7 ? " + Utils.gr(5.70001, 5.7));
+      System.out.println("5.70001 >= 5.7 ? " + Utils.grOrEq(5.70001, 5.7));
+      System.out.println("5.7 < 5.70001 ? " + Utils.sm(5.7, 5.70001));
+      System.out.println("5.7 <= 5.70001 ? " + Utils.smOrEq(5.7, 5.70001));
+      
+      // Math
+      System.out.println("Info (ints): " + Utils.info(ints));
+      System.out.println("log2(4.6): " + Utils.log2(4.6));
+      System.out.println("5 * log(5): " + Utils.xlogx(5));
+      System.out.println("5.5 rounded: " + Utils.round(5.5));
+      System.out.println("5.55555 rounded to 2 decimal places: " + 
+			 Utils.roundDouble(5.55555, 2));
+    } catch (Exception e) {
+      e.printStackTrace();
+    }
+  }
+}
+  
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/WeightedInstancesHandler.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/WeightedInstancesHandler.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/WeightedInstancesHandler.java	(revision 8815)
@@ -0,0 +1,43 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    WeightedInstancesHandler.java
+ *    Copyright (C) 1999 Eibe Frank
+ *
+ */
+
+package weka.core;
+
+/** 
+ * Interface to something that makes use of the information provided
+ * by instance weights.
+ *
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$ 
+*/
+public interface WeightedInstancesHandler {
+
+  // Nothing in here, because the class is just used as an indicator
+}
+
+
+
+
+
+
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/core/WekaException.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/core/WekaException.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/core/WekaException.java	(revision 8815)
@@ -0,0 +1,50 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    WekaException.java
+ *    Copyright (C) 2001 Webmind Corp.
+ */
+
+package weka.core;
+
+/**
+ * <code>WekaException</code> is used when some Weka-specific
+ * checked exception must be raised.
+ *
+ * @author <a href="mailto:len@webmind.com">Len Trigg</a>
+ * @version $Revision$
+ */
+public class WekaException extends Exception {
+
+  /**
+   * Creates a new <code>WekaException</code> instance
+   * with no detail message.
+   */
+  public WekaException() { 
+    super(); 
+  }
+
+  /**
+   * Creates a new <code>WekaException</code> instance
+   * with a specified message.
+   *
+   * @param messagae a <code>String</code> containing the message.
+   */
+  public WekaException(String message) { 
+    super(message); 
+  }
+}
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/experiment/Stats.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/experiment/Stats.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/experiment/Stats.java	(revision 8815)
@@ -0,0 +1,188 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    Stats.java
+ *    Copyright (C) 1999 Len Trigg
+ *
+ */
+
+
+package weka.experiment;
+import weka.core.Utils;
+
+/**
+ * A class to store simple statistics
+ *
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class Stats {
+  
+  /** The number of values seen */
+  public double count = 0;
+
+  /** The sum of values seen */
+  public double sum = 0;
+
+  /** The sum of values squared seen */
+  public double sumSq = 0;
+
+  /** The std deviation of values at the last calculateDerived() call */    
+  public double stdDev = Double.NaN;
+
+  /** The mean of values at the last calculateDerived() call */    
+  public double mean = Double.NaN;
+
+  /** The minimum value seen, or Double.NaN if no values seen */
+  public double min = Double.NaN;
+
+  /** The maximum value seen, or Double.NaN if no values seen */
+  public double max = Double.NaN;
+    
+  /**
+   * Adds a value to the observed values
+   *
+   * @param value the observed value
+   */
+  public void add(double value) {
+
+    add(value, 1);
+  }
+
+  /**
+   * Adds a value that has been seen n times to the observed values
+   *
+   * @param value the observed value
+   * @param n the number of times to add value
+   */
+  public void add(double value, double n) {
+
+    sum += value * n;
+    sumSq += value * value * n;
+    count += n;
+    if (Double.isNaN(min)) {
+      min = max = value;
+    } else if (value < min) {
+      min = value;
+    } else if (value > max) {
+      max = value;
+    }
+  }
+
+  /**
+   * Removes a value to the observed values (no checking is done
+   * that the value being removed was actually added). 
+   *
+   * @param value the observed value
+   */
+  public void subtract(double value) {
+
+    sum -= value;
+    sumSq -= value * value;
+    count --;
+  }
+
+  /**
+   * Tells the object to calculate any statistics that don't have their
+   * values automatically updated during add. Currently updates the mean
+   * and standard deviation.
+   */
+  public void calculateDerived() {
+
+    mean = Double.NaN;
+    stdDev = Double.NaN;
+    if (count > 0) {
+      mean = sum / count;
+      stdDev = Double.POSITIVE_INFINITY;
+      if (count > 1) {
+	stdDev = sumSq - (sum * sum) / count;
+	stdDev /= (count - 1);
+        if (stdDev < 0) {
+          System.err.println("Warning: stdDev value = " + stdDev 
+                             + " -- rounded to zero.");
+          stdDev = 0;
+        }
+	stdDev = Math.sqrt(stdDev);
+      }
+    }
+  }
+    
+  /**
+   * Returns a string summarising the stats so far.
+   *
+   * @return the summary string
+   */
+  public String toString() {
+
+    calculateDerived();
+    return
+      "Count   " + Utils.doubleToString(count, 8) + '\n'
+      + "Min     " + Utils.doubleToString(min, 8) + '\n'
+      + "Max     " + Utils.doubleToString(max, 8) + '\n'
+      + "Sum     " + Utils.doubleToString(sum, 8) + '\n'
+      + "SumSq   " + Utils.doubleToString(sumSq, 8) + '\n'
+      + "Mean    " + Utils.doubleToString(mean, 8) + '\n'
+      + "StdDev  " + Utils.doubleToString(stdDev, 8) + '\n';
+  }
+
+  /**
+   * Tests the paired stats object from the command line.
+   * reads line from stdin, expecting two values per line.
+   *
+   * @param args ignored.
+   */
+  public static void main(String [] args) {
+
+    try {
+      Stats ps = new Stats();
+      java.io.LineNumberReader r = new java.io.LineNumberReader(
+				   new java.io.InputStreamReader(System.in));
+      String line;
+      while ((line = r.readLine()) != null) {
+        line = line.trim();
+        if (line.equals("") || line.startsWith("@") || line.startsWith("%")) {
+          continue;
+        }
+	java.util.StringTokenizer s 
+          = new java.util.StringTokenizer(line, " ,\t\n\r\f");
+	int count = 0;
+	double v1 = 0;
+	while (s.hasMoreTokens()) {
+	  double val = (new Double(s.nextToken())).doubleValue();
+	  if (count == 0) {
+	    v1 = val;
+	  } else {
+            System.err.println("MSG: Too many values in line \"" 
+                               + line + "\", skipped.");
+	    break;
+	  }
+	  count++;
+	}
+        if (count == 1) {
+          ps.add(v1);
+        }
+      }
+      ps.calculateDerived();
+      System.err.println(ps);
+    } catch (Exception ex) {
+      ex.printStackTrace();
+      System.err.println(ex.getMessage());
+    }
+  }
+
+} // Stats
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/filters/DiscretizeFilter.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/filters/DiscretizeFilter.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/filters/DiscretizeFilter.java	(revision 8815)
@@ -0,0 +1,1292 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ *    DiscretizeFilter.java
+ *    Copyright (C) 1999 Eibe Frank,Len Trigg
+ *
+ */
+
+
+package weka.filters;
+
+import java.io.*;
+import java.util.*;
+import weka.core.*;
+
+/** 
+ * An instance filter that discretizes a range of numeric attributes in 
+ * the dataset into nominal attributes. Discretization can be either by 
+ * simple binning, or by Fayyad & Irani's MDL method (the default).<p>
+ *
+ * Valid filter-specific options are: <p>
+ *
+ * -B num <br>
+ * Specifies the (maximum) number of bins to divide numeric attributes into.
+ * (default: class-based discretisation).<p>
+ *
+ * -F <br>
+ * Use equal-frequency instead of equal-width discretization if 
+ * class-based discretisation is turned off.<p>
+ *
+ * -O <br>
+ * Optimize the number of bins using a leave-one-out estimate of the 
+ * entropy (for equal-width binning).<p>
+ *
+ * -R col1,col2-col4,... <br>
+ * Specifies list of columns to Discretize. First
+ * and last are valid indexes. (default: none) <p>
+ *
+ * -V <br>
+ * Invert matching sense.<p>
+ *
+ * -D <br>
+ * Make binary nominal attributes. <p>
+ *
+ * -E <br>
+ * Use better encoding of split point for MDL. <p>
+ *   
+ * -K <br>
+ * Use Kononeko's MDL criterion. <p>
+ * 
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @author Eibe Frank (eibe@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public class DiscretizeFilter extends Filter 
+  implements OptionHandler, WeightedInstancesHandler {
+
+  /** Stores which columns to Discretize */
+  protected Range m_DiscretizeCols = new Range();
+
+  /** The number of bins to divide the attribute into */
+  protected int m_NumBins = 10;
+
+  /** Store the current cutpoints */
+  protected double [][] m_CutPoints = null;
+
+  /** True if discretisation will be done by MDL rather than binning */
+  protected boolean m_UseMDL = true;
+
+  /** Output binary attributes for discretized attributes. */
+  protected boolean m_MakeBinary = false;
+
+  /** Use better encoding of split point for MDL. */
+  protected boolean m_UseBetterEncoding = false;
+
+  /** Use Kononenko's MDL criterion instead of Fayyad et al.'s */
+  protected boolean m_UseKononenko = false;
+
+  /** Find the number of bins using cross-validated entropy. */
+  protected boolean m_FindNumBins = false;
+
+  /** Use equal-frequency binning if unsupervised discretization turned on */
+  protected boolean m_UseEqualFrequency = false;
+
+  /** Constructor - initialises the filter */
+  public DiscretizeFilter() {
+
+    setAttributeIndices("first-last");
+  }
+
+
+  /**
+   * Gets an enumeration describing the available options
+   *
+   * @return an enumeration of all the available options
+   */
+  public Enumeration listOptions() {
+
+    Vector newVector = new Vector(7);
+
+    newVector.addElement(new Option(
+              "\tSpecifies the (maximum) number of bins to divide numeric"
+	      + " attributes into.\n"
+	      + "\t(default class-based discretization)",
+              "B", 1, "-B <num>"));
+
+    newVector.addElement(new Option(
+              "\tUse equal-frequency instead of equal-width with\n"+
+	      "\tunsupervised discretization.",
+              "F", 0, "-F"));
+
+    newVector.addElement(new Option(
+              "\tOptimize number of bins using leave-one-out estimate\n"+
+	      "\tof estimated entropy (for equal-width discretization).",
+              "O", 0, "-O"));
+
+    /* If we decide to implement loading and saving cutfiles like 
+     * the C Discretizer (which is probably not necessary)
+    newVector.addElement(new Option(
+              "\tSpecify that the cutpoints should be loaded from a file.",
+              "L", 1, "-L <file>"));
+    newVector.addElement(new Option(
+              "\tSpecify that the chosen cutpoints should be saved to a file.",
+              "S", 1, "-S <file>"));
+    */
+
+    newVector.addElement(new Option(
+              "\tSpecifies list of columns to Discretize. First"
+	      + " and last are valid indexes.\n"
+	      + "\t(default none)",
+              "R", 1, "-R <col1,col2-col4,...>"));
+
+    newVector.addElement(new Option(
+              "\tInvert matching sense of column indexes.",
+              "V", 0, "-V"));
+
+    newVector.addElement(new Option(
+              "\tOutput binary attributes for discretized attributes.",
+              "D", 0, "-D"));
+
+    newVector.addElement(new Option(
+              "\tUse better encoding of split point for MDL.",
+              "E", 0, "-E"));
+
+    newVector.addElement(new Option(
+              "\tUse Kononenko's MDL criterion.",
+              "K", 0, "-K"));
+
+    return newVector.elements();
+  }
+
+
+  /**
+   * Parses the options for this object. Valid options are: <p>
+   *
+   * -B num <br>
+   * Specifies the (maximum) number of bins to divide numeric attributes into.
+   * (default class-based discretisation).<p>
+   *
+   * -F <br>
+   * Use equal-frequency instead of equal-width discretization if 
+   * class-based discretisation is turned off.<p>
+   *
+   * -O <br>
+   * Optimize the number of bins using a leave-one-out estimate of the 
+   * entropy (for equal-width binning).<p>
+   *
+   * -R col1,col2-col4,... <br>
+   * Specifies list of columns to Discretize. First
+   * and last are valid indexes. (default none) <p>
+   *
+   * -V <br>
+   * Invert matching sense.<p>
+   *
+   * -D <br>
+   * Make binary nominal attributes. <p>
+   *
+   * -E <br>
+   * Use better encoding of split point for MDL. <p>
+   *   
+   * -K <br>
+   * Use Kononeko's MDL criterion. <p>
+   * 
+   * @param options the list of options as an array of strings
+   * @exception Exception if an option is not supported
+   */
+  public void setOptions(String[] options) throws Exception {
+
+    setMakeBinary(Utils.getFlag('D', options));
+    setUseEqualFrequency(Utils.getFlag('F', options));
+    setUseBetterEncoding(Utils.getFlag('E', options));
+    setUseKononenko(Utils.getFlag('K', options));
+    setFindNumBins(Utils.getFlag('O', options));
+    setInvertSelection(Utils.getFlag('V', options));
+    setUseMDL(true);
+
+    String numBins = Utils.getOption('B', options);
+    if (numBins.length() != 0) {
+      setBins(Integer.parseInt(numBins));
+      setUseMDL(false);
+    } else {
+      setBins(10);
+    }
+    
+    String convertList = Utils.getOption('R', options);
+    if (convertList.length() != 0) {
+      setAttributeIndices(convertList);
+    } else {
+      setAttributeIndices("first-last");
+    }
+
+    if (getInputFormat() != null) {
+      setInputFormat(getInputFormat());
+    }
+  }
+  /**
+   * Gets the current settings of the filter.
+   *
+   * @return an array of strings suitable for passing to setOptions
+   */
+  public String [] getOptions() {
+
+    String [] options = new String [12];
+    int current = 0;
+
+    if (getMakeBinary()) {
+      options[current++] = "-D";
+    }
+    if (getUseEqualFrequency()) {
+      options[current++] = "-F";
+    }
+    if (getUseBetterEncoding()) {
+      options[current++] = "-E";
+    }
+    if (getUseKononenko()) {
+      options[current++] = "-K";
+    }
+    if (getFindNumBins()) {
+      options[current++] = "-O";
+    }
+    if (getInvertSelection()) {
+      options[current++] = "-V";
+    }
+    if (!getUseMDL()) {
+      options[current++] = "-B"; options[current++] = "" + getBins();
+    }
+    if (!getAttributeIndices().equals("")) {
+      options[current++] = "-R"; options[current++] = getAttributeIndices();
+    }
+    while (current < options.length) {
+      options[current++] = "";
+    }
+    return options;
+  }
+
+
+  /**
+   * Sets the format of the input instances.
+   *
+   * @param instanceInfo an Instances object containing the input instance
+   * structure (any instances contained in the object are ignored - only the
+   * structure is required).
+   * @return true if the outputFormat may be collected immediately
+   * @exception Exception if the input format can't be set successfully
+   */
+  public boolean setInputFormat(Instances instanceInfo) throws Exception {
+
+    super.setInputFormat(instanceInfo);
+
+    m_DiscretizeCols.setUpper(instanceInfo.numAttributes() - 1);
+    m_CutPoints = null;
+    if (m_UseMDL) {
+      if (instanceInfo.classIndex() < 0) {
+	throw new UnassignedClassException("Cannot use class-based discretization: "
+                                           + "no class assigned to the dataset");
+      }
+      if (!instanceInfo.classAttribute().isNominal()) {
+	throw new UnsupportedClassTypeException("Supervised discretization not possible:"
+                                                + " class is not nominal!");
+      }
+    } else {
+      if (getFindNumBins() && getUseEqualFrequency()) {
+	throw new IllegalArgumentException("Bin number optimization in conjunction "+
+					   "with equal-frequency binning not implemented.");
+      }
+    }
+
+    // If we implement loading cutfiles, then load 
+    //them here and set the output format
+    return false;
+  }
+
+  
+
+  /**
+   * Input an instance for filtering. Ordinarily the instance is processed
+   * and made available for output immediately. Some filters require all
+   * instances be read before producing output.
+   *
+   * @param instance the input instance
+   * @return true if the filtered instance may now be
+   * collected with output().
+   * @exception IllegalStateException if no input format has been defined.
+   */
+  public boolean input(Instance instance) {
+
+    if (getInputFormat() == null) {
+      throw new IllegalStateException("No input instance format defined");
+    }
+    if (m_NewBatch) {
+      resetQueue();
+      m_NewBatch = false;
+    }
+    
+    if (m_CutPoints != null) {
+      convertInstance(instance);
+      return true;
+    }
+
+    bufferInput(instance);
+    return false;
+  }
+
+
+  /**
+   * Signifies that this batch of input to the filter is finished. If the 
+   * filter requires all instances prior to filtering, output() may now 
+   * be called to retrieve the filtered instances.
+   *
+   * @return true if there are instances pending output
+   * @exception IllegalStateException if no input structure has been defined
+   */
+  public boolean batchFinished() {
+
+    if (getInputFormat() == null) {
+      throw new IllegalStateException("No input instance format defined");
+    }
+    if (m_CutPoints == null) {
+      calculateCutPoints();
+
+      setOutputFormat();
+
+      // If we implement saving cutfiles, save the cuts here
+
+      // Convert pending input instances
+      for(int i = 0; i < getInputFormat().numInstances(); i++) {
+	convertInstance(getInputFormat().instance(i));
+      }
+    } 
+    flushInput();
+
+    m_NewBatch = true;
+    return (numPendingOutput() != 0);
+  }
+
+  /**
+   * Returns a string describing this filter
+   *
+   * @return a description of the filter suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String globalInfo() {
+
+    return "An instance filter that discretizes a range of numeric"
+      + " attributes in the dataset into nominal attributes."
+      + " Discretization can be either by simple binning, or by"
+      + " Fayyad & Irani's MDL method (the default).";
+  }
+  
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String findNumBinsTipText() {
+
+    return "Optimize number of equal-width bins using leave-one-out.";
+  }
+
+  /**
+   * Get the value of FindNumBins.
+   *
+   * @return Value of FindNumBins.
+   */
+  public boolean getFindNumBins() {
+    
+    return m_FindNumBins;
+  }
+  
+  /**
+   * Set the value of FindNumBins.
+   *
+   * @param newFindNumBins Value to assign to FindNumBins.
+   */
+  public void setFindNumBins(boolean newFindNumBins) {
+    
+    m_FindNumBins = newFindNumBins;
+  }
+  
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String makeBinaryTipText() {
+
+    return "Make resulting attributes binary.";
+  }
+
+  /**
+   * Gets whether binary attributes should be made for discretized ones.
+   *
+   * @return true if attributes will be binarized
+   */
+  public boolean getMakeBinary() {
+
+    return m_MakeBinary;
+  }
+
+  /** 
+   * Sets whether binary attributes should be made for discretized ones.
+   *
+   * @param makeBinary if binary attributes are to be made
+   */
+  public void setMakeBinary(boolean makeBinary) {
+
+    m_MakeBinary = makeBinary;
+  }
+
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String useMDLTipText() {
+
+    return "Use class-based discretization. If set to false, does"
+      + " not require a class attribute, and uses a fixed number"
+      + " of bins (according to bins setting).";
+  }
+
+  /**
+   * Gets whether MDL will be used as the discretisation method.
+   *
+   * @return true if so, false if fixed bins should be used.
+   */
+  public boolean getUseMDL() {
+
+    return m_UseMDL;
+  }
+
+  /** 
+   * Sets whether MDL will be used as the discretisation method.
+   *
+   * @param useMDL true if MDL should be used, false if fixed bins should
+   * be used.
+   */
+  public void setUseMDL(boolean useMDL) {
+
+    m_UseMDL = useMDL;
+  }
+
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String useKononenkoTipText() {
+
+    return "Use Kononenko's MDL criterion. If set to false"
+      + " uses the Fayyad & Irani criterion.";
+  }
+  
+  /**
+   * Get the value of UseEqualFrequency.
+   *
+   * @return Value of UseEqualFrequency.
+   */
+  public boolean getUseEqualFrequency() {
+    
+    return m_UseEqualFrequency;
+  }
+  
+  /**
+   * Set the value of UseEqualFrequency.
+   *
+   * @param newUseEqualFrequency Value to assign to UseEqualFrequency.
+   */
+  public void setUseEqualFrequency(boolean newUseEqualFrequency) {
+    
+    m_UseEqualFrequency = newUseEqualFrequency;
+  }
+  
+  /**
+   * Gets whether Kononenko's MDL criterion is to be used.
+   *
+   * @return true if Kononenko's criterion will be used.
+   */
+  public boolean getUseKononenko() {
+
+    return m_UseKononenko;
+  }
+
+  /** 
+   * Sets whether Kononenko's MDL criterion is to be used.
+   *
+   * @param useKon true if Kononenko's one is to be used
+   */
+  public void setUseKononenko(boolean useKon) {
+
+    m_UseKononenko = useKon;
+  }
+
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String useBetterEncodingTipText() {
+
+    return "Uses a more efficient split point encoding.";
+  }
+
+  /**
+   * Gets whether better encoding is to be used for MDL.
+   *
+   * @return true if the better MDL encoding will be used
+   */
+  public boolean getUseBetterEncoding() {
+
+    return m_UseBetterEncoding;
+  }
+
+  /** 
+   * Sets whether better encoding is to be used for MDL.
+   *
+   * @param useBetterEncoding true if better encoding to be used.
+   */
+  public void setUseBetterEncoding(boolean useBetterEncoding) {
+
+    m_UseBetterEncoding = useBetterEncoding;
+  }
+
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String binsTipText() {
+
+    return "Number of bins for class-blind discretisation. This"
+      + " setting is ignored if MDL-based discretisation is used.";
+  }
+
+  /**
+   * Gets the number of bins numeric attributes will be divided into
+   *
+   * @return the number of bins.
+   */
+  public int getBins() {
+
+    return m_NumBins;
+  }
+
+  /**
+   * Sets the number of bins to divide each selected numeric attribute into
+   *
+   * @param numBins the number of bins
+   */
+  public void setBins(int numBins) {
+
+    m_NumBins = numBins;
+  }
+
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String invertSelectionTipText() {
+
+    return "Set attribute selection mode. If false, only selected"
+      + " (numeric) attributes in the range will be discretized; if"
+      + " true, only non-selected attributes will be discretized.";
+  }
+
+  /**
+   * Gets whether the supplied columns are to be removed or kept
+   *
+   * @return true if the supplied columns will be kept
+   */
+  public boolean getInvertSelection() {
+
+    return m_DiscretizeCols.getInvert();
+  }
+
+  /**
+   * Sets whether selected columns should be removed or kept. If true the 
+   * selected columns are kept and unselected columns are deleted. If false
+   * selected columns are deleted and unselected columns are kept.
+   *
+   * @param invert the new invert setting
+   */
+  public void setInvertSelection(boolean invert) {
+
+    m_DiscretizeCols.setInvert(invert);
+  }
+
+  /**
+   * Returns the tip text for this property
+   *
+   * @return tip text for this property suitable for
+   * displaying in the explorer/experimenter gui
+   */
+  public String attributeIndicesTipText() {
+    return "Specify range of attributes to act on."
+      + " This is a comma separated list of attribute indices, with"
+      + " \"first\" and \"last\" valid values. Specify an inclusive"
+      + " range with \"-\". E.g: \"first-3,5,6-10,last\".";
+  }
+
+  /**
+   * Gets the current range selection
+   *
+   * @return a string containing a comma separated list of ranges
+   */
+  public String getAttributeIndices() {
+
+    return m_DiscretizeCols.getRanges();
+  }
+
+  /**
+   * Sets which attributes are to be Discretized (only numeric
+   * attributes among the selection will be Discretized).
+   *
+   * @param rangeList a string representing the list of attributes. Since
+   * the string will typically come from a user, attributes are indexed from
+   * 1. <br>
+   * eg: first-3,5,6-last
+   * @exception IllegalArgumentException if an invalid range list is supplied 
+   */
+  public void setAttributeIndices(String rangeList) {
+
+    m_DiscretizeCols.setRanges(rangeList);
+  }
+
+  /**
+   * Sets which attributes are to be Discretized (only numeric
+   * attributes among the selection will be Discretized).
+   *
+   * @param attributes an array containing indexes of attributes to Discretize.
+   * Since the array will typically come from a program, attributes are indexed
+   * from 0.
+   * @exception IllegalArgumentException if an invalid set of ranges
+   * is supplied 
+   */
+  public void setAttributeIndicesArray(int [] attributes) {
+
+    setAttributeIndices(Range.indicesToRangeList(attributes));
+  }
+
+  /**
+   * Gets the cut points for an attribute
+   *
+   * @param the index (from 0) of the attribute to get the cut points of
+   * @return an array containing the cutpoints (or null if the
+   * attribute requested isn't being Discretized
+   */
+  public double [] getCutPoints(int attributeIndex) {
+
+    if (m_CutPoints == null) {
+      return null;
+    }
+    return m_CutPoints[attributeIndex];
+  }
+
+  /** Generate the cutpoints for each attribute */
+  protected void calculateCutPoints() {
+
+    Instances copy = null;
+
+    m_CutPoints = new double [getInputFormat().numAttributes()] [];
+    for(int i = getInputFormat().numAttributes() - 1; i >= 0; i--) {
+      if ((m_DiscretizeCols.isInRange(i)) && 
+	  (getInputFormat().attribute(i).isNumeric())) {
+	if (m_UseMDL) {
+
+	  // Use copy to preserve order
+	  if (copy == null) {
+	    copy = new Instances(getInputFormat());
+	  }
+	  calculateCutPointsByMDL(i, copy);
+	} else {
+	  if (m_FindNumBins) {
+	    findNumBins(i);
+	  } else if (!m_UseEqualFrequency) {
+	    calculateCutPointsByEqualWidthBinning(i);
+	  } else {
+	    calculateCutPointsByEqualFrequencyBinning(i);
+	  }
+	}
+      }
+    }
+  }
+
+  /**
+   * Set cutpoints for a single attribute using MDL.
+   *
+   * @param index the index of the attribute to set cutpoints for
+   */
+  protected void calculateCutPointsByMDL(int index,
+					 Instances data) {
+
+    // Sort instances
+    data.sort(data.attribute(index));
+
+    // Find first instances that's missing
+    int firstMissing = data.numInstances();
+    for (int i = 0; i < data.numInstances(); i++) {
+      if (data.instance(i).isMissing(index)) {
+        firstMissing = i;
+        break;
+      }
+    }
+    m_CutPoints[index] = cutPointsForSubset(data, index, 0, firstMissing);
+  }
+
+  /** Test using Kononenko's MDL criterion. */
+  private boolean KononenkosMDL(double[] priorCounts,
+				double[][] bestCounts,
+				double numInstances,
+				int numCutPoints) {
+
+    double distPrior, instPrior, distAfter = 0, sum, instAfter = 0;
+    double before, after;
+    int numClassesTotal;
+
+    // Number of classes occuring in the set
+    numClassesTotal = 0;
+    for (int i = 0; i < priorCounts.length; i++) {
+      if (priorCounts[i] > 0) {
+	numClassesTotal++;
+      }
+    }
+
+    // Encode distribution prior to split
+    distPrior = SpecialFunctions.log2Binomial(numInstances 
+					      + numClassesTotal - 1,
+					      numClassesTotal - 1);
+
+    // Encode instances prior to split.
+    instPrior = SpecialFunctions.log2Multinomial(numInstances,
+						 priorCounts);
+
+    before = instPrior + distPrior;
+
+    // Encode distributions and instances after split.
+    for (int i = 0; i < bestCounts.length; i++) {
+      sum = Utils.sum(bestCounts[i]);
+      distAfter += SpecialFunctions.log2Binomial(sum + numClassesTotal - 1,
+						 numClassesTotal - 1);
+      instAfter += SpecialFunctions.log2Multinomial(sum,
+						    bestCounts[i]);
+    }
+
+    // Coding cost after split
+    after = Utils.log2(numCutPoints) + distAfter + instAfter;
+
+    // Check if split is to be accepted
+    return (Utils.gr(before, after));
+  }
+
+
+  /** Test using Fayyad and Irani's MDL criterion. */
+  private boolean FayyadAndIranisMDL(double[] priorCounts,
+				     double[][] bestCounts,
+				     double numInstances,
+				     int numCutPoints) {
+
+    double priorEntropy, entropy, gain; 
+    double entropyLeft, entropyRight, delta;
+    int numClassesTotal, numClassesRight, numClassesLeft;
+
+    // Compute entropy before split.
+    priorEntropy = ContingencyTables.entropy(priorCounts);
+
+    // Compute entropy after split.
+    entropy = ContingencyTables.entropyConditionedOnRows(bestCounts);
+
+    // Compute information gain.
+    gain = priorEntropy - entropy;
+
+    // Number of classes occuring in the set
+    numClassesTotal = 0;
+    for (int i = 0; i < priorCounts.length; i++) {
+      if (priorCounts[i] > 0) {
+	numClassesTotal++;
+      }
+    }
+
+    // Number of classes occuring in the left subset
+    numClassesLeft = 0;
+    for (int i = 0; i < bestCounts[0].length; i++) {
+      if (bestCounts[0][i] > 0) {
+	numClassesLeft++;
+      }
+    }
+
+    // Number of classes occuring in the right subset
+    numClassesRight = 0;
+    for (int i = 0; i < bestCounts[1].length; i++) {
+      if (bestCounts[1][i] > 0) {
+	numClassesRight++;
+      }
+    }
+
+    // Entropy of the left and the right subsets
+    entropyLeft = ContingencyTables.entropy(bestCounts[0]);
+    entropyRight = ContingencyTables.entropy(bestCounts[1]);
+
+    // Compute terms for MDL formula
+    delta = Utils.log2(Math.pow(3, numClassesTotal) - 2) - 
+      (((double) numClassesTotal * priorEntropy) - 
+       (numClassesRight * entropyRight) - 
+       (numClassesLeft * entropyLeft));
+
+    // Check if split is to be accepted
+    return (Utils.gr(gain, (Utils.log2(numCutPoints) + delta) /
+		     (double)numInstances));
+  }
+    
+
+  /** Selects cutpoints for sorted subset. */
+  private double[] cutPointsForSubset(Instances instances, int attIndex, 
+				      int first, int lastPlusOne) { 
+
+    double[][] counts, bestCounts;
+    double[] priorCounts, left, right, cutPoints;
+    double currentCutPoint = -Double.MAX_VALUE, bestCutPoint = -1, 
+      currentEntropy, bestEntropy, priorEntropy, gain;
+    int bestIndex = -1, numInstances = 0, numCutPoints = 0;
+
+    // Compute number of instances in set
+    if ((lastPlusOne - first) < 2) {
+      return null;
+    }
+
+    // Compute class counts.
+    counts = new double[2][instances.numClasses()];
+    for (int i = first; i < lastPlusOne; i++) {
+      numInstances += instances.instance(i).weight();
+      counts[1][(int)instances.instance(i).classValue()] +=
+	instances.instance(i).weight();
+    }
+
+    // Save prior counts
+    priorCounts = new double[instances.numClasses()];
+    System.arraycopy(counts[1], 0, priorCounts, 0, 
+		     instances.numClasses());
+
+    // Entropy of the full set
+    priorEntropy = ContingencyTables.entropy(priorCounts);
+    bestEntropy = priorEntropy;
+    
+    // Find best entropy.
+    bestCounts = new double[2][instances.numClasses()];
+    for (int i = first; i < (lastPlusOne - 1); i++) {
+      counts[0][(int)instances.instance(i).classValue()] +=
+	instances.instance(i).weight();
+      counts[1][(int)instances.instance(i).classValue()] -=
+	instances.instance(i).weight();
+      if (Utils.sm(instances.instance(i).value(attIndex), 
+		   instances.instance(i + 1).value(attIndex))) {
+	currentCutPoint = instances.instance(i).value(attIndex); //+ 
+	//instances.instance(i + 1).value(attIndex)) / 2.0;
+	currentEntropy = ContingencyTables.entropyConditionedOnRows(counts);
+	if (Utils.sm(currentEntropy, bestEntropy)) {
+	  bestCutPoint = currentCutPoint;
+	  bestEntropy = currentEntropy;
+	  bestIndex = i;
+	  System.arraycopy(counts[0], 0, 
+			   bestCounts[0], 0, instances.numClasses());
+	  System.arraycopy(counts[1], 0, 
+			   bestCounts[1], 0, instances.numClasses()); 
+	}
+	numCutPoints++;
+      }
+    }
+
+    // Use worse encoding?
+    if (!m_UseBetterEncoding) {
+      numCutPoints = (lastPlusOne - first) - 1;
+    }
+
+    // Checks if gain is zero
+    gain = priorEntropy - bestEntropy;
+    if (Utils.eq(gain, 0)) {
+      return null;
+    }
+
+    // Check if split is to be accepted
+    if ((m_UseKononenko && KononenkosMDL(priorCounts, bestCounts,
+					 numInstances, numCutPoints)) ||
+	(!m_UseKononenko && FayyadAndIranisMDL(priorCounts, bestCounts,
+					       numInstances, numCutPoints))) {
+      
+      // Select split points for the left and right subsets
+      left = cutPointsForSubset(instances, attIndex, first, bestIndex + 1);
+      right = cutPointsForSubset(instances, attIndex, 
+				 bestIndex + 1, lastPlusOne);
+      
+      // Merge cutpoints and return them
+      if ((left == null) && (right) == null) {
+	cutPoints = new double[1];
+	cutPoints[0] = bestCutPoint;
+      } else if (right == null) {
+	cutPoints = new double[left.length + 1];
+	System.arraycopy(left, 0, cutPoints, 0, left.length);
+	cutPoints[left.length] = bestCutPoint;
+      } else if (left == null) {
+	cutPoints = new double[1 + right.length];
+	cutPoints[0] = bestCutPoint;
+	System.arraycopy(right, 0, cutPoints, 1, right.length);
+      } else {
+	cutPoints =  new double[left.length + right.length + 1];
+	cutPoints = new double[left.length + right.length + 1];
+	System.arraycopy(left, 0, cutPoints, 0, left.length);
+	cutPoints[left.length] = bestCutPoint;
+	System.arraycopy(right, 0, cutPoints, left.length + 1, right.length);
+      }
+      
+      return cutPoints;
+    } else
+      return null;
+  }
+ 
+  /**
+   * Set cutpoints for a single attribute.
+   *
+   * @param index the index of the attribute to set cutpoints for
+   */
+  protected void calculateCutPointsByEqualWidthBinning(int index) {
+
+    // Scan for max and min values
+    double max = 0, min = 1, currentVal;
+    Instance currentInstance;
+    for(int i = 0; i < getInputFormat().numInstances(); i++) {
+      currentInstance = getInputFormat().instance(i);
+      if (!currentInstance.isMissing(index)) {
+	currentVal = currentInstance.value(index);
+	if (max < min) {
+	  max = min = currentVal;
+	}
+	if (currentVal > max) {
+	  max = currentVal;
+	}
+	if (currentVal < min) {
+	  min = currentVal;
+	}
+      }
+    }
+    double binWidth = (max - min) / m_NumBins;
+    double [] cutPoints = null;
+    if ((m_NumBins > 1) && (binWidth > 0)) {
+      cutPoints = new double [m_NumBins - 1];
+      for(int i = 1; i < m_NumBins; i++) {
+	cutPoints[i - 1] = min + binWidth * i;
+      }
+    }
+    m_CutPoints[index] = cutPoints;
+  }
+ 
+  /**
+   * Set cutpoints for a single attribute.
+   *
+   * @param index the index of the attribute to set cutpoints for
+   */
+  protected void calculateCutPointsByEqualFrequencyBinning(int index) {
+
+    // Copy data so that it can be sorted
+    Instances data = new Instances(getInputFormat());
+
+    // Sort input data
+    data.sort(index);
+
+    // Compute weight of instances without missing values
+    double sumOfWeights = 0;
+    for (int i = 0; i < data.numInstances(); i++) {
+      if (data.instance(i).isMissing(index)) {
+	break;
+      } else {
+	sumOfWeights += data.instance(i).weight();
+      }
+    }
+    double freq = sumOfWeights / m_NumBins;
+
+    // Compute break points
+    double[] cutPoints = new double[m_NumBins - 1];
+    double counter = 0;
+    int cpindex = 0;
+    for (int i = 0; i < data.numInstances() - 1; i++) {
+
+      // Stop if value missing
+      if (data.instance(i).isMissing(index)) {
+	break;
+      }
+      counter += data.instance(i).weight();
+
+      // Do we have a potential breakpoint?
+      if (data.instance(i).value(index) < 
+	  data.instance(i + 1).value(index)) {
+	if (counter >= freq) {
+	  cutPoints[cpindex] = (data.instance(i).value(index) +
+				data.instance(i + 1).value(index)) / 2;
+	  cpindex++;
+	  counter = counter - freq;
+	}
+      }
+    }
+
+    // Did we find any cutpoints?
+    if (cpindex == 0) {
+      m_CutPoints[index] = null;
+    } else {
+      double[] cp = new double[cpindex];
+      for (int i = 0; i < cpindex; i++) {
+	cp[i] = cutPoints[i];
+      }
+      m_CutPoints[index] = cp;
+    }
+  }
+
+  /**
+   * Optimizes the number of bins using leave-one-out cross-validation.
+   *
+   * @param index the attribute index
+   */
+  protected void findNumBins(int index) {
+
+    double min = Double.MAX_VALUE, max = -Double.MIN_VALUE, binWidth = 0, 
+      entropy, bestEntropy = Double.MAX_VALUE, currentVal;
+    double[] distribution;
+    int bestNumBins  = 1;
+    Instance currentInstance;
+
+    // Find minimum and maximum
+    for (int i = 0; i < getInputFormat().numInstances(); i++) {
+      currentInstance = getInputFormat().instance(i);
+      if (!currentInstance.isMissing(index)) {
+	currentVal = currentInstance.value(index);
+	if (currentVal > max) {
+	  max = currentVal;
+	}
+	if (currentVal < min) {
+	  min = currentVal;
+	}
+      }
+    }
+
+    // Find best number of bins
+    for (int i = 0; i < m_NumBins; i++) {
+      distribution = new double[i + 1];
+      binWidth = (max - min) / (i + 1);
+
+      // Compute distribution
+      for (int j = 0; j < getInputFormat().numInstances(); j++) {
+	currentInstance = getInputFormat().instance(j);
+	if (!currentInstance.isMissing(index)) {
+	  for (int k = 0; k < i + 1; k++) {
+	    if (currentInstance.value(index) <= 
+		(min + (((double)k + 1) * binWidth))) {
+	      distribution[k] += currentInstance.weight();
+	      break;
+	    }
+	  }
+	}
+      }
+
+      // Compute cross-validated entropy
+      entropy = 0;
+      for (int k = 0; k < i + 1; k++) {
+	if (distribution[k] < 2) {
+	  entropy = Double.MAX_VALUE;
+	  break;
+	}
+	entropy -= distribution[k] * Math.log((distribution[k] - 1) / 
+					      binWidth);
+      }
+
+      // Best entropy so far?
+      if (entropy < bestEntropy) {
+	bestEntropy = entropy;
+	bestNumBins = i + 1;
+      }
+    }
+
+    // Compute cut points
+    double [] cutPoints = null;
+    if ((bestNumBins > 1) && (binWidth > 0)) {
+      cutPoints = new double [bestNumBins - 1];
+      for(int i = 1; i < bestNumBins; i++) {
+	cutPoints[i - 1] = min + binWidth * i;
+      }
+    }
+    m_CutPoints[index] = cutPoints;
+   }
+
+  /**
+   * Set the output format. Takes the currently defined cutpoints and 
+   * m_InputFormat and calls setOutputFormat(Instances) appropriately.
+   */
+  protected void setOutputFormat() {
+
+    if (m_CutPoints == null) {
+      setOutputFormat(null);
+      return;
+    }
+    FastVector attributes = new FastVector(getInputFormat().numAttributes());
+    int classIndex = getInputFormat().classIndex();
+    for(int i = 0; i < getInputFormat().numAttributes(); i++) {
+      if ((m_DiscretizeCols.isInRange(i)) 
+	  && (getInputFormat().attribute(i).isNumeric())) {
+	if (!m_MakeBinary) {
+	  FastVector attribValues = new FastVector(1);
+	  if (m_CutPoints[i] == null) {
+	    attribValues.addElement("'All'");
+	  } else {
+	    for(int j = 0; j <= m_CutPoints[i].length; j++) {
+	      if (j == 0) {
+		attribValues.addElement("'(-inf-"
+			+ Utils.doubleToString(m_CutPoints[i][j], 6) + "]'");
+	      } else if (j == m_CutPoints[i].length) {
+		attribValues.addElement("'("
+			+ Utils.doubleToString(m_CutPoints[i][j - 1], 6) 
+					+ "-inf)'");
+	      } else {
+		attribValues.addElement("'("
+			+ Utils.doubleToString(m_CutPoints[i][j - 1], 6) + "-"
+			+ Utils.doubleToString(m_CutPoints[i][j], 6) + "]'");
+	      }
+	    }
+	  }
+	  attributes.addElement(new Attribute(getInputFormat().
+					      attribute(i).name(),
+					      attribValues));
+	} else {
+	  if (m_CutPoints[i] == null) {
+	    FastVector attribValues = new FastVector(1);
+	    attribValues.addElement("'All'");
+	    attributes.addElement(new Attribute(getInputFormat().
+						attribute(i).name(),
+						attribValues));
+	  } else {
+	    if (i < getInputFormat().classIndex()) {
+	      classIndex += m_CutPoints[i].length - 1;
+	    }
+	    for(int j = 0; j < m_CutPoints[i].length; j++) {
+	      FastVector attribValues = new FastVector(2);
+	      attribValues.addElement("'(-inf-"
+		      + Utils.doubleToString(m_CutPoints[i][j], 6) + "]'");
+	      attribValues.addElement("'("
+		      + Utils.doubleToString(m_CutPoints[i][j], 6) + "-inf)'");
+	      attributes.addElement(new Attribute(getInputFormat().
+						  attribute(i).name(),
+						  attribValues));
+	    }
+	  }
+	}
+      } else {
+	attributes.addElement(getInputFormat().attribute(i).copy());
+      }
+    }
+    Instances outputFormat = 
+      new Instances(getInputFormat().relationName(), attributes, 0);
+    outputFormat.setClassIndex(classIndex);
+    setOutputFormat(outputFormat);
+  }
+
+  /**
+   * Convert a single instance over. The converted instance is added to 
+   * the end of the output queue.
+   *
+   * @param instance the instance to convert
+   */
+  protected void convertInstance(Instance instance) {
+
+    int index = 0;
+    double [] vals = new double [outputFormatPeek().numAttributes()];
+    // Copy and convert the values
+    for(int i = 0; i < getInputFormat().numAttributes(); i++) {
+      if (m_DiscretizeCols.isInRange(i) && 
+	  getInputFormat().attribute(i).isNumeric()) {
+	int j;
+	double currentVal = instance.value(i);
+	if (m_CutPoints[i] == null) {
+	  if (instance.isMissing(i)) {
+	    vals[index] = Instance.missingValue();
+	  } else {
+	    vals[index] = 0;
+	  }
+	  index++;
+	} else {
+	  if (!m_MakeBinary) {
+	    if (instance.isMissing(i)) {
+	      vals[index] = Instance.missingValue();
+	    } else {
+	      for (j = 0; j < m_CutPoints[i].length; j++) {
+		if (currentVal <= m_CutPoints[i][j]) {
+		  break;
+		}
+	      }
+              vals[index] = j;
+	    }
+	    index++;
+	  } else {
+	    for (j = 0; j < m_CutPoints[i].length; j++) {
+	      if (instance.isMissing(i)) {
+                vals[index] = Instance.missingValue();
+	      } else if (currentVal <= m_CutPoints[i][j]) {
+                vals[index] = 0;
+	      } else {
+                vals[index] = 1;
+	      }
+	      index++;
+	    }
+	  }   
+	}
+      } else {
+        vals[index] = instance.value(i);
+	index++;
+      }
+    }
+    
+    Instance inst = null;
+    if (instance instanceof SparseInstance) {
+      inst = new SparseInstance(instance.weight(), vals);
+    } else {
+      inst = new Instance(instance.weight(), vals);
+    }
+    copyStringValues(inst, false, instance.dataset(), getInputStringIndex(),
+                     getOutputFormat(), getOutputStringIndex());
+    inst.setDataset(getOutputFormat());
+    push(inst);
+  }
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param argv should contain arguments to the filter: use -h for help
+   */
+  public static void main(String [] argv) {
+
+    try {
+      if (Utils.getFlag('b', argv)) {
+ 	Filter.batchFilterFile(new DiscretizeFilter(), argv);
+      } else {
+	Filter.filterFile(new DiscretizeFilter(), argv);
+      }
+    } catch (Exception ex) {
+      System.out.println(ex.getMessage());
+    }
+  }
+}
+
+
+
+
+
+
+
+
Index: /trunk/gsdl/packages/kea/kea-3.0/weka/filters/Filter.java
===================================================================
--- /trunk/gsdl/packages/kea/kea-3.0/weka/filters/Filter.java	(revision 8815)
+++ /trunk/gsdl/packages/kea/kea-3.0/weka/filters/Filter.java	(revision 8815)
@@ -0,0 +1,934 @@
+/*
+ *    This program is free software; you can redistribute it and/or modify
+ *    it under the terms of the GNU General Public License as published by
+ *    the Free Software Foundation; either version 2 of the License, or
+ *    (at your option) any later version.
+ *
+ *    This program 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 General Public License for more details.
+ *
+ *    You should have received a copy of the GNU General Public License
+ *    along with this program; if not, write to the Free Software
+ *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+/*
+ *    Filter.java
+ *    Copyright (C) 1999 Len Trigg
+ *
+ */
+
+
+package weka.filters;
+
+import java.io.BufferedReader;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.io.Reader;
+import java.io.Serializable;
+import java.util.Enumeration;
+import weka.core.Attribute;
+import weka.core.Instance;
+import weka.core.Instances;
+import weka.core.Option;
+import weka.core.OptionHandler;
+import weka.core.Queue;
+import weka.core.Utils;
+
+/** 
+ * An abstract class for instance filters: objects that take instances
+ * as input, carry out some transformation on the instance and then
+ * output the instance. The method implementations in this class
+ * assume that most of the work will be done in the methods overridden
+ * by subclasses.<p>
+ *
+ * A simple example of filter use. This example doesn't remove
+ * instances from the output queue until all instances have been
+ * input, so has higher memory consumption than an approach that
+ * uses output instances as they are made available:<p>
+ *
+ * <code> <pre>
+ *  Filter filter = ..some type of filter..
+ *  Instances instances = ..some instances..
+ *  for (int i = 0; i < data.numInstances(); i++) {
+ *    filter.input(data.instance(i));
+ *  }
+ *  filter.batchFinished();
+ *  Instances newData = filter.outputFormat();
+ *  Instance processed;
+ *  while ((processed = filter.output()) != null) {
+ *    newData.add(processed);
+ *  }
+ *  ..do something with newData..
+ * </pre> </code>
+ *
+ * @author Len Trigg (trigg@cs.waikato.ac.nz)
+ * @version $Revision$
+ */
+public abstract class Filter implements Serializable {
+
+  /*
+   * Filter refactoring TODO:
+   *
+   * - Update all filters to use getOutputFormat and setInputFormat
+   * instead of outputFormat, outputFormatPeek and inputFormat.
+   * - Update users of filters to use getOutputFormat and setInputFormat
+   * - remove outputFormat, outputFormatPeek and inputFormat
+   *
+   */
+
+  /** Debugging mode */
+  private boolean m_Debug = false;
+
+  /** The output format for instances */
+  private Instances m_OutputFormat = null;
+
+  /** The output instance queue */
+  private Queue m_OutputQueue = null;
+
+  /** Indices of string attributes in the output format */
+  private int [] m_OutputStringAtts = null;
+
+  /** Indices of string attributes in the input format */
+  private int [] m_InputStringAtts = null;
+
+  /** The input format for instances */
+  private Instances m_InputFormat = null;
+
+  /** Record whether the filter is at the start of a batch */
+  protected boolean m_NewBatch = true;
+
+  /**
+   * Sets the format of output instances. The derived class should use this
+   * method once it has determined the outputformat. The 
+   * output queue is cleared.
+   *
+   * @param outputFormat the new output format
+   */
+  protected void setOutputFormat(Instances outputFormat) {
+
+    if (outputFormat != null) {
+      m_OutputFormat = outputFormat.stringFreeStructure();
+      m_OutputStringAtts = getStringIndices(m_OutputFormat);
+
+      // Rename the attribute
+      String relationName = outputFormat.relationName() 
+        + "-" + this.getClass().getName();
+      if (this instanceof OptionHandler) {
+        String [] options = ((OptionHandler)this).getOptions();
+        for (int i = 0; i < options.length; i++) {
+          relationName += options[i].trim();
+        }
+      }
+      m_OutputFormat.setRelationName(relationName);
+    } else {
+      m_OutputFormat = null;
+    }
+    m_OutputQueue = new Queue();
+  }
+
+  /**
+   * Gets the currently set inputformat instances. This dataset may contain
+   * buffered instances.
+   *
+   * @return the input Instances.
+   */
+  protected Instances getInputFormat() {
+
+    return m_InputFormat;
+  }
+
+  /**
+   * Returns a reference to the current output format without
+   * copying it.
+   *
+   * @return a reference to the current output format
+   */
+  protected Instances outputFormatPeek() {
+
+    return m_OutputFormat;
+  }
+
+  /**
+   * Adds an output instance to the queue. The derived class should use this
+   * method for each output instance it makes available. 
+   *
+   * @param instance the instance to be added to the queue
+   */
+  protected void push(Instance instance) {
+
+    if (instance != null) {
+      copyStringValues(instance, m_OutputFormat, m_OutputStringAtts);
+      instance.setDataset(m_OutputFormat);
+      m_OutputQueue.push(instance);
+    }
+  }
+
+  /**
+   * Clears the output queue.
+   */
+  protected void resetQueue() {
+
+    m_OutputQueue = new Queue();
+  }
+
+  /**
+   * Adds the supplied input instance to the inputformat dataset for
+   * later processing.  Use this method rather than
+   * getInputFormat().add(instance). Or else.
+   *
+   * @param instance the <code>Instance</code> to buffer.  
+   */
+  protected void bufferInput(Instance instance) {
+
+    if (instance != null) {
+      copyStringValues(instance, m_InputFormat, m_InputStringAtts);
+      instance.setDataset(m_InputFormat);
+      m_InputFormat.add(instance);
+    }
+  }
+
+  /**
+   * Returns an array containing the indices of all string attributes in the
+   * input format. This index is created during setInputFormat()
+   *
+   * @return an array containing the indices of string attributes in the 
+   * input dataset.
+   */
+  protected int [] getInputStringIndex() {
+
+    return m_InputStringAtts;
+  }
+
+  /**
+   * Returns an array containing the indices of all string attributes in the
+   * output format. This index is created during setOutputFormat()
+   *
+   * @return an array containing the indices of string attributes in the 
+   * output dataset.
+   */
+  protected int [] getOutputStringIndex() {
+
+    return m_OutputStringAtts;
+  }
+
+  /**
+   * Copies string values contained in the instance copied to a new
+   * dataset. The Instance must already be assigned to a dataset. This
+   * dataset and the destination dataset must have the same structure.
+   *
+   * @param instance the Instance containing the string values to copy.
+   * @param destDataset the destination set of Instances
+   * @param strAtts an array containing the indices of any string attributes
+   * in the dataset.  
+   */
+  private void copyStringValues(Instance inst, Instances destDataset, 
+                                int []strAtts) {
+
+    if (strAtts.length == 0) {
+      return;
+    }
+    if (inst.dataset() == null) {
+      throw new IllegalArgumentException("Instance has no dataset assigned!!");
+    } else if (inst.dataset().numAttributes() != destDataset.numAttributes()) {
+      throw new IllegalArgumentException("Src and Dest differ in # of attributes!!");
+    } 
+    copyStringValues(inst, true, inst.dataset(), strAtts,
+                     destDataset, strAtts);
+  }
+
+  /**
+   * Takes string values referenced by an Instance and copies them from a
+   * source dataset to a destination dataset. The instance references are
+   * updated to be valid for the destination dataset. The instance may have the 
+   * structure (i.e. number and attribute position) of either dataset (this
+   * affects where references are obtained from). The source dataset must
+   * have the same structure as the filter input format and the destination
+   * must have the same structure as the filter output format.
+   *
+   * @param instance the instance containing references to strings in the source
+   * dataset that will have references updated to be valid for the destination
+   * dataset.
+   * @param instSrcCompat true if the instance structure is the same as the
+   * source, or false if it is the same as the destination
+   * @param srcDataset the dataset for which the current instance string
+   * references are valid (after any position mapping if needed)
+   * @param destDataset the dataset for which the current instance string
+   * references need to be inserted (after any position mapping if needed)
+   */
+  protected void copyStringValues(Instance instance, boolean instSrcCompat,
+                                  Instances srcDataset, Instances destDataset) {
+
+    copyStringValues(instance, instSrcCompat, srcDataset, m_InputStringAtts,
+                     destDataset, m_OutputStringAtts);
+  }
+
+  /**
+   * Takes string values referenced by an Instance and copies them from a
+   * source dataset to a destination dataset. The instance references are
+   * updated to be valid for the destination dataset. The instance may have the 
+   * structure (i.e. number and attribute position) of either dataset (this
+   * affects where references are obtained from). Only works if the number
+   * of string attributes is the same in both indices (implicitly these string
+   * attributes should be semantically same but just with shifted positions).
+   *
+   * @param instance the instance containing references to strings in the source
+   * dataset that will have references updated to be valid for the destination
+   * dataset.
+   * @param instSrcCompat true if the instance structure is the same as the
+   * source, or false if it is the same as the destination (i.e. which of the
+   * string attribute indices contains the correct locations for this instance).
+   * @param srcDataset the dataset for which the current instance string
+   * references are valid (after any position mapping if needed)
+   * @param srcStrAtts an array containing the indices of string attributes
+   * in the source datset.
+   * @param destDataset the dataset for which the current instance string
+   * references need to be inserted (after any position mapping if needed)
+   * @param destStrAtts an array containing the indices of string attributes
+   * in the destination datset.
+   */
+  protected void copyStringValues(Instance instance, boolean instSrcCompat,
+                                  Instances srcDataset, int []srcStrAtts,
+                                  Instances destDataset, int []destStrAtts) {
+    if (srcDataset == destDataset) {
+      return;
+    }
+    if (srcStrAtts.length != destStrAtts.length) {
+      throw new IllegalArgumentException("Src and Dest string indices differ in length!!");
+    }
+    for (int i = 0; i < srcStrAtts.length; i++) {
+      int instIndex = instSrcCompat ? srcStrAtts[i] : destStrAtts[i];
+      Attribute src = srcDataset.attribute(srcStrAtts[i]);
+      Attribute dest = destDataset.attribute(destStrAtts[i]);
+      if (!instance.isMissing(instIndex)) {
+        //System.err.println(instance.value(srcIndex) 
+        //                   + " " + src.numValues()
+        //                   + " " + dest.numValues());
+        int valIndex = dest.addStringValue(src, (int)instance.value(instIndex));
+        // setValue here shouldn't be too slow here unless your dataset has
+        // squillions of string attributes
+        instance.setValue(instIndex, (double)valIndex);
+      }
+    }
+  }
+
+  /**
+   * This will remove all buffered instances from the inputformat dataset.
+   * Use this method rather than getInputFormat().delete();
+   */
+  protected void flushInput() {
+
+    if (m_InputStringAtts.length > 0) {
+      m_InputFormat = m_InputFormat.stringFreeStructure();
+    } else {
+      // This more efficient than new Instances(m_InputFormat, 0);
+      m_InputFormat.delete();
+    }
+  }
+
+  /**
+   * @deprecated use <code>setInputFormat(Instances)</code> instead.
+   */
+  public boolean inputFormat(Instances instanceInfo) throws Exception {
+
+    return setInputFormat(instanceInfo);
+  }
+
+  /**
+   * Sets the format of the input instances. If the filter is able to
+   * determine the output format before seeing any input instances, it
+   * does so here. This default implementation clears the output format
+   * and output queue, and the new batch flag is set. Overriders should
+   * call <code>super.setInputFormat(Instances)</code>
+   *
+   * @param instanceInfo an Instances object containing the input instance
+   * structure (any instances contained in the object are ignored - only the
+   * structure is required).
+   * @return true if the outputFormat may be collected immediately
+   * @exception Exception if the inputFormat can't be set successfully 
+   */
+  public boolean setInputFormat(Instances instanceInfo) throws Exception {
+
+    m_InputFormat = instanceInfo.stringFreeStructure();
+    m_InputStringAtts = getStringIndices(instanceInfo);
+    m_OutputFormat = null;
+    m_OutputQueue = new Queue();
+    m_NewBatch = true;
+    return false;
+  }
+
+  /**
+   * @deprecated use <code>getOutputFormat()</code> instead.
+   */
+  public final Instances outputFormat() {
+
+    return getOutputFormat();
+  }
+
+  /**
+   * Gets the format of the output instances. This should only be called
+   * after input() or batchFinished() has returned true. The relation
+   * name of the output instances should be changed to reflect the
+   * action of the filter (eg: add the filter name and options).
+   *
+   * @return an Instances object containing the output instance
+   * structure only.
+   * @exception NullPointerException if no input structure has been
+   * defined (or the output format hasn't been determined yet) 
+   */
+  public final Instances getOutputFormat() {
+
+    if (m_OutputFormat == null) {
+      throw new NullPointerException("No output format defined.");
+    }
+    return new Instances(m_OutputFormat, 0);
+  }
+
+  /**
+   * Input an instance for filtering. Ordinarily the instance is
+   * processed and made available for output immediately. Some filters
+   * require all instances be read before producing output, in which
+   * case output instances should be collected after calling
+   * batchFinished(). If the input marks the start of a new batch, the
+   * output queue is cleared. This default implementation assumes all
+   * instance conversion will occur when batchFinished() is called.
+   *
+   * @param instance the input instance
+   * @return true if the filtered instance may now be
+   * collected with output().
+   * @exception NullPointerException if the input format has not been
+   * defined.
+   * @exception Exception if the input instance was not of the correct 
+   * format or if there was a problem with the filtering.  
+   */
+  public boolean input(Instance instance) throws Exception {
+
+    if (m_InputFormat == null) {
+      throw new NullPointerException("No input instance format defined");
+    }
+    if (m_NewBatch) {
+      m_OutputQueue = new Queue();
+      m_NewBatch = false;
+    }
+    bufferInput(instance);
+    return false;
+  }
+
+  /**
+   * Signify that this batch of input to the filter is finished. If
+   * the filter requires all instances prior to filtering, output()
+   * may now be called to retrieve the filtered instances. Any
+   * subsequent instances filtered should be filtered based on setting
+   * obtained from the first batch (unless the inputFormat has been
+   * re-assigned or new options have been set). This default
+   * implementation assumes all instance processing occurs during
+   * inputFormat() and input().
+   *
+   * @return true if there are instances pending output
+   * @exception NullPointerException if no input structure has been defined,
+   * @exception Exception if there was a problem finishing the batch.
+   */
+  public boolean batchFinished() throws Exception {
+
+    if (m_InputFormat == null) {
+      throw new NullPointerException("No input instance format defined");
+    }
+    flushInput();
+    m_NewBatch = true;
+    return (numPendingOutput() != 0);
+  }
+
+
+  /**
+   * Output an instance after filtering and remove from the output queue.
+   *
+   * @return the instance that has most recently been filtered (or null if
+   * the queue is empty).
+   * @exception NullPointerException if no output structure has been defined
+   */
+  public Instance output() {
+
+    if (m_OutputFormat == null) {
+      throw new NullPointerException("No output instance format defined");
+    }
+    if (m_OutputQueue.empty()) {
+      return null;
+    }
+    Instance result = (Instance)m_OutputQueue.pop();
+    // Clear out references to old strings occasionally
+    if (m_OutputQueue.empty() && m_NewBatch) {
+      if (m_OutputStringAtts.length > 0) {
+        m_OutputFormat = m_OutputFormat.stringFreeStructure();
+      }
+    }
+    return result;
+  }
+  
+  /**
+   * Output an instance after filtering but do not remove from the
+   * output queue.
+   *
+   * @return the instance that has most recently been filtered (or null if
+   * the queue is empty).
+   * @exception NullPointerException if no input structure has been defined 
+   */
+  public Instance outputPeek() {
+
+    if (m_OutputFormat == null) {
+      throw new NullPointerException("No output instance format defined");
+    }
+    if (m_OutputQueue.empty()) {
+      return null;
+    }
+    Instance result = (Instance)m_OutputQueue.peek();
+    return result;
+  }
+
+  /**
+   * Returns the number of instances pending output
+   *
+   * @return the number of instances  pending output
+   * @exception NullPointerException if no input structure has been defined
+   */
+  public int numPendingOutput() {
+
+    if (m_OutputFormat == null) {
+      throw new NullPointerException("No output instance format defined");
+    }
+    return m_OutputQueue.size();
+  }
+
+  /**
+   * Returns whether the output format is ready to be collected
+   *
+   * @return true if the output format is set
+   */
+  public boolean isOutputFormatDefined() {
+
+    return (m_OutputFormat != null);
+  }
+
+  /**
+   * Gets an array containing the indices of all string attributes.
+   *
+   * @param insts the Instances to scan for string attributes. 
+   * @return an array containing the indices of string attributes in
+   * the input structure. Will be zero-length if there are no
+   * string attributes
+   */
+  protected int [] getStringIndices(Instances insts) {
+    
+    // Scan through getting the indices of String attributes
+    int [] index = new int [insts.numAttributes()];
+    int indexSize = 0;
+    for (int i = 0; i < insts.numAttributes(); i++) {
+      if (insts.attribute(i).type() == Attribute.STRING) {
+        index[indexSize++] = i;
+      }
+    }
+    int [] result = new int [indexSize];
+    System.arraycopy(index, 0, result, 0, indexSize);
+    return result;
+  }
+  
+  /**
+   * Filters an entire set of instances through a filter and returns
+   * the new set. 
+   *
+   * @param data the data to be filtered
+   * @param filter the filter to be used
+   * @return the filtered set of data
+   * @exception Exception if the filter can't be used successfully
+   */
+  public static Instances useFilter(Instances data,
+				    Filter filter) throws Exception {
+    /*
+    System.err.println(filter.getClass().getName() 
+                       + " in:" + data.numInstances());
+    */
+    for (int i = 0; i < data.numInstances(); i++) {
+      filter.input(data.instance(i));
+    }
+    filter.batchFinished();
+    Instances newData = filter.getOutputFormat();
+    Instance processed;
+    while ((processed = filter.output()) != null) {
+      newData.add(processed);
+    }
+
+    /*
+    System.err.println(filter.getClass().getName() 
+                       + " out:" + newData.numInstances());
+    */
+    return newData;
+  }
+
+  /**
+   * Method for testing filters.
+   *
+   * @param argv should contain the following arguments: <br>
+   * -i input_file <br>
+   * -o output_file <br>
+   * -c class_index <br>
+   * or -h for help on options
+   * @exception Exception if something goes wrong or the user requests help on
+   * command options
+   */
+  public static void filterFile(Filter filter, String [] options) 
+    throws Exception {
+
+    boolean debug = false;
+    Instances data = null;
+    Reader input = null;
+    PrintWriter output = null;
+    boolean helpRequest;
+
+    try {
+       helpRequest = Utils.getFlag('h', options);
+
+      if (Utils.getFlag('d', options)) {
+	debug = true;
+      }
+      String infileName = Utils.getOption('i', options);
+      String outfileName = Utils.getOption('o', options); 
+      String classIndex = Utils.getOption('c', options);
+      
+      if (filter instanceof OptionHandler) {
+	((OptionHandler)filter).setOptions(options);
+      }
+
+      Utils.checkForRemainingOptions(options);
+      if (helpRequest) {
+	throw new Exception("Help requested.\n");
+      }
+      if (infileName.length() != 0) {
+	input = new BufferedReader(new FileReader(infileName));
+      } else {
+	input = new BufferedReader(new InputStreamReader(System.in));
+      }
+      if (outfileName.length() != 0) {
+	output = new PrintWriter(new FileOutputStream(outfileName));
+      } else { 
+	output = new PrintWriter(System.out);
+      }
+
+      data = new Instances(input, 1);
+      if (classIndex.length() != 0) {
+	if (classIndex.equals("first")) {
+	  data.setClassIndex(0);
+	} else if (classIndex.equals("last")) {
+	  data.setClassIndex(data.numAttributes() - 1);
+	} else {
+	  data.setClassIndex(Integer.parseInt(classIndex) - 1);
+	}
+      }
+    } catch (Exception ex) {
+      String filterOptions = "";
+      // Output the error and also the valid options
+      if (filter instanceof OptionHandler) {
+	filterOptions += "\nFilter options:\n\n";
+	Enumeration enum = ((OptionHandler)filter).listOptions();
+	while (enum.hasMoreElements()) {
+	  Option option = (Option) enum.nextElement();
+	  filterOptions += option.synopsis() + '\n'
+	    + option.description() + "\n";
+	}
+      }
+
+      String genericOptions = "\nGeneral options:\n\n"
+	+ "-h\n"
+	+ "\tGet help on available options.\n"
+	+ "\t(use -b -h for help on batch mode.)\n"
+	+ "-i <file>\n"
+	+ "\tThe name of the file containing input instances.\n"
+	+ "\tIf not supplied then instances will be read from stdin.\n"
+	+ "-o <file>\n"
+	+ "\tThe name of the file output instances will be written to.\n"
+	+ "\tIf not supplied then instances will be written to stdout.\n"
+	+ "-c <class index>\n"
+	+ "\tThe number of the attribute to use as the class.\n"
+	+ "\t\"first\" and \"last\" are also valid entries.\n"
+	+ "\tIf not supplied then no class is assigned.\n";
+
+      throw new Exception('\n' + ex.getMessage()
+			  + filterOptions+genericOptions);
+    }
+    
+    if (debug) {
+      System.err.println("Setting input format");
+    }
+    boolean printedHeader = false;
+    if (filter.setInputFormat(data)) {
+      if (debug) {
+	System.err.println("Getting output format");
+      }
+      output.println(filter.getOutputFormat().toString());
+      printedHeader = true;
+    }
+    
+    // Pass all the instances to the filter
+    while (data.readInstance(input)) {
+      if (debug) {
+	System.err.println("Input instance to filter");
+      }
+      if (filter.input(data.instance(0))) {
+	if (debug) {
+	  System.err.println("Filter said collect immediately");
+	}
+	if (!printedHeader) {
+	  throw new Error("Filter didn't return true from setInputFormat() "
+			  + "earlier!");
+	}
+	if (debug) {
+	  System.err.println("Getting output instance");
+	}
+	output.println(filter.output().toString());
+      }
+      data.delete(0);
+    }
+    
+    // Say that input has finished, and print any pending output instances
+    if (debug) {
+      System.err.println("Setting end of batch");
+    }
+    if (filter.batchFinished()) {
+      if (debug) {
+	System.err.println("Filter said collect output");
+      }
+      if (!printedHeader) {
+	if (debug) {
+	  System.err.println("Getting output format");
+	}
+	output.println(filter.getOutputFormat().toString());
+      }
+      if (debug) {
+	System.err.println("Getting output instance");
+      }
+      while (filter.numPendingOutput() > 0) {
+	output.println(filter.output().toString());
+	if (debug){
+	  System.err.println("Getting output instance");
+	}
+      }
+    }
+    if (debug) {
+      System.err.println("Done");
+    }
+    
+    if (output != null) {
+      output.close();
+    }
+  }
+
+  /**
+   * Method for testing filters ability to process multiple batches.
+   *
+   * @param argv should contain the following arguments:<br>
+   * -i (first) input file <br>
+   * -o (first) output file <br>
+   * -r (second) input file <br>
+   * -s (second) output file <br>
+   * -c class_index <br>
+   * or -h for help on options
+   * @exception Exception if something goes wrong or the user requests help on
+   * command options
+   */
+  public static void batchFilterFile(Filter filter, String [] options) 
+    throws Exception {
+
+    Instances firstData = null;
+    Instances secondData = null;
+    Reader firstInput = null;
+    Reader secondInput = null;
+    PrintWriter firstOutput = null;
+    PrintWriter secondOutput = null;
+    boolean helpRequest;
+    try {
+      helpRequest = Utils.getFlag('h', options);
+
+      String fileName = Utils.getOption('i', options); 
+      if (fileName.length() != 0) {
+	firstInput = new BufferedReader(new FileReader(fileName));
+      } else {
+	throw new Exception("No first input file given.\n");
+      }
+
+      fileName = Utils.getOption('r', options); 
+      if (fileName.length() != 0) {
+	secondInput = new BufferedReader(new FileReader(fileName));
+      } else {
+	throw new Exception("No second input file given.\n");
+      }
+
+      fileName = Utils.getOption('o', options); 
+      if (fileName.length() != 0) {
+	firstOutput = new PrintWriter(new FileOutputStream(fileName));
+      } else {
+	firstOutput = new PrintWriter(System.out);
+      }
+      
+      fileName = Utils.getOption('s', options); 
+      if (fileName.length() != 0) {
+	secondOutput = new PrintWriter(new FileOutputStream(fileName));
+      } else {
+	secondOutput = new PrintWriter(System.out);
+      }
+      String classIndex = Utils.getOption('c', options);
+
+      if (filter instanceof OptionHandler) {
+	((OptionHandler)filter).setOptions(options);
+      }
+      Utils.checkForRemainingOptions(options);
+      
+      if (helpRequest) {
+	throw new Exception("Help requested.\n");
+      }
+      firstData = new Instances(firstInput, 1);
+      secondData = new Instances(secondInput, 1);
+      if (!secondData.equalHeaders(firstData)) {
+	throw new Exception("Input file formats differ.\n");
+      }
+      if (classIndex.length() != 0) {
+	if (classIndex.equals("first")) {
+	  firstData.setClassIndex(0);
+	  secondData.setClassIndex(0);
+	} else if (classIndex.equals("last")) {
+	  firstData.setClassIndex(firstData.numAttributes() - 1);
+	  secondData.setClassIndex(secondData.numAttributes() - 1);
+	} else {
+	  firstData.setClassIndex(Integer.parseInt(classIndex) - 1);
+	  secondData.setClassIndex(Integer.parseInt(classIndex) - 1);
+	}
+      }
+    } catch (Exception ex) {
+      String filterOptions = "";
+      // Output the error and also the valid options
+      if (filter instanceof OptionHandler) {
+	filterOptions += "\nFilter options:\n\n";
+	Enumeration enum = ((OptionHandler)filter).listOptions();
+	while (enum.hasMoreElements()) {
+	  Option option = (Option) enum.nextElement();
+	  filterOptions += option.synopsis() + '\n'
+	    + option.description() + "\n";
+	}
+      }
+
+      String genericOptions = "\nGeneral options:\n\n"
+	+ "-h\n"
+	+ "\tGet help on available options.\n"
+	+ "-i <filename>\n"
+	+ "\tThe file containing first input instances.\n"
+	+ "-o <filename>\n"
+	+ "\tThe file first output instances will be written to.\n"
+	+ "-r <filename>\n"
+	+ "\tThe file containing second input instances.\n"
+	+ "-s <filename>\n"
+	+ "\tThe file second output instances will be written to.\n"
+	+ "-c <class index>\n"
+	+ "\tThe number of the attribute to use as the class.\n"
+	+ "\t\"first\" and \"last\" are also valid entries.\n"
+	+ "\tIf not supplied then no class is assigned.\n";
+
+      throw new Exception('\n' + ex.getMessage()
+			  + filterOptions+genericOptions);
+    }
+    boolean printedHeader = false;
+    if (filter.setInputFormat(firstData)) {
+      firstOutput.println(filter.getOutputFormat().toString());
+      printedHeader = true;
+    }
+    
+    // Pass all the instances to the filter
+    while (firstData.readInstance(firstInput)) {
+      if (filter.input(firstData.instance(0))) {
+	if (!printedHeader) {
+	  throw new Error("Filter didn't return true from setInputFormat() "
+			  + "earlier!");
+	}
+	firstOutput.println(filter.output().toString());
+      }
+      firstData.delete(0);
+    }
+    
+    // Say that input has finished, and print any pending output instances
+    if (filter.batchFinished()) {
+      if (!printedHeader) {
+	firstOutput.println(filter.getOutputFormat().toString());
+      }
+      while (filter.numPendingOutput() > 0) {
+	firstOutput.println(filter.output().toString());
+      }
+    }
+    
+    if (firstOutput != null) {
+      firstOutput.close();
+    }    
+    printedHeader = false;
+    if (filter.isOutputFormatDefined()) {
+      secondOutput.println(filter.getOutputFormat().toString());
+      printedHeader = true;
+    }
+    // Pass all the second instances to the filter
+    while (secondData.readInstance(secondInput)) {
+      if (filter.input(secondData.instance(0))) {
+	if (!printedHeader) {
+	  throw new Error("Filter didn't return true from"
+			  + " isOutputFormatDefined() earlier!");
+	}
+	secondOutput.println(filter.output().toString());
+      }
+      secondData.delete(0);
+    }
+    
+    // Say that input has finished, and print any pending output instances
+    if (filter.batchFinished()) {
+      if (!printedHeader) {
+	secondOutput.println(filter.getOutputFormat().toString());
+      }
+      while (filter.numPendingOutput() > 0) {
+	secondOutput.println(filter.output().toString());
+      }
+    }
+    if (secondOutput != null) {
+      secondOutput.close();
+    }
+  }
+
+  /**
+   * Main method for testing this class.
+   *
+   * @param argv should contain arguments to the filter: use -h for help
+   */
+  public static void main(String [] args) {
+    
+    try {
+      if (args.length == 0) {
+        throw new Exception("First argument must be the class name of a Filter");
+      }
+      String fname = args[0];
+      Filter f = (Filter)Class.forName(fname).newInstance();
+      args[0] = "";
+      if (Utils.getFlag('b', args)) {
+	Filter.batchFilterFile(f, args);
+      } else {
+	Filter.filterFile(f, args);
+      }
+    } catch (Exception ex) {
+      ex.printStackTrace();
+      System.out.println(ex.getMessage());
+    }
+  }
+}
+
+
+
+
+
+
+
+
