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