001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.databind.io;
007
008import java.util.Arrays;
009import java.util.HashSet;
010import java.util.List;
011import java.util.Locale;
012import java.util.Set;
013import java.util.stream.Collectors;
014
015import dev.metaschema.core.metapath.format.IPathFormatter;
016import dev.metaschema.core.metapath.format.PathFormatSelection;
017import dev.metaschema.core.util.CollectionUtil;
018import edu.umd.cs.findbugs.annotations.NonNull;
019import edu.umd.cs.findbugs.annotations.Nullable;
020import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
021
022/**
023 * Selections of serialization formats.
024 */
025public enum Format {
026  /**
027   * The <a href="https://www.w3.org/XML/">Extensible Markup Language</a> format.
028   */
029  XML(".xml", Set.of()),
030  /**
031   * The <a href="https://www.json.org/">JavaScript Object Notation</a> format.
032   */
033  JSON(".json", Set.of()),
034  /**
035   * The <a href="https://yaml.org/">YAML Ain't Markup Language</a> format.
036   */
037  YAML(".yaml", Set.of(".yml"));
038
039  private static final List<String> NAMES;
040
041  @NonNull
042  private final String defaultExtension;
043  @NonNull
044  private final Set<String> recognizedExtensions;
045
046  static {
047    NAMES = Arrays.stream(values())
048        .map(format -> format.name().toLowerCase(Locale.ROOT))
049        .collect(Collectors.toUnmodifiableList());
050  }
051
052  /**
053   * Get a list of all format names in lowercase.
054   *
055   * @return the list of names
056   */
057  @SuppressFBWarnings(value = "MS_EXPOSE_REP", justification = "Exposes names provided by the enum")
058  public static List<String> names() {
059    return NAMES;
060  }
061
062  Format(@NonNull String defaultExtension, Set<String> otherExtensions) {
063    this.defaultExtension = defaultExtension;
064
065    Set<String> recognizedExtensions = new HashSet<>();
066    recognizedExtensions.add(defaultExtension);
067    recognizedExtensions.addAll(otherExtensions);
068
069    this.recognizedExtensions = CollectionUtil.unmodifiableSet(recognizedExtensions);
070  }
071
072  /**
073   * Get the default extension to use for the format.
074   *
075   * @return the default extension
076   */
077  @NonNull
078  public Set<String> getRecognizedExtensions() {
079    return recognizedExtensions;
080  }
081
082  /**
083   * Get the default extension to use for the format.
084   *
085   * @return the default extension
086   */
087  @NonNull
088  public String getDefaultExtension() {
089    return defaultExtension;
090  }
091
092  /**
093   * Get the appropriate path formatter for this format.
094   * <p>
095   * Returns:
096   * <ul>
097   * <li>{@link IPathFormatter#XPATH_PATH_FORMATTER} for XML</li>
098   * <li>{@link IPathFormatter#JSON_POINTER_PATH_FORMATTER} for JSON and YAML</li>
099   * </ul>
100   *
101   * @return the path formatter appropriate for this format
102   */
103  @NonNull
104  public IPathFormatter getPathFormatter() {
105    return this == XML
106        ? IPathFormatter.XPATH_PATH_FORMATTER
107        : IPathFormatter.JSON_POINTER_PATH_FORMATTER;
108  }
109
110  /**
111   * Resolve the path formatter based on the selection and document format.
112   * <p>
113   * When {@link PathFormatSelection#AUTO} is specified, the formatter is
114   * determined by the document format. For explicit selections, the corresponding
115   * formatter is returned regardless of document format.
116   *
117   * @param selection
118   *          the path format selection
119   * @param format
120   *          the document format, used when selection is AUTO; may be null
121   * @return the resolved path formatter
122   */
123  @NonNull
124  public static IPathFormatter resolvePathFormatter(
125      @NonNull PathFormatSelection selection,
126      @Nullable Format format) {
127    switch (selection) {
128    case AUTO:
129      return format != null ? format.getPathFormatter() : IPathFormatter.METAPATH_PATH_FORMATER;
130    case METAPATH:
131      return IPathFormatter.METAPATH_PATH_FORMATER;
132    case XPATH:
133      return IPathFormatter.XPATH_PATH_FORMATTER;
134    case JSON_POINTER:
135      return IPathFormatter.JSON_POINTER_PATH_FORMATTER;
136    default:
137      return IPathFormatter.METAPATH_PATH_FORMATER;
138    }
139  }
140}