home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / text / SimpleTextBoundary.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  10.4 KB  |  354 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)SimpleTextBoundary.java    1.23 98/07/27
  3.  *
  4.  * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved
  5.  * (C) Copyright IBM Corp. 1996 - 1998 - All Rights Reserved
  6.  *
  7.  * Portions copyright (c) 1996-1998 Sun Microsystems, Inc.
  8.  * All Rights Reserved.
  9.  *
  10.  * The original version of this source code and documentation
  11.  * is copyrighted and owned by Taligent, Inc., a wholly-owned
  12.  * subsidiary of IBM. These materials are provided under terms
  13.  * of a License Agreement between Taligent and Sun. This technology
  14.  * is protected by multiple US and International patents.
  15.  *
  16.  * This notice and attribution to Taligent may not be removed.
  17.  * Taligent is a registered trademark of Taligent, Inc.
  18.  *
  19.  * Permission to use, copy, modify, and distribute this software
  20.  * and its documentation for NON-COMMERCIAL purposes and without
  21.  * fee is hereby granted provided that this copyright notice
  22.  * appears in all copies. Please refer to the file "copyright.html"
  23.  * for further important copyright and licensing information.
  24.  *
  25.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF
  26.  * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  27.  * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
  28.  * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR
  29.  * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
  30.  * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES.
  31.  *
  32.  */
  33.  
  34. package java.text;
  35.  
  36. import java.io.IOException;
  37.  
  38. /**
  39.  * SimpleTextBoundary is an implementation of the BreakIterator
  40.  * protocol.  SimpleTextBoundary uses a state machine to compute breaks.
  41.  * There are currently several subclasses of SimpleTextBoundary that
  42.  * compute breaks for sentences, words, lines, and characters.  They are
  43.  * accessable through static functions of SimpleTextBoundary.
  44.  *
  45.  * @see BreakIterator
  46.  */
  47.  
  48. final class SimpleTextBoundary extends BreakIterator
  49. {
  50.  
  51.     private transient int pos;
  52.     private transient CharacterIterator text;
  53.     private TextBoundaryData data;
  54.  
  55.     // internally, the not-a-Unicode value is used as a sentinel value meaning
  56.     // "the end of the string" for the purposes of looking up an appropriate
  57.     // state transition when you've run off the end of the string
  58.     private static final char END_OF_STRING = '\uffff';
  59.  
  60.     /**
  61.      * Create a SimpleTextBoundary using the specified tables. Currently,
  62.      * the table format is private.
  63.      * @param data data used for boundary determination
  64.      */
  65.     protected SimpleTextBoundary(TextBoundaryData data)
  66.     {
  67.         this.data = data;
  68.         text = new StringCharacterIterator("");
  69.         pos = text.getBeginIndex();
  70.     }
  71.  
  72.     /**
  73.      * Compares the equality of two SimpleTextBoundary objects.
  74.      * @param obj the SimpleTextBoundary object to be compared with.
  75.      * @return true if the given obj is the same as this
  76.      * SimpleTextBoundary object; false otherwise.
  77.      */
  78.     public boolean equals(Object obj)
  79.     {
  80.         if (this == obj)
  81.             return true;
  82.         if (!(obj instanceof SimpleTextBoundary))
  83.             return false;
  84.  
  85.         SimpleTextBoundary that = (SimpleTextBoundary) obj;
  86.  
  87.         // The data classes are final and sharable. Only the
  88.         // class type needs to be compared.
  89.         if (this.data.getClass() != that.data.getClass())
  90.             return false;
  91.         if (this.hashCode() != that.hashCode())
  92.             return false;
  93.         if (pos != that.pos)
  94.             return false;
  95.         if (!text.equals(that.text))
  96.             return false;
  97.         return true;
  98.     }
  99.  
  100.     /**
  101.      * Compute a hashcode for this enumeration
  102.      * @return A hash code
  103.      */
  104.     public int hashCode()
  105.     {
  106.         return getClass().hashCode() ^ text.hashCode();
  107.     }
  108.  
  109.     /**
  110.      * Overrides Cloneable
  111.      */
  112.     public Object clone()
  113.     {
  114.         try {
  115.             SimpleTextBoundary other = (SimpleTextBoundary) super.clone();
  116.             other.text = (CharacterIterator) text.clone();
  117.             // The data classes are final and sharable.
  118.             // They don't need to be cloned.
  119.             return other;
  120.         } catch (InternalError e) {
  121.             throw new InternalError();
  122.         }
  123.     }
  124.  
  125.     /**
  126.      * Get the text being scanned by the enumeration
  127.      * @return the text being scanned by the enumeration
  128.      */
  129.     public CharacterIterator getText()
  130.     {
  131.         return text;
  132.     }
  133.  
  134.     /**
  135.      * Set a new text string for enumeration.  The position of the
  136.      * enumerator is reset to first().
  137.      * @param newText new text to scan.
  138.      */
  139.     public void setText(String newText)
  140.     {
  141.         text = new StringCharacterIterator(newText);
  142.         pos = text.getBeginIndex();
  143.     }
  144.  
  145.     /**
  146.      * Set a new text to scan.  The position is reset to first().
  147.      * @param newText new text to scan.
  148.      */
  149.     public void setText(CharacterIterator newText)
  150.     {
  151.         text = newText;
  152.         pos = text.getBeginIndex();
  153.     }
  154.  
  155.     /**
  156.      * Return the first boundary. The iterator's current position is set
  157.      * to the first boundary.
  158.      */
  159.     public int first()
  160.     {
  161.         pos = text.getBeginIndex();
  162.         return pos;
  163.     }
  164.  
  165.     /**
  166.      * Return the last boundary. The iterator's current position is set
  167.      * to the last boundary.
  168.      */
  169.     public int last()
  170.     {
  171.         pos = text.getEndIndex();
  172.         return pos;
  173.     }
  174.  
  175.     /**
  176.      * Return the nth boundary from the current boundary
  177.      * @param index which boundary to return.  A value of 0
  178.      * does nothing.
  179.      * @return the nth boundary from the current position.
  180.      */
  181.     public int next(int increment)
  182.     {
  183.         int result = current();
  184.         if (increment < 0) {
  185.             for (int i = increment; (i < 0) && (result != DONE); ++i) {
  186.                 result = previous();
  187.             }
  188.         }
  189.         else {
  190.             for(int i = increment; (i > 0) && (result != DONE); --i) {
  191.                 result = next();
  192.             }
  193.         }
  194.         return result;
  195.     }
  196.  
  197.     /**
  198.      * Return the boundary preceding the last boundary
  199.      */
  200.     public int previous()
  201.     {
  202.         if (pos > text.getBeginIndex()) {
  203.             int startBoundary = pos;
  204.             pos = previousSafePosition(pos-1);
  205.             int prev = pos;
  206.             int next = next();
  207.             while (next < startBoundary && next != DONE) {
  208.                 prev = next;
  209.                 next = next();
  210.             }
  211.             pos = prev;
  212.             return pos;
  213.         }
  214.         else {
  215.             return DONE;
  216.         }
  217.     }
  218.  
  219.     /**
  220.      * Return the next text boundary
  221.      * @return the character offset of the text boundary or DONE if all
  222.      * boundaries have been returned.
  223.      */
  224.     public int next()
  225.     {
  226.         int result = pos;
  227.         if (pos < text.getEndIndex()) {
  228.             pos = nextPosition(pos);
  229.             result = pos;
  230.         }
  231.         else {
  232.             result = DONE;
  233.         }
  234.         return result;
  235.     }
  236.  
  237.     /**
  238.      * Return true if the specified position is a boundary position.
  239.      * @param offset the offset to check.
  240.      * @return True if "offset" is a boundary position.
  241.      */
  242.     public boolean isBoundary(int offset) {
  243.         int begin = text.getBeginIndex();
  244.         if (offset < begin || offset >= text.getEndIndex())
  245.             throw new IllegalArgumentException(
  246.               "isBoundary offset out of bounds");
  247.  
  248.         if (offset == begin)
  249.             return true;
  250.         else
  251.             return following(offset - 1) == offset;
  252.     }
  253.  
  254.     /**
  255.      * Return the first boundary after the specified offset
  256.      * @param offset the offset to start
  257.      * @return int the first boundary after offset
  258.      */
  259.     public int following(int offset)
  260.     {
  261.         if (offset < text.getBeginIndex() || offset >= text.getEndIndex())
  262.             throw new IllegalArgumentException(
  263.               "nextBoundaryAt offset out of bounds");
  264.         pos = previousSafePosition(offset);
  265.         int result;
  266.         do {
  267.             result = next();
  268.         } while (result <= offset && result != DONE);
  269.         return result;
  270.     }
  271.  
  272.     /**
  273.      * Return the last boundary preceding the specified offset
  274.      * @param offset the offset to start
  275.      * @return the last boundary before offset
  276.      */
  277.     public int preceding(int offset)
  278.     {
  279.         if (offset < text.getBeginIndex() || offset >= text.getEndIndex())
  280.             throw new IllegalArgumentException("preceding() offset out of bounds");
  281.         if (offset == text.getBeginIndex())
  282.             return BreakIterator.DONE;
  283.         pos = previousSafePosition(offset);
  284.         int curr = pos;
  285.         int last;
  286.         do {
  287.             last = curr;
  288.             curr = next();
  289.         } while (curr < offset && curr != BreakIterator.DONE);
  290.         pos = last;
  291.         return last;
  292.     }
  293.  
  294.     /**
  295.      * Return the boundary last returned by previous or next
  296.      * @return int the boundary last returned by previous or next
  297.      */
  298.     public int current()
  299.     {
  300.         return pos;
  301.     }
  302.  
  303.     //.................................................
  304.     //utility functions.  These functions don't change the current position.
  305.     private int previousSafePosition(int offset)
  306.     {
  307.         int result = text.getBeginIndex();
  308.         int state = data.backward().initialState();
  309.  
  310.         if (offset == result)
  311.             ++offset;
  312.         for (char c = text.setIndex(offset - 1);
  313.              c != CharacterIterator.DONE && !data.backward().isEndState(state);
  314.              c = text.previous()) {
  315.  
  316.             state = data.backward().get(state, mappedChar(c));
  317.             if (data.backward().isMarkState(state)) {
  318.                 result = text.getIndex();
  319.             }
  320.         }
  321.         return result;
  322.     }
  323.  
  324.     private int nextPosition(int offset)
  325.     {
  326.         int getEndIndex = text.getEndIndex();
  327.         int state = data.forward().initialState();
  328.  
  329.         for (char c = text.setIndex(offset);
  330.              c != CharacterIterator.DONE && !data.forward().isEndState(state);
  331.              c = text.next()) {
  332.             state = data.forward().get(state, mappedChar(c));
  333.             if (data.forward().isMarkState(state)) {
  334.                 getEndIndex = text.getIndex();
  335.             }
  336.         }
  337.         if (data.forward().isEndState(state))
  338.             return getEndIndex;
  339.         else {
  340.             state = data.forward().get(state, mappedChar(END_OF_STRING));
  341.             if (data.forward().isMarkState(state))
  342.                 return text.getEndIndex();
  343.             else
  344.                 return getEndIndex;
  345.         }
  346.     }
  347.  
  348.     protected int mappedChar(char c)
  349.     {
  350.         return data.map().mappedChar(c);
  351.     }
  352.  
  353. }
  354.