• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.unicode.cldr.util;
2 
3 import static com.google.common.base.Preconditions.checkArgument;
4 import static com.google.common.base.Preconditions.checkNotNull;
5 import static com.google.common.collect.Comparators.lexicographical;
6 import static com.google.common.collect.ImmutableList.toImmutableList;
7 
8 import com.google.common.base.Joiner;
9 import com.google.common.base.Splitter;
10 import com.google.common.collect.ImmutableList;
11 import java.util.Collection;
12 import java.util.Comparator;
13 import java.util.Set;
14 import java.util.stream.Stream;
15 
16 public final class PreferredAndAllowedHour implements Comparable<PreferredAndAllowedHour> {
17     // DO NOT change enum item names, they are mapped directly from data values via "valueOf".
18     public enum HourStyle {
19         H,
20         Hb(H),
21         HB(H),
22         k,
23         h,
24         hb(h),
25         hB(h),
26         K;
27         public final HourStyle base;
28 
HourStyle()29         HourStyle() {
30             base = this;
31         }
32 
HourStyle(HourStyle base)33         HourStyle(HourStyle base) {
34             this.base = base;
35         }
36 
isHourCharacter(String c)37         public static boolean isHourCharacter(String c) {
38             try {
39                 HourStyle.valueOf(c);
40                 return true;
41             } catch (IllegalArgumentException e) {
42                 return false;
43             }
44         }
45     }
46 
47     // For splitting the style ID string.
48     private static final Splitter SPACE_SPLITTER = Splitter.on(' ').trimResults();
49 
50     // If this used "getter" method references it wouldn't need so much explicit generic typing.
51     private static final Comparator<PreferredAndAllowedHour> COMPARATOR =
52             Comparator.<PreferredAndAllowedHour, HourStyle>comparing(t -> t.preferred)
53                     .thenComparing(
54                             t -> t.allowed, lexicographical(Comparator.<HourStyle>naturalOrder()));
55 
56     public final HourStyle preferred;
57     /** Unique allowed styles, in the order they were specified during construction. */
58     public final ImmutableList<HourStyle> allowed;
59 
60     /**
61      * Creates a PreferredAndAllowedHour instance with "allowed" styles derived from single
62      * character IDs in the given collection. Note that the iteration order of the allowed styles is
63      * retained.
64      *
65      * <p>This constructor is limiting, since some styles are identified by two character strings,
66      * which cannot be referenced via this constructor.
67      */
PreferredAndAllowedHour(char preferred, Set<Character> allowed)68     public PreferredAndAllowedHour(char preferred, Set<Character> allowed) {
69         this(String.valueOf(preferred), allowed.stream().map(String::valueOf));
70     }
71 
72     /**
73      * Creates a PreferredAndAllowedHour instance with "allowed" styles derived from a space
74      * separated list of unique IDs. Note that the iteration order of the allowed styles is
75      * retained, since in some situations it is necessary that the preferred style should also be
76      * the first allowed style. The list of allowed style IDs must not contain duplicates.
77      */
PreferredAndAllowedHour(String preferred, String allowedString)78     public PreferredAndAllowedHour(String preferred, String allowedString) {
79         this(preferred, SPACE_SPLITTER.splitToList(allowedString).stream());
80     }
81 
PreferredAndAllowedHour(String preferredStyle, Stream<String> allowedStyles)82     private PreferredAndAllowedHour(String preferredStyle, Stream<String> allowedStyles) {
83         this.preferred = checkNotNull(HourStyle.valueOf(preferredStyle));
84         this.allowed = allowedStyles.map(HourStyle::valueOf).collect(toImmutableList());
85         checkArgument(
86                 allowed.stream().distinct().count() == allowed.size(),
87                 "Allowed (%s) must not contain duplicates",
88                 allowed);
89         // Note: In *some* cases the preferred style is required to be the first style in
90         // the allowed set, but not always (thus we cannot do a better check here).
91         // TODO: Figure out if we can enforce preferred == first(allowed) here.
92         checkArgument(
93                 allowed.contains(preferred),
94                 "Allowed (%s) must contain preferred (%s)",
95                 allowed,
96                 preferred);
97     }
98 
99     @Override
compareTo(PreferredAndAllowedHour other)100     public int compareTo(PreferredAndAllowedHour other) {
101         return COMPARATOR.compare(this, other);
102     }
103 
104     @Override
toString()105     public String toString() {
106         return toString(ImmutableList.of("?"));
107     }
108 
toString(Collection<String> regions)109     public String toString(Collection<String> regions) {
110         Joiner withSpaces = Joiner.on(" ");
111         return "<hours preferred=\""
112                 + preferred
113                 + "\" allowed=\""
114                 + withSpaces.join(allowed)
115                 + "\" regions=\""
116                 + withSpaces.join(regions)
117                 + "\"/>";
118     }
119 
120     @Override
equals(Object obj)121     public boolean equals(Object obj) {
122         return obj instanceof PreferredAndAllowedHour
123                 && compareTo((PreferredAndAllowedHour) obj) == 0;
124     }
125 }
126