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.implementation.java;
020
021import org.apache.reef.tang.Configuration;
022import org.apache.reef.tang.ExternalConstructor;
023import org.apache.reef.tang.JavaClassHierarchy;
024import org.apache.reef.tang.JavaConfigurationBuilder;
025import org.apache.reef.tang.annotations.Name;
026import org.apache.reef.tang.exceptions.BindException;
027import org.apache.reef.tang.implementation.ConfigurationBuilderImpl;
028import org.apache.reef.tang.implementation.ConfigurationImpl;
029import org.apache.reef.tang.types.ClassNode;
030import org.apache.reef.tang.types.NamedParameterNode;
031import org.apache.reef.tang.types.Node;
032import org.apache.reef.tang.util.ReflectionUtilities;
033
034import java.lang.reflect.Type;
035import java.net.URL;
036import java.util.ArrayList;
037import java.util.List;
038import java.util.Set;
039
040public class JavaConfigurationBuilderImpl extends ConfigurationBuilderImpl
041    implements JavaConfigurationBuilder {
042
043  public JavaConfigurationBuilderImpl(URL[] jars, Configuration[] confs, Class<? extends ExternalConstructor<?>>[] parsers)
044      throws BindException {
045    super(jars, confs, parsers);
046  }
047
048  JavaConfigurationBuilderImpl() {
049    super();
050  }
051
052  public JavaConfigurationBuilderImpl(URL[] jars) throws BindException {
053    super(jars);
054  }
055
056  JavaConfigurationBuilderImpl(JavaConfigurationBuilderImpl impl) {
057    super(impl);
058  }
059
060  public JavaConfigurationBuilderImpl(Configuration[] confs)
061      throws BindException {
062    super(confs);
063  }
064
065  @Override
066  public ConfigurationImpl build() {
067    return new JavaConfigurationImpl(new JavaConfigurationBuilderImpl(this));
068  }
069
070  private Node getNode(Class<?> c) {
071    return ((JavaClassHierarchy) namespace).getNode(c);
072  }
073
074  @Override
075  public <T> JavaConfigurationBuilder bind(Class<T> c, Class<?> val) throws BindException {
076    super.bind(getNode(c), getNode(val));
077    return this;
078  }
079
080  @Override
081  @SuppressWarnings("unchecked")
082  public <T> JavaConfigurationBuilder bindImplementation(Class<T> c, Class<? extends T> d)
083      throws BindException {
084    final Node cn = getNode(c);
085    final Node dn = getNode(d);
086    if (!(cn instanceof ClassNode)) {
087      throw new BindException(
088          "bindImplementation passed interface that resolved to " + cn
089              + " expected a ClassNode<?>");
090    }
091    if (!(dn instanceof ClassNode)) {
092      throw new BindException(
093          "bindImplementation passed implementation that resolved to " + dn
094              + " expected a ClassNode<?>");
095    }
096    super.bindImplementation((ClassNode<T>) cn, (ClassNode<? extends T>) dn);
097    return this;
098  }
099
100  @Override
101  public JavaConfigurationBuilder bindNamedParameter(final Class<? extends Name<?>> name, final String value)
102      throws BindException {
103    if (value == null) {
104      throw new IllegalStateException("The value null set to the named parameter is illegal: " + name);
105    }
106    final Node np = getNode(name);
107    if (np instanceof NamedParameterNode) {
108      super.bindParameter((NamedParameterNode<?>) np, value);
109      return this;
110    } else {
111      throw new BindException(
112          "Detected type mismatch when setting named parameter " + name
113              + "  Expected NamedParameterNode, but namespace contains a " + np);
114    }
115  }
116
117  @Override
118  public <T> JavaConfigurationBuilder bindNamedParameter(Class<? extends Name<T>> iface,
119                                                         Class<? extends T> impl) throws BindException {
120    Node ifaceN = getNode(iface);
121    Node implN = getNode(impl);
122    if (!(ifaceN instanceof NamedParameterNode)) {
123      throw new BindException("Type mismatch when setting named parameter " + ifaceN
124          + " Expected NamedParameterNode");
125    }
126    bind(ifaceN, implN);
127    return this;
128  }
129
130  @SuppressWarnings({"unchecked"})
131  public <T> JavaConfigurationBuilder bindConstructor(Class<T> c,
132                                                      Class<? extends ExternalConstructor<? extends T>> v) throws BindException {
133    final Node n = getNode(c);
134    final Node m = getNode(v);
135    if (!(n instanceof ClassNode)) {
136      throw new BindException("BindConstructor got class that resolved to " + n + "; expected ClassNode");
137    }
138    if (!(m instanceof ClassNode)) {
139      throw new BindException("BindConstructor got class that resolved to " + m + "; expected ClassNode");
140    }
141    super.bindConstructor((ClassNode<T>) n, (ClassNode<? extends ExternalConstructor<? extends T>>) m);
142    return this;
143  }
144
145  @SuppressWarnings("unchecked")
146  @Override
147  public <T> JavaConfigurationBuilder bindSetEntry(Class<? extends Name<Set<T>>> iface, String value) throws BindException {
148    final Node n = getNode(iface);
149
150    if (!(n instanceof NamedParameterNode)) {
151      throw new BindException("BindSetEntry got an interface that resolved to " + n + "; expected a NamedParameter");
152    }
153    final Type setType = ReflectionUtilities.getInterfaceTarget(Name.class, iface);
154    if (!ReflectionUtilities.getRawClass(setType).equals(Set.class)) {
155      throw new BindException("BindSetEntry got a NamedParameter that takes a " + setType + "; expected Set<...>");
156    }
157//    Type valType = ReflectionUtilities.getInterfaceTarget(Set.class, setType);
158    super.bindSetEntry((NamedParameterNode<Set<T>>) n, value);
159    return this;
160  }
161
162  @SuppressWarnings("unchecked")
163  @Override
164  public <T> JavaConfigurationBuilder bindSetEntry(Class<? extends Name<Set<T>>> iface, Class<? extends T> impl) throws BindException {
165    final Node n = getNode(iface);
166    final Node m = getNode(impl);
167
168    if (!(n instanceof NamedParameterNode)) {
169      throw new BindException("BindSetEntry got an interface that resolved to " + n + "; expected a NamedParameter");
170    }
171    final Type setType = ReflectionUtilities.getInterfaceTarget(Name.class, iface);
172    if (!ReflectionUtilities.getRawClass(setType).equals(Set.class)) {
173      throw new BindException("BindSetEntry got a NamedParameter that takes a " + setType + "; expected Set<...>");
174    }
175    final Type valType = ReflectionUtilities.getInterfaceTarget(Set.class, setType);
176    if (!ReflectionUtilities.getRawClass(valType).isAssignableFrom(impl)) {
177      throw new BindException("BindSetEntry got implementation " + impl + " that is incompatible with expected type " + valType);
178    }
179
180    super.bindSetEntry((NamedParameterNode<Set<T>>) n, m);
181    return this;
182  }
183
184  /**
185   * Binding list method for JavaConfigurationBuilder. It checks the type of a given named parameter,
186   * and whether all the list's elements can be applied to the named parameter. The elements' type
187   * should be either java Class or String.
188   * <p/>
189   * It does not check whether the list's String values can be parsed to T, like bindSetEntry.
190   *
191   * @param iface    target named parameter to be instantiated
192   * @param implList implementation list used to instantiate the named parameter
193   * @param <T>      type of the list
194   * @return bound JavaConfigurationBuilder object
195   * @throws BindException
196   */
197  @SuppressWarnings("unchecked")
198  @Override
199  public <T> JavaConfigurationBuilder bindList(Class<? extends Name<List<T>>> iface, List implList)
200      throws BindException {
201    final Node n = getNode(iface);
202    List<Object> result = new ArrayList<>();
203
204    if (!(n instanceof NamedParameterNode)) {
205      throw new BindException("BindList got an interface that resolved to " + n + "; expected a NamedParameter");
206    }
207    final Type listType = ReflectionUtilities.getInterfaceTarget(Name.class, iface);
208    if (!ReflectionUtilities.getRawClass(listType).equals(List.class)) {
209      throw new BindException("BindList got a NamedParameter that takes a " + listType + "; expected List<...>");
210    }
211    if (!implList.isEmpty()) {
212      final Type valType = ReflectionUtilities.getInterfaceTarget(List.class, listType);
213      for (Object item : implList) {
214        if (item instanceof Class) {
215          if (!ReflectionUtilities.getRawClass(valType).isAssignableFrom((Class) item)) {
216            throw new BindException("BindList got a list element which is not assignable to the given Type; " +
217                "expected: " + valType);
218          }
219          result.add(getNode((Class) item));
220        } else if (item instanceof String) {
221          result.add(item);
222        } else {
223          throw new BindException("BindList got an list element with unsupported type; expected Class or String " +
224              "object");
225        }
226      }
227    }
228
229    super.bindList((NamedParameterNode<List<T>>) n, result);
230    return this;
231  }
232
233  private class JavaConfigurationImpl extends ConfigurationImpl {
234    JavaConfigurationImpl(JavaConfigurationBuilderImpl builder) {
235      super(builder);
236    }
237  }
238}