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.IBoundObject;
009import gov.nist.secauto.metaschema.core.model.IFeatureDefinitionInstanceInlined;
010import gov.nist.secauto.metaschema.core.model.IFlagInstance;
011import gov.nist.secauto.metaschema.core.util.ObjectUtils;
012import gov.nist.secauto.metaschema.databind.io.BindingException;
013import gov.nist.secauto.metaschema.databind.model.impl.InstanceFlagInline;
014import gov.nist.secauto.metaschema.databind.model.info.IFeatureScalarItemValueHandler;
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 javax.xml.namespace.QName;
022
023import edu.umd.cs.findbugs.annotations.NonNull;
024
025/**
026 * Represents a flag instance bound to Java data.
027 */
028public interface IBoundInstanceFlag
029    extends IFlagInstance, IBoundDefinitionFlag,
030    IFeatureScalarItemValueHandler,
031    IBoundInstance<Object>,
032    IFeatureDefinitionInstanceInlined<IBoundDefinitionFlag, IBoundInstanceFlag> {
033
034  /**
035   * Create a new bound flag instance.
036   *
037   * @param field
038   *          the Java field the instance is bound to
039   * @param containingDefinition
040   *          the definition containing the instance
041   * @return the new instance
042   */
043  @NonNull
044  static IBoundInstanceFlag newInstance(
045      @NonNull Field field,
046      @NonNull IBoundDefinitionModel<IBoundObject> containingDefinition) {
047    return new InstanceFlagInline(field, containingDefinition);
048  }
049
050  /**
051   * Determines if this flag's value is used as the property name for the JSON
052   * object that holds the remaining data based on this flag's containing
053   * definition.
054   *
055   * @return {@code true} if this flag is used as a JSON key, or {@code false}
056   *         otherwise
057   */
058  boolean isJsonKey();
059
060  /**
061   * Determines if this flag is used as a JSON "value key". A "value key" is a
062   * flag who's value is used as the property name for the containing objects
063   * value.
064   *
065   * @return {@code true} if the flag is used as a JSON "value key", or
066   *         {@code false} otherwise
067   */
068  boolean isJsonValueKey();
069
070  // Flag Instance Features
071  // ======================
072
073  @Override
074  @NonNull
075  IBoundDefinitionModel<IBoundObject> getContainingDefinition();
076
077  @Override
078  @NonNull
079  default IBoundDefinitionModel<IBoundObject> getParentContainer() {
080    return getContainingDefinition();
081  }
082
083  /**
084   * {@inheritDoc}
085   * <p>
086   * For an inline instance, this instance is the definition.
087   */
088  @Override
089  @NonNull
090  IBoundDefinitionFlag getDefinition();
091
092  @Override
093  @NonNull
094  default IBoundInstanceFlag getInlineInstance() {
095    // always inline
096    return this;
097  }
098
099  @Override
100  default void deepCopy(@NonNull IBoundObject fromInstance, @NonNull IBoundObject toInstance) throws BindingException {
101    Object value = getValue(fromInstance);
102    if (value != null) {
103      setValue(toInstance, deepCopyItem(value, toInstance));
104    }
105  }
106
107  @Override
108  @NonNull
109  default Object readItem(IBoundObject parent, @NonNull IItemReadHandler handler) throws IOException {
110    return handler.readItemFlag(ObjectUtils.requireNonNull(parent, "parent"), this);
111  }
112
113  @Override
114  default void writeItem(Object item, IItemWriteHandler handler) throws IOException {
115    handler.writeItemFlag(item, this);
116  }
117
118  @Override
119  default boolean canHandleXmlQName(@NonNull QName qname) {
120    return qname.equals(getXmlQName());
121  }
122}