]> gitweb.fperrin.net Git - Dictionary.git/blobdiff - jars/icu4j-52_1/main/classes/core/src/com/ibm/icu/text/DateIntervalInfo.java
Upgrade ICU4J.
[Dictionary.git] / jars / icu4j-52_1 / main / classes / core / src / com / ibm / icu / text / DateIntervalInfo.java
similarity index 88%
rename from jars/icu4j-4_8_1_1/main/classes/core/src/com/ibm/icu/text/DateIntervalInfo.java
rename to jars/icu4j-52_1/main/classes/core/src/com/ibm/icu/text/DateIntervalInfo.java
index f3bd62c925af349ac356d4beda937425fa02a0fb..c17d2eea9226c0a68a990589cfbb4ab8513b1fe8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 2008-2010, International Business Machines Corporation and    *
+ * Copyright (C) 2008-2013, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -10,8 +10,12 @@ package com.ibm.icu.text;
 import java.io.Serializable;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.MissingResourceException;
+import java.util.Set;
 
 import com.ibm.icu.impl.ICUCache;
 import com.ibm.icu.impl.ICUResourceBundle;
@@ -22,7 +26,6 @@ import com.ibm.icu.util.Freezable;
 import com.ibm.icu.util.ULocale;
 import com.ibm.icu.util.UResourceBundle;
 
-
 /**
  * DateIntervalInfo is a public class for encapsulating localizable
  * date time interval patterns. It is used by DateIntervalFormat.
@@ -279,6 +282,12 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
     private Map<String, Map<String, PatternInfo>> fIntervalPatterns = null;
 
     private transient boolean frozen = false;
+    
+    // If true, fIntervalPatterns should not be modified in-place because it
+    // is shared with other objects. Unlike frozen which is always true once
+    // set to true, this field can go from true to false as long as frozen is
+    // false.
+    private transient boolean fIntervalPatternsReadOnly = false;
 
 
     /**
@@ -326,26 +335,26 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
         if ( dii == null ) {
             // initialize data from scratch
             setup(locale);
-            // TODO: should put a clone in cache?
-            // or put itself in cache?
-            // DIICACHE.put(key, this);
-            dii = (DateIntervalInfo)this.clone();
-            DIICACHE.put(key, dii);
+            // Marking fIntervalPatterns read-only makes cloning cheaper.
+            fIntervalPatternsReadOnly = true;
+            // We freeze what goes in the cache without freezing this object.
+            DIICACHE.put(key, ((DateIntervalInfo) clone()).freeze());
         } else {
-            initializeData(dii);
+            initializeFromReadOnlyPatterns(dii);
         }
     }
 
  
 
-    /*
-     * Initialize DateIntervalInfo from another instance
-     * @param dii  an DateIntervalInfo instance
+    /**
+     * Initialize this object
+     * @param dii must have read-only fIntervalPatterns.
      */
-    private void initializeData(DateIntervalInfo dii) {
+    private void initializeFromReadOnlyPatterns(DateIntervalInfo dii) {
         fFallbackIntervalPattern = dii.fFallbackIntervalPattern;
         fFirstDateInPtnIsLaterDate = dii.fFirstDateInPtnIsLaterDate;
         fIntervalPatterns = dii.fIntervalPatterns;
+        fIntervalPatternsReadOnly = true;
     }
 
 
@@ -363,7 +372,7 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
         try {
             // loop through all locales to get all available skeletons'
             // interval format
-            ULocale parentLocale = locale;
+            ULocale currentLocale = locale;
             // Get the correct calendar type
             String calendarTypeToUse = locale.getKeywordValue("calendar");
             if ( calendarTypeToUse == null ) {
@@ -374,21 +383,24 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
                 calendarTypeToUse = "gregorian"; // fallback
             }
             do {
-                String name = parentLocale.getName();
+                String name = currentLocale.getName();
                 if ( name.length() == 0 ) {
                     break;
                 }
 
-                ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.
-                  getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,locale);
-                rb = rb.getWithFallback("calendar");
-                ICUResourceBundle calTypeBundle = rb.getWithFallback(
-                                                              calendarTypeToUse);
-                ICUResourceBundle itvDtPtnResource =calTypeBundle.
-                                      getWithFallback("intervalFormats");
+                ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,currentLocale);
+                // Note:
+                //      ICU4J getWithFallback does not work well when
+                //      1) A nested table is an alias to /LOCALE/...
+                //      2) getWithFallback is called multiple times for going down hierarchical resource path
+                //      #9987 resolved the issue of alias table when full path is specified in getWithFallback,
+                //      but there is no easy solution when the equivalent operation is done by multiple operations.
+                //      This issue is addressed in #9964.
+//                ICUResourceBundle calBundle = rb.getWithFallback("calendar");
+//                ICUResourceBundle calTypeBundle = calBundle.getWithFallback(calendarTypeToUse);
+                ICUResourceBundle itvDtPtnResource =rb.getWithFallback("calendar/" + calendarTypeToUse + "/intervalFormats");
                 // look for fallback first, since it establishes the default order
-                String fallback = itvDtPtnResource.getStringWithFallback(
-                                                          FALLBACK_STRING);
+                String fallback = itvDtPtnResource.getStringWithFallback(FALLBACK_STRING);
                 setFallbackIntervalPattern(fallback);
                 int size = itvDtPtnResource.getSize();
                 for ( int index = 0; index < size; ++index ) {
@@ -400,8 +412,7 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
                     if ( skeleton.compareTo(FALLBACK_STRING) == 0 ) {
                         continue;
                     }
-                    ICUResourceBundle intervalPatterns =
-                        itvDtPtnResource.getWithFallback(skeleton);
+                    ICUResourceBundle intervalPatterns = (ICUResourceBundle)itvDtPtnResource.get(skeleton);
                     int ptnNum = intervalPatterns.getSize();
                     for ( int ptnIndex = 0; ptnIndex < ptnNum; ++ptnIndex) {
                         String key = intervalPatterns.get(ptnIndex).getKey();
@@ -427,8 +438,13 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
                         }
                     }
                 }
-                parentLocale = parentLocale.getFallback();
-            } while (parentLocale != null && !parentLocale.equals(ULocale.ROOT));
+                try {
+                    UResourceBundle parentNameBundle = rb.get("%%Parent");
+                    currentLocale = new ULocale(parentNameBundle.getString());
+                } catch (MissingResourceException e) {
+                    currentLocale = currentLocale.getFallback();
+                }
+            } while (currentLocale != null && !currentLocale.getBaseName().equals("root"));
         } catch ( MissingResourceException e) {
             // ok, will fallback to {data0} - {date1}
         }
@@ -547,7 +563,10 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
         if ( lrgDiffCalUnit > MINIMUM_SUPPORTED_CALENDAR_FIELD ) {
             throw new IllegalArgumentException("calendar field is larger than MINIMUM_SUPPORTED_CALENDAR_FIELD");
         }
-
+        if (fIntervalPatternsReadOnly) {
+            fIntervalPatterns = cloneIntervalPatterns(fIntervalPatterns);
+            fIntervalPatternsReadOnly = false;
+        }
         PatternInfo ptnInfo = setIntervalPatternInternally(skeleton,
                           CALENDAR_FIELD_TO_PATTERN_LETTER[lrgDiffCalUnit], 
                           intervalPattern);
@@ -756,15 +775,12 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
             DateIntervalInfo other = (DateIntervalInfo) super.clone();
             other.fFallbackIntervalPattern=fFallbackIntervalPattern;
             other.fFirstDateInPtnIsLaterDate = fFirstDateInPtnIsLaterDate;
-            other.fIntervalPatterns = new HashMap<String, Map<String, PatternInfo>>();
-            for (String skeleton : fIntervalPatterns.keySet()) {
-                Map<String, PatternInfo> patternsOfOneSkeleton = fIntervalPatterns.get(skeleton);
-                Map<String, PatternInfo> oneSetPtn = new HashMap<String, PatternInfo>();
-                for (String calField : patternsOfOneSkeleton.keySet()) {
-                    PatternInfo value = patternsOfOneSkeleton.get(calField);
-                    oneSetPtn.put(calField, value);
-                }
-                other.fIntervalPatterns.put(skeleton, oneSetPtn);
+            if (fIntervalPatternsReadOnly) {
+                other.fIntervalPatterns = fIntervalPatterns;
+                other.fIntervalPatternsReadOnly = true;
+            } else {
+                other.fIntervalPatterns = cloneIntervalPatterns(fIntervalPatterns);
+                other.fIntervalPatternsReadOnly = false;
             }
             other.frozen = false;
             return other;
@@ -774,6 +790,24 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
             ///CLOVER:ON
         }
     }
+    
+    private static Map<String, Map<String, PatternInfo>> cloneIntervalPatterns(
+            Map<String, Map<String, PatternInfo>> patterns) {
+        Map<String, Map<String, PatternInfo>> result = new HashMap<String, Map<String, PatternInfo>>();
+        for (Entry<String, Map<String, PatternInfo>> skeletonEntry : patterns.entrySet()) {
+            String skeleton = skeletonEntry.getKey();
+            Map<String, PatternInfo> patternsOfOneSkeleton = skeletonEntry.getValue();
+            Map<String, PatternInfo> oneSetPtn = new HashMap<String, PatternInfo>();
+            for (Entry<String, PatternInfo> calEntry : patternsOfOneSkeleton.entrySet()) {
+                String calField = calEntry.getKey();
+                PatternInfo value = calEntry.getValue();
+                oneSetPtn.put(calField, value);
+            }
+            result.put(skeleton, oneSetPtn);
+        }
+        return result;
+    }
+    
 
     
     /**
@@ -790,6 +824,7 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
      */
     public DateIntervalInfo freeze() {
         frozen = true;
+        fIntervalPatternsReadOnly = true;
         return this;
     }
     
@@ -945,4 +980,16 @@ public class DateIntervalInfo implements Cloneable, Freezable<DateIntervalInfo>,
     public int hashCode() {
         return fIntervalPatterns.hashCode();
     }
+    
+    /**
+     * @internal CLDR
+     * @deprecated This API is ICU internal only.
+     */
+    public Map<String,Set<String>> getPatterns() {
+        LinkedHashMap<String,Set<String>> result = new LinkedHashMap<String,Set<String>>();
+        for (Entry<String, Map<String, PatternInfo>> entry : fIntervalPatterns.entrySet()) {
+            result.put(entry.getKey(), new LinkedHashSet<String>(entry.getValue().keySet()));
+        }
+        return result;
+    }
 }// end class DateIntervalInfo