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; 014 015import java.lang.reflect.*; 016import java.util.*; 017 018import org.apache.juneau.annotation.*; 019import org.apache.juneau.csv.annotation.*; 020import org.apache.juneau.html.annotation.*; 021import org.apache.juneau.jso.annotation.*; 022import org.apache.juneau.json.annotation.*; 023import org.apache.juneau.jsonschema.annotation.*; 024import org.apache.juneau.msgpack.annotation.*; 025import org.apache.juneau.oapi.annotation.*; 026import org.apache.juneau.parser.annotation.*; 027import org.apache.juneau.plaintext.annotation.*; 028import org.apache.juneau.reflect.*; 029import org.apache.juneau.serializer.annotation.*; 030import org.apache.juneau.soap.annotation.*; 031import org.apache.juneau.svl.*; 032import org.apache.juneau.uon.annotation.*; 033import org.apache.juneau.urlencoding.annotation.*; 034import org.apache.juneau.xml.annotation.*; 035 036/** 037 * Builder class for building instances of serializers and parsers. 038 */ 039public abstract class ContextBuilder { 040 041 /** Contains all the modifiable settings for the implementation class. */ 042 protected final PropertyStoreBuilder psb; 043 044 /** 045 * Constructor. 046 * Default settings. 047 */ 048 public ContextBuilder() { 049 this.psb = PropertyStore.create(); 050 } 051 052 /** 053 * Constructor. 054 * 055 * @param ps The initial configuration settings for this builder. 056 */ 057 public ContextBuilder(PropertyStore ps) { 058 if (ps == null) 059 ps = PropertyStore.DEFAULT; 060 this.psb = ps.builder(); 061 } 062 063 /** 064 * Constructor. 065 * 066 * <p> 067 * Used in cases where multiple context builder are sharing the same property store builder. 068 * <br>(e.g. <c>HtlmlDocBuilder</c>) 069 * 070 * @param psb The property store builder to use. 071 */ 072 protected ContextBuilder(PropertyStoreBuilder psb) { 073 this.psb = psb; 074 } 075 076 /** 077 * Returns access to the inner property store builder. 078 * 079 * <p> 080 * Used in conjunction with {@link #ContextBuilder(PropertyStoreBuilder)} when builders share property store builders. 081 * 082 * @return The inner property store builder. 083 */ 084 protected PropertyStoreBuilder getPropertyStoreBuilder() { 085 return psb; 086 } 087 088 /** 089 * Build the object. 090 * 091 * @return The built object. 092 * Subsequent calls to this method will create new instances. 093 */ 094 public abstract Context build(); 095 096 /** 097 * Copies the settings from the specified property store into this builder. 098 * 099 * @param copyFrom The factory whose settings are being copied. 100 * @return This object (for method chaining). 101 */ 102 public ContextBuilder apply(PropertyStore copyFrom) { 103 this.psb.apply(copyFrom); 104 return this; 105 } 106 107 /** 108 * Applies a set of annotations to this property store. 109 * 110 * @param al The list of all annotations annotated with {@link PropertyStoreApply}. 111 * @param r The string resolver for resolving variables in annotation values. 112 * @return This object (for method chaining). 113 */ 114 public ContextBuilder applyAnnotations(AnnotationList al, VarResolverSession r) { 115 this.psb.applyAnnotations(al, r); 116 return this; 117 } 118 119 /** 120 * Applies any of the various <ja>@XConfig</ja> annotations on the specified class to this context. 121 * 122 * <p> 123 * Applies any of the following annotations: 124 * <ul class='javatree'> 125 * <li class ='ja'>{@link BeanConfig} 126 * <li class ='ja'>{@link CsvConfig} 127 * <li class ='ja'>{@link HtmlConfig} 128 * <li class ='ja'>{@link HtmlDocConfig} 129 * <li class ='ja'>{@link JsoConfig} 130 * <li class ='ja'>{@link JsonConfig} 131 * <li class ='ja'>{@link JsonSchemaConfig} 132 * <li class ='ja'>{@link MsgPackConfig} 133 * <li class ='ja'>{@link OpenApiConfig} 134 * <li class ='ja'>{@link ParserConfig} 135 * <li class ='ja'>{@link PlainTextConfig} 136 * <li class ='ja'>{@link SerializerConfig} 137 * <li class ='ja'>{@link SoapXmlConfig} 138 * <li class ='ja'>{@link UonConfig} 139 * <li class ='ja'>{@link UrlEncodingConfig} 140 * <li class ='ja'>{@link XmlConfig} 141 * <li class ='ja'><c>RdfConfig</c> 142 * </ul> 143 * 144 * <p> 145 * Annotations are appended in the following order: 146 * <ol> 147 * <li>On the package of this class. 148 * <li>On interfaces ordered parent-to-child. 149 * <li>On parent classes ordered parent-to-child. 150 * <li>On this class. 151 * </ol> 152 * 153 * @param fromClass The class on which the annotations are defined. 154 * @return This object (for method chaining). 155 */ 156 public ContextBuilder applyAnnotations(Class<?> fromClass) { 157 applyAnnotations(ClassInfo.of(fromClass).getAnnotationListParentFirst(ConfigAnnotationFilter.INSTANCE), VarResolver.DEFAULT.createSession()); 158 return this; 159 } 160 161 /** 162 * Applies any of the various <ja>@XConfig</ja> annotations on the specified method to this context. 163 * 164 * <p> 165 * Applies any of the following annotations: 166 * <ul class='javatree'> 167 * <li class ='ja'>{@link BeanConfig} 168 * <li class ='ja'>{@link CsvConfig} 169 * <li class ='ja'>{@link HtmlConfig} 170 * <li class ='ja'>{@link HtmlDocConfig} 171 * <li class ='ja'>{@link JsoConfig} 172 * <li class ='ja'>{@link JsonConfig} 173 * <li class ='ja'>{@link JsonSchemaConfig} 174 * <li class ='ja'>{@link MsgPackConfig} 175 * <li class ='ja'>{@link OpenApiConfig} 176 * <li class ='ja'>{@link ParserConfig} 177 * <li class ='ja'>{@link PlainTextConfig} 178 * <li class ='ja'>{@link SerializerConfig} 179 * <li class ='ja'>{@link SoapXmlConfig} 180 * <li class ='ja'>{@link UonConfig} 181 * <li class ='ja'>{@link UrlEncodingConfig} 182 * <li class ='ja'>{@link XmlConfig} 183 * <li class ='ja'><c>RdfConfig</c> 184 * </ul> 185 * 186 * <p> 187 * Annotations are appended in the following orders: 188 * <ol> 189 * <li>On the package of the method class. 190 * <li>On interfaces ordered parent-to-child. 191 * <li>On parent classes ordered parent-to-child. 192 * <li>On the method class. 193 * <li>On this method and matching methods ordered parent-to-child. 194 * </ol> 195 * 196 * @param fromMethod The method on which the annotations are defined. 197 * @return This object (for method chaining). 198 */ 199 public ContextBuilder applyAnnotations(Method fromMethod) { 200 applyAnnotations(MethodInfo.of(fromMethod).getAnnotationListParentFirst(ConfigAnnotationFilter.INSTANCE), VarResolver.DEFAULT.createSession()); 201 return this; 202 } 203 204 /** 205 * Build a new instance of the specified object. 206 * 207 * @param c The subclass of {@link Context} to instantiate. 208 * @return A new object using the settings defined in this builder. 209 */ 210 211 public <T extends Context> T build(Class<T> c) { 212 return ContextCache.INSTANCE.create(c, getPropertyStore()); 213 } 214 215 /** 216 * Returns a read-only snapshot of the current property store on this builder. 217 * 218 * @return A property store object. 219 */ 220 public PropertyStore getPropertyStore() { 221 return psb.build(); 222 } 223 224 //----------------------------------------------------------------------------------------------------------------- 225 // Properties 226 //----------------------------------------------------------------------------------------------------------------- 227 228 /** 229 * Sets a configuration property on this object. 230 * 231 * @param name The property name. 232 * @param value The property value. 233 * @return This object (for method chaining). 234 * @see PropertyStoreBuilder#set(String, Object) 235 */ 236 public ContextBuilder set(String name, Object value) { 237 psb.set(name, value); 238 return this; 239 } 240 241 /** 242 * Peeks at a configuration property on this object. 243 * 244 * @param key The property name. 245 * @return This object (for method chaining). 246 */ 247 public Object peek(String key) { 248 return psb.peek(key); 249 } 250 251 /** 252 * Peeks at a configuration property on this object. 253 * 254 * @param c The type to convert to. 255 * @param key The property name. 256 * @return This object (for method chaining). 257 * @param <T> The type to convert to. 258 */ 259 public <T> T peek(Class<T> c, String key) { 260 return psb.peek(c, key); 261 } 262 263 /** 264 * Sets multiple configuration properties on this object. 265 * 266 * @param properties The properties to set on this class. 267 * @return This object (for method chaining). 268 * @see PropertyStoreBuilder#set(java.util.Map) 269 */ 270 public ContextBuilder set(Map<String,Object> properties) { 271 psb.set(properties); 272 return this; 273 } 274 275 /** 276 * Adds multiple configuration properties on this object. 277 * 278 * @param properties The properties to set on this class. 279 * @return This object (for method chaining). 280 * @see PropertyStoreBuilder#add(java.util.Map) 281 */ 282 public ContextBuilder add(Map<String,Object> properties) { 283 psb.add(properties); 284 return this; 285 } 286 287 /** 288 * Adds a value to a SET or LIST property. 289 * 290 * @param name The property name. 291 * @param value The new value to add to the SET property. 292 * @return This object (for method chaining). 293 * @throws ConfigException If property is not a SET property. 294 */ 295 public ContextBuilder addTo(String name, Object value) { 296 psb.addTo(name, value); 297 return this; 298 } 299 300 /** 301 * Adds or overwrites a value to a SET, LIST, or MAP property. 302 * 303 * @param name The property name. 304 * @param key The property value map key. 305 * @param value The property value map value. 306 * @return This object (for method chaining). 307 * @throws ConfigException If property is not a MAP property. 308 */ 309 public ContextBuilder addTo(String name, String key, Object value) { 310 psb.addTo(name, key, value); 311 return this; 312 } 313 314 /** 315 * Removes a value from a SET, LIST, or MAP property. 316 * 317 * @param name The property name. 318 * @param value The property value in the SET property. 319 * @return This object (for method chaining). 320 * @throws ConfigException If property is not a SET property. 321 */ 322 public ContextBuilder removeFrom(String name, Object value) { 323 psb.removeFrom(name, value); 324 return this; 325 } 326}