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 * When possible, the methods in this interface eagerly check for these
047 * errors.  Methods that check for configuration and other runtime or
048 * application-level errors are declared to throw BindException.
049 * <p>
050 * Furthermore, all methods in Tang, may throw RuntimeException if they
051 * encounter inconsistencies in the underlying ClassHierarchy.  Such errors
052 * reflect problems that existed when the application was compiled or
053 * packaged, and cannot be corrected at runtime.  Examples include
054 * inconsistent type hierarchies (such as version mismatches between jars),
055 * and unparsable default values (such as an int that defaults to "false"
056 * or "five").  These exceptions are analogous to the runtime exceptions
057 * thrown by the Java classloader; other than logging them or reporting them
058 * to an end user, applications have little recourse when such problems are
059 * encountered.
060 *
061 * @see JavaConfigurationBuilder for convenience methods that assume the
062 * underlying ClassHierarchy object delegates to the default
063 * classloader, and enable many compile time static checks.
064 * @see org.apache.reef.tang.formats.ConfigurationModule which pushes additional type checks to class load
065 * time.  This allows Tint, Tang's static analysis tool, to detect a wide
066 * range of runtime configuration errors at build time.
067 */
068public interface ConfigurationBuilder {
069
070  /**
071   * Add all configuration parameters from the given Configuration object.
072   *
073   * @param c the configuration to be added
074   */
075  void addConfiguration(final Configuration c) throws BindException;
076
077  /**
078   * Each ConfigurationBuilder instance is associated with a ClassHierarchy.
079   * It uses this ClassHierarchy to validate the configuration options that it
080   * processes.
081   *
082   * @return a reference to the ClassHierarchy instance backing this
083   * ConfigurationBuilder. No copy is made, since ClassHierarchy objects
084   * are effectively immutable.
085   */
086  ClassHierarchy getClassHierarchy();
087
088  /**
089   * Force Tang to treat the specified constructor as though it had an @Inject
090   * annotation.
091   * <p>
092   * This method takes ClassNode objects.  Like all of the methods in this
093   * API, the ClassNode objects must come from the ClassHierarchy instance
094   * returned by getClassHierarchy().
095   *
096   * @param cn   The class the constructor instantiates.
097   * @param args The types of the arguments taken by the constructor, in declaration order.
098   * @throws BindException if the constructor does not exist, or if it has already been bound as a legacy constructor.
099   */
100  void registerLegacyConstructor(ClassNode<?> cn, ClassNode<?>... args)
101      throws BindException;
102
103  /**
104   * Force Tang to treat the specified constructor as though it had an @Inject
105   * annotation.
106   *
107   * @param cn   The full name of the class the constructor instantiates.
108   * @param args The full names of the types of the arguments taken by the constructor, in declaration order.
109   * @throws BindException if the constructor does not exist, or if it has already been bound as a legacy constructor.
110   */
111  void registerLegacyConstructor(String cn, String... args)
112      throws BindException;
113
114  /**
115   * Force Tang to treat the specified constructor as though it had an @Inject
116   * annotation.
117   * <p>
118   * This method takes ClassNode and ConstructorArg objects.  Like all of the
119   * methods in this API, these objects must come from the ClassHierarchy
120   * instance returned by getClassHierarchy().
121   *
122   * @param c   The class the constructor instantiates.
123   * @param args The parsed ConstructorArg objects corresponding to the types of the arguments taken by the constructor,
124   *             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 <T> a type
135   * @param iface The full name of the interface that should resolve to impl,
136   *              or the NamedParameter to be set.
137   * @param impl  The full name of the implementation that will be used in
138   *              place of impl, or the value the NamedParameter should be set to.
139   * @throws BindException If (In the case of interfaces and implementations)
140   *                       the underlying ClassHierarchy does not recognise iface and
141   *                       impl as known, valid classes, or if impl is not a in
142   *                       implementation of iface, or (in the case of NamedParameters
143   *                       and values) if iface is not a NamedParameter, or if impl
144   *                       fails to parse as the type the iface expects.
145   */
146  <T> void bind(String iface, String impl)
147      throws BindException;
148
149  /**
150   * Bind classes to each other, based on their full class names; alternatively,
151   * bound a NamedParameter configuration option to a configuration value.
152   * <p>
153   * This method takes Node objects.  Like all of the methods in this API,
154   * these objects must come from the ClassHierarchy instance returned by
155   * getClassHierarchy().
156   *
157   * @param iface   The interface / NamedParameter to be bound.
158   * @param impl The implementation / value iface should be set to.
159   * @throws BindException if there is a type checking error
160   * See {@link #bind(String, String) bind(String,String)} for a more complete description.
161   */
162  void bind(Node iface, Node impl) throws BindException;
163
164  /**
165   * Register an ExternalConstructor implementation with Tang.
166   * ExternalConstructors are proxy classes that instantiate some
167   * other class.  They have two primary use cases: (1) adding new
168   * constructors to classes that you cannot modify and (2) implementing
169   * constructors that examine their arguments and return an instance of a
170   * subclass of the requested object.
171   * <p>
172   * To see how the second use case could be useful, consider a implementing a
173   * URI interface with a distinct subclass for each valid URI prefix (e.g.,
174   * http://, ssh://, etc...).  An ExternalConstructor could examine the prefix
175   * and delegate to a constructor of the correct implementation (e.g, HttpURL,
176   * SshURL, etc...) which would validate the remainder of the provided string.
177   * URI's external constructor would return the validated subclass of URI that
178   * corresponds to the provided string, allowing instanceof and downcasts to
179   * behave as expected in the code that invoked Tang.
180   * <p>
181   * Both use cases should be avoided when possible, since they can
182   * unnecessarily complicate object injections and undermine Tang's ability
183   * to statically check a given configuration.
184   * <p>
185   * This method takes ClassNode objects.  Like all of the methods in this API,
186   * these objects must come from the ClassHierarchy instance returned by
187   * getClassHierarchy().
188   *
189   * @param <T> a type
190   * @param iface The class or interface to be instantiated.
191   * @param impl  The ExternalConstructor class that will be used to instantiate iface.
192   * @throws BindException If impl does not instantiate a subclass of iface.
193   */
194  <T> void bindConstructor(ClassNode<T> iface,
195                           ClassNode<? extends ExternalConstructor<? extends T>> impl)
196      throws BindException;
197
198  /**
199   * Pretty print the default implementation / value of the provided class / NamedParameter.
200   * This is used by Tang to produce human readable error messages.
201   *
202   * @param longName a name of class or parameter
203   * @return a pretty-formatted string for class or named parameter
204   * @throws BindException if name resolution fails
205   */
206  String classPrettyDefaultString(String longName) throws BindException;
207
208  /**
209   * Pretty print the human readable documentation of the provided class / NamedParameter.
210   * This is used by Tang to produce human readable error messages.
211   *
212   * @param longName a name of class or parameter
213   * @return a pretty-formatted class description string
214   * @throws BindException if name resolution fails
215   */
216  String classPrettyDescriptionString(String longName)
217      throws BindException;
218
219  /**
220   * Produce an immutable Configuration object that contains the current
221   * bindings and ClassHierarchy of this ConfigurationBuilder.  Future
222   * changes to this ConfigurationBuilder will not be reflected in the
223   * returned Configuration.
224   * <p>
225   * Since Tang eagerly checks for configuration errors, this method does not
226   * perform any additional validation, and does not throw any checkable
227   * exceptions.
228   *
229   * @return the Configuration
230   */
231  Configuration build();
232
233  <T> void bindSetEntry(NamedParameterNode<Set<T>> iface, Node impl)
234      throws BindException;
235
236  <T> void bindSetEntry(NamedParameterNode<Set<T>> iface, String impl)
237      throws BindException;
238
239  void bindSetEntry(String iface, String impl) throws BindException;
240
241  void bindSetEntry(String iface, Node impl) throws BindException;
242
243  /**
244   * Bind an list of implementations(Class or String) to an given NamedParameter.
245   * Unlike bindSetEntry, bindListEntry will bind a whole list to the parameter,
246   * not an element of the list.
247   * <p>
248   * Since ordering of the list is important, list binding cannot be repeated or
249   * merged unlike set binding. If the elements of the list are Classes, the objects
250   * created by the Classes will be injected. If the elements are Strings, the values
251   * will be injected directly to a given list parameter.
252   *
253   * @param <T> a type
254   * @param iface    The list named parameter to be instantiated
255   * @param implList The list of class or value will be used to instantiated the named parameter
256   * @throws BindException if implementation class does not fit to the named parameter
257   */
258  <T> void bindList(NamedParameterNode<List<T>> iface, List implList) throws BindException;
259
260  void bindList(String iface, List implList) throws BindException;
261
262}