1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.databind.model.impl;
7   
8   import gov.nist.secauto.metaschema.core.model.IBoundObject;
9   import gov.nist.secauto.metaschema.core.util.ObjectUtils;
10  import gov.nist.secauto.metaschema.databind.IBindingContext;
11  import gov.nist.secauto.metaschema.databind.io.BindingException;
12  import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelComplex;
13  import gov.nist.secauto.metaschema.databind.model.IBoundInstanceFlag;
14  import gov.nist.secauto.metaschema.databind.model.IBoundModule;
15  
16  import java.lang.annotation.Annotation;
17  import java.lang.reflect.Method;
18  
19  import javax.xml.namespace.QName;
20  
21  import edu.umd.cs.findbugs.annotations.NonNull;
22  import edu.umd.cs.findbugs.annotations.Nullable;
23  import nl.talsmasoftware.lazy4j.Lazy;
24  
25  public abstract class AbstractBoundDefinitionModelComplex<A extends Annotation>
26      implements IBoundDefinitionModelComplex {
27    @NonNull
28    private final Class<? extends IBoundObject> clazz;
29    @NonNull
30    private final A annotation;
31    @NonNull
32    private final IBindingContext bindingContext;
33    @NonNull
34    private final IBoundModule module;
35    @NonNull
36    private final Lazy<QName> qname;
37    @NonNull
38    private final Lazy<QName> definitionQName;
39    @Nullable
40    private final Method beforeDeserializeMethod;
41    @Nullable
42    private final Method afterDeserializeMethod;
43  
44    protected AbstractBoundDefinitionModelComplex(
45        @NonNull Class<? extends IBoundObject> clazz,
46        @NonNull A annotation,
47        @NonNull IBoundModule module,
48        @NonNull IBindingContext bindingContext) {
49      this.clazz = clazz;
50      this.annotation = annotation;
51      this.bindingContext = bindingContext;
52      this.module = module;
53      this.qname = ObjectUtils.notNull(Lazy.lazy(() -> getContainingModule().toModelQName(getEffectiveName())));
54      this.definitionQName = ObjectUtils.notNull(Lazy.lazy(() -> getContainingModule().toModelQName(getName())));
55      this.beforeDeserializeMethod = ClassIntrospector.getMatchingMethod(
56          clazz,
57          "beforeDeserialize",
58          Object.class);
59      this.afterDeserializeMethod = ClassIntrospector.getMatchingMethod(
60          clazz,
61          "afterDeserialize",
62          Object.class);
63    }
64  
65    @Override
66    public Class<? extends IBoundObject> getBoundClass() {
67      return clazz;
68    }
69  
70    @NonNull
71    public A getAnnotation() {
72      return annotation;
73    }
74  
75    @Override
76    @NonNull
77    public IBoundModule getContainingModule() {
78      return module;
79    }
80  
81    @Override
82    @NonNull
83    public IBindingContext getBindingContext() {
84      return bindingContext;
85    }
86  
87    @SuppressWarnings("null")
88    @Override
89    public final QName getXmlQName() {
90      return qname.get();
91    }
92  
93    @SuppressWarnings("null")
94    @Override
95    public final QName getDefinitionQName() {
96      return definitionQName.get();
97    }
98  
99    @Override
100   public Method getBeforeDeserializeMethod() {
101     return beforeDeserializeMethod;
102   }
103 
104   @Override
105   public Method getAfterDeserializeMethod() {
106     return afterDeserializeMethod;
107   }
108 
109   // @Override
110   // public String getJsonKeyFlagName() {
111   // // definition items never have a JSON key
112   // return null;
113   // }
114 
115   @Override
116   public IBoundObject deepCopyItem(IBoundObject item, IBoundObject parentInstance) throws BindingException {
117     IBoundObject instance = newInstance(item::getMetaschemaData);
118 
119     callBeforeDeserialize(instance, parentInstance);
120 
121     deepCopyItemInternal(item, instance);
122 
123     callAfterDeserialize(instance, parentInstance);
124 
125     return instance;
126   }
127 
128   protected void deepCopyItemInternal(@NonNull IBoundObject fromObject, @NonNull IBoundObject toObject)
129       throws BindingException {
130     for (IBoundInstanceFlag instance : getFlagInstances()) {
131       instance.deepCopy(fromObject, toObject);
132     }
133   }
134 }