]> granicus.if.org Git - icu/commitdiff
ICU-10606 Introduce DontCareFieldPosition.
authorTravis Keep <keep94@gmail.com>
Wed, 18 Dec 2013 23:05:12 +0000 (23:05 +0000)
committerTravis Keep <keep94@gmail.com>
Wed, 18 Dec 2013 23:05:12 +0000 (23:05 +0000)
X-SVN-Rev: 34799

.gitattributes
icu4j/main/classes/core/src/com/ibm/icu/impl/DontCareFieldPosition.java [new file with mode: 0644]
icu4j/main/classes/core/src/com/ibm/icu/text/MeasureFormat.java
icu4j/main/classes/core/src/com/ibm/icu/text/TimeUnitFormat.java
icu4j/main/tests/core/src/com/ibm/icu/dev/test/format/MeasureUnitTest.java

index 7f14ac6854291ddf90bdaa12fb1bcad70aae256b..7d7b04f6c10ee1aba3a08c35468b4fb4e89dac56 100644 (file)
@@ -272,6 +272,7 @@ icu4j/main/classes/core/.settings/edu.umd.cs.findbugs.core.prefs -text
 icu4j/main/classes/core/.settings/org.eclipse.core.resources.prefs -text
 icu4j/main/classes/core/.settings/org.eclipse.jdt.core.prefs -text
 icu4j/main/classes/core/manifest.stub -text
+icu4j/main/classes/core/src/com/ibm/icu/impl/DontCareFieldPosition.java -text
 icu4j/main/classes/core/src/com/ibm/icu/text/QuantityFormatter.java -text
 icu4j/main/classes/core/src/com/ibm/icu/text/RelativeDateTimeFormatter.java -text
 icu4j/main/classes/currdata/.externalToolBuilders/copy-data-currdata.launch -text
diff --git a/icu4j/main/classes/core/src/com/ibm/icu/impl/DontCareFieldPosition.java b/icu4j/main/classes/core/src/com/ibm/icu/impl/DontCareFieldPosition.java
new file mode 100644 (file)
index 0000000..cf65de5
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+**********************************************************************
+* Copyright (c) 2004-2013, International Business Machines
+* Corporation and others.  All Rights Reserved.
+**********************************************************************
+*/
+package com.ibm.icu.impl;
+
+import java.text.FieldPosition;
+
+/**
+ * DontCareFieldPosition is a subclass of FieldPosition that indicates that the
+ * caller is not interested in the start and end position of any field.
+ * <p>
+ * DontCareFieldPosition is a singleton, and its instance is immutable.
+ * <p>
+ * A <code>format</code> method use <code>fpos == DontCareFieldPosition.INSTANCE</code>
+ * to tell whether or not it needs to calculate a field position.
+ *
+ */
+public final class DontCareFieldPosition extends FieldPosition {
+    
+    public static final DontCareFieldPosition INSTANCE = new DontCareFieldPosition(); 
+    
+    private DontCareFieldPosition() {
+        // Pick some random number to be sure that we don't accidentally match with
+        // a field.
+        super(-913028704);
+    }
+    
+    @Override
+    public void setBeginIndex(int i) {
+        // Do nothing
+    }
+    
+    @Override
+    public void setEndIndex(int i) {
+        // Do nothing
+    }
+
+}
index d1ea18545d1978ff97b7d751069bc1c5717141bd..7511f0fb4734cec61f6b94031ac6f02153a2a8e0 100644 (file)
@@ -28,6 +28,7 @@ import java.util.Map.Entry;
 import java.util.MissingResourceException;
 import java.util.Set;
 
+import com.ibm.icu.impl.DontCareFieldPosition;
 import com.ibm.icu.impl.ICUResourceBundle;
 import com.ibm.icu.impl.SimpleCache;
 import com.ibm.icu.util.Currency;
@@ -239,6 +240,10 @@ public class MeasureFormat extends UFormat {
      * then its indices are set to the beginning and end of the first such field
      * encountered. MeasureFormat itself does not supply any fields.
      * 
+     * Calling a
+     * <code>formatMeasures</code> method is preferred over calling
+     * this method as they give better performance.
+     * 
      * @param obj must be a Collection<? extends Measure>, Measure[], or Measure object.
      * @param toAppendTo Formatted string appended here.
      * @pram pos Identifies a field in the formatted text.
@@ -296,7 +301,7 @@ public class MeasureFormat extends UFormat {
      */
     public String formatMeasures(Measure... measures) {
         StringBuilder result = this.formatMeasures(
-                new StringBuilder(), new FieldPosition(0), measures);
+                new StringBuilder(), DontCareFieldPosition.INSTANCE, measures);
         return result.toString();
     }
     
@@ -335,48 +340,29 @@ public class MeasureFormat extends UFormat {
             }
         }
         
-        // Zero out our field position so that we can tell when we find our field.
-        FieldPosition fpos = new FieldPosition(fieldPosition.getFieldAttribute(), fieldPosition.getField());
-        FieldPosition dummyPos = new FieldPosition(0);
-        
-        int fieldPositionFoundIndex = -1;
-        StringBuilder[] results = new StringBuilder[measures.length];
-        for (int i = 0; i < measures.length; ++i) {
-            if (fieldPositionFoundIndex == -1) {
-                results[i] = formatMeasure(measures[i], new StringBuilder(), fpos);
-                if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
-                    fieldPositionFoundIndex = i;    
-                }
-            } else {
-                results[i] = formatMeasure(measures[i], new StringBuilder(), dummyPos);
-            }
-        }
         ListFormatter listFormatter = ListFormatter.getInstance(getLocale(), 
                 length == FormatWidth.WIDE ? ListFormatter.Style.DURATION : ListFormatter.Style.DURATION_SHORT);
-        
-        // Fix up FieldPosition indexes if our field is found.
-        if (fieldPositionFoundIndex != -1) {
-            String listPattern = listFormatter.getPatternForNumItems(measures.length);
-            int positionInPattern = listPattern.indexOf("{" + fieldPositionFoundIndex + "}");
-            if (positionInPattern == -1) {
-                throw new IllegalStateException("Can't find position with ListFormatter.");
-            }
-            // Now we have to adjust our position in pattern
-            // based on the previous values.
-            for (int i = 0; i < fieldPositionFoundIndex; i++) {
-                positionInPattern += (results[i].length() - ("{" + i + "}").length());
+        String[] results = null;
+        if (fieldPosition == DontCareFieldPosition.INSTANCE) {
+            
+            // Fast track: No field position.
+            results = new String[measures.length];
+            for (int i = 0; i < measures.length; i++) {
+                results[i] = formatMeasure(measures[i]);
             }
-            fieldPosition.setBeginIndex(fpos.getBeginIndex() + positionInPattern);
-            fieldPosition.setEndIndex(fpos.getEndIndex() + positionInPattern);
-        }
+        } else {
             
+            // Slow track: Have to calculate field position.
+            results = formatMeasuresSlowTrack(listFormatter, fieldPosition, measures);            
+        }
+                 
         // This is safe because appendable is of type T.
         try {
             return (T) appendable.append(listFormatter.format((Object[]) results));
         } catch (IOException e) {
             throw new RuntimeException(e);
         }
-    }
+    }   
     
     /**
      * Two MeasureFormats, a and b, are equal if and only if they have the same width,
@@ -612,6 +598,12 @@ public class MeasureFormat extends UFormat {
         return unitToStyleToCountToFormat;
     }
     
+    private String formatMeasure(Measure measure) {
+        return formatMeasure(
+                measure, new StringBuilder(),
+                DontCareFieldPosition.INSTANCE).toString();
+    }
+    
     private <T extends Appendable> T formatMeasure(
             Measure measure, T appendable, FieldPosition fieldPosition) {
         Number n = measure.getNumber();
@@ -689,6 +681,43 @@ public class MeasureFormat extends UFormat {
         return new MeasureProxy(getLocale(), length, numberFormat.get(), CURRENCY_FORMAT);
     }
     
+    private String[] formatMeasuresSlowTrack(ListFormatter listFormatter, FieldPosition fieldPosition,
+            Measure... measures) {
+        String[] results = new String[measures.length];
+        
+        // Zero out our field position so that we can tell when we find our field.
+        FieldPosition fpos = new FieldPosition(fieldPosition.getFieldAttribute(), fieldPosition.getField());
+        
+        int fieldPositionFoundIndex = -1;
+        for (int i = 0; i < measures.length; ++i) {
+            if (fieldPositionFoundIndex == -1) {
+                results[i] = formatMeasure(measures[i], new StringBuilder(), fpos).toString();
+                if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
+                    fieldPositionFoundIndex = i;    
+                }
+            } else {
+                results[i] = formatMeasure(measures[i]);
+            }
+        }
+        
+        // Fix up FieldPosition indexes if our field is found.
+        if (fieldPositionFoundIndex != -1) {
+            String listPattern = listFormatter.getPatternForNumItems(measures.length);
+            int positionInPattern = listPattern.indexOf("{" + fieldPositionFoundIndex + "}");
+            if (positionInPattern == -1) {
+                throw new IllegalStateException("Can't find position with ListFormatter.");
+            }
+            // Now we have to adjust our position in pattern
+            // based on the previous values.
+            for (int i = 0; i < fieldPositionFoundIndex; i++) {
+                positionInPattern += (results[i].length() - ("{" + i + "}").length());
+            }
+            fieldPosition.setBeginIndex(fpos.getBeginIndex() + positionInPattern);
+            fieldPosition.setEndIndex(fpos.getEndIndex() + positionInPattern);
+        }
+        return results;
+    }
+    
     // type is one of "hm", "ms" or "hms"
     private static DateFormat loadNumericDurationFormat(
             ICUResourceBundle r, String type) {
index 9fd647175db0176e95510b71fc3ea7255edf19e6..ad58a0bf8f4356819f7070756ffe49b1274cc9dd 100644 (file)
@@ -515,7 +515,7 @@ if ( searchPluralCount.equals("other") ) {
     
     // boilerplate code to make TimeUnitFormat otherwise follow the contract of
     // MeasureFormat
-    
+
     /**
      * @draft ICU 53
      * @provisional
index 2d85fa0940c44794f3c88093109d206735a1c987..4e0be3b366f70e6ba0103ab835a479b47a1014a2 100644 (file)
@@ -163,6 +163,11 @@ public class MeasureUnitTest extends TestFmwk {
             assertSame("Identity check", expected, actual);
         }
     }
+    
+    public void testFormatMeasureSingleArg() {
+        MeasureFormat mf = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE);
+        assertEquals("", "5 meters", mf.format(new Measure(5, MeasureUnit.METER)));
+    }
 
     public void testMultiples() {
         ULocale russia = new ULocale("ru");