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