All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.hazelcast.org.checkerframework.checker.i18nformatter.qual.I18nConversionCategory Maven / Gradle / Ivy

package com.hazelcast.org.checkerframework.checker.i18nformatter.qual;

import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import java.util.StringJoiner;
import com.hazelcast.org.checkerframework.checker.nullness.qual.Nullable;
import com.hazelcast.org.checkerframework.framework.qual.AnnotatedFor;

/**
 * Elements of this enumeration are used in a {@link I18nFormat} annotation to indicate the valid
 * types that may be passed as a format parameter. For example:
 *
 * 
{@literal @}I18nFormat({GENERAL, NUMBER}) String f = "{0}{1, number}";
 * MessageFormat.format(f, "Example", 0) // valid
* * The annotation indicates that the format string requires any object as the first parameter * ({@link I18nConversionCategory#GENERAL}) and a number as the second parameter ({@link * I18nConversionCategory#NUMBER}). * * @checker_framework.manual #i18n-formatter-checker Internationalization Format String Checker */ @AnnotatedFor("nullness") public enum I18nConversionCategory { /** * Use if a parameter is not used by the formatter. For example, in * *
   * MessageFormat.format("{1}", a, b);
   * 
* * only the second argument ("b") is used. The first argument ("a") is ignored. */ UNUSED(null /* everything */, null), /** Use if the parameter can be of any type. */ GENERAL(null /* everything */, null), /** Use if the parameter can be of date, time, or number types. */ DATE(new Class[] {Date.class, Number.class}, new String[] {"date", "time"}), /** * Use if the parameter can be of number or choice types. An example of choice: * *
{@code
   * format("{0, choice, 0#zero|1#one|1<{0, number} is more than 1}", 2)
   * }
* * This will print "2 is more than 1". */ NUMBER(new Class[] {Number.class}, new String[] {"number", "choice"}); @SuppressWarnings("ImmutableEnumChecker") // TODO: clean this up! public final Class @Nullable [] types; @SuppressWarnings("ImmutableEnumChecker") // TODO: clean this up! public final String @Nullable [] strings; I18nConversionCategory(Class @Nullable [] types, String @Nullable [] strings) { this.types = types; this.strings = strings; } /** Used by {@link #stringToI18nConversionCategory}. */ static I18nConversionCategory[] namedCategories = new I18nConversionCategory[] {DATE, NUMBER}; /** * Creates a conversion cagetogry from a string name. * *
   * I18nConversionCategory.stringToI18nConversionCategory("number") == I18nConversionCategory.NUMBER;
   * 
* * @return the I18nConversionCategory associated with the given string */ @SuppressWarnings( "nullness:iterating.over.nullable") // in namedCategories, `strings` field is non-null public static I18nConversionCategory stringToI18nConversionCategory(String string) { string = string.toLowerCase(); for (I18nConversionCategory v : namedCategories) { for (String s : v.strings) { if (s.equals(string)) { return v; } } } throw new IllegalArgumentException("Invalid format type " + string); } private static Set arrayToSet(E[] a) { return new HashSet<>(Arrays.asList(a)); } /** * Return true if a is a subset of b. * * @return true if a is a subset of b */ public static boolean isSubsetOf(I18nConversionCategory a, I18nConversionCategory b) { return intersect(a, b) == a; } /** * Returns the intersection of the two given I18nConversionCategories. * *
* *
   * I18nConversionCategory.intersect(DATE, NUMBER) == NUMBER;
   * 
* *
*/ public static I18nConversionCategory intersect( I18nConversionCategory a, I18nConversionCategory b) { if (a == UNUSED) { return b; } if (b == UNUSED) { return a; } if (a == GENERAL) { return b; } if (b == GENERAL) { return a; } @SuppressWarnings("nullness:argument" // types field is only null in UNUSED and GENERAL ) Set> as = arrayToSet(a.types); @SuppressWarnings("nullness:argument" // types field is only null in UNUSED and GENERAL ) Set> bs = arrayToSet(b.types); as.retainAll(bs); // intersection for (I18nConversionCategory v : new I18nConversionCategory[] {DATE, NUMBER}) { @SuppressWarnings("nullness:argument") // in those values, `types` field is non-null Set> vs = arrayToSet(v.types); if (vs.equals(as)) { return v; } } throw new RuntimeException(); } /** * Returns the union of the two given I18nConversionCategories. * *
   * I18nConversionCategory.intersect(DATE, NUMBER) == DATE;
   * 
*/ public static I18nConversionCategory union(I18nConversionCategory a, I18nConversionCategory b) { if (a == UNUSED || b == UNUSED) { return UNUSED; } if (a == GENERAL || b == GENERAL) { return GENERAL; } if (a == DATE || b == DATE) { return DATE; } return NUMBER; } /** * Returns true if {@code argType} can be an argument used by this format specifier. * * @param argType an argument type * @return true if {@code argType} can be an argument used by this format specifier */ public boolean isAssignableFrom(Class argType) { if (types == null) { return true; } if (argType == void.class) { return true; } for (Class c : types) { if (c.isAssignableFrom(argType)) { return true; } } return false; } /** Returns a pretty printed {@link I18nConversionCategory}. */ @Override public String toString() { StringBuilder sb = new StringBuilder(this.name()); if (this.types == null) { sb.append(" conversion category (all types)"); } else { StringJoiner sj = new StringJoiner(", ", " conversion category (one of: ", ")"); for (Class cls : this.types) { sj.add(cls.getCanonicalName()); } sb.append(sj); } return sb.toString(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy