1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.databind.model;
7   
8   import java.lang.reflect.InvocationTargetException;
9   import java.lang.reflect.Method;
10  import java.util.Map;
11  import java.util.function.Predicate;
12  
13  import dev.metaschema.core.model.IBoundObject;
14  import dev.metaschema.databind.io.BindingException;
15  import dev.metaschema.databind.model.info.IFeatureComplexItemValueHandler;
16  import edu.umd.cs.findbugs.annotations.NonNull;
17  import edu.umd.cs.findbugs.annotations.Nullable;
18  
19  /**
20   * Represents a field or assembly instance bound to Java class.
21   */
22  public interface IBoundDefinitionModelComplex
23      extends IBoundDefinitionModel<IBoundObject>, IFeatureComplexItemValueHandler {
24  
25    /**
26     * Get a mapping of JSON property names to their corresponding bound properties.
27     *
28     * @param flagFilter
29     *          a predicate to filter which flag instances to include, or
30     *          {@code null} to include all flags
31     * @return a map of property names to bound properties
32     */
33    @NonNull
34    Map<String, IBoundProperty<?>> getJsonProperties(@Nullable Predicate<IBoundInstanceFlag> flagFilter);
35  
36    /**
37     * Get the "beforeDeserialize" method for this bound class, if one exists.
38     * <p>
39     * This method is called before data is read and applied during deserialization.
40     *
41     * @return the method, or {@code null} if no such method exists
42     */
43    @Nullable
44    Method getBeforeDeserializeMethod();
45  
46    /**
47     * Calls the method named "beforeDeserialize" on each class in the object's
48     * hierarchy if the method exists on the class.
49     * <p>
50     * These methods can be used to set the initial state of the target bound object
51     * before data is read and applied during deserialization.
52     *
53     * @param targetObject
54     *          the data object target to call the method(s) on
55     * @param parentObject
56     *          the object target's parent object, which is used as the method
57     *          argument
58     * @throws BindingException
59     *           if an error occurs while calling the method
60     */
61    @Override
62    default void callBeforeDeserialize(IBoundObject targetObject, IBoundObject parentObject) throws BindingException {
63      Method beforeDeserializeMethod = getBeforeDeserializeMethod();
64      if (beforeDeserializeMethod != null) {
65        try {
66          beforeDeserializeMethod.invoke(targetObject, parentObject);
67        } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
68          throw new BindingException(ex);
69        }
70      }
71    }
72  
73    /**
74     * Get the "afterDeserialize" method for this bound class, if one exists.
75     * <p>
76     * This method is called after data is read and applied during deserialization.
77     *
78     * @return the method, or {@code null} if no such method exists
79     */
80    @Nullable
81    Method getAfterDeserializeMethod();
82  
83    /**
84     * Calls the method named "afterDeserialize" on each class in the object's
85     * hierarchy if the method exists.
86     * <p>
87     * These methods can be used to modify the state of the target bound object
88     * after data is read and applied during deserialization.
89     *
90     * @param targetObject
91     *          the data object target to call the method(s) on
92     * @param parentObject
93     *          the object target's parent object, which is used as the method
94     *          argument
95     * @throws BindingException
96     *           if an error occurs while calling the method
97     */
98    @Override
99    default void callAfterDeserialize(IBoundObject targetObject, IBoundObject parentObject) throws BindingException {
100     Method afterDeserializeMethod = getAfterDeserializeMethod();
101     if (afterDeserializeMethod != null) {
102       try {
103         afterDeserializeMethod.invoke(targetObject, parentObject);
104       } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
105         throw new BindingException(ex);
106       }
107     }
108   }
109 
110   // @Override
111   // public String getJsonKeyFlagName() {
112   // // definition items never have a JSON key
113   // return null;
114   // }
115 
116 }