001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package dev.metaschema.databind.model; 007 008import java.lang.reflect.Field; 009 010import dev.metaschema.core.datatype.IDataTypeAdapter; 011import dev.metaschema.core.model.IBoundObject; 012import dev.metaschema.core.model.IFieldInstanceAbsolute; 013import dev.metaschema.core.qname.IEnhancedQName; 014import dev.metaschema.core.util.ObjectUtils; 015import dev.metaschema.databind.IBindingContext; 016import dev.metaschema.databind.model.impl.DefinitionField; 017import dev.metaschema.databind.model.impl.InstanceModelFieldComplex; 018import dev.metaschema.databind.model.impl.InstanceModelFieldScalar; 019import edu.umd.cs.findbugs.annotations.NonNull; 020 021/** 022 * Represents a field instance bound to a Java field. 023 * <p> 024 * This interface handles both scalar (simple type) and complex (class-bound) 025 * field instances. 026 * 027 * @param <ITEM> 028 * the Java type for associated bound objects 029 */ 030public interface IBoundInstanceModelField<ITEM> extends IBoundInstanceModelNamed<ITEM>, IFieldInstanceAbsolute { 031 032 @Override 033 IBoundDefinitionModelField<ITEM> getDefinition(); 034 035 /** 036 * Create a new bound field instance. 037 * 038 * @param field 039 * the Java field the instance is bound to 040 * @param containingDefinition 041 * the definition containing the instance 042 * @return the new instance 043 */ 044 @NonNull 045 static IBoundInstanceModelField<?> newInstance( 046 @NonNull Field field, 047 @NonNull IBoundDefinitionModelAssembly containingDefinition) { 048 Class<?> itemType = IBoundInstanceModel.getItemType(field); 049 050 IBoundInstanceModelField<?> retval; 051 if (IBoundObject.class.isAssignableFrom(itemType)) { 052 IBindingContext bindingContext = containingDefinition.getBindingContext(); 053 IBoundDefinitionModel<?> definition = bindingContext.getBoundDefinitionForClass( 054 ObjectUtils.notNull(itemType.asSubclass(IBoundObject.class))); 055 if (definition == null) { 056 throw new IllegalStateException(String.format( 057 "The field '%s' on class '%s' is not bound to a Metaschema field", 058 field.toString(), 059 field.getDeclaringClass().getName())); 060 } 061 retval = InstanceModelFieldComplex.newInstance(field, (DefinitionField) definition, containingDefinition); 062 } else { 063 064 retval = InstanceModelFieldScalar.newInstance(field, containingDefinition); 065 } 066 return retval; 067 } 068 069 @Override 070 default boolean canHandleXmlQName(IEnhancedQName qname) { 071 boolean retval; 072 if (isEffectiveValueWrappedInXml()) { 073 retval = qname.equals(getQName()); 074 } else { 075 IDataTypeAdapter<?> adapter = getDefinition().getJavaTypeAdapter(); 076 // we are to parse the data type 077 retval = adapter.canHandleQName(qname); 078 } 079 return retval; 080 } 081}