MetaschemaJsonUtil.java
/*
* SPDX-FileCopyrightText: none
* SPDX-License-Identifier: CC0-1.0
*/
package gov.nist.secauto.metaschema.databind.io.json;
import gov.nist.secauto.metaschema.core.model.IFieldDefinition;
import gov.nist.secauto.metaschema.core.util.CollectionUtil;
import gov.nist.secauto.metaschema.core.util.ObjectUtils;
import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModel;
import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelAssembly;
import gov.nist.secauto.metaschema.databind.model.IBoundDefinitionModelFieldComplex;
import gov.nist.secauto.metaschema.databind.model.IBoundFieldValue;
import gov.nist.secauto.metaschema.databind.model.IBoundInstanceFlag;
import gov.nist.secauto.metaschema.databind.model.IBoundProperty;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import edu.umd.cs.findbugs.annotations.NonNull;
import edu.umd.cs.findbugs.annotations.Nullable;
final class MetaschemaJsonUtil {
private MetaschemaJsonUtil() {
// disable construction
}
/**
* Generates a mapping of property names to associated Module instances.
* <p>
* If {@code requiresJsonKey} is {@code true} then the instance used as the JSON
* key is not included in the mapping.
* <p>
* If the {@code targetDefinition} is an instance of {@link IFieldDefinition}
* and a JSON value key property is configured, then the value key flag and
* value are also omitted from the mapping. Otherwise, the value is included in
* the mapping.
*
* @param targetDefinition
* the definition to get JSON instances from
* @param jsonKey
* the flag instance used as the JSON key, or {@code null} otherwise
* @return a mapping of JSON property to related Module instance
*/
@NonNull
public static Map<String, ? extends IBoundProperty<?>> getJsonInstanceMap(
@NonNull IBoundDefinitionModel<?> targetDefinition,
@Nullable IBoundInstanceFlag jsonKey) {
Collection<? extends IBoundInstanceFlag> flags = targetDefinition.getFlagInstances();
int flagCount = flags.size() - (jsonKey == null ? 0 : 1);
Stream<? extends IBoundProperty<?>> instanceStream;
if (targetDefinition instanceof IBoundDefinitionModelAssembly) {
// use all child instances
instanceStream = ((IBoundDefinitionModelAssembly) targetDefinition).getModelInstances().stream();
} else if (targetDefinition instanceof IBoundDefinitionModelFieldComplex) {
IBoundDefinitionModelFieldComplex targetFieldDefinition = (IBoundDefinitionModelFieldComplex) targetDefinition;
IBoundInstanceFlag jsonValueKeyFlag = targetFieldDefinition.getJsonValueKeyFlagInstance();
if (jsonValueKeyFlag == null && flagCount > 0) {
// the field value is handled as named field
IBoundFieldValue fieldValue = targetFieldDefinition.getFieldValue();
instanceStream = Stream.of(fieldValue);
} else {
// only the value, with no flags or a JSON value key flag
instanceStream = Stream.empty();
}
} else {
throw new UnsupportedOperationException(
String.format("Unsupported class binding type: %s", targetDefinition.getClass().getName()));
}
if (jsonKey != null) {
instanceStream = Stream.concat(
flags.stream().filter(flag -> !jsonKey.equals(flag)),
instanceStream);
} else {
instanceStream = Stream.concat(
flags.stream(),
instanceStream);
}
return CollectionUtil.unmodifiableMap(ObjectUtils.notNull(instanceStream.collect(
Collectors.toMap(
IBoundProperty::getJsonName,
Function.identity(),
(v1, v2) -> v2,
LinkedHashMap::new))));
}
}