1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.databind.io;
7   
8   import java.util.Arrays;
9   import java.util.HashSet;
10  import java.util.List;
11  import java.util.Locale;
12  import java.util.Set;
13  import java.util.stream.Collectors;
14  
15  import dev.metaschema.core.metapath.format.IPathFormatter;
16  import dev.metaschema.core.metapath.format.PathFormatSelection;
17  import dev.metaschema.core.util.CollectionUtil;
18  import edu.umd.cs.findbugs.annotations.NonNull;
19  import edu.umd.cs.findbugs.annotations.Nullable;
20  import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
21  
22  /**
23   * Selections of serialization formats.
24   */
25  public enum Format {
26    /**
27     * The <a href="https://www.w3.org/XML/">Extensible Markup Language</a> format.
28     */
29    XML(".xml", Set.of()),
30    /**
31     * The <a href="https://www.json.org/">JavaScript Object Notation</a> format.
32     */
33    JSON(".json", Set.of()),
34    /**
35     * The <a href="https://yaml.org/">YAML Ain't Markup Language</a> format.
36     */
37    YAML(".yaml", Set.of(".yml"));
38  
39    private static final List<String> NAMES;
40  
41    @NonNull
42    private final String defaultExtension;
43    @NonNull
44    private final Set<String> recognizedExtensions;
45  
46    static {
47      NAMES = Arrays.stream(values())
48          .map(format -> format.name().toLowerCase(Locale.ROOT))
49          .collect(Collectors.toUnmodifiableList());
50    }
51  
52    /**
53     * Get a list of all format names in lowercase.
54     *
55     * @return the list of names
56     */
57    @SuppressFBWarnings(value = "MS_EXPOSE_REP", justification = "Exposes names provided by the enum")
58    public static List<String> names() {
59      return NAMES;
60    }
61  
62    Format(@NonNull String defaultExtension, Set<String> otherExtensions) {
63      this.defaultExtension = defaultExtension;
64  
65      Set<String> recognizedExtensions = new HashSet<>();
66      recognizedExtensions.add(defaultExtension);
67      recognizedExtensions.addAll(otherExtensions);
68  
69      this.recognizedExtensions = CollectionUtil.unmodifiableSet(recognizedExtensions);
70    }
71  
72    /**
73     * Get the default extension to use for the format.
74     *
75     * @return the default extension
76     */
77    @NonNull
78    public Set<String> getRecognizedExtensions() {
79      return recognizedExtensions;
80    }
81  
82    /**
83     * Get the default extension to use for the format.
84     *
85     * @return the default extension
86     */
87    @NonNull
88    public String getDefaultExtension() {
89      return defaultExtension;
90    }
91  
92    /**
93     * Get the appropriate path formatter for this format.
94     * <p>
95     * Returns:
96     * <ul>
97     * <li>{@link IPathFormatter#XPATH_PATH_FORMATTER} for XML</li>
98     * <li>{@link IPathFormatter#JSON_POINTER_PATH_FORMATTER} for JSON and YAML</li>
99     * </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 }