001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.bean.openapi3; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020import static org.apache.juneau.marshall.internal.ConverterUtils.*; 021 022import java.util.*; 023 024import org.apache.juneau.commons.collections.*; 025 026/** 027 * A metadata object that allows for more fine-tuned XML model definitions. 028 * 029 * <p> 030 * The Xml Object is a metadata object that allows for more fine-tuned XML model definitions. When using arrays, 031 * XML element names are not inferred (for singular/plural forms) and the name property should be used to add that 032 * information. This object is used to control how schema properties are serialized to XML. 033 * 034 * <h5 class='section'>OpenAPI Specification:</h5> 035 * <p> 036 * The Xml Object is composed of the following fields: 037 * <ul class='spaced-list'> 038 * <li><c>name</c> (string) - Replaces the name of the element/attribute used for the described schema property 039 * <li><c>namespace</c> (string) - The URI of the namespace definition 040 * <li><c>prefix</c> (string) - The prefix to be used for the name 041 * <li><c>attribute</c> (boolean) - Declares whether the property definition translates to an attribute instead of an element 042 * <li><c>wrapped</c> (boolean) - May be used only for an array definition. Signifies whether the array is wrapped 043 * </ul> 044 * 045 * <h5 class='section'>Example:</h5> 046 * <p class='bcode'> 047 * <jc>// Construct using SwaggerBuilder.</jc> 048 * Xml <jv>x</jv> = <jsm>xml</jsm>().setName(<js>"book"</js>).setNamespace(<js>"http://example.com/schema"</js>); 049 * 050 * <jc>// Serialize using JsonSerializer.</jc> 051 * String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>x</jv>); 052 * 053 * <jc>// Or just use toString() which does the same as above.</jc> 054 * <jv>json</jv> = <jv>x</jv>.toString(); 055 * </p> 056 * <p class='bcode'> 057 * <jc>// Output</jc> 058 * { 059 * <js>"name"</js>: <js>"book"</js>, 060 * <js>"namespace"</js>: <js>"http://example.com/schema"</js> 061 * } 062 * </p> 063 * 064 * <h5 class='section'>See Also:</h5><ul> 065 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#xml-object">OpenAPI Specification > XML Object</a> 066 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/data-models/representing-xml/">OpenAPI Representing XML</a> 067 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a> 068 * </ul> 069 */ 070@SuppressWarnings({ 071 "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants 072}) 073public class Xml extends OpenApiElement { 074 075 private String name; 076 private String namespace; 077 private String prefix; 078 private Boolean attribute; 079 private Boolean wrapped; 080 081 /** 082 * Default constructor. 083 */ 084 public Xml() {} 085 086 /** 087 * Copy constructor. 088 * 089 * @param copyFrom The object to copy. 090 */ 091 public Xml(Xml copyFrom) { 092 super(copyFrom); 093 094 this.name = copyFrom.name; 095 this.namespace = copyFrom.namespace; 096 this.prefix = copyFrom.prefix; 097 this.attribute = copyFrom.attribute; 098 this.wrapped = copyFrom.wrapped; 099 } 100 101 /** 102 * Make a deep copy of this object. 103 * 104 * @return A deep copy of this object. 105 */ 106 public Xml copy() { 107 return new Xml(this); 108 } 109 110 @Override /* Overridden from OpenApiElement */ 111 public <T> T get(String property, Class<T> type) { 112 reqnn("property", property); 113 return switch (property) { 114 case "name" -> toType(getName(), type); 115 case "namespace" -> toType(getNamespace(), type); 116 case "prefix" -> toType(getPrefix(), type); 117 case "attribute" -> toType(getAttribute(), type); 118 case "wrapped" -> toType(getWrapped(), type); 119 default -> super.get(property, type); 120 }; 121 } 122 123 /** 124 * Bean property getter: <property>attribute</property>. 125 * 126 * <p> 127 * Declares whether the property definition translates to an attribute instead of an element. 128 * 129 * @return The property value, or <jk>null</jk> if it is not set. 130 */ 131 public Boolean getAttribute() { return attribute; } 132 133 /** 134 * Bean property getter: <property>name</property>. 135 * 136 * <p> 137 * Replaces the name of the element/attribute used for the described schema property. 138 * 139 * <p> 140 * When defined within the Items Object (<code>items</code>), it will affect the name of the individual XML elements 141 * within the list. 142 * <br>When defined alongside <code>type</code> being array (outside the <code>items</code>), it will affect the 143 * wrapping element and only if wrapped is <jk>true</jk>. 144 * <br>If wrapped is <jk>false</jk>, it will be ignored. 145 * 146 * @return The property value, or <jk>null</jk> if it is not set. 147 */ 148 public String getName() { return name; } 149 150 /** 151 * Bean property getter: <property>namespace</property>. 152 * 153 * <p> 154 * The URL of the namespace definition. Value SHOULD be in the form of a URL. 155 * 156 * @return The property value, or <jk>null</jk> if it is not set. 157 */ 158 public String getNamespace() { return namespace; } 159 160 /** 161 * Bean property getter: <property>prefix</property>. 162 * 163 * <p> 164 * The prefix to be used for the name. 165 * 166 * @return The property value, or <jk>null</jk> if it is not set. 167 */ 168 public String getPrefix() { return prefix; } 169 170 /** 171 * Bean property getter: <property>wrapped</property>. 172 * 173 * <p> 174 * MAY be used only for an array definition. 175 * 176 * <p> 177 * Signifies whether the array is wrapped (for example, 178 * <code><books><book/><book/><books></code>) or unwrapped 179 * (<code><book/><book/></code>). 180 * <br>The definition takes effect only when defined alongside <code>type</code> being <code>array</code> 181 * (outside the <code>items</code>). 182 * 183 * @return The property value, or <jk>null</jk> if it is not set. 184 */ 185 public Boolean getWrapped() { return wrapped; } 186 187 @Override /* Overridden from OpenApiElement */ 188 public Set<String> keySet() { 189 // @formatter:off 190 var s = stb(String.class) 191 .addIf(nn(attribute), "attribute") 192 .addIf(nn(name), "name") 193 .addIf(nn(namespace), "namespace") 194 .addIf(nn(prefix), "prefix") 195 .addIf(nn(wrapped), "wrapped") 196 .build(); 197 // @formatter:on 198 return new MultiSet<>(s, super.keySet()); 199 } 200 201 @Override /* Overridden from OpenApiElement */ 202 public Xml set(String property, Object value) { 203 reqnn("property", property); 204 return switch (property) { 205 case "attribute" -> setAttribute(toBoolean(value)); 206 case "name" -> setName(s(value)); 207 case "namespace" -> setNamespace(s(value)); 208 case "prefix" -> setPrefix(s(value)); 209 case "wrapped" -> setWrapped(toBoolean(value)); 210 default -> { 211 super.set(property, value); 212 yield this; 213 } 214 }; 215 } 216 217 /** 218 * Bean property setter: <property>attribute</property>. 219 * 220 * <p> 221 * Declares whether the property definition translates to an attribute instead of an element. 222 * 223 * @param value 224 * The new value for this property. 225 * <br>Default value is <jk>false</jk>. 226 * <br>Can be <jk>null</jk> to unset the property. 227 * @return This object 228 */ 229 public Xml setAttribute(Boolean value) { 230 attribute = value; 231 return this; 232 } 233 234 /** 235 * Bean property setter: <property>name</property>. 236 * 237 * <p> 238 * Replaces the name of the element/attribute used for the described schema property. 239 * 240 * <p> 241 * When defined within the Items Object (<code>items</code>), it will affect the name of the individual XML elements 242 * within the list. 243 * <br>When defined alongside <code>type</code> being array (outside the <code>items</code>), it will affect the 244 * wrapping element and only if wrapped is <jk>true</jk>. 245 * <br>If wrapped is <jk>false</jk>, it will be ignored. 246 * 247 * @param value 248 * The new value for this property. 249 * <br>Can be <jk>null</jk> to unset the property. 250 * @return This object 251 */ 252 public Xml setName(String value) { 253 name = value; 254 return this; 255 } 256 257 /** 258 * Bean property setter: <property>namespace</property>. 259 * 260 * <p> 261 * The URL of the namespace definition. Value SHOULD be in the form of a URL. 262 * 263 * @param value 264 * The new value for this property. 265 * <br>Can be <jk>null</jk> to unset the property. 266 * @return This object 267 */ 268 public Xml setNamespace(String value) { 269 namespace = value; 270 return this; 271 } 272 273 /** 274 * Bean property setter: <property>prefix</property>. 275 * 276 * <p> 277 * The prefix to be used for the name. 278 * 279 * @param value 280 * The new value for this property. 281 * <br>Can be <jk>null</jk> to unset the property. 282 * @return This object 283 */ 284 public Xml setPrefix(String value) { 285 prefix = value; 286 return this; 287 } 288 289 /** 290 * Bean property setter: <property>wrapped</property>. 291 * 292 * <p> 293 * MAY be used only for an array definition. 294 * 295 * <p> 296 * Signifies whether the array is wrapped (for example, 297 * <code><books><book/><book/><books></code>) or unwrapped 298 * (<code><book/><book/></code>). 299 * <br>The definition takes effect only when defined alongside <code>type</code> being <code>array</code> 300 * (outside the <code>items</code>). 301 * 302 * @param value 303 * The new value for this property. 304 * <br>Can be <jk>null</jk> to unset the property. 305 * @return This object 306 */ 307 public Xml setWrapped(Boolean value) { 308 wrapped = value; 309 return this; 310 } 311 312 @Override /* Overridden from OpenApiElement */ 313 public Xml strict() { 314 super.strict(); 315 return this; 316 } 317 318 @Override /* Overridden from OpenApiElement */ 319 public Xml strict(Object value) { 320 super.strict(value); 321 return this; 322 } 323}