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.types.ConstructorDef;
022
023import java.lang.reflect.Constructor;
024import java.lang.reflect.InvocationTargetException;
025
026/**
027 * A simple interface that allows external code to interpose on Tang object
028 * injections.  This can be used to implement simplistic aspect oriented
029 * design patterns by interposing wrapper objects at injection time.  It
030 * can also be used for more mundane purposes, such as tracking the
031 * relationship between the objects that are instantiated at runtime.
032 * <p>
033 * The Wake project contains a full-featured implementation of this API that
034 * may serve as a useful example.
035 */
036public interface Aspect {
037  /**
038   * Inject an object of type T.
039   * <p>
040   * Note that it is never OK to return an instance of ExternalConstructor.
041   * Typical implementations check to see if they are about to return an
042   * instance of ExternalConstructor.  If so, they return ret.newInstance()
043   * instead.
044   * It throws a number of exceptions which are passed-through from the wrapped call to newInstance().
045   *
046   * @param def         information about the constructor to be invoked.  This is
047   *                    mostly useful because it contains references to any relevant named
048   *                    parameters, and to the class to be injected.
049   * @param constructor The java constructor to be injected.  Tang automatically
050   *                    chooses the appropriate constructor and ensures that we have permission
051   *                    to invoke it.
052   * @param args        The parameters to be passed into constructor.newInstance(), in the correct order.
053   * @return A new instance of T.
054   * Note, it is inject()'s responsibility to call <tt>ret.getInstance() if ret instanceof ExternalConstructor</tt>.
055   * @throws InvocationTargetException
056   * @throws IllegalAccessException
057   * @throws IllegalArgumentException
058   * @throws InstantiationException
059   */
060  <T> T inject(ConstructorDef<T> def, Constructor<T> constructor, Object[] args)
061      throws InvocationTargetException, IllegalAccessException, IllegalArgumentException, InstantiationException;
062
063  /**
064   * TANG calls this the first time get() is called on an injection future.  This informs the aspect of
065   * the relationship between InjectionFutures (that were already passed into inject()) and the instantiated
066   * object.
067   *
068   * @param f An InjectionFuture that was passed to the args[] array of inject at some point in the past.
069   * @param t An object instance that was returned by inject().
070   */
071  <T> void injectionFutureInstantiated(InjectionFuture<T> f, T t);
072
073  /**
074   * This method creates a child aspect, and returns it.  This allows aspects to track information about
075   * Tang injection scopes.  If such information is not needed, it is legal for Aspect implementations to
076   * return "this".
077   */
078  Aspect createChildAspect();
079}