001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.databind.model;
007
008import java.io.IOException;
009import java.lang.reflect.Field;
010
011import dev.metaschema.core.model.IAssemblyInstanceAbsolute;
012import dev.metaschema.core.model.IBoundObject;
013import dev.metaschema.core.util.ObjectUtils;
014import dev.metaschema.databind.IBindingContext;
015import dev.metaschema.databind.io.BindingException;
016import dev.metaschema.databind.model.impl.InstanceModelAssemblyComplex;
017import dev.metaschema.databind.model.info.IFeatureComplexItemValueHandler;
018import dev.metaschema.databind.model.info.IItemReadHandler;
019import dev.metaschema.databind.model.info.IItemWriteHandler;
020import edu.umd.cs.findbugs.annotations.NonNull;
021
022/**
023 * Represents an assembly instance bound to Java field.
024 */
025public interface IBoundInstanceModelAssembly
026    extends IBoundInstanceModelNamed<IBoundObject>, IAssemblyInstanceAbsolute, IFeatureComplexItemValueHandler {
027  /**
028   * Create a new bound assembly instance.
029   *
030   * @param field
031   *          the Java field the instance is bound to
032   * @param containingDefinition
033   *          the definition containing the instance
034   * @return the new instance
035   */
036  @NonNull
037  static IBoundInstanceModelAssembly newInstance(
038      @NonNull Field field,
039      @NonNull IBoundDefinitionModelAssembly containingDefinition) {
040    Class<? extends IBoundObject> itemType = IBoundInstanceModel.getItemType(field, IBoundObject.class);
041    IBindingContext bindingContext = containingDefinition.getBindingContext();
042    IBoundDefinitionModel<?> definition = bindingContext.getBoundDefinitionForClass(itemType);
043    if (definition instanceof IBoundDefinitionModelAssembly) {
044      return InstanceModelAssemblyComplex.newInstance(
045          field,
046          (IBoundDefinitionModelAssembly) definition,
047          containingDefinition);
048    }
049
050    throw new IllegalStateException(String.format(
051        "The field '%s' on class '%s' is not bound to a Metaschema assembly",
052        field.toString(),
053        field.getDeclaringClass().getName()));
054  }
055
056  @Override
057  @NonNull
058  IBoundDefinitionModelAssembly getDefinition();
059  // @Override
060  // default Object getValue(Object parent) {
061  // return IBoundInstanceModelNamed.super.getValue(parent);
062  // }
063
064  // @Override
065  // default void setValue(Object parentObject, Object value) {
066  // IBoundInstanceModelNamed.super.setValue(parentObject, value);
067  // }
068
069  @Override
070  default IBoundObject readItem(IBoundObject parent, IItemReadHandler handler) throws IOException {
071    return handler.readItemAssembly(ObjectUtils.requireNonNull(parent, "parent"), this);
072  }
073
074  @Override
075  default void writeItem(IBoundObject item, IItemWriteHandler handler) throws IOException {
076    handler.writeItemAssembly(item, this);
077  }
078
079  @Override
080  default IBoundObject deepCopyItem(IBoundObject item, IBoundObject parentInstance) throws BindingException {
081    return getDefinition().deepCopyItem(item, parentInstance);
082  }
083
084  @Override
085  default Class<? extends IBoundObject> getBoundClass() {
086    return getDefinition().getBoundClass();
087  }
088
089  @Override
090  default void callBeforeDeserialize(IBoundObject targetObject, IBoundObject parentObject) throws BindingException {
091    getDefinition().callBeforeDeserialize(targetObject, parentObject);
092  }
093
094  @Override
095  default void callAfterDeserialize(IBoundObject targetObject, IBoundObject parentObject) throws BindingException {
096    getDefinition().callAfterDeserialize(targetObject, parentObject);
097  }
098}