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

com.squarespace.cldrengine.calendars.CalendarPatterns Maven / Gradle / Ivy

The newest version!
package com.squarespace.cldrengine.calendars;

import static com.squarespace.cldrengine.utils.StringUtils.isEmpty;
import static com.squarespace.cldrengine.utils.StringUtils.parseArray;

import java.util.HashMap;
import java.util.Map;

import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.squarespace.cldrengine.api.Bundle;
import com.squarespace.cldrengine.api.CalendarDate;
import com.squarespace.cldrengine.api.FormatWidthType;
import com.squarespace.cldrengine.api.PluralType;
import com.squarespace.cldrengine.internal.CalendarExternalData;
import com.squarespace.cldrengine.internal.CalendarSchema;
import com.squarespace.cldrengine.internal.DateTimePatternFieldType;
import com.squarespace.cldrengine.internal.Internals;
import com.squarespace.cldrengine.parsing.DateTimePattern;
import com.squarespace.cldrengine.utils.JsonUtils;
import com.squarespace.cldrengine.utils.LRU;
import com.squarespace.cldrengine.utils.StringUtils;

import lombok.AllArgsConstructor;

/**
 * Manages patterns for a given calendar.
 */
class CalendarPatterns {

  @AllArgsConstructor
  public static class TimeData {
    String _1;
    String _2;

    @Override
    public String toString() {
      return "TimeData(" + _1 + ", " + _2 + ")";
    }
  }

  private static final Map> TIMEDATA = new HashMap<>();

  static {
    String[] timeStrings = JsonUtils.decodeArray(JsonParser.parseString(CalendarExternalData.TIMESTRINGS));

    JsonObject root = JsonParser.parseString(CalendarExternalData.TIMEDATA).getAsJsonObject();
    for (String lang : root.keySet()) {
      Map map = new HashMap<>();
      TIMEDATA.put(lang, map);

      JsonObject regions = root.getAsJsonObject(lang);
      for (String region : regions.keySet()) {
        int index = regions.get(region).getAsInt();
        String str = timeStrings[index];
        String[] parts = str.split("\\|");
        TimeData data = new TimeData(parts[0], parts[1]);
        map.put(region, data);
      }
    }
  }

  private final String language;
  private final String region;

  private final DateSkeletonParser skeletonParser;
//  private final LRU skeletonRequestCache = new LRU<>(512);
  private final LRU intervalRequestCache = new LRU<>(512);
  private final Map dateFormats;
  private final Map timeFormats;
  private final Map wrapperFormats;
  private final Map wrapperFormatsAt;

  private final DatePatternMatcher availableMatcher = new DatePatternMatcher();
  private final Map intervalMatcher = new HashMap<>();
  private final Map> rawIntervalFormats;
  private final String intervalFallback;

  protected final Bundle bundle;
  protected final Internals internals;
  protected final Map rawAvailableFormats;
  protected final Map> rawPluralFormats;

  public CalendarPatterns(Bundle bundle, Internals internals, CalendarSchema schema) {
    this.bundle = bundle;
    this.language = bundle.language();
    this.region = bundle.region();
    this.internals = internals;

    this.dateFormats = schema.dateFormats.mapping(bundle);
    this.timeFormats = schema.timeFormats.mapping(bundle);
    this.wrapperFormats = schema.dateTimeFormats.mapping(bundle);
    this.wrapperFormatsAt = schema.dateTimeFormatsAt.mapping(bundle);
    this.skeletonParser = buildSkeletonParser();

    this.rawAvailableFormats = schema.availableFormats.mapping(bundle);
    this.rawPluralFormats = schema.pluralFormats.mapping(bundle);
    this.rawIntervalFormats = schema.intervalFormats.mapping(bundle);
    this.buildAvailableMatcher();
    this.buildIntervalMatcher();

    this.intervalFallback = schema.intervalFormatFallback.get(bundle);
  }

  public DateSkeleton parseSkeleton(String raw) {
    return this.skeletonParser.parse(raw, false);
  }

  public DateTimePattern getDatePattern(FormatWidthType width) {
    String pattern = this.dateFormats.getOrDefault(width, "");
    return DateTimePattern.parse(pattern);
  }

  public DateTimePattern getTimePattern(FormatWidthType width) {
    String pattern = this.timeFormats.getOrDefault(width, "");
    return DateTimePattern.parse(pattern);
  }

//  public CachedSkeletonRequest getCachedSkeletonRequest(String key) {
//    return this.skeletonRequestCache.get(key);
//  }
//
//  public void setCachedSkeletonRequest(String key, CachedSkeletonRequest req) {
//    this.skeletonRequestCache.set(key, req);
//  }

  public CachedIntervalRequest getCachedIntervalRequest(String key) {
    return this.intervalRequestCache.get(key);
  }

  public void setCachedIntervalRequest(String key, CachedIntervalRequest req) {
    this.intervalRequestCache.set(key, req);
  }

  public String getWrapperPattern(FormatWidthType width, boolean atTime) {
    String w = this.wrapperFormatsAt.getOrDefault(width, "");
    return atTime ? w : this.wrapperFormats.getOrDefault(width, "");
  }

  public DateTimePattern getAvailablePattern(CalendarDate d, DateSkeleton s) {
    String pattern = s.pattern;
    if (pattern == null) {
      pattern = this.rawAvailableFormats.get(s.skeleton);
      if (pattern == null) {
        Map formats = this.rawPluralFormats.get(PluralType.OTHER);
        pattern = formats.get(s.skeleton);
      }
    }
    return DateTimePattern.parse(pattern == null ? "" : pattern);
  }

  public DateTimePattern getIntervalPatern(DateTimePatternFieldType field, String skeleton) {
    Map group = this.rawIntervalFormats.get(field);
    String raw = group == null ? "" : group.get(skeleton);
    return this.internals.calendars.parseDatePattern(raw == null ? "" : raw);
  }

  public String getIntervalFallback() {
    return this.intervalFallback;
  }

  public DateTimePattern adjustPattern(DateTimePattern pattern, DateSkeleton skeleton, String decimal) {
    return this.availableMatcher.adjust(pattern, skeleton, decimal);
  }

  public DateSkeleton matchAvailable(DateSkeleton skeleton) {
    return this.availableMatcher.match(skeleton);
  }

  public DateSkeleton matchInterval(DateSkeleton skeleton, DateTimePatternFieldType field) {
    if (field == DateTimePatternFieldType.SECOND) {
      field = DateTimePatternFieldType.MINUTE;
    }
    return this.intervalMatcher.get(field).match(skeleton);
  }

  protected TimeData getTimeData() {
    Map root = TIMEDATA.get("");
    TimeData world = root.get("001");
    TimeData timedata = root.get(this.region);
    if (timedata == null) {
      Map lang = TIMEDATA.get(this.language);
      if (lang != null) {
        timedata = lang.get(this.region);
      }
    }
    return timedata == null ? world : timedata;
  }

  protected DateSkeletonParser buildSkeletonParser() {
    TimeData pair = this.getTimeData();
    DateTimePattern[] allowedFlex = parseArray(pair._1, DateTimePattern.class, DateTimePattern::parse);
    DateTimePattern preferredFlex = DateTimePattern.parse(pair._2);
    return new DateSkeletonParser(preferredFlex.nodes, allowedFlex[0].nodes);
  }

  protected void buildAvailableMatcher() {
    for (FormatWidthType key : this.dateFormats.keySet()) {
      this.availableMatcher.add(this.skeletonParser.parse(this.dateFormats.get(key), true), null);
      this.availableMatcher.add(this.skeletonParser.parse(this.timeFormats.get(key), true), null);
    }

    // For the pluralized formats use the 'other' category which will
    // be populated for every locale.
    this.buildAvailableMatcherFormats(this.rawAvailableFormats);
    this.buildAvailableMatcherFormats(this.rawPluralFormats.get(PluralType.OTHER));
  }

  protected void buildAvailableMatcherFormats(Map formats) {
    if (formats != null) {
      for (String skeleton : formats.keySet()) {
        // Only add skeletons which point to valid formats for this locale.
        // Not all skeletons are implemented for all locales.
        String value = formats.get(skeleton);
        if (!StringUtils.isEmpty(value)) {
          this.availableMatcher.add(this.skeletonParser.parse(skeleton, false), null);
        }
      }
    }
  }

  protected void buildIntervalMatcher() {
    for (DateTimePatternFieldType field : this.rawIntervalFormats.keySet()) {
      Map group = this.rawIntervalFormats.get(field);
      DatePatternMatcher matcher = new DatePatternMatcher();
      for (String skeleton : group.keySet()) {
        // Only add skeletons which point to valid formats for this locale. Not all
        // skeletons are implemented for all locales.
        String raw = group.get(skeleton);
        if (!isEmpty(raw)) {
          DateSkeleton parsed = this.skeletonParser.parse(skeleton, false);
          matcher.add(parsed, null);
        }
      }
      this.intervalMatcher.put(field, matcher);
    }
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy