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