001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package dev.metaschema.core.model; 007 008import java.util.Collection; 009 010import dev.metaschema.core.qname.IEnhancedQName; 011import dev.metaschema.core.util.CollectionUtil; 012import dev.metaschema.core.util.ObjectUtils; 013import edu.umd.cs.findbugs.annotations.NonNull; 014import edu.umd.cs.findbugs.annotations.Nullable; 015 016/** 017 * This behavioral interface represents an instance that supports grouped 018 * values. 019 */ 020public interface IGroupable extends IInstance { 021 022 /** 023 * The default Metaschema grouping minimum occurrence. 024 */ 025 int DEFAULT_GROUP_AS_MIN_OCCURS = 0; 026 /** 027 * The default Metaschema grouping maximum occurrence. 028 */ 029 int DEFAULT_GROUP_AS_MAX_OCCURS = 1; 030 /** 031 * The default Metaschema grouping behavior for JSON data. 032 */ 033 @NonNull 034 JsonGroupAsBehavior DEFAULT_JSON_GROUP_AS_BEHAVIOR = JsonGroupAsBehavior.SINGLETON_OR_LIST; 035 /** 036 * The default Metaschema grouping behavior for XML data. 037 */ 038 @NonNull 039 XmlGroupAsBehavior DEFAULT_XML_GROUP_AS_BEHAVIOR = XmlGroupAsBehavior.UNGROUPED; 040 041 /** 042 * Get the minimum cardinality for this associated instance. This value must be 043 * less than or equal to the maximum cardinality returned by 044 * {@link #getMaxOccurs()}. 045 * 046 * @return {@code 0} or a positive integer value 047 * @see #DEFAULT_GROUP_AS_MIN_OCCURS 048 */ 049 int getMinOccurs(); 050 051 /** 052 * Get the maximum cardinality for this associated instance. This value must be 053 * greater than or equal to the minimum cardinality returned by 054 * {@link #getMinOccurs()}, or {@code -1} if unbounded. 055 * 056 * @return a positive integer value or {@code -1} if unbounded 057 * @see #DEFAULT_GROUP_AS_MAX_OCCURS 058 */ 059 int getMaxOccurs(); 060 061 /** 062 * Get the name provided for grouping. An instance in Metaschema must have a 063 * group name if the instance has a cardinality greater than {@code 1}. 064 * 065 * @return the group-as name or {@code null} if no name is configured, such as 066 * when {@link #getMaxOccurs()} = 1 067 */ 068 @Nullable 069 default String getGroupAsName() { 070 // no group-as by default 071 return null; 072 } 073 074 /** 075 * Get the name used for the associated element wrapping a collection of 076 * elements in XML. This value is required when {@link #getXmlGroupAsBehavior()} 077 * = {@link XmlGroupAsBehavior#GROUPED}. This name will be the element name 078 * wrapping a collection of elements. 079 * <p> 080 * If this instance doesn't have a namespace defined, then the module's XML 081 * namespace will be used. 082 * 083 * @return the groupAs QName or {@code null} if no name is configured, such as 084 * when {@link #getMaxOccurs()} = 1. 085 */ 086 @Nullable 087 default IEnhancedQName getEffectiveXmlGroupAsQName() { 088 return getXmlGroupAsBehavior() == XmlGroupAsBehavior.GROUPED 089 ? IEnhancedQName.of( 090 getContainingDefinition().getQName().getNamespace(), 091 ObjectUtils.requireNonNull(getGroupAsName())) 092 : null; 093 } 094 095 /** 096 * Gets the configured JSON group-as strategy. A JSON group-as strategy is only 097 * required when {@link #getMaxOccurs()} > 1. 098 * <p> 099 * The default for this method is {@link JsonGroupAsBehavior#NONE}, since the 100 * default behavior is to have no grouping. If {@link #getMaxOccurs()} is 101 * greater than {@code 1}, then the default behavior is 102 * {@code #DEFAULT_JSON_GROUP_AS_BEHAVIOR}. 103 * 104 * @return the JSON group-as strategy, or {@code JsonGroupAsBehavior#NONE} if 105 * {@link #getMaxOccurs()} = 1 106 * @see #DEFAULT_JSON_GROUP_AS_BEHAVIOR 107 */ 108 @NonNull 109 default JsonGroupAsBehavior getJsonGroupAsBehavior() { 110 return JsonGroupAsBehavior.NONE; 111 } 112 113 /** 114 * Gets the configured XML group-as strategy. A XML group-as strategy is only 115 * required when {@link #getMaxOccurs()} > 1. 116 * 117 * @return the JSON group-as strategy, or {@code XmlGroupAsBehavior#UNGROUPED} 118 * if {@link #getMaxOccurs()} = 1 119 * @see #DEFAULT_XML_GROUP_AS_BEHAVIOR 120 */ 121 @NonNull 122 default XmlGroupAsBehavior getXmlGroupAsBehavior() { 123 return DEFAULT_XML_GROUP_AS_BEHAVIOR; 124 } 125 126 /** 127 * Get the item values for the provided {@code instanceValue}. An instance may 128 * be singular or many valued. 129 * 130 * @param instanceValue 131 * the instance 132 * @return the item values or an empty collection if no item values exist 133 */ 134 @NonNull 135 default Collection<?> getItemValues(@NonNull Object instanceValue) { 136 // no item values by default 137 return CollectionUtil.emptyList(); 138 } 139}