1 /*
   2  * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 /*
  27  * (C) Copyright Taligent, Inc. 1996 - All Rights Reserved
  28  * (C) Copyright IBM Corp. 1996 - All Rights Reserved
  29  *
  30  *   The original version of this source code and documentation is copyrighted
  31  * and owned by Taligent, Inc., a wholly-owned subsidiary of IBM. These
  32  * materials are provided under terms of a License Agreement between Taligent
  33  * and Sun. This technology is protected by multiple US and International
  34  * patents. This notice and attribution to Taligent may not be removed.
  35  *   Taligent is a registered trademark of Taligent, Inc.
  36  *
  37  */
  38 
  39 package java.text;
  40 
  41 /**
  42  * <code>FieldPosition</code> is a simple class used by <code>Format</code>
  43  * and its subclasses to identify fields in formatted output. Fields can
  44  * be identified in two ways:
  45  * <ul>
  46  *  <li>By an integer constant, whose names typically end with
  47  *      <code>_FIELD</code>. The constants are defined in the various
  48  *      subclasses of <code>Format</code>.
  49  *  <li>By a <code>Format.Field</code> constant, see <code>ERA_FIELD</code>
  50  *      and its friends in <code>DateFormat</code> for an example.
  51  * </ul>
  52  * <p>
  53  * <code>FieldPosition</code> keeps track of the position of the
  54  * field within the formatted output with two indices: the index
  55  * of the first character of the field and the index of the last
  56  * character of the field.
  57  *
  58  * <p>
  59  * One version of the <code>format</code> method in the various
  60  * <code>Format</code> classes requires a <code>FieldPosition</code>
  61  * object as an argument. You use this <code>format</code> method
  62  * to perform partial formatting or to get information about the
  63  * formatted output (such as the position of a field).
  64  *
  65  * <p>
  66  * If you are interested in the positions of all attributes in the
  67  * formatted string use the <code>Format</code> method
  68  * <code>formatToCharacterIterator</code>.
  69  *
  70  * @author      Mark Davis
  71  * @since 1.1
  72  * @see         java.text.Format
  73  */
  74 public class FieldPosition {
  75 
  76     /**
  77      * Input: Desired field to determine start and end offsets for.
  78      * The meaning depends on the subclass of Format.
  79      */
  80     int field = 0;
  81 
  82     /**
  83      * Output: End offset of field in text.
  84      * If the field does not occur in the text, 0 is returned.
  85      */
  86     int endIndex = 0;
  87 
  88     /**
  89      * Output: Start offset of field in text.
  90      * If the field does not occur in the text, 0 is returned.
  91      */
  92     int beginIndex = 0;
  93 
  94     /**
  95      * Desired field this FieldPosition is for.
  96      */
  97     private Format.Field attribute;
  98 
  99     /**
 100      * Creates a FieldPosition object for the given field.  Fields are
 101      * identified by constants, whose names typically end with _FIELD,
 102      * in the various subclasses of Format.
 103      *
 104      * @param field the field identifier
 105      * @see java.text.NumberFormat#INTEGER_FIELD
 106      * @see java.text.NumberFormat#FRACTION_FIELD
 107      * @see java.text.DateFormat#YEAR_FIELD
 108      * @see java.text.DateFormat#MONTH_FIELD
 109      */
 110     public FieldPosition(int field) {
 111         this.field = field;
 112     }
 113 
 114     /**
 115      * Creates a FieldPosition object for the given field constant. Fields are
 116      * identified by constants defined in the various <code>Format</code>
 117      * subclasses. This is equivalent to calling
 118      * <code>new FieldPosition(attribute, -1)</code>.
 119      *
 120      * @param attribute Format.Field constant identifying a field
 121      * @since 1.4
 122      */
 123     public FieldPosition(Format.Field attribute) {
 124         this(attribute, -1);
 125     }
 126 
 127     /**
 128      * Creates a <code>FieldPosition</code> object for the given field.
 129      * The field is identified by an attribute constant from one of the
 130      * <code>Field</code> subclasses as well as an integer field ID
 131      * defined by the <code>Format</code> subclasses. <code>Format</code>
 132      * subclasses that are aware of <code>Field</code> should give precedence
 133      * to <code>attribute</code> and ignore <code>fieldID</code> if
 134      * <code>attribute</code> is not null. However, older <code>Format</code>
 135      * subclasses may not be aware of <code>Field</code> and rely on
 136      * <code>fieldID</code>. If the field has no corresponding integer
 137      * constant, <code>fieldID</code> should be -1.
 138      *
 139      * @param attribute Format.Field constant identifying a field
 140      * @param fieldID integer constant identifying a field
 141      * @since 1.4
 142      */
 143     public FieldPosition(Format.Field attribute, int fieldID) {
 144         this.attribute = attribute;
 145         this.field = fieldID;
 146     }
 147 
 148     /**
 149      * Returns the field identifier as an attribute constant
 150      * from one of the <code>Field</code> subclasses. May return null if
 151      * the field is specified only by an integer field ID.
 152      *
 153      * @return Identifier for the field
 154      * @since 1.4
 155      */
 156     public Format.Field getFieldAttribute() {
 157         return attribute;
 158     }
 159 
 160     /**
 161      * Retrieves the field identifier.
 162      *
 163      * @return the field identifier
 164      */
 165     public int getField() {
 166         return field;
 167     }
 168 
 169     /**
 170      * Retrieves the index of the first character in the requested field.
 171      *
 172      * @return the begin index
 173      */
 174     public int getBeginIndex() {
 175         return beginIndex;
 176     }
 177 
 178     /**
 179      * Retrieves the index of the character following the last character in the
 180      * requested field.
 181      *
 182      * @return the end index
 183      */
 184     public int getEndIndex() {
 185         return endIndex;
 186     }
 187 
 188     /**
 189      * Sets the begin index.  For use by subclasses of Format.
 190      *
 191      * @param bi the begin index
 192      * @since 1.2
 193      */
 194     public void setBeginIndex(int bi) {
 195         beginIndex = bi;
 196     }
 197 
 198     /**
 199      * Sets the end index.  For use by subclasses of Format.
 200      *
 201      * @param ei the end index
 202      * @since 1.2
 203      */
 204     public void setEndIndex(int ei) {
 205         endIndex = ei;
 206     }
 207 
 208     /**
 209      * Returns a <code>Format.FieldDelegate</code> instance that is associated
 210      * with the FieldPosition. When the delegate is notified of the same
 211      * field the FieldPosition is associated with, the begin/end will be
 212      * adjusted.
 213      */
 214     Format.FieldDelegate getFieldDelegate() {
 215         return new Delegate();
 216     }
 217 
 218     /**
 219      * Overrides equals
 220      */
 221     public boolean equals(Object obj)
 222     {
 223         if (obj == null) return false;
 224         if (!(obj instanceof FieldPosition))
 225             return false;
 226         FieldPosition other = (FieldPosition) obj;
 227         if (attribute == null) {
 228             if (other.attribute != null) {
 229                 return false;
 230             }
 231         }
 232         else if (!attribute.equals(other.attribute)) {
 233             return false;
 234         }
 235         return (beginIndex == other.beginIndex
 236             && endIndex == other.endIndex
 237             && field == other.field);
 238     }
 239 
 240     /**
 241      * Returns a hash code for this FieldPosition.
 242      * @return a hash code value for this object
 243      */
 244     public int hashCode() {
 245         return (field << 24) | (beginIndex << 16) | endIndex;
 246     }
 247 
 248     /**
 249      * Return a string representation of this FieldPosition.
 250      * @return  a string representation of this object
 251      */
 252     public String toString() {
 253         return getClass().getName() +
 254             "[field=" + field + ",attribute=" + attribute +
 255             ",beginIndex=" + beginIndex +
 256             ",endIndex=" + endIndex + ']';
 257     }
 258 
 259 
 260     /**
 261      * Return true if the receiver wants a <code>Format.Field</code> value and
 262      * <code>attribute</code> is equal to it.
 263      */
 264     private boolean matchesField(Format.Field attribute) {
 265         if (this.attribute != null) {
 266             return this.attribute.equals(attribute);
 267         }
 268         return false;
 269     }
 270 
 271     /**
 272      * Return true if the receiver wants a <code>Format.Field</code> value and
 273      * <code>attribute</code> is equal to it, or true if the receiver
 274      * represents an inteter constant and <code>field</code> equals it.
 275      */
 276     private boolean matchesField(Format.Field attribute, int field) {
 277         if (this.attribute != null) {
 278             return this.attribute.equals(attribute);
 279         }
 280         return (field == this.field);
 281     }
 282 
 283 
 284     /**
 285      * An implementation of FieldDelegate that will adjust the begin/end
 286      * of the FieldPosition if the arguments match the field of
 287      * the FieldPosition.
 288      */
 289     private class Delegate implements Format.FieldDelegate {
 290         /**
 291          * Indicates whether the field has been  encountered before. If this
 292          * is true, and <code>formatted</code> is invoked, the begin/end
 293          * are not updated.
 294          */
 295         private boolean encounteredField;
 296 
 297         public void formatted(Format.Field attr, Object value, int start,
 298                               int end, StringBuffer buffer) {
 299             if (!encounteredField && matchesField(attr)) {
 300                 setBeginIndex(start);
 301                 setEndIndex(end);
 302                 encounteredField = (start != end);
 303             }
 304         }
 305 
 306         public void formatted(int fieldID, Format.Field attr, Object value,
 307                               int start, int end, StringBuffer buffer) {
 308             if (!encounteredField && matchesField(attr, fieldID)) {
 309                 setBeginIndex(start);
 310                 setEndIndex(end);
 311                 encounteredField = (start != end);
 312             }
 313         }
 314     }
 315 }