1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package dev.metaschema.core.model;
7   
8   import static org.junit.jupiter.api.Assertions.assertEquals;
9   import static org.junit.jupiter.api.Assertions.assertNull;
10  import static org.junit.jupiter.api.Assertions.assertSame;
11  
12  import org.junit.jupiter.api.Test;
13  import org.mockito.Mockito;
14  
15  import dev.metaschema.core.model.impl.DefaultContainerModelAssemblySupport;
16  import dev.metaschema.core.qname.IEnhancedQName;
17  import dev.metaschema.core.util.CollectionUtil;
18  
19  /**
20   * Tests for {@code any} instance support in container model classes.
21   */
22  class ContainerModelAnyInstanceTest {
23  
24    @Test
25    void testInterfaceDefaultReturnsNull() {
26      IContainerModelAssemblySupport<?, ?, ?, ?, ?, ?> empty
27          = IContainerModelAssemblySupport.empty();
28      assertNull(empty.getAnyInstance(), "Default getAnyInstance() should return null");
29    }
30  
31    @Test
32    void testEmptyContainerReturnsNull() {
33      @SuppressWarnings("unchecked")
34      DefaultContainerModelAssemblySupport<IModelInstance, INamedModelInstance,
35          IFieldInstance, IAssemblyInstance, IChoiceInstance, IChoiceGroupInstance> empty
36              = DefaultContainerModelAssemblySupport.EMPTY;
37      assertNull(empty.getAnyInstance(), "EMPTY container should return null for getAnyInstance()");
38    }
39  
40    @Test
41    void testContainerStoresAnyInstance() {
42      IAnyInstance mockAny = Mockito.mock(IAnyInstance.class);
43  
44      DefaultContainerModelAssemblySupport<IModelInstance, INamedModelInstance,
45          IFieldInstance, IAssemblyInstance, IChoiceInstance, IChoiceGroupInstance> container
46              = new DefaultContainerModelAssemblySupport<>(
47                  CollectionUtil.emptyList(),
48                  CollectionUtil.emptyMap(),
49                  CollectionUtil.emptyMap(),
50                  CollectionUtil.emptyMap(),
51                  CollectionUtil.emptyList(),
52                  CollectionUtil.emptyMap(),
53                  mockAny);
54      assertSame(mockAny, container.getAnyInstance(),
55          "Container should return the IAnyInstance passed to the constructor");
56    }
57  
58    @Test
59    void testContainerConstructorWithNullAnyInstance() {
60      DefaultContainerModelAssemblySupport<IModelInstance, INamedModelInstance,
61          IFieldInstance, IAssemblyInstance, IChoiceInstance, IChoiceGroupInstance> container
62              = new DefaultContainerModelAssemblySupport<>(
63                  CollectionUtil.emptyList(),
64                  CollectionUtil.emptyMap(),
65                  CollectionUtil.emptyMap(),
66                  CollectionUtil.emptyMap(),
67                  CollectionUtil.emptyList(),
68                  CollectionUtil.emptyMap(),
69                  null);
70      assertNull(container.getAnyInstance(),
71          "Container should return null when constructed with null anyInstance");
72    }
73  
74    @SuppressWarnings("unchecked")
75    @Test
76    void testBuilderDefaultAnyInstanceIsNull() {
77      DefaultAssemblyModelBuilder<IModelInstance, INamedModelInstance,
78          IFieldInstance, IAssemblyInstance, IChoiceInstance, IChoiceGroupInstance> builder
79              = new DefaultAssemblyModelBuilder<>();
80  
81      assertNull(builder.getAnyInstance(),
82          "Builder should return null by default for getAnyInstance()");
83    }
84  
85    @SuppressWarnings("unchecked")
86    @Test
87    void testBuilderStoresAnyInstance() {
88      IAnyInstance mockAny = Mockito.mock(IAnyInstance.class);
89  
90      DefaultAssemblyModelBuilder<IModelInstance, INamedModelInstance,
91          IFieldInstance, IAssemblyInstance, IChoiceInstance, IChoiceGroupInstance> builder
92              = new DefaultAssemblyModelBuilder<>();
93      builder.setAnyInstance(mockAny);
94  
95      assertSame(mockAny, builder.getAnyInstance(),
96          "Builder should return the IAnyInstance that was set");
97    }
98  
99    @SuppressWarnings("unchecked")
100   @Test
101   void testBuilderPassesAnyInstanceToContainer() {
102     IAnyInstance mockAny = Mockito.mock(IAnyInstance.class);
103     IFieldInstance mockField = Mockito.mock(IFieldInstance.class);
104     IEnhancedQName mockQName = Mockito.mock(IEnhancedQName.class);
105     Mockito.when(mockQName.getIndexPosition()).thenReturn(1);
106     Mockito.when(mockField.getQName()).thenReturn(mockQName);
107 
108     DefaultAssemblyModelBuilder<IModelInstance, INamedModelInstance,
109         IFieldInstance, IAssemblyInstance, IChoiceInstance, IChoiceGroupInstance> builder
110             = new DefaultAssemblyModelBuilder<>();
111 
112     // Add a model instance so the builder doesn't return EMPTY
113     builder.append(mockField);
114     builder.setAnyInstance(mockAny);
115 
116     IContainerModelAssemblySupport<IModelInstance, INamedModelInstance,
117         IFieldInstance, IAssemblyInstance, IChoiceInstance, IChoiceGroupInstance> container
118             = builder.buildAssembly();
119 
120     assertSame(mockAny, container.getAnyInstance(),
121         "Built container should contain the IAnyInstance from the builder");
122     assertEquals(1, container.getModelInstances().size(),
123         "Built container should contain the field instance");
124   }
125 
126   @SuppressWarnings("unchecked")
127   @Test
128   void testBuilderBuildEmptyStillReturnsNullAny() {
129     DefaultAssemblyModelBuilder<IModelInstance, INamedModelInstance,
130         IFieldInstance, IAssemblyInstance, IChoiceInstance, IChoiceGroupInstance> builder
131             = new DefaultAssemblyModelBuilder<>();
132 
133     // Don't add any instances - should return empty container
134     IContainerModelAssemblySupport<IModelInstance, INamedModelInstance,
135         IFieldInstance, IAssemblyInstance, IChoiceInstance, IChoiceGroupInstance> container
136             = builder.buildAssembly();
137 
138     assertNull(container.getAnyInstance(),
139         "Empty built container should return null for getAnyInstance()");
140   }
141 }