1   /*
2    * SPDX-FileCopyrightText: none
3    * SPDX-License-Identifier: CC0-1.0
4    */
5   
6   package gov.nist.secauto.metaschema.schemagen.json.impl.builder;
7   
8   import com.fasterxml.jackson.databind.node.ArrayNode;
9   import com.fasterxml.jackson.databind.node.ObjectNode;
10  
11  import gov.nist.secauto.metaschema.core.model.IFieldInstance;
12  import gov.nist.secauto.metaschema.core.model.IModelDefinition;
13  import gov.nist.secauto.metaschema.core.model.INamedModelInstanceAbsolute;
14  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
15  import gov.nist.secauto.metaschema.schemagen.json.IJsonGenerationState;
16  
17  import java.util.List;
18  
19  public class KeyedObjectBuilder
20      extends AbstractCollectionBuilder<KeyedObjectBuilder> {
21  
22    @Override
23    protected KeyedObjectBuilder thisBuilder() {
24      return this;
25    }
26  
27    @Override
28    public void build(
29        ObjectNode object,
30        IJsonGenerationState state) {
31      object.put("type", "object");
32  
33      if (getMinOccurrence() > 0) {
34        object.put("minProperties", getMinOccurrence());
35      }
36  
37      if (getMaxOccurrence() != -1) {
38        object.put("maxProperties", getMaxOccurrence());
39      }
40  
41      List<IType> types = getTypes();
42  
43      if (!types.isEmpty()) {
44        ObjectNode propertyNames = ObjectUtils.notNull(object.putObject("propertyNames"));
45        if (types.size() == 1) {
46          types.iterator().next().build(propertyNames, state);
47        } else {
48          ArrayNode anyOf = propertyNames.putArray("anyOf");
49          for (IType type : types) {
50            type.build(ObjectUtils.notNull(anyOf.objectNode()), state);
51          }
52        }
53      }
54  
55      if (!types.isEmpty()) {
56        ObjectNode patternProperties = ObjectUtils.notNull(object.putObject("patternProperties"));
57        ObjectNode wildcard = ObjectUtils.notNull(patternProperties.putObject("^.*$"));
58        if (types.size() == 1) {
59          types.iterator().next().build(wildcard, state);
60        } else {
61          ArrayNode oneOf = ObjectUtils.notNull(wildcard.putArray("anyOf"));
62          for (IType type : types) {
63            type.build(oneOf, state);
64          }
65        }
66      }
67    }
68  
69    @Override
70    public KeyedObjectBuilder addItemType(INamedModelInstanceAbsolute itemType) {
71  
72      IModelDefinition definition = itemType.getDefinition();
73  
74      int flagCount = definition.getFlagInstances().size();
75      if (definition.getJsonKey() != null) {
76        --flagCount;
77      }
78  
79      if (flagCount > 0 || itemType instanceof IFieldInstance) {
80        super.addItemType(itemType);
81      }
82      return this;
83    }
84  }