1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.juneau.bean.openapi3;
18
19 import static org.apache.juneau.commons.utils.AssertionUtils.*;
20 import static org.apache.juneau.commons.utils.CollectionUtils.*;
21 import static org.apache.juneau.commons.utils.Utils.*;
22 import static org.apache.juneau.internal.ConverterUtils.*;
23
24 import java.util.*;
25
26 import org.apache.juneau.commons.collections.*;
27
28 /**
29 * A metadata object that allows for more fine-tuned XML model definitions.
30 *
31 * <p>
32 * The Xml Object is a metadata object that allows for more fine-tuned XML model definitions. When using arrays,
33 * XML element names are not inferred (for singular/plural forms) and the name property should be used to add that
34 * information. This object is used to control how schema properties are serialized to XML.
35 *
36 * <h5 class='section'>OpenAPI Specification:</h5>
37 * <p>
38 * The Xml Object is composed of the following fields:
39 * <ul class='spaced-list'>
40 * <li><c>name</c> (string) - Replaces the name of the element/attribute used for the described schema property
41 * <li><c>namespace</c> (string) - The URI of the namespace definition
42 * <li><c>prefix</c> (string) - The prefix to be used for the name
43 * <li><c>attribute</c> (boolean) - Declares whether the property definition translates to an attribute instead of an element
44 * <li><c>wrapped</c> (boolean) - May be used only for an array definition. Signifies whether the array is wrapped
45 * </ul>
46 *
47 * <h5 class='section'>Example:</h5>
48 * <p class='bcode'>
49 * <jc>// Construct using SwaggerBuilder.</jc>
50 * Xml <jv>x</jv> = <jsm>xml</jsm>().setName(<js>"book"</js>).setNamespace(<js>"http://example.com/schema"</js>);
51 *
52 * <jc>// Serialize using JsonSerializer.</jc>
53 * String <jv>json</jv> = Json.<jsm>from</jsm>(<jv>x</jv>);
54 *
55 * <jc>// Or just use toString() which does the same as above.</jc>
56 * <jv>json</jv> = <jv>x</jv>.toString();
57 * </p>
58 * <p class='bcode'>
59 * <jc>// Output</jc>
60 * {
61 * <js>"name"</js>: <js>"book"</js>,
62 * <js>"namespace"</js>: <js>"http://example.com/schema"</js>
63 * }
64 * </p>
65 *
66 * <h5 class='section'>See Also:</h5><ul>
67 * <li class='link'><a class="doclink" href="https://spec.openapis.org/oas/v3.0.0#xml-object">OpenAPI Specification > XML Object</a>
68 * <li class='link'><a class="doclink" href="https://swagger.io/docs/specification/data-models/representing-xml/">OpenAPI Representing XML</a>
69 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanOpenApi3">juneau-bean-openapi-v3</a>
70 * </ul>
71 */
72 public class Xml extends OpenApiElement {
73
74 private String name, namespace, prefix;
75 private Boolean attribute, wrapped;
76
77 /**
78 * Default constructor.
79 */
80 public Xml() {}
81
82 /**
83 * Copy constructor.
84 *
85 * @param copyFrom The object to copy.
86 */
87 public Xml(Xml copyFrom) {
88 super(copyFrom);
89
90 this.name = copyFrom.name;
91 this.namespace = copyFrom.namespace;
92 this.prefix = copyFrom.prefix;
93 this.attribute = copyFrom.attribute;
94 this.wrapped = copyFrom.wrapped;
95 }
96
97 /**
98 * Make a deep copy of this object.
99 *
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 }