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 fromClasses The classes on which the annotations are defined. 154 * @return This object (for method chaining). 155 */ 156 public ContextBuilder applyAnnotations(Class<?>...fromClasses) { 157 for (Class<?> c : fromClasses) 158 applyAnnotations(ClassInfo.of(c).getAnnotationListParentFirst(ConfigAnnotationFilter.INSTANCE), VarResolver.DEFAULT.createSession()); 159 return this; 160 } 161 162 /** 163 * Applies any of the various <ja>@XConfig</ja> annotations on the specified method to this context. 164 * 165 * <p> 166 * Applies any of the following annotations: 167 * <ul class='javatree'> 168 * <li class ='ja'>{@link BeanConfig} 169 * <li class ='ja'>{@link CsvConfig} 170 * <li class ='ja'>{@link HtmlConfig} 171 * <li class ='ja'>{@link HtmlDocConfig} 172 * <li class ='ja'>{@link JsoConfig} 173 * <li class ='ja'>{@link JsonConfig} 174 * <li class ='ja'>{@link JsonSchemaConfig} 175 * <li class ='ja'>{@link MsgPackConfig} 176 * <li class ='ja'>{@link OpenApiConfig} 177 * <li class ='ja'>{@link ParserConfig} 178 * <li class ='ja'>{@link PlainTextConfig} 179 * <li class ='ja'>{@link SerializerConfig} 180 * <li class ='ja'>{@link SoapXmlConfig} 181 * <li class ='ja'>{@link UonConfig} 182 * <li class ='ja'>{@link UrlEncodingConfig} 183 * <li class ='ja'>{@link XmlConfig} 184 * <li class ='ja'><c>RdfConfig</c> 185 * </ul> 186 * 187 * <p> 188 * Annotations are appended in the following orders: 189 * <ol> 190 * <li>On the package of the method class. 191 * <li>On interfaces ordered parent-to-child. 192 * <li>On parent classes ordered parent-to-child. 193 * <li>On the method class. 194 * <li>On this method and matching methods ordered parent-to-child. 195 * </ol> 196 * 197 * @param fromMethods The methods on which the annotations are defined. 198 * @return This object (for method chaining). 199 */ 200 public ContextBuilder applyAnnotations(Method...fromMethods) { 201 for (Method m : fromMethods) 202 applyAnnotations(MethodInfo.of(m).getAnnotationListParentFirst(ConfigAnnotationFilter.INSTANCE), VarResolver.DEFAULT.createSession()); 203 return this; 204 } 205 206 /** 207 * Build a new instance of the specified object. 208 * 209 * @param c The subclass of {@link Context} to instantiate. 210 * @return A new object using the settings defined in this builder. 211 */ 212 213 public <T extends Context> T build(Class<T> c) { 214 return ContextCache.INSTANCE.create(c, getPropertyStore()); 215 } 216 217 /** 218 * Returns a read-only snapshot of the current property store on this builder. 219 * 220 * @return A property store object. 221 */ 222 public PropertyStore getPropertyStore() { 223 return psb.build(); 224 } 225 226 //----------------------------------------------------------------------------------------------------------------- 227 // Properties 228 //----------------------------------------------------------------------------------------------------------------- 229 230 /** 231 * Sets a configuration property on this object. 232 * 233 * @param name The property name. 234 * @param value The property value. 235 * @return This object (for method chaining). 236 * @see PropertyStoreBuilder#set(String, Object) 237 */ 238 public ContextBuilder set(String name, Object value) { 239 psb.set(name, value); 240 return this; 241 } 242 243 /** 244 * Peeks at a configuration property on this object. 245 * 246 * @param key The property name. 247 * @return This object (for method chaining). 248 */ 249 public Object peek(String key) { 250 return psb.peek(key); 251 } 252 253 /** 254 * Peeks at a configuration property on this object. 255 * 256 * @param c The type to convert to. 257 * @param key The property name. 258 * @return This object (for method chaining). 259 * @param <T> The type to convert to. 260 */ 261 public <T> T peek(Class<T> c, String key) { 262 return psb.peek(c, key); 263 } 264 265 /** 266 * Sets multiple configuration properties on this object. 267 * 268 * @param properties The properties to set on this class. 269 * @return This object (for method chaining). 270 * @see PropertyStoreBuilder#set(java.util.Map) 271 */ 272 public ContextBuilder set(Map<String,Object> properties) { 273 psb.set(properties); 274 return this; 275 } 276 277 /** 278 * Adds multiple configuration properties on this object. 279 * 280 * @param properties The properties to set on this class. 281 * @return This object (for method chaining). 282 * @see PropertyStoreBuilder#add(java.util.Map) 283 */ 284 public ContextBuilder add(Map<String,Object> properties) { 285 psb.add(properties); 286 return this; 287 } 288 289 /** 290 * Adds a value to a SET or LIST property. 291 * 292 * @param name The property name. 293 * @param value The new value to add to the SET property. 294 * @return This object (for method chaining). 295 * @throws ConfigException If property is not a SET property. 296 */ 297 public ContextBuilder addTo(String name, Object value) { 298 psb.addTo(name, value); 299 return this; 300 } 301 302 /** 303 * Adds or overwrites a value to a SET, LIST, or MAP property. 304 * 305 * @param name The property name. 306 * @param key The property value map key. 307 * @param value The property value map value. 308 * @return This object (for method chaining). 309 * @throws ConfigException If property is not a MAP property. 310 */ 311 public ContextBuilder addTo(String name, String key, Object value) { 312 psb.addTo(name, key, value); 313 return this; 314 } 315 316 /** 317 * Removes a value from a SET, LIST, or MAP property. 318 * 319 * @param name The property name. 320 * @param value The property value in the SET property. 321 * @return This object (for method chaining). 322 * @throws ConfigException If property is not a SET property. 323 */ 324 public ContextBuilder removeFrom(String name, Object value) { 325 psb.removeFrom(name, value); 326 return this; 327 } 328}