1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.databind.model;
7   
8   import java.io.IOException;
9   import java.lang.reflect.Field;
10  
11  import dev.metaschema.core.model.IAssemblyInstanceAbsolute;
12  import dev.metaschema.core.model.IBoundObject;
13  import dev.metaschema.core.util.ObjectUtils;
14  import dev.metaschema.databind.IBindingContext;
15  import dev.metaschema.databind.io.BindingException;
16  import dev.metaschema.databind.model.impl.InstanceModelAssemblyComplex;
17  import dev.metaschema.databind.model.info.IFeatureComplexItemValueHandler;
18  import dev.metaschema.databind.model.info.IItemReadHandler;
19  import dev.metaschema.databind.model.info.IItemWriteHandler;
20  import edu.umd.cs.findbugs.annotations.NonNull;
21  
22  /**
23   * Represents an assembly instance bound to Java field.
24   */
25  public interface IBoundInstanceModelAssembly
26      extends IBoundInstanceModelNamed<IBoundObject>, IAssemblyInstanceAbsolute, IFeatureComplexItemValueHandler {
27    /**
28     * Create a new bound assembly 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 IBoundInstanceModelAssembly newInstance(
38        @NonNull Field field,
39        @NonNull IBoundDefinitionModelAssembly containingDefinition) {
40      Class<? extends IBoundObject> itemType = IBoundInstanceModel.getItemType(field, IBoundObject.class);
41      IBindingContext bindingContext = containingDefinition.getBindingContext();
42      IBoundDefinitionModel<?> definition = bindingContext.getBoundDefinitionForClass(itemType);
43      if (definition instanceof IBoundDefinitionModelAssembly) {
44        return InstanceModelAssemblyComplex.newInstance(
45            field,
46            (IBoundDefinitionModelAssembly) definition,
47            containingDefinition);
48      }
49  
50      throw new IllegalStateException(String.format(
51          "The field '%s' on class '%s' is not bound to a Metaschema assembly",
52          field.toString(),
53          field.getDeclaringClass().getName()));
54    }
55  
56    @Override
57    @NonNull
58    IBoundDefinitionModelAssembly getDefinition();
59    // @Override
60    // default Object getValue(Object parent) {
61    // return IBoundInstanceModelNamed.super.getValue(parent);
62    // }
63  
64    // @Override
65    // default void setValue(Object parentObject, Object value) {
66    // IBoundInstanceModelNamed.super.setValue(parentObject, value);
67    // }
68  
69    @Override
70    default IBoundObject readItem(IBoundObject parent, IItemReadHandler handler) throws IOException {
71      return handler.readItemAssembly(ObjectUtils.requireNonNull(parent, "parent"), this);
72    }
73  
74    @Override
75    default void writeItem(IBoundObject item, IItemWriteHandler handler) throws IOException {
76      handler.writeItemAssembly(item, this);
77    }
78  
79    @Override
80    default IBoundObject deepCopyItem(IBoundObject item, IBoundObject parentInstance) throws BindingException {
81      return getDefinition().deepCopyItem(item, parentInstance);
82    }
83  
84    @Override
85    default Class<? extends IBoundObject> getBoundClass() {
86      return getDefinition().getBoundClass();
87    }
88  
89    @Override
90    default void callBeforeDeserialize(IBoundObject targetObject, IBoundObject parentObject) throws BindingException {
91      getDefinition().callBeforeDeserialize(targetObject, parentObject);
92    }
93  
94    @Override
95    default void callAfterDeserialize(IBoundObject targetObject, IBoundObject parentObject) throws BindingException {
96      getDefinition().callAfterDeserialize(targetObject, parentObject);
97    }
98  }