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;
020
021import org.apache.reef.tang.*;
022import org.apache.reef.tang.exceptions.BindException;
023import org.apache.reef.tang.implementation.java.ClassHierarchyImpl;
024import org.apache.reef.tang.implementation.java.InjectorImpl;
025import org.apache.reef.tang.implementation.java.JavaConfigurationBuilderImpl;
026
027import java.net.URL;
028import java.util.*;
029
030public class TangImpl implements Tang {
031
032  private static Map<SetValuedKey, JavaClassHierarchy> defaultClassHierarchy = new HashMap<>();
033
034  /**
035   * Only for testing. Deletes Tang's current database of known classes, forcing
036   * it to rebuild them over time.
037   */
038  public static void reset() {
039    defaultClassHierarchy = new HashMap<>(); //new ClassHierarchyImpl();
040  }
041
042  @Override
043  public Injector newInjector(final Configuration... confs) throws BindException {
044    return new InjectorImpl(new JavaConfigurationBuilderImpl(confs).build());
045  }
046
047  @SuppressWarnings("unchecked")
048  @Override
049  public JavaConfigurationBuilder newConfigurationBuilder() {
050    try {
051      return newConfigurationBuilder(new URL[0], new Configuration[0], new Class[0]);
052    } catch (final BindException e) {
053      throw new IllegalStateException(
054          "Caught unexpeceted bind exception!  Implementation bug.", e);
055    }
056  }
057
058  @Override
059  public ConfigurationBuilder newConfigurationBuilder(final ClassHierarchy ch) {
060    return new ConfigurationBuilderImpl(ch);
061  }
062
063  @SuppressWarnings("unchecked")
064  @Override
065  public JavaConfigurationBuilder newConfigurationBuilder(final URL... jars) {
066    try {
067      return newConfigurationBuilder(jars, new Configuration[0], new Class[0]);
068    } catch (final BindException e) {
069      throw new IllegalStateException(
070          "Caught unexpeceted bind exception!  Implementation bug.", e);
071    }
072  }
073
074  @SuppressWarnings("unchecked")
075  @Override
076  public JavaConfigurationBuilder newConfigurationBuilder(
077      final Configuration... confs) throws BindException {
078    return newConfigurationBuilder(new URL[0], confs, new Class[0]);
079  }
080
081  @Override
082  public final JavaConfigurationBuilder newConfigurationBuilder(
083      @SuppressWarnings("unchecked") final Class<? extends ExternalConstructor<?>>... parsers) throws BindException {
084    return newConfigurationBuilder(new URL[0], new Configuration[0], parsers);
085  }
086
087  @Override
088  public JavaConfigurationBuilder newConfigurationBuilder(final URL[] jars, final Configuration[] confs,
089          final Class<? extends ExternalConstructor<?>>[] parameterParsers)
090      throws BindException {
091    final JavaConfigurationBuilder cb = new JavaConfigurationBuilderImpl(jars, confs, parameterParsers);
092//    for (Configuration c : confs) {
093//      cb.addConfiguration(c);
094//    }
095    return cb;
096  }
097
098  @SuppressWarnings("unchecked")
099  @Override
100  public JavaClassHierarchy getDefaultClassHierarchy() {
101    return getDefaultClassHierarchy(new URL[0], new Class[0]);
102  }
103
104  @Override
105  public JavaClassHierarchy getDefaultClassHierarchy(final URL[] jars,
106                                                     final Class<? extends ExternalConstructor<?>>[] parameterParsers) {
107    final SetValuedKey key = new SetValuedKey(jars, parameterParsers);
108
109    JavaClassHierarchy ret = defaultClassHierarchy.get(key);
110    if (ret == null) {
111      ret = new ClassHierarchyImpl(jars, parameterParsers);
112      defaultClassHierarchy.put(key, ret);
113    }
114    return ret;
115  }
116
117  @Override
118  public Injector newInjector(final Configuration confs) {
119    try {
120      return newInjector(new Configuration[]{confs});
121    } catch (final BindException e) {
122      throw new IllegalStateException("Unexpected error cloning configuration", e);
123    }
124  }
125
126  @Override
127  public Injector newInjector() {
128    try {
129      return newInjector(new Configuration[]{});
130    } catch (final BindException e) {
131      throw new IllegalStateException("Unexpected error from empty configuration", e);
132    }
133  }
134
135  private class SetValuedKey {
136    private final Set<Object> key;
137
138    public SetValuedKey(final Object[] ts, final Object[] us) {
139      key = new HashSet<Object>(Arrays.asList(ts));
140      key.addAll(Arrays.asList(us));
141    }
142
143    @Override
144    public int hashCode() {
145      int i = 0;
146      for (final Object t : key) {
147        i += t.hashCode();
148      }
149      return i;
150    }
151
152    @Override
153    public boolean equals(final Object o) {
154      final SetValuedKey other = (SetValuedKey) o;
155      if (other.key.size() != this.key.size()) {
156        return false;
157      }
158      return key.containsAll(other.key);
159    }
160  }
161
162
163}