1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.core.metapath.format;
7   
8   import java.util.stream.Collectors;
9   
10  import dev.metaschema.core.metapath.item.node.IAssemblyInstanceGroupedNodeItem;
11  import dev.metaschema.core.metapath.item.node.IAssemblyNodeItem;
12  import dev.metaschema.core.metapath.item.node.IDocumentNodeItem;
13  import dev.metaschema.core.metapath.item.node.IFieldNodeItem;
14  import dev.metaschema.core.metapath.item.node.IFlagNodeItem;
15  import dev.metaschema.core.metapath.item.node.IModuleNodeItem;
16  import dev.metaschema.core.metapath.item.node.IRootAssemblyNodeItem;
17  import edu.umd.cs.findbugs.annotations.NonNull;
18  
19  /**
20   * This interface provides an implementation contract for all path formatters.
21   * When {@link #format(IPathSegment)} is called on a formatter implementation,
22   * the formatter will render the path segments based on the implemented path
23   * syntax. This allows a collection of path segments to be rendered in different
24   * forms by swapping out the formatter used.
25   *
26   * A path formatter is expected to be stateless and thus thread safe.
27   */
28  public interface IPathFormatter {
29    /**
30     * A path formatter that produces Metapath-based paths.
31     */
32    @NonNull
33    IPathFormatter METAPATH_PATH_FORMATER = new MetapathFormatter();
34  
35    /**
36     * A path formatter that produces XPath 3.1 paths with EQName-qualified names.
37     * <p>
38     * This formatter generates namespace-qualified paths using the EQName format
39     * (e.g., {@code Q{http://example.com}element[1]}), suitable for use with XML
40     * tooling that requires namespace qualification.
41     *
42     * @see XPathFormatter
43     */
44    @NonNull
45    IPathFormatter XPATH_PATH_FORMATTER = new XPathFormatter();
46  
47    /**
48     * A path formatter that produces RFC 6901 JSON Pointer paths.
49     * <p>
50     * This formatter generates JSON Pointer paths suitable for use with JSON
51     * tooling and JSON-based error reporting. Uses JSON property names, 0-based
52     * array indices, and proper RFC 6901 escaping.
53     *
54     * @see JsonPointerFormatter
55     * @see <a href="https://www.rfc-editor.org/rfc/rfc6901">RFC 6901 - JSON
56     *      Pointer</a>
57     */
58    @NonNull
59    IPathFormatter JSON_POINTER_PATH_FORMATTER = new JsonPointerFormatter();
60  
61    /**
62     * Format the path represented by the provided path segment. The provided
63     * segment is expected to be the last node in this path. A call to
64     * {@link IPathSegment#getPathStream()} or {@link IPathSegment#getPath()} can be
65     * used to walk the path tree in descending order.
66     *
67     * @param segment
68     *          The last segment in a sequence of path segments
69     * @return a formatted path
70     * @see IPathSegment#getPathStream()
71     * @see IPathSegment#getPath()
72     */
73    @SuppressWarnings("null")
74    @NonNull
75    default String format(@NonNull IPathSegment segment) {
76      return segment.getPathStream().map(pathSegment -> {
77        return pathSegment.format(this);
78      }).collect(Collectors.joining("/"));
79    }
80  
81    /**
82     * This visitor callback is used to format an individual flag path segment.
83     *
84     * @param flag
85     *          the node to format
86     * @return the formatted text for the segment
87     */
88    @NonNull
89    String formatFlag(@NonNull IFlagNodeItem flag);
90  
91    /**
92     * This visitor callback is used to format an individual field path segment.
93     *
94     * @param field
95     *          the node to format
96     * @return the formatted text for the segment
97     */
98    @NonNull
99    String formatField(@NonNull IFieldNodeItem field);
100 
101   /**
102    * This visitor callback is used to format an individual assembly path segment.
103    *
104    * @param assembly
105    *          the node to format
106    * @return the formatted text for the segment
107    */
108   @NonNull
109   String formatAssembly(@NonNull IAssemblyNodeItem assembly);
110 
111   /**
112    * This visitor callback is used to format an individual grouped assembly path
113    * segment.
114    *
115    * @param assembly
116    *          the node to format
117    * @return the formatted text for the segment
118    */
119   @NonNull
120   String formatAssembly(@NonNull IAssemblyInstanceGroupedNodeItem assembly);
121 
122   /**
123    * This visitor callback is used to format a root assembly path segment.
124    *
125    * @param root
126    *          the node to format
127    * @return the formatted text for the segment
128    */
129   @NonNull
130   String formatRootAssembly(@NonNull IRootAssemblyNodeItem root);
131 
132   /**
133    * This visitor callback is used to format an individual document path segment.
134    *
135    * @param document
136    *          the node to format
137    * @return the formatted text for the segment
138    */
139   @NonNull
140   String formatDocument(@NonNull IDocumentNodeItem document);
141 
142   /**
143    * This visitor callback is used to format an individual metaschema path
144    * segment.
145    *
146    * @param metaschema
147    *          the node to format
148    * @return the formatted text for the segment
149    */
150   @NonNull
151   String formatMetaschema(@NonNull IModuleNodeItem metaschema);
152 }