001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.bean.swagger; 018 019import static org.apache.juneau.commons.utils.CollectionUtils.*; 020import static org.apache.juneau.commons.utils.Shorts.*; 021import static org.apache.juneau.marshall.internal.ConverterUtils.*; 022 023import java.util.*; 024 025import org.apache.juneau.commons.bean.*; 026import org.apache.juneau.marshall.collections.*; 027import org.apache.juneau.marshall.marshaller.*; 028 029/** 030 * Root class for all Swagger beans. 031 * 032 * <h5 class='section'>See Also:</h5><ul> 033 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JuneauBeanSwagger2">juneau-bean-swagger-v2</a> 034 * </ul> 035 */ 036@SuppressWarnings({ 037 "java:S1192" // Duplicated literals (argument/property names) read more clearly inline than as constants 038}) 039public abstract class SwaggerElement { 040 041 private boolean strict; 042 private Map<String,Object> extra; 043 044 SwaggerElement() {} 045 046 SwaggerElement(SwaggerElement copyFrom) { 047 this.strict = copyFrom.strict; 048 this.extra = cp(copyFrom.extra); 049 } 050 051 /** 052 * Returns a copy of this swagger element as a modifiable map. 053 * 054 * <p> 055 * Each call produces a new map. 056 * 057 * @return A map containing all the values in this swagger element. 058 */ 059 public JsonMap asMap() { 060 var m = new JsonMap(); 061 keySet().forEach(x -> m.put(x, get(x, Object.class))); 062 return m; 063 } 064 065 /** 066 * Generic property keyset. 067 * 068 * @return 069 * All the non-standard keys on this element. 070 * <br>Never <jk>null</jk>. 071 */ 072 @BeanProp("*") 073 public Set<String> extraKeys() { 074 return extra == null ? Collections.emptySet() : u(extra.keySet()); 075 } 076 077 /** 078 * Generic property getter. 079 * 080 * <p> 081 * Can be used to retrieve non-standard Swagger fields such as <js>"$ref"</js>. 082 * 083 * @param property The property name to retrieve. Must not be <jk>null</jk>, or an {@link IllegalArgumentException} is thrown. 084 * @return The property value, or <jk>null</jk> if the property does not exist or is not set. 085 */ 086 @BeanProp("*") 087 public Object get(String property) { 088 reqnn("property", property); 089 return o(extra).map(x -> x.get(property)).orElse(null); 090 } 091 092 /** 093 * Generic property getter. 094 * 095 * <p> 096 * Can be used to retrieve non-standard Swagger fields such as <js>"$ref"</js>. 097 * 098 * @param <T> The datatype to cast the value to. 099 * @param property The property name to retrieve. 100 * @param type The datatype to cast the value to. 101 * @return The property value, or <jk>null</jk> if the property does not exist or is not set. 102 */ 103 public <T> T get(String property, Class<T> type) { 104 reqnn("property", property); 105 return toType(get(property), type); 106 } 107 108 /** 109 * Returns all the keys on this element. 110 * 111 * @return 112 * All the keys on this element. 113 * <br>Never <jk>null</jk>. 114 */ 115 public Set<String> keySet() { 116 return extraKeys(); 117 } 118 119 /** 120 * Generic property setter. 121 * 122 * <p> 123 * Can be used to set non-standard Swagger fields such as <js>"$ref"</js>. 124 * 125 * @param property The property name to set. Must not be <jk>null</jk>, or an {@link IllegalArgumentException} is thrown. 126 * @param value The new value for the property. 127 * @return This object. 128 */ 129 @BeanProp("*") 130 public SwaggerElement set(String property, Object value) { 131 reqnn("property", property); 132 if (strict) 133 throw rex("Cannot set property '%s' in strict mode.", property); 134 if (extra == null) 135 extra = map(); 136 extra.put(property, value); 137 return this; 138 } 139 140 @Override /* Overridden from Object */ 141 public String toString() { 142 return Json.of(this); 143 } 144 145 /** 146 * Returns <jk>true</jk> if contents should be validated per the Swagger spec. 147 * 148 * @return <jk>true</jk> if contents should be validated per the Swagger spec. 149 */ 150 protected boolean isStrict() { return strict; } 151 152 /** 153 * Sets strict mode on this bean. 154 * 155 * @return This object. 156 */ 157 protected SwaggerElement strict() { 158 strict = true; 159 return this; 160 } 161 162 /** 163 * Sets strict mode on this bean. 164 * 165 * @param value 166 * The new value for this property. 167 * <br>Non-boolean values will be converted to boolean using <code>Boolean.<jsm>valueOf</jsm>(value.toString())</code>. 168 * @return This object. 169 */ 170 protected SwaggerElement strict(Object value) { 171 reqnn("value", value); 172 strict = toBoolean(value); 173 return this; 174 } 175}