This project has retired. For details please refer to its Attic page.
Source code
001/**
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *   http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing,
013 * software distributed under the License is distributed on an
014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015 * KIND, either express or implied.  See the License for the
016 * specific language governing permissions and limitations
017 * under the License.
018 */
019package org.apache.reef.tang;
020
021import org.apache.reef.tang.exceptions.BindException;
022import org.apache.reef.tang.types.ClassNode;
023import org.apache.reef.tang.types.ConstructorArg;
024import org.apache.reef.tang.types.NamedParameterNode;
025import org.apache.reef.tang.types.Node;
026
027import java.util.List;
028import java.util.Set;
029
030/**
031 * This class allows applications to register bindings with Tang.  Tang
032 * configurations are simply sets of bindings of various types.  The most
033 * common bindings are of interfaces (or superclasses) to implementation
034 * classes, and of configuration options ("NamedParameters") to values.
035 * <p/>
036 * Implementations of this class type check the bindings against an underlying
037 * ClassHierarchy implementation.  Typically, the backing ClassHierarchy will
038 * be delegate to the default classloader (the one that loaded the code that is
039 * invoking Tang), though other scenarios are possible.  For instance, the
040 * ClassHierarchy could incorporate additional Jars, or it might not delegate
041 * to the default classloader at all.  In fact, Tang supports ClassHierarchy
042 * objects that are derived from reflection data from other languages, such as
043 * C#.  This enables cross-language injection sessions, where Java code
044 * configures C# code, or vice versa.
045 * <p/>
046 * <p/>
047 * When possible, the methods in this interface eagerly check for these
048 * errors.  Methods that check for configuration and other runtime or
049 * application-level errors are declared to throw BindException.
050 * <p/>
051 * Furthermore, all methods in Tang, may throw RuntimeException if they
052 * encounter inconsistencies in the underlying ClassHierarchy.  Such errors
053 * reflect problems that existed when the application was compiled or
054 * packaged, and cannot be corrected at runtime.  Examples include
055 * inconsistent type hierarchies (such as version mismatches between jars),
056 * and unparsable default values (such as an int that defaults to "false"
057 * or "five").  These exceptions are analogous to the runtime exceptions
058 * thrown by the Java classloader; other than logging them or reporting them
059 * to an end user, applications have little recourse when such problems are
060 * encountered.
061 *
062 * @see JavaConfigurationBuilder for convenience methods that assume the
063 * underlying ClassHierarchy object delegates to the default
064 * classloader, and enable many compile time static checks.
065 * @see ConfigurationModule which pushes additional type checks to class load
066 * time.  This allows Tint, Tang's static analysis tool, to detect a wide
067 * range of runtime configuration errors at build time.
068 */
069public interface ConfigurationBuilder {
070
071  /**
072   * Add all configuration parameters from the given Configuration object.
073   *
074   * @param c
075   */
076  public void addConfiguration(final Configuration c) throws BindException;
077
078  /**
079   * Each ConfigurationBuilder instance is associated with a ClassHierarchy.
080   * It uses this ClassHierarchy to validate the configuration options that it
081   * processes.
082   *
083   * @return a reference to the ClassHierarchy instance backing this
084   * ConfigurationBuilder. No copy is made, since ClassHierarchy objects
085   * are effectively immutable.
086   */
087  public ClassHierarchy getClassHierarchy();
088
089  /**
090   * Force Tang to treat the specified constructor as though it had an @Inject
091   * annotation.
092   * <p/>
093   * This method takes ClassNode objects.  Like all of the methods in this
094   * API, the ClassNode objects must come from the ClassHierarchy instance
095   * returned by getClassHierarchy().
096   *
097   * @param cn   The class the constructor instantiates.
098   * @param args The types of the arguments taken by the constructor, in declaration order.
099   * @throws BindException if the constructor does not exist, or if it has already been bound as a legacy constructor.
100   */
101  void registerLegacyConstructor(ClassNode<?> cn, ClassNode<?>... args)
102      throws BindException;
103
104  /**
105   * Force Tang to treat the specified constructor as though it had an @Inject
106   * annotation.
107   *
108   * @param cn   The full name of the class the constructor instantiates.
109   * @param args The full names of the types of the arguments taken by the constructor, in declaration order.
110   * @throws BindException if the constructor does not exist, or if it has already been bound as a legacy constructor.
111   */
112  void registerLegacyConstructor(String cn, String... args)
113      throws BindException;
114
115  /**
116   * Force Tang to treat the specified constructor as though it had an @Inject
117   * annotation.
118   * <p/>
119   * This method takes ClassNode and ConstructorArg objects.  Like all of the
120   * methods in this API, these objects must come from the ClassHierarchy
121   * instance returned by getClassHierarchy().
122   *
123   * @param cn   The class the constructor instantiates.
124   * @param args The parsed ConstructorArg objects correspdonding to the types of the arguments taken by the constructor, in declaration order.
125   * @throws BindException if the constructor does not exist, or if it has already been bound as a legacy constructor.
126   */
127  void registerLegacyConstructor(ClassNode<?> c, ConstructorArg... args)
128      throws BindException;
129
130  /**
131   * Bind classes to each other, based on their full class names; alternatively,
132   * bound a NamedParameter configuration option to a configuration value.
133   *
134   * @param iface The full name of the interface that should resolve to impl,
135   *              or the NamedParameter to be set.
136   * @param impl  The full name of the implementation that will be used in
137   *              place of impl, or the value the NamedParameter should be set to.
138   * @throws BindException If (In the case of interfaces and implementations)
139   *                       the underlying ClassHierarchy does not recognice iface and
140   *                       impl as known, valid classes, or if impl is not a in
141   *                       implementation of iface, or (in the case of NamedParameters
142   *                       and values) if iface is not a NamedParameter, or if impl
143   *                       fails to parse as the type the iface expects.
144   */
145  public <T> void bind(String iface, String impl)
146      throws BindException;
147
148  /**
149   * Bind classes to each other, based on their full class names; alternatively,
150   * bound a NamedParameter configuration option to a configuration value.
151   * <p/>
152   * This method takes Node objects.  Like all of the methods in this API,
153   * these objects must come from the ClassHierarchy instance returned by
154   * getClassHierarchy().
155   *
156   * @param key   The interface / NamedParmaeter to be bound.
157   * @param value The implementation / value iface should be set to.
158   * @throws BindException if there is a type checking error
159   * @see bind(String, String) for a more complete description.
160   */
161  void bind(Node iface, Node impl) throws BindException;
162
163  /**
164   * Register an ExternalConstructor implementation with Tang.
165   * ExternalConstructors are proxy classes that instantiate some
166   * other class.  They have two primary use cases: (1) adding new
167   * constructors to classes that you cannot modify and (2) implementing
168   * constructors that exmanine their arguments and return an instance of a
169   * subclass of the requested object.
170   * <p/>
171   * To see how the second use case could be useful, consider a implementing a
172   * URI interface with a distinct subclass for each valid URI prefix (e.g.,
173   * http://, ssh://, etc...).  An ExternalConstructor could examine the prefix
174   * and delegate to a constructor of the correct implementation (e.g, HttpURL,
175   * SshURL, etc...) which would validate the remainder of the provided string.
176   * URI's external constructor would return the validated subclass of URI that
177   * corresponds to the provided string, allowing instanceof and downcasts to
178   * behave as expected in the code that invoked Tang.
179   * <p/>
180   * Both use cases should be avoided when possible, since they can
181   * unnecessarily complicate object injections and undermine Tang's ability
182   * to statically check a given configuration.
183   * <p/>
184   * This method takes ClassNode objects.  Like all of the methods in this API,
185   * these objects must come from the ClassHierarchy instance returned by
186   * getClassHierarchy().
187   *
188   * @param iface The class or interface to be instantiated.
189   * @param impl  The ExternalConstructor class that will be used to instantiate iface.
190   * @throws BindException If impl does not instantiate a subclass of iface.
191   */
192  public <T> void bindConstructor(ClassNode<T> iface,
193                                  ClassNode<? extends ExternalConstructor<? extends T>> impl)
194      throws BindException;
195
196  /**
197   * Pretty print the default implementation / value of the provided class / NamedParamter.
198   * This is used by Tang to produce human readable error messages.
199   */
200  public String classPrettyDefaultString(String longName) throws BindException;
201
202  /**
203   * Pretty print the human readable documentation of the provided class / NamedParamter.
204   * This is used by Tang to produce human readable error messages.
205   */
206  public String classPrettyDescriptionString(String longName)
207      throws BindException;
208
209  /**
210   * Produce an immutable Configuration object that contains the current
211   * bindings and ClassHierarchy of this ConfigurationBuilder.  Future
212   * changes to this ConfigurationBuilder will not be reflected in the
213   * returned Configuration.
214   * <p/>
215   * Since Tang eagerly checks for configuration errors, this method does not
216   * perform any additional validation, and does not throw any checkable
217   * exceptions.
218   *
219   * @return
220   */
221  public Configuration build();
222
223  public <T> void bindSetEntry(NamedParameterNode<Set<T>> iface, Node impl)
224      throws BindException;
225
226  public <T> void bindSetEntry(NamedParameterNode<Set<T>> iface, String impl)
227      throws BindException;
228
229  public void bindSetEntry(String iface, String impl) throws BindException;
230
231  public void bindSetEntry(String iface, Node impl) throws BindException;
232
233  /**
234   * Bind an list of implementations(Class or String) to an given NamedParameter.
235   * Unlike bindSetEntry, bindListEntry will bind a whole list to the parameter,
236   * not an element of the list.
237   * <p/>
238   * Since ordering of the list is important, list binding cannot be repeated or
239   * merged unlike set binding. If the elements of the list are Classes, the objects
240   * created by the Classes will be injected. If the elements are Strings, the values
241   * will be injected directly to a given list parameter.
242   *
243   * @param iface    The list named parameter to be instantiated
244   * @param implList The list of class or value will be used to instantiated the named parameter
245   * @throws BindException
246   */
247  public <T> void bindList(NamedParameterNode<List<T>> iface, List implList) throws BindException;
248
249  public void bindList(String iface, List implList) throws BindException;
250
251}