1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.databind.model;
7   
8   import gov.nist.secauto.metaschema.core.datatype.IDataTypeAdapter;
9   import gov.nist.secauto.metaschema.core.model.IBoundObject;
10  import gov.nist.secauto.metaschema.core.model.IFieldInstanceAbsolute;
11  import gov.nist.secauto.metaschema.databind.IBindingContext;
12  import gov.nist.secauto.metaschema.databind.model.impl.DefinitionField;
13  import gov.nist.secauto.metaschema.databind.model.impl.InstanceModelFieldComplex;
14  import gov.nist.secauto.metaschema.databind.model.impl.InstanceModelFieldScalar;
15  
16  import java.lang.reflect.Field;
17  
18  import javax.xml.namespace.QName;
19  
20  import edu.umd.cs.findbugs.annotations.NonNull;
21  
22  public interface IBoundInstanceModelField<ITEM> extends IBoundInstanceModelNamed<ITEM>, IFieldInstanceAbsolute {
23  
24    @Override
25    IBoundDefinitionModelField<ITEM> getDefinition();
26  
27    /**
28     * Create a new bound field instance.
29     *
30     * @param field
31     *          the Java field the instance is bound to
32     * @param containingDefinition
33     *          the definition containing the instance
34     * @return the new instance
35     */
36    @NonNull
37    static IBoundInstanceModelField<?> newInstance(
38        @NonNull Field field,
39        @NonNull IBoundDefinitionModelAssembly containingDefinition) {
40      Class<?> itemType = IBoundInstanceModel.getItemType(field);
41  
42      IBoundInstanceModelField<?> retval;
43      if (IBoundObject.class.isAssignableFrom(itemType)) {
44        IBindingContext bindingContext = containingDefinition.getBindingContext();
45        IBoundDefinitionModel<?> definition
46            = bindingContext.getBoundDefinitionForClass(itemType.asSubclass(IBoundObject.class));
47        if (definition == null) {
48          throw new IllegalStateException(String.format(
49              "The field '%s' on class '%s' is not bound to a Metaschema field",
50              field.toString(),
51              field.getDeclaringClass().getName()));
52        }
53        retval = InstanceModelFieldComplex.newInstance(field, (DefinitionField) definition, containingDefinition);
54      } else {
55  
56        retval = InstanceModelFieldScalar.newInstance(field, containingDefinition);
57      }
58      return retval;
59    }
60  
61    @Override
62    default boolean canHandleXmlQName(QName qname) {
63      boolean retval;
64      if (isEffectiveValueWrappedInXml()) {
65        retval = qname.equals(getXmlQName());
66      } else {
67        IDataTypeAdapter<?> adapter = getDefinition().getJavaTypeAdapter();
68        // we are to parse the data type
69        retval = adapter.canHandleQName(qname);
70      }
71      return retval;
72    }
73  }