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.AssertionUtils.*; 020import static org.apache.juneau.commons.utils.CollectionUtils.*; 021import static org.apache.juneau.commons.utils.Utils.*; 022import static org.apache.juneau.internal.ConverterUtils.*; 023 024import java.util.*; 025 026import org.apache.juneau.commons.collections.*; 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 name, namespace, prefix; 075 private Boolean attribute, wrapped; 076 077 /** 078 * Default constructor. 079 */ 080 public Xml() {} 081 082 /** 083 * Copy constructor. 084 * 085 * @param copyFrom The object to copy. 086 */ 087 public Xml(Xml copyFrom) { 088 super(copyFrom); 089 090 this.name = copyFrom.name; 091 this.namespace = copyFrom.namespace; 092 this.prefix = copyFrom.prefix; 093 this.attribute = copyFrom.attribute; 094 this.wrapped = copyFrom.wrapped; 095 } 096 097 /** 098 * Make a deep copy of this object. 099 * 100 * @return A deep copy of this object. 101 */ 102 public Xml copy() { 103 return new Xml(this); 104 } 105 106 @Override /* Overridden from OpenApiElement */ 107 public <T> T get(String property, Class<T> type) { 108 assertArgNotNull("property", property); 109 return switch (property) { 110 case "name" -> toType(getName(), type); 111 case "namespace" -> toType(getNamespace(), type); 112 case "prefix" -> toType(getPrefix(), type); 113 case "attribute" -> toType(getAttribute(), type); 114 case "wrapped" -> toType(getWrapped(), type); 115 default -> super.get(property, type); 116 }; 117 } 118 119 /** 120 * Bean property getter: <property>attribute</property>. 121 * 122 * <p> 123 * Declares whether the property definition translates to an attribute instead of an element. 124 * 125 * @return The property value, or <jk>null</jk> if it is not set. 126 */ 127 public Boolean getAttribute() { return attribute; } 128 129 /** 130 * Bean property getter: <property>name</property>. 131 * 132 * <p> 133 * Replaces the name of the element/attribute used for the described schema property. 134 * 135 * <p> 136 * When defined within the Items Object (<code>items</code>), it will affect the name of the individual XML elements 137 * within the list. 138 * <br>When defined alongside <code>type</code> being array (outside the <code>items</code>), it will affect the 139 * wrapping element and only if wrapped is <jk>true</jk>. 140 * <br>If wrapped is <jk>false</jk>, it will be ignored. 141 * 142 * @return The property value, or <jk>null</jk> if it is not set. 143 */ 144 public String getName() { return name; } 145 146 /** 147 * Bean property getter: <property>namespace</property>. 148 * 149 * <p> 150 * The URL of the namespace definition. Value SHOULD be in the form of a URL. 151 * 152 * @return The property value, or <jk>null</jk> if it is not set. 153 */ 154 public String getNamespace() { return namespace; } 155 156 /** 157 * Bean property getter: <property>prefix</property>. 158 * 159 * <p> 160 * The prefix to be used for the name. 161 * 162 * @return The property value, or <jk>null</jk> if it is not set. 163 */ 164 public String getPrefix() { return prefix; } 165 166 /** 167 * Bean property getter: <property>wrapped</property>. 168 * 169 * <p> 170 * MAY be used only for an array definition. 171 * 172 * <p> 173 * Signifies whether the array is wrapped (for example, 174 * <code><books><book/><book/><books></code>) or unwrapped 175 * (<code><book/><book/></code>). 176 * <br>The definition takes effect only when defined alongside <code>type</code> being <code>array</code> 177 * (outside the <code>items</code>). 178 * 179 * @return The property value, or <jk>null</jk> if it is not set. 180 */ 181 public Boolean getWrapped() { return wrapped; } 182 183 @Override /* Overridden from OpenApiElement */ 184 public Set<String> keySet() { 185 // @formatter:off 186 var s = setb(String.class) 187 .addIf(nn(attribute), "attribute") 188 .addIf(nn(name), "name") 189 .addIf(nn(namespace), "namespace") 190 .addIf(nn(prefix), "prefix") 191 .addIf(nn(wrapped), "wrapped") 192 .build(); 193 // @formatter:on 194 return new MultiSet<>(s, super.keySet()); 195 } 196 197 @Override /* Overridden from OpenApiElement */ 198 public Xml set(String property, Object value) { 199 assertArgNotNull("property", property); 200 return switch (property) { 201 case "attribute" -> setAttribute(toBoolean(value)); 202 case "name" -> setName(s(value)); 203 case "namespace" -> setNamespace(s(value)); 204 case "prefix" -> setPrefix(s(value)); 205 case "wrapped" -> setWrapped(toBoolean(value)); 206 default -> { 207 super.set(property, value); 208 yield this; 209 } 210 }; 211 } 212 213 /** 214 * Bean property setter: <property>attribute</property>. 215 * 216 * <p> 217 * Declares whether the property definition translates to an attribute instead of an element. 218 * 219 * @param value 220 * The new value for this property. 221 * <br>Default value is <jk>false</jk>. 222 * <br>Can be <jk>null</jk> to unset the property. 223 * @return This object 224 */ 225 public Xml setAttribute(Boolean value) { 226 attribute = value; 227 return this; 228 } 229 230 /** 231 * Bean property setter: <property>name</property>. 232 * 233 * <p> 234 * Replaces the name of the element/attribute used for the described schema property. 235 * 236 * <p> 237 * When defined within the Items Object (<code>items</code>), it will affect the name of the individual XML elements 238 * within the list. 239 * <br>When defined alongside <code>type</code> being array (outside the <code>items</code>), it will affect the 240 * wrapping element and only if wrapped is <jk>true</jk>. 241 * <br>If wrapped is <jk>false</jk>, it will be ignored. 242 * 243 * @param value 244 * The new value for this property. 245 * <br>Can be <jk>null</jk> to unset the property. 246 * @return This object 247 */ 248 public Xml setName(String value) { 249 name = value; 250 return this; 251 } 252 253 /** 254 * Bean property setter: <property>namespace</property>. 255 * 256 * <p> 257 * The URL of the namespace definition. Value SHOULD be in the form of a URL. 258 * 259 * @param value 260 * The new value for this property. 261 * <br>Can be <jk>null</jk> to unset the property. 262 * @return This object 263 */ 264 public Xml setNamespace(String value) { 265 namespace = value; 266 return this; 267 } 268 269 /** 270 * Bean property setter: <property>prefix</property>. 271 * 272 * <p> 273 * The prefix to be used for the name. 274 * 275 * @param value 276 * The new value for this property. 277 * <br>Can be <jk>null</jk> to unset the property. 278 * @return This object 279 */ 280 public Xml setPrefix(String value) { 281 prefix = value; 282 return this; 283 } 284 285 /** 286 * Bean property setter: <property>wrapped</property>. 287 * 288 * <p> 289 * MAY be used only for an array definition. 290 * 291 * <p> 292 * Signifies whether the array is wrapped (for example, 293 * <code><books><book/><book/><books></code>) or unwrapped 294 * (<code><book/><book/></code>). 295 * <br>The definition takes effect only when defined alongside <code>type</code> being <code>array</code> 296 * (outside the <code>items</code>). 297 * 298 * @param value 299 * The new value for this property. 300 * <br>Can be <jk>null</jk> to unset the property. 301 * @return This object 302 */ 303 public Xml setWrapped(Boolean value) { 304 wrapped = value; 305 return this; 306 } 307 308 @Override /* Overridden from OpenApiElement */ 309 public Xml strict() { 310 super.strict(); 311 return this; 312 } 313 314 @Override /* Overridden from OpenApiElement */ 315 public Xml strict(Object value) { 316 super.strict(value); 317 return this; 318 } 319}