001/*
002 * SPDX-FileCopyrightText: none
003 * SPDX-License-Identifier: CC0-1.0
004 */
005
006package dev.metaschema.databind.model;
007
008import java.lang.reflect.InvocationTargetException;
009import java.lang.reflect.Method;
010import java.util.Map;
011import java.util.function.Predicate;
012
013import dev.metaschema.core.model.IBoundObject;
014import dev.metaschema.databind.io.BindingException;
015import dev.metaschema.databind.model.info.IFeatureComplexItemValueHandler;
016import edu.umd.cs.findbugs.annotations.NonNull;
017import edu.umd.cs.findbugs.annotations.Nullable;
018
019/**
020 * Represents a field or assembly instance bound to Java class.
021 */
022public interface IBoundDefinitionModelComplex
023    extends IBoundDefinitionModel<IBoundObject>, IFeatureComplexItemValueHandler {
024
025  /**
026   * Get a mapping of JSON property names to their corresponding bound properties.
027   *
028   * @param flagFilter
029   *          a predicate to filter which flag instances to include, or
030   *          {@code null} to include all flags
031   * @return a map of property names to bound properties
032   */
033  @NonNull
034  Map<String, IBoundProperty<?>> getJsonProperties(@Nullable Predicate<IBoundInstanceFlag> flagFilter);
035
036  /**
037   * Get the "beforeDeserialize" method for this bound class, if one exists.
038   * <p>
039   * This method is called before data is read and applied during deserialization.
040   *
041   * @return the method, or {@code null} if no such method exists
042   */
043  @Nullable
044  Method getBeforeDeserializeMethod();
045
046  /**
047   * Calls the method named "beforeDeserialize" on each class in the object's
048   * hierarchy if the method exists on the class.
049   * <p>
050   * These methods can be used to set the initial state of the target bound object
051   * before data is read and applied during deserialization.
052   *
053   * @param targetObject
054   *          the data object target to call the method(s) on
055   * @param parentObject
056   *          the object target's parent object, which is used as the method
057   *          argument
058   * @throws BindingException
059   *           if an error occurs while calling the method
060   */
061  @Override
062  default void callBeforeDeserialize(IBoundObject targetObject, IBoundObject parentObject) throws BindingException {
063    Method beforeDeserializeMethod = getBeforeDeserializeMethod();
064    if (beforeDeserializeMethod != null) {
065      try {
066        beforeDeserializeMethod.invoke(targetObject, parentObject);
067      } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
068        throw new BindingException(ex);
069      }
070    }
071  }
072
073  /**
074   * Get the "afterDeserialize" method for this bound class, if one exists.
075   * <p>
076   * This method is called after data is read and applied during deserialization.
077   *
078   * @return the method, or {@code null} if no such method exists
079   */
080  @Nullable
081  Method getAfterDeserializeMethod();
082
083  /**
084   * Calls the method named "afterDeserialize" on each class in the object's
085   * hierarchy if the method exists.
086   * <p>
087   * These methods can be used to modify the state of the target bound object
088   * after data is read and applied during deserialization.
089   *
090   * @param targetObject
091   *          the data object target to call the method(s) on
092   * @param parentObject
093   *          the object target's parent object, which is used as the method
094   *          argument
095   * @throws BindingException
096   *           if an error occurs while calling the method
097   */
098  @Override
099  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}