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