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.datatype.markup.MarkupLine;
9   import gov.nist.secauto.metaschema.core.datatype.markup.MarkupMultiline;
10  import gov.nist.secauto.metaschema.core.model.AbstractFieldInstance;
11  import gov.nist.secauto.metaschema.core.model.IAttributable;
12  import gov.nist.secauto.metaschema.core.model.IBoundObject;
13  import gov.nist.secauto.metaschema.core.util.CollectionUtil;
14  import gov.nist.secauto.metaschema.core.util.ObjectUtils;
15  import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly;
16  import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelFieldComplex;
17  import gov.nist.secauto.metaschema.databind.model.IBoundInstanceFlag;
18  import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelChoiceGroup;
19  import gov.nist.secauto.metaschema.databind.model.IBoundInstanceModelGroupedField;
20  import gov.nist.secauto.metaschema.databind.model.IBoundProperty;
21  import gov.nist.secauto.metaschema.databind.model.annotations.BoundGroupedField;
22  import gov.nist.secauto.metaschema.databind.model.annotations.ModelUtil;
23  
24  import java.util.Arrays;
25  import java.util.LinkedHashMap;
26  import java.util.Map;
27  import java.util.Set;
28  import java.util.function.Predicate;
29  import java.util.stream.Collectors;
30  
31  import edu.umd.cs.findbugs.annotations.NonNull;
32  import nl.talsmasoftware.lazy4j.Lazy;
33  
34  /**
35   * Represents an field model instance that is a member of a choice group
36   * instance.
37   */
38  public class InstanceModelGroupedFieldComplex
39      extends AbstractFieldInstance<
40          IBoundInstanceModelChoiceGroup,
41          IBoundDefinitionModelFieldComplex,
42          IBoundInstanceModelGroupedField,
43          IBoundDefinitionModelAssembly>
44      implements IBoundInstanceModelGroupedField {
45    @NonNull
46    private final BoundGroupedField annotation;
47    @NonNull
48    private final DefinitionField definition;
49    @NonNull
50    private final Lazy<Map<String, IBoundProperty<?>>> jsonProperties;
51    @NonNull
52    private final Lazy<Map<IAttributable.Key, Set<String>>> properties;
53  
54    /**
55     * Construct a new field model instance instance that is a member of a choice
56     * group instance.
57     *
58     * @param annotation
59     *          the Java annotation the instance is bound to
60     * @param definition
61     *          the assembly definition this instance is bound to
62     * @param container
63     *          the choice group instance containing the instance
64     */
65    public InstanceModelGroupedFieldComplex(
66        @NonNull BoundGroupedField annotation,
67        @NonNull DefinitionField definition,
68        @NonNull IBoundInstanceModelChoiceGroup container) {
69      super(container);
70      this.annotation = annotation;
71      this.definition = definition;
72      this.jsonProperties = ObjectUtils.notNull(Lazy.lazy(() -> {
73        Predicate<IBoundInstanceFlag> flagFilter = null;
74        IBoundInstanceFlag jsonKey = getEffectiveJsonKey();
75        if (jsonKey != null) {
76          flagFilter = flag -> !jsonKey.equals(flag);
77        }
78  
79        IBoundInstanceFlag jsonValueKey = getDefinition().getJsonValueKeyFlagInstance();
80        if (jsonValueKey != null) {
81          Predicate<IBoundInstanceFlag> jsonValueKeyFilter = flag -> !flag.equals(jsonValueKey);
82          flagFilter = flagFilter == null ? jsonValueKeyFilter : flagFilter.and(jsonValueKeyFilter);
83        }
84        return getDefinition().getJsonProperties(flagFilter);
85      }));
86      this.properties = ObjectUtils.notNull(
87          Lazy.lazy(() -> CollectionUtil.unmodifiableMap(ObjectUtils.notNull(
88              Arrays.stream(annotation.properties())
89                  .map(ModelUtil::toPropertyEntry)
90                  .collect(
91                      Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (v1, v2) -> v2, LinkedHashMap::new))))));
92    }
93  
94    private BoundGroupedField getAnnotation() {
95      return annotation;
96    }
97  
98    // ------------------------------------------
99    // - Start annotation driven code - CPD-OFF -
100   // ------------------------------------------
101 
102   @Override
103   public Class<? extends IBoundObject> getBoundClass() {
104     return getAnnotation().binding();
105   }
106 
107   @Override
108   public Map<String, IBoundProperty<?>> getJsonProperties() {
109     return ObjectUtils.notNull(jsonProperties.get());
110   }
111 
112   @Override
113   public DefinitionField getDefinition() {
114     return definition;
115   }
116 
117   @Override
118   public String getFormalName() {
119     return ModelUtil.resolveNoneOrValue(getAnnotation().formalName());
120   }
121 
122   @Override
123   public MarkupLine getDescription() {
124     return ModelUtil.resolveToMarkupLine(getAnnotation().description());
125   }
126 
127   @Override
128   public Map<Key, Set<String>> getProperties() {
129     return ObjectUtils.notNull(properties.get());
130   }
131 
132   @Override
133   public MarkupMultiline getRemarks() {
134     return ModelUtil.resolveToMarkupMultiline(getAnnotation().remarks());
135   }
136 
137   @Override
138   public String getDiscriminatorValue() {
139     return ModelUtil.resolveNoneOrValue(getAnnotation().formalName());
140   }
141 
142   @Override
143   public String getUseName() {
144     return ModelUtil.resolveNoneOrValue(getAnnotation().useName());
145   }
146 
147   @Override
148   public Integer getUseIndex() {
149     return ModelUtil.resolveDefaultInteger(getAnnotation().useIndex());
150   }
151 
152   // ----------------------------------------
153   // - End annotation driven code - CPD-OFF -
154   // ----------------------------------------
155 }