1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.databind.model;
7   
8   import gov.nist.secauto.metaschema.core.model.IBoundObject;
9   import gov.nist.secauto.metaschema.core.model.IFeatureDefinitionInstanceInlined;
10  import gov.nist.secauto.metaschema.core.model.IFlagInstance;
11  import gov.nist.secauto.metaschema.core.qname.IEnhancedQName;
12  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
13  import gov.nist.secauto.metaschema.databind.io.BindingException;
14  import gov.nist.secauto.metaschema.databind.model.impl.InstanceFlagInline;
15  import gov.nist.secauto.metaschema.databind.model.info.IFeatureScalarItemValueHandler;
16  import gov.nist.secauto.metaschema.databind.model.info.IItemReadHandler;
17  import gov.nist.secauto.metaschema.databind.model.info.IItemWriteHandler;
18  
19  import java.io.IOException;
20  import java.lang.reflect.Field;
21  
22  import edu.umd.cs.findbugs.annotations.NonNull;
23  
24  /**
25   * Represents a flag instance bound to Java data.
26   */
27  public interface IBoundInstanceFlag
28      extends IFlagInstance, IBoundDefinitionFlag,
29      IFeatureScalarItemValueHandler,
30      IBoundInstance<Object>,
31      IFeatureDefinitionInstanceInlined<IBoundDefinitionFlag, IBoundInstanceFlag> {
32  
33    /**
34     * Create a new bound flag instance.
35     *
36     * @param field
37     *          the Java field the instance is bound to
38     * @param containingDefinition
39     *          the definition containing the instance
40     * @return the new instance
41     */
42    @NonNull
43    static IBoundInstanceFlag newInstance(
44        @NonNull Field field,
45        @NonNull IBoundDefinitionModel<IBoundObject> containingDefinition) {
46      return new InstanceFlagInline(field, containingDefinition);
47    }
48  
49    /**
50     * Determines if this flag's value is used as the property name for the JSON
51     * object that holds the remaining data based on this flag's containing
52     * definition.
53     *
54     * @return {@code true} if this flag is used as a JSON key, or {@code false}
55     *         otherwise
56     */
57    boolean isJsonKey();
58  
59    /**
60     * Determines if this flag is used as a JSON "value key". A "value key" is a
61     * flag who's value is used as the property name for the containing objects
62     * value.
63     *
64     * @return {@code true} if the flag is used as a JSON "value key", or
65     *         {@code false} otherwise
66     */
67    boolean isJsonValueKey();
68  
69    // Flag Instance Features
70    // ======================
71  
72    @Override
73    @NonNull
74    IBoundDefinitionModel<IBoundObject> getContainingDefinition();
75  
76    @Override
77    @NonNull
78    default IBoundDefinitionModel<IBoundObject> getParentContainer() {
79      return getContainingDefinition();
80    }
81  
82    /**
83     * {@inheritDoc}
84     * <p>
85     * For an inline instance, this instance is the definition.
86     */
87    @Override
88    @NonNull
89    IBoundDefinitionFlag getDefinition();
90  
91    @Override
92    @NonNull
93    default IBoundInstanceFlag getInlineInstance() {
94      // always inline
95      return this;
96    }
97  
98    @Override
99    default void deepCopy(@NonNull IBoundObject fromInstance, @NonNull IBoundObject toInstance) throws BindingException {
100     Object value = getValue(fromInstance);
101     if (value != null) {
102       setValue(toInstance, deepCopyItem(value, toInstance));
103     }
104   }
105 
106   @Override
107   @NonNull
108   default Object readItem(IBoundObject parent, @NonNull IItemReadHandler handler) throws IOException {
109     return handler.readItemFlag(ObjectUtils.requireNonNull(parent, "parent"), this);
110   }
111 
112   @Override
113   default void writeItem(Object item, IItemWriteHandler handler) throws IOException {
114     handler.writeItemFlag(item, this);
115   }
116 
117   @Override
118   default boolean canHandleXmlQName(@NonNull IEnhancedQName qname) {
119     return qname.equals(getQName());
120   }
121 }