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.*;
020import org.apache.juneau.annotation.*;
021import org.apache.juneau.json.*;
022import org.apache.juneau.utils.*;
023
024/**
025 * Root class for all Swagger beans.
026 *
027 * <h5 class='section'>See Also:</h5>
028 * <ul class='doctree'>
029 *    <li class='link'>{@doc juneau-dto.Swagger}
030 * </ul>
031 */
032public abstract class SwaggerElement {
033
034   private boolean strict;
035   private Map<String,Object> extra;
036
037   // TODO - Make package-protected in 8.0
038   @SuppressWarnings("javadoc")
039   public SwaggerElement() {}
040
041   SwaggerElement(SwaggerElement copyFrom) {
042      this.strict = copyFrom.strict;
043      this.extra = copyFrom.extra == null ? null : new LinkedHashMap<>(copyFrom.extra);
044   }
045
046   /**
047    * Returns <jk>true</jk> if contents should be validated per the Swagger spec.
048    *
049    * @return <jk>true</jk> if contents should be validated per the Swagger spec.
050    */
051   protected boolean isStrict() {
052      return strict;
053   }
054
055   /**
056    * Sets strict mode on this bean.
057    *
058    * @return This object (for method chaining).
059    */
060   protected SwaggerElement strict() {
061      strict = true;
062      return this;
063   }
064
065   /**
066    * Sets strict mode on this bean.
067    *
068    * @param value
069    *    The new value for this property.
070    *    <br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>.
071    *    <br>Can be <jk>null</jk> (interpreted as <jk>false</jk>).
072    * @return This object (for method chaining).
073    */
074   protected SwaggerElement strict(Object value) {
075      strict = value == null ? false : toBoolean(value);
076      return this;
077   }
078
079   /**
080    * Generic property getter.
081    *
082    * <p>
083    * Can be used to retrieve non-standard Swagger fields such as <js>"$ref"</js>.
084    *
085    * @param property The property name to retrieve.
086    * @param type The datatype to cast the value to.
087    * @return The property value, or <jk>null</jk> if the property does not exist or is not set.
088    */
089   public <T> T get(String property, Class<T> type) {
090      if (property == null)
091         return null;
092      switch (property) {
093         case "strict": return toType(isStrict(), type);
094         default: return toType(get(property), type);
095      }
096   };
097
098   /**
099    * Generic property getter.
100    *
101    * <p>
102    * Can be used to retrieve non-standard Swagger fields such as <js>"$ref"</js>.
103    *
104    * @param property The property name to retrieve.
105    * @return The property value, or <jk>null</jk> if the property does not exist or is not set.
106    */
107   @BeanProperty("*")
108   public Object get(String property) {
109      if (property == null || extra == null)
110         return null;
111      return extra.get(property);
112   };
113
114   /**
115    * Generic property setter.
116    *
117    * <p>
118    * Can be used to set non-standard Swagger fields such as <js>"$ref"</js>.
119    *
120    * @param property The property name to set.
121    * @param value The new value for the property.
122    * @return This object (for method chaining).
123    */
124   @BeanProperty("*")
125   public SwaggerElement set(String property, Object value) {
126      if (property == null)
127         return this;
128      switch (property) {
129         case "strict": return strict(value);
130         default:
131            if (extra == null)
132               extra = new LinkedHashMap<>();
133            extra.put(property, value);
134            return this;
135      }
136   }
137
138   /**
139    * Generic property keyset.
140    *
141    * @return
142    *    All the non-standard keys on this element.
143    *    <br>Never <jk>null</jk>.
144    */
145   @BeanProperty("*")
146   public Set<String> extraKeys() {
147      return extra == null ? Collections.EMPTY_SET : extra.keySet();
148   }
149
150   /**
151    * Returns all the keys on this element.
152    *
153    * @return
154    *    All the keys on this element.
155    *    <br>Never <jk>null</jk>.
156    */
157   public Set<String> keySet() {
158      ASet<String> s = new ASet<String>()
159         .appendIf(strict, "strict");
160      s.addAll(extraKeys());
161      return s;
162   }
163
164   /**
165    * Returns a copy of this swagger element as a modifiable map.
166    *
167    * <p>
168    * Each call produces a new map.
169    *
170    * @return A map containing all the values in this swagger element.
171    */
172   public ObjectMap asMap() {
173      ObjectMap m = new ObjectMap();
174      for (String s : keySet())
175         m.put(s, get(s, Object.class));
176      return m;
177   }
178
179   @Override /* Object */
180   public String toString() {
181      return JsonSerializer.DEFAULT.toString(this);
182   }
183
184   /**
185    * @deprecated Use {@link #get(String)}
186    */
187   @Deprecated
188   @SuppressWarnings("javadoc")
189   public Map<String,Object> getExtraProperties() {
190      if (extra == null)
191         extra = new LinkedHashMap<>();
192      return extra;
193   }
194}