1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.databind;
7   
8   import javax.xml.namespace.QName;
9   
10  import dev.metaschema.core.model.IBoundObject;
11  import dev.metaschema.core.util.ObjectUtils;
12  import dev.metaschema.databind.IBindingContext.IBindingMatcher;
13  import dev.metaschema.databind.model.IBoundDefinitionModelAssembly;
14  import edu.umd.cs.findbugs.annotations.NonNull;
15  import nl.talsmasoftware.lazy4j.Lazy;
16  
17  /**
18   * A binding matcher that matches based on a root assembly definition.
19   * <p>
20   * This implementation matches XML elements by their qualified name and
21   * JSON/YAML properties by their root name, allowing the binding context to
22   * identify the correct bound class for a given document root element.
23   */
24  class RootAssemblyBindingMatcher implements IBindingMatcher {
25    @NonNull
26    private final IBoundDefinitionModelAssembly definition;
27    @NonNull
28    private final Lazy<QName> rootQName = ObjectUtils.notNull(
29        Lazy.of(() -> getDefinition().getRootQName().toQName()));
30  
31    /**
32     * Construct a new binding matcher for the provided root assembly definition.
33     *
34     * @param definition
35     *          the root assembly definition to match against
36     */
37    public RootAssemblyBindingMatcher(
38        @NonNull IBoundDefinitionModelAssembly definition) {
39      this.definition = definition;
40    }
41  
42    /**
43     * Get the assembly definition this matcher is based on.
44     *
45     * @return the assembly definition
46     */
47    protected IBoundDefinitionModelAssembly getDefinition() {
48      return definition;
49    }
50  
51    /**
52     * Get the bound class associated with this matcher's definition.
53     *
54     * @return the bound class
55     */
56    protected Class<? extends IBoundObject> getClazz() {
57      return getDefinition().getBoundClass();
58    }
59  
60    /**
61     * Get the XML qualified name for the root element.
62     *
63     * @return the root element's QName
64     */
65    @NonNull
66    protected QName getRootQName() {
67      return ObjectUtils.notNull(rootQName.get());
68    }
69  
70    /**
71     * Get the JSON/YAML root property name.
72     *
73     * @return the root JSON name
74     */
75    @SuppressWarnings("null")
76    @NonNull
77    protected String getRootJsonName() {
78      return getDefinition().getRootJsonName();
79    }
80  
81    @Override
82    public Class<? extends IBoundObject> getBoundClassForXmlQName(QName rootQName) {
83      return getRootQName().equals(rootQName) ? getClazz() : null;
84    }
85  
86    @Override
87    public Class<? extends IBoundObject> getBoundClassForJsonName(String rootName) {
88      return getRootJsonName().equals(rootName) ? getClazz() : null;
89    }
90  
91    @Override
92    public String toString() {
93      return getDefinition().getRootQName().toString();
94    }
95  }