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.util.*;
016
017/**
018 * Builder class for building instances of serializers and parsers.
019 */
020public abstract class ContextBuilder {
021
022   /** Contains all the modifiable settings for the implementation class. */
023   protected final PropertyStoreBuilder psb;
024
025   /**
026    * Constructor.
027    * Default settings.
028    */
029   public ContextBuilder() {
030      this.psb = PropertyStore.create();
031   }
032
033   /**
034    * Constructor.
035    * 
036    * @param ps The initial configuration settings for this builder.
037    */
038   public ContextBuilder(PropertyStore ps) {
039      this.psb = ps.builder();
040   }
041
042   /**
043    * Constructor.
044    * 
045    * <p>
046    * Used in cases where multiple context builder are sharing the same property store builder.
047    * <br>(e.g. <code>HtlmlDocBuilder</code>)
048    * 
049    * @param psb The property store builder to use.
050    */
051   protected ContextBuilder(PropertyStoreBuilder psb) {
052      this.psb = psb;
053   }
054   
055   /**
056    * Returns access to the inner property store builder.
057    * 
058    * <p>
059    * Used in conjunction with {@link #ContextBuilder(PropertyStoreBuilder)} when builders share property store builders.
060    * 
061    * @return The inner property store builder.
062    */
063   protected PropertyStoreBuilder getPropertyStoreBuilder() {
064      return psb;
065   }
066
067   /**
068    * Build the object.
069    * 
070    * @return The built object.
071    * Subsequent calls to this method will create new instances.
072    */
073   public abstract Context build();
074
075   /**
076    * Copies the settings from the specified property store into this builder.
077    * 
078    * @param copyFrom The factory whose settings are being copied.
079    * @return This object (for method chaining).
080    */
081   public ContextBuilder apply(PropertyStore copyFrom) {
082      this.psb.apply(copyFrom);
083      return this;
084   }
085
086   /**
087    * Build a new instance of the specified object.
088    * 
089    * @param c The subclass of {@link Context} to instantiate.
090    * @return A new object using the settings defined in this builder.
091    */
092
093   public <T extends Context> T build(Class<T> c) {
094      return ContextCache.INSTANCE.create(c, getPropertyStore());
095   }
096
097   /**
098    * Returns a read-only snapshot of the current property store on this builder.
099    * 
100    * @return A property store object.
101    */
102   public PropertyStore getPropertyStore() {
103      return psb.build();
104   }
105   
106   //--------------------------------------------------------------------------------
107   // Properties
108   //--------------------------------------------------------------------------------
109
110   /**
111    * Sets a configuration property on this object.
112    * 
113    * @param name The property name.
114    * @param value The property value.
115    * @return This object (for method chaining).
116    * @see PropertyStoreBuilder#set(String, Object)
117    */
118   public ContextBuilder set(String name, Object value) {
119      psb.set(name, value);
120      return this;
121   }
122
123   /**
124    * Sets or adds to a SET or LIST property.
125    * 
126    * @param append
127    *    If <jk>true</jk>, the previous value is appended to.  Otherwise, the previous value is replaced. 
128    * @param name The property name.
129    * @param value The property value.
130    * @return This object (for method chaining).
131    * @see PropertyStoreBuilder#set(String, Object)
132    */
133   public ContextBuilder set(boolean append, String name, Object value) {
134      if (append)
135         psb.addTo(name, value);
136      else
137         psb.set(name, value);
138      return this;
139   }
140
141   /**
142    * Sets multiple configuration properties on this object.
143    * 
144    * @param properties The properties to set on this class.
145    * @return This object (for method chaining).
146    * @see PropertyStoreBuilder#set(java.util.Map)
147    */
148   public ContextBuilder set(Map<String,Object> properties) {
149      psb.set(properties);
150      return this;
151   }
152
153   /**
154    * Adds multiple configuration properties on this object.
155    * 
156    * @param properties The properties to set on this class.
157    * @return This object (for method chaining).
158    * @see PropertyStoreBuilder#add(java.util.Map)
159    */
160   public ContextBuilder add(Map<String,Object> properties) {
161      psb.add(properties);
162      return this;
163   }
164
165   /**
166    * Adds a value to a SET or LIST property.
167    * 
168    * @param name The property name.
169    * @param value The new value to add to the SET property.
170    * @return This object (for method chaining).
171    * @throws ConfigException If property is not a SET property.
172    */
173   public ContextBuilder addTo(String name, Object value) {
174      psb.addTo(name, value);
175      return this;
176   }
177
178   /**
179    * Adds or overwrites a value to a SET, LIST, or MAP property.
180    * 
181    * @param name The property name.
182    * @param key The property value map key.
183    * @param value The property value map value.
184    * @return This object (for method chaining).
185    * @throws ConfigException If property is not a MAP property.
186    */
187   public ContextBuilder addTo(String name, String key, Object value) {
188      psb.addTo(name, key, value);
189      return this;
190   }
191
192   /**
193    * Removes a value from a SET, LIST, or MAP property.
194    * 
195    * @param name The property name.
196    * @param value The property value in the SET property.
197    * @return This object (for method chaining).
198    * @throws ConfigException If property is not a SET property.
199    */
200   public ContextBuilder removeFrom(String name, Object value) {
201      psb.removeFrom(name, value);
202      return this;
203   }
204}