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