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