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.swagger; 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 in Swagger 2.0. When using 033 * arrays, XML element names are not inferred (for singular/plural forms) and the name property should be used to add 034 * that information. This object is used to control how schema properties are serialized to XML. 035 * 036 * <h5 class='section'>Swagger 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='bjava'> 049 * <jc>// Construct using SwaggerBuilder.</jc> 050 * Xml <jv>xml</jv> = <jsm>xml</jsm>() 051 * .name(<js>"foo"</js>) 052 * .namespace(<js>"http://foo"</js>) 053 * 054 * <jc>// Serialize using JsonSerializer.</jc> 055 * String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>xml</jv>); 056 * 057 * <jc>// Or just use toString() which does the same as above.</jc> 058 * <jv>json</jv> = <jv>xml</jv>.toString(); 059 * </p> 060 * <p class='bjson'> 061 * <jc>// Output</jc> 062 * { 063 * <js>"name"</js>: <js>"foo"</js>, 064 * <js>"namespace"</js>: <js>"http://foo"</js> 065 * } 066 * </p> 067 * 068 * <h5 class='section'>See Also:</h5><ul> 069 * <li class='link'><a class="doclink" href="https://swagger.io/specification/v2/#xml-object">Swagger 2.0 Specification > XML Object</a> 070 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/2-0/describing-models/">Swagger Describing Models</a> 071 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a> 072 * </ul> 073 */ 074public class Xml extends SwaggerElement { 075 076 private String name, namespace, prefix; 077 private Boolean attribute, wrapped; 078 079 /** 080 * Default constructor. 081 */ 082 public Xml() {} 083 084 /** 085 * Copy constructor. 086 * 087 * @param copyFrom The object to copy. 088 */ 089 public Xml(Xml copyFrom) { 090 super(copyFrom); 091 092 this.attribute = copyFrom.attribute; 093 this.name = copyFrom.name; 094 this.namespace = copyFrom.namespace; 095 this.prefix = copyFrom.prefix; 096 this.wrapped = copyFrom.wrapped; 097 } 098 099 /** 100 * Make a deep copy of this object. 101 * 102 * @return A deep copy of this object. 103 */ 104 public Xml copy() { 105 return new Xml(this); 106 } 107 108 @Override /* Overridden from SwaggerElement */ 109 public <T> T get(String property, Class<T> type) { 110 assertArgNotNull("property", property); 111 return switch (property) { 112 case "attribute" -> toType(getAttribute(), type); 113 case "name" -> toType(getName(), type); 114 case "namespace" -> toType(getNamespace(), type); 115 case "prefix" -> toType(getPrefix(), type); 116 case "wrapped" -> toType(getWrapped(), type); 117 default -> super.get(property, type); 118 }; 119 } 120 121 /** 122 * Bean property getter: <property>attribute</property>. 123 * 124 * <p> 125 * Declares whether the property definition translates to an attribute instead of an element. 126 * 127 * @return The property value, or <jk>null</jk> if it is not set. 128 */ 129 public Boolean getAttribute() { return attribute; } 130 131 /** 132 * Bean property getter: <property>name</property>. 133 * 134 * <p> 135 * The name of the element/attribute used for the described schema property. 136 * 137 * @return The property value, or <jk>null</jk> if it is not set. 138 */ 139 public String getName() { return name; } 140 141 /** 142 * Bean property getter: <property>namespace</property>. 143 * 144 * <p> 145 * The URL of the namespace definition. 146 * 147 * @return The property value, or <jk>null</jk> if it is not set. 148 */ 149 public String getNamespace() { return namespace; } 150 151 /** 152 * Bean property getter: <property>prefix</property>. 153 * 154 * <p> 155 * The prefix to be used for the name. 156 * 157 * @return The property value, or <jk>null</jk> if it is not set. 158 */ 159 public String getPrefix() { return prefix; } 160 161 /** 162 * Bean property getter: <property>wrapped</property>. 163 * 164 * <p> 165 * Signifies whether the array is wrapped (for example, 166 * <c><books><book/><book/><books></c>) or unwrapped 167 * (<c><book/><book/></c>). 168 * <br>The definition takes effect only when defined alongside <c>type</c> being <c>array</c> 169 * (outside the <c>items</c>). 170 * 171 * @return The property value, or <jk>null</jk> if it is not set. 172 */ 173 public Boolean getWrapped() { return wrapped; } 174 175 @Override /* Overridden from SwaggerElement */ 176 public Set<String> keySet() { 177 // @formatter:off 178 var s = setb(String.class) 179 .addIf(nn(attribute), "attribute") 180 .addIf(nn(name), "name") 181 .addIf(nn(namespace), "namespace") 182 .addIf(nn(prefix), "prefix") 183 .addIf(nn(wrapped), "wrapped") 184 .build(); 185 // @formatter:on 186 return new MultiSet<>(s, super.keySet()); 187 } 188 189 @Override /* Overridden from SwaggerElement */ 190 public Xml set(String property, Object value) { 191 assertArgNotNull("property", property); 192 return switch (property) { 193 case "attribute" -> setAttribute(toBoolean(value)); 194 case "name" -> setName(s(value)); 195 case "namespace" -> setNamespace(s(value)); 196 case "prefix" -> setPrefix(s(value)); 197 case "wrapped" -> setWrapped(toBoolean(value)); 198 default -> { 199 super.set(property, value); 200 yield this; 201 } 202 }; 203 } 204 205 /** 206 * Bean property setter: <property>attribute</property>. 207 * 208 * <p> 209 * Declares whether the property definition translates to an attribute instead of an element. 210 * 211 * @param value 212 * The new value for this property. 213 * <br>Default value is <jk>false</jk>. 214 * <br>Can be <jk>null</jk> to unset the property. 215 * @return This object. 216 */ 217 public Xml setAttribute(Boolean value) { 218 attribute = value; 219 return this; 220 } 221 222 /** 223 * Bean property setter: <property>name</property>. 224 * 225 * <p> 226 * The name of the element/attribute used for the described schema property. 227 * 228 * @param value 229 * The new value for this property. 230 * <br>Can be <jk>null</jk> to unset the property. 231 * @return This object. 232 */ 233 public Xml setName(String value) { 234 name = value; 235 return this; 236 } 237 238 /** 239 * Bean property setter: <property>namespace</property>. 240 * 241 * <p> 242 * The URL of the namespace definition. 243 * 244 * @param value 245 * The new value for this property. 246 * <br>Can be <jk>null</jk> to unset the property. 247 * @return This object. 248 */ 249 public Xml setNamespace(String value) { 250 namespace = value; 251 return this; 252 } 253 254 /** 255 * Bean property setter: <property>prefix</property>. 256 * 257 * <p> 258 * The prefix to be used for the name. 259 * 260 * @param value 261 * The new value for this property. 262 * <br>Can be <jk>null</jk> to unset the property. 263 * @return This object. 264 */ 265 public Xml setPrefix(String value) { 266 prefix = value; 267 return this; 268 } 269 270 /** 271 * Bean property setter: <property>wrapped</property>. 272 * 273 * 274 * <p> 275 * Signifies whether the array is wrapped (for example, 276 * <c><books><book/><book/><books></c>) or unwrapped 277 * (<c><book/><book/></c>). 278 * <br>The definition takes effect only when defined alongside <c>type</c> being <c>array</c> 279 * (outside the <c>items</c>). 280 * 281 * @param value 282 * The new value for this property. 283 * <br>Can be <jk>null</jk> to unset the property. 284 * @return This object. 285 */ 286 public Xml setWrapped(Boolean value) { 287 wrapped = value; 288 return this; 289 } 290 291 /** 292 * Sets strict mode on this bean. 293 * 294 * @return This object. 295 */ 296 @Override 297 public Xml strict() { 298 super.strict(); 299 return this; 300 } 301 302 /** 303 * Sets strict mode on this bean. 304 * 305 * @param value 306 * The new value for this property. 307 * <br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>. 308 * <br>Can be <jk>null</jk> (interpreted as <jk>false</jk>). 309 * @return This object. 310 */ 311 @Override 312 public Xml strict(Object value) { 313 super.strict(value); 314 return this; 315 } 316}