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.openapi3;
014
015import static org.apache.juneau.common.internal.StringUtils.*;
016import static org.apache.juneau.internal.CollectionUtils.*;
017import static org.apache.juneau.internal.ConverterUtils.*;
018
019import org.apache.juneau.annotation.Bean;
020import org.apache.juneau.internal.*;
021
022import java.util.Set;
023
024/**
025 * A metadata object that allows for more fine-tuned XML model definitions.
026 *
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@Bean(properties="name,namespace,prefix,attribute,wrapped,*")
031@FluentSetters
032public class Xml extends OpenApiElement {
033
034   private String
035      name,
036      namespace,
037      prefix;
038   private Boolean
039      attribute,
040      wrapped;
041
042   /**
043    * Default constructor.
044    */
045   public Xml() {}
046
047   /**
048    * Copy constructor.
049    *
050    * @param copyFrom The object to copy.
051    */
052   public Xml(Xml copyFrom) {
053      super(copyFrom);
054
055      this.name = copyFrom.name;
056      this.namespace = copyFrom.namespace;
057      this.prefix = copyFrom.prefix;
058      this.attribute = copyFrom.attribute;
059      this.wrapped = copyFrom.wrapped;
060   }
061
062   /**
063    * Make a deep copy of this object.
064    *
065    * @return A deep copy of this object.
066    */
067   public Xml copy() {
068      return new Xml(this);
069   }
070
071   /**
072    * Bean property getter:  <property>name</property>.
073    *
074    * <p>
075    * Replaces the name of the element/attribute used for the described schema property.
076    *
077    * <p>
078    * When defined within the Items Object (<code>items</code>), it will affect the name of the individual XML elements
079    * within the list.
080    * <br>When defined alongside <code>type</code> being array (outside the <code>items</code>), it will affect the
081    * wrapping element and only if wrapped is <jk>true</jk>.
082    * <br>If wrapped is <jk>false</jk>, it will be ignored.
083    *
084    * @return The property value, or <jk>null</jk> if it is not set.
085    */
086   public String getName() {
087      return name;
088   }
089
090   /**
091    * Bean property setter:  <property>name</property>.
092    *
093    * <p>
094    * Replaces the name of the element/attribute used for the described schema property.
095    *
096    * <p>
097    * When defined within the Items Object (<code>items</code>), it will affect the name of the individual XML elements
098    * within the list.
099    * <br>When defined alongside <code>type</code> being array (outside the <code>items</code>), it will affect the
100    * wrapping element and only if wrapped is <jk>true</jk>.
101    * <br>If wrapped is <jk>false</jk>, it will be ignored.
102    *
103    * @param value
104    *    The new value for this property.
105    *    <br>Can be <jk>null</jk> to unset the property.
106    * @return This object
107    */
108   public Xml setName(String value) {
109      name = value;
110      return this;
111   }
112
113   /**
114    * Bean property getter:  <property>namespace</property>.
115    *
116    * <p>
117    * The URL of the namespace definition. Value SHOULD be in the form of a URL.
118    *
119    * @return The property value, or <jk>null</jk> if it is not set.
120    */
121   public String getNamespace() {
122      return namespace;
123   }
124
125   /**
126    * Bean property setter:  <property>namespace</property>.
127    *
128    * <p>
129    * The URL of the namespace definition. Value SHOULD be in the form of a URL.
130    *
131    * @param value
132    *    The new value for this property.
133    *    <br>Can be <jk>null</jk> to unset the property.
134    * @return This object
135    */
136   public Xml setNamespace(String value) {
137      namespace = value;
138      return this;
139   }
140
141   /**
142    * Bean property getter:  <property>prefix</property>.
143    *
144    * <p>
145    * The prefix to be used for the name.
146    *
147    * @return The property value, or <jk>null</jk> if it is not set.
148    */
149   public String getPrefix() {
150      return prefix;
151   }
152
153   /**
154    * Bean property setter:  <property>prefix</property>.
155    *
156    * <p>
157    * The prefix to be used for the name.
158    *
159    * @param value
160    *    The new value for this property.
161    *    <br>Can be <jk>null</jk> to unset the property.
162    * @return This object
163    */
164   public Xml setPrefix(String value) {
165      prefix = value;
166      return this;
167   }
168
169   /**
170    * Bean property getter:  <property>attribute</property>.
171    *
172    * <p>
173    * Declares whether the property definition translates to an attribute instead of an element.
174    *
175    * @return The property value, or <jk>null</jk> if it is not set.
176    */
177   public Boolean getAttribute() {
178      return attribute;
179   }
180
181   /**
182    * Bean property setter:  <property>attribute</property>.
183    *
184    * <p>
185    * Declares whether the property definition translates to an attribute instead of an element.
186    *
187    * @param value
188    *    The new value for this property.
189    *    <br>Default value is <jk>false</jk>.
190    *    <br>Can be <jk>null</jk> to unset the property.
191    * @return This object
192    */
193   public Xml setAttribute(Boolean value) {
194      attribute = value;
195      return this;
196   }
197
198   /**
199    * Bean property getter:  <property>wrapped</property>.
200    *
201    * <p>
202    * MAY be used only for an array definition.
203    *
204    * <p>
205    * Signifies whether the array is wrapped (for example,
206    * <code>&lt;books&gt;&lt;book/&gt;&lt;book/&gt;&lt;books&gt;</code>) or unwrapped
207    * (<code>&lt;book/&gt;&lt;book/&gt;</code>).
208    * <br>The definition takes effect only when defined alongside <code>type</code> being <code>array</code>
209    * (outside the <code>items</code>).
210    *
211    * @return The property value, or <jk>null</jk> if it is not set.
212    */
213   public Boolean getWrapped() {
214      return wrapped;
215   }
216
217   /**
218    * Bean property setter:  <property>wrapped</property>.
219    *
220    * <p>
221    * MAY be used only for an array definition.
222    *
223    * <p>
224    * Signifies whether the array is wrapped (for example,
225    * <code>&lt;books&gt;&lt;book/&gt;&lt;book/&gt;&lt;books&gt;</code>) or unwrapped
226    * (<code>&lt;book/&gt;&lt;book/&gt;</code>).
227    * <br>The definition takes effect only when defined alongside <code>type</code> being <code>array</code>
228    * (outside the <code>items</code>).
229    *
230    * @param value
231    *    The new value for this property.
232    *    <br>Can be <jk>null</jk> to unset the property.
233    * @return This object
234    */
235   public Xml setWrapped(Boolean value) {
236      this.wrapped = value;
237      return this;
238   }
239
240   // <FluentSetters>
241
242   // </FluentSetters>
243
244   @Override /* OpenApiElement */
245   public <T> T get(String property, Class<T> type) {
246      if (property == null)
247         return null;
248      switch (property) {
249         case "name": return toType(getName(), type);
250         case "namespace": return toType(getNamespace(), type);
251         case "prefix": return toType(getPrefix(), type);
252         case "attribute": return toType(getAttribute(), type);
253         case "wrapped": return toType(getWrapped(), type);
254         default: return super.get(property, type);
255      }
256   }
257
258   @Override /* OpenApiElement */
259   public Xml set(String property, Object value) {
260      if (property == null)
261         return this;
262      switch (property) {
263         case "name": return setName(stringify(value));
264         case "namespace": return setNamespace(stringify(value));
265         case "prefix": return setPrefix(stringify(value));
266         case "attribute": return setAttribute(toBoolean(value));
267         case "wrapped": return setWrapped(toBoolean(value));
268         default:
269            super.set(property, value);
270            return this;
271      }
272   }
273
274   @Override /* OpenApiElement */
275   public Set<String> keySet() {
276      Set<String> s = setBuilder(String.class)
277         .addIf(name != null, "name")
278         .addIf(namespace != null, "namespace")
279         .addIf(prefix != null, "prefix")
280         .addIf(attribute != null, "attribute")
281         .addIf(wrapped != null, "wrapped")
282         .build();
283      return new MultiSet<>(s, super.keySet());
284   }
285}