blob: 569d4670a110064e5f1cb801efc07ba513a63c0c [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
using System;
using System.Collections.Generic;
using System.Globalization;
using Org.Apache.REEF.Tang.Annotations;
using Org.Apache.REEF.Tang.Exceptions;
using Org.Apache.REEF.Tang.Interface;
using Org.Apache.REEF.Tang.Types;
using Org.Apache.REEF.Tang.Util;
using Org.Apache.REEF.Utilities.Logging;
namespace Org.Apache.REEF.Tang.Implementations.Configuration
{
internal sealed class CsConfigurationBuilderImpl : ConfigurationBuilderImpl, ICsInternalConfigurationBuilder
{
private static readonly Logger LOGGER = Logger.GetLogger(typeof(CsConfigurationBuilderImpl));
#region Constructors
public CsConfigurationBuilderImpl(string[] assemblies, IConfiguration[] confs, Type[] parsers)
: base(assemblies, confs, parsers)
{
}
public CsConfigurationBuilderImpl(IConfiguration[] confs) : base(confs)
{
}
public CsConfigurationBuilderImpl(CsConfigurationBuilderImpl impl) : base(impl)
{
}
public CsConfigurationBuilderImpl(ICsClassHierarchy classHierarchy)
: base(classHierarchy)
{
}
public CsConfigurationBuilderImpl(string[] assemblies)
: base(assemblies)
{
}
#endregion Constructors
#region ICsConfigurationBuilder
/// <summary>
/// Builds this instance.
/// </summary>
/// <returns></returns>
public CsConfigurationImpl build()
{
return new CsConfigurationImpl(new CsConfigurationBuilderImpl(this));
}
/// <summary>
/// Binds a string to a named parameter.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="value">The value.</param>
/// <returns></returns>
/// <exception cref="BindException">Detected type mismatch when setting named parameter + name
/// + Expected NamedParameterNode, but namespace contains a + np</exception>
public ICsConfigurationBuilder BindNamedParameter(Type name, string value)
{
if (value == null)
{
var ex = new IllegalStateException(string.Format(CultureInfo.CurrentCulture, "The value null set to the named parameter {0} is illegal.", name));
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
INode np = GetNode(name);
if (np is INamedParameterNode)
{
BindParameter((INamedParameterNode)np, value);
}
else
{
var ex = new BindException(
"Detected type mismatch when setting named parameter " + name
+ " Expected NamedParameterNode, but namespace contains a " + np);
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
return this;
}
/// <summary>
/// Binds the class impl as the implementation of the interface iface
/// </summary>
/// <param name="iface">The iface.</param>
/// <param name="impl">The impl.</param>
/// <returns></returns>
public ICsConfigurationBuilder BindImplementation(Type iface, Type impl)
{
INode cn = GetNode(iface);
INode dn = GetNode(impl);
if (!(cn is IClassNode))
{
var ex = new BindException(
"bindImplementation passed interface that resolved to " + cn
+ " expected a ClassNode<?>");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
if (!(dn is IClassNode))
{
var ex = new BindException(
"bindImplementation passed implementation that resolved to " + dn
+ " expected a ClassNode<?>");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
BindImplementation((IClassNode)cn, (IClassNode)dn);
return this;
}
/// <summary>
/// Binds the implementation to the interface
/// </summary>
/// <typeparam name="U"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="iface">The iface.</param>
/// <param name="impl">The impl.</param>
/// <returns></returns>
public ICsConfigurationBuilder BindImplementation<U, T>(GenericType<U> iface, GenericType<T> impl)
where T : U
{
return BindImplementation(typeof(U), typeof(T));
}
/// <summary>
/// Binds a value to a named parameter.
/// </summary>
/// <typeparam name="U"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="name">The name.</param>
/// <param name="value">The value.</param>
/// <returns></returns>
public ICsConfigurationBuilder BindNamedParameter<U, T>(GenericType<U> name, string value)
where U : Name<T>
{
return BindNamedParameter(typeof(U), value);
}
/// <summary>
/// Binds an implementation to a named parameter.
/// </summary>
/// <typeparam name="U"></typeparam>
/// <typeparam name="V"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="iface">The iface.</param>
/// <param name="impl">The impl.</param>
/// <returns></returns>
public ICsConfigurationBuilder BindNamedParameter<U, V, T>(GenericType<U> iface, GenericType<V> impl)
where U : Name<T>
where V : T
{
return ((ICsInternalConfigurationBuilder)this).BindNamedParameter(typeof(U), typeof(V));
}
/// <summary>
/// Binds an external constructor.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <typeparam name="U"></typeparam>
/// <param name="c">The c.</param>
/// <param name="v">The v.</param>
/// <returns></returns>
public ICsConfigurationBuilder BindConstructor<T, U>(GenericType<T> c, GenericType<U> v)
where U : IExternalConstructor<T>
{
return ((ICsInternalConfigurationBuilder)this).BindConstructor(typeof(T), typeof(U));
}
//// public <T> void bindSetEntry(Class<? extends Name<Set<T>>> iface, String value) throws BindException;
/// <summary>
/// Binds a string value to a named parameter of ISet.
/// </summary>
/// <typeparam name="U"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="iface">The iface.</param>
/// <param name="value">The value.</param>
/// <returns></returns>
public ICsConfigurationBuilder BindSetEntry<U, T>(GenericType<U> iface, string value)
where U : Name<ISet<T>>
{
return ((ICsInternalConfigurationBuilder)this).BindSetEntry(typeof(U), value);
}
//// public <T> void bindSetEntry(Class<? extends Name<Set<T>>> iface, Class<? extends T> impl) throws BindException;
/// <summary>
/// Binds an implementation of T to a named parameter of ISet of T.
/// </summary>
/// <typeparam name="U"></typeparam>
/// <typeparam name="V"></typeparam>
/// <typeparam name="T"></typeparam>
/// <param name="iface">The iface.</param>
/// <param name="impl">The impl.</param>
/// <returns></returns>
public ICsConfigurationBuilder BindSetEntry<U, V, T>(GenericType<U> iface, GenericType<V> impl)
where U : Name<ISet<T>>
where V : T
{
return ((ICsInternalConfigurationBuilder)this).BindSetEntry(typeof(U), typeof(V));
}
public ICsConfigurationBuilder BindList<U, V, T>(GenericType<U> iface, IList<GenericType<V>> impl)
where U : Name<IList<T>>
where V : T
{
IList<Type> implTypes = new List<Type>();
foreach (var item in impl)
{
implTypes.Add(item.TypeT);
}
return ((ICsInternalConfigurationBuilder)this).BindList(typeof(U), implTypes);
}
public ICsConfigurationBuilder BindList<U, T>(GenericType<U> iface, IList<string> impl)
where U : Name<IList<T>>
{
return ((ICsInternalConfigurationBuilder)this).BindList(typeof(U), impl);
}
public ICsConfigurationBuilder BindList(Type iface, IList<Type> implList)
{
INode n = GetNode(iface);
IList<INode> result = new List<INode>();
if (!(n is INamedParameterNode))
{
var ex = new BindException("BindList got an interface that resolved to " + n + "; expected a NamedParameter");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
Type listType = ReflectionUtilities.GetInterfaceTarget(typeof(Name<>), iface);
if (!ReflectionUtilities.IsGenericTypeof(typeof(IList<>), listType))
{
var ex = new BindException("BindList got a NamedParameter that takes a " + listType + "; expected List<...>");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
if (implList != null && implList.Count > 0)
{
Type valType = ReflectionUtilities.GetInterfaceTarget(typeof(IList<>), listType);
foreach (var item in implList)
{
if (!valType.IsAssignableFrom((Type)item))
{
var ex =
new BindException("BindList got implementation " + item +
" that is incompatible with expected type " + valType);
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
result.Add(GetNode(item));
}
}
BindList((INamedParameterNode)n, result);
return this;
}
#endregion ICsConfigurationBuilder
#region ICsInternalConfigurationBuilder
/// <summary>
/// Bind named parameters, implementations or external constructors, depending
/// on the types of the classes passed in.
/// </summary>
/// <param name="iface">The iface.</param>
/// <param name="impl">The impl.</param>
/// <returns></returns>
ICsInternalConfigurationBuilder ICsInternalConfigurationBuilder.Bind(Type iface, Type impl)
{
Bind(GetNode(iface), GetNode(impl));
return this;
}
/// <summary>
/// Binds an implementation for a named parameter.
/// </summary>
/// <param name="iface">The iface.</param>
/// <param name="impl">The impl.</param>
/// <returns></returns>
/// <exception cref="BindException">Type mismatch when setting named parameter + ifaceN
/// + Expected NamedParameterNode</exception>
ICsInternalConfigurationBuilder ICsInternalConfigurationBuilder.BindNamedParameter(Type iface, Type impl)
{
INode ifaceN = GetNode(iface);
INode implN = GetNode(impl);
if (!(ifaceN is INamedParameterNode))
{
var ex = new BindException("Type mismatch when setting named parameter " + ifaceN
+ " Expected NamedParameterNode");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
Bind(ifaceN, implN);
return this;
}
//// public <T> void bindSetEntry(Class<? extends Name<Set<T>>> iface, String value) throws BindException;
/// <summary>
/// Binds a string value to to a named parameter of ISet entry
/// </summary>
/// <param name="iface">The iface.</param>
/// <param name="value">The value.</param>
/// <returns></returns>
/// <exception cref="BindException">BindSetEntry got an interface that resolved to + n + ; expected a NamedParameter</exception>
ICsInternalConfigurationBuilder ICsInternalConfigurationBuilder.BindSetEntry(Type iface, string value)
{
INode n = GetNode(iface);
if (!(n is INamedParameterNode))
{
var ex = new BindException("BindSetEntry got an interface that resolved to " + n + "; expected a NamedParameter");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
Type setType = ReflectionUtilities.GetInterfaceTarget(typeof(Name<>), iface);
// check if setType is ISet
if (ReflectionUtilities.GetInterfaceTarget(typeof(ISet<>), setType) == null)
{
var ex = new BindException("BindSetEntry got a NamedParameter that takes a " + setType + "; expected Set<...>");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
//// Type valType = ReflectionUtilities.getInterfaceTarget(Set.class, setType);
BindSetEntry((INamedParameterNode)n, value);
return this;
}
//// public <T> void bindSetEntry(Class<? extends Name<Set<T>>> iface, Class<? extends T> impl) throws BindException;
/// <summary>
/// Binds an implementation to a named parameter of ISet entry.
/// </summary>
/// <param name="iface">The iface.</param>
/// <param name="impl">The impl.</param>
/// <returns></returns>
/// <exception cref="BindException">BindSetEntry got an interface that resolved to + n + ; expected a NamedParameter</exception>
ICsInternalConfigurationBuilder ICsInternalConfigurationBuilder.BindSetEntry(Type iface, Type impl)
{
INode n = GetNode(iface);
INode m = GetNode(impl);
if (!(n is INamedParameterNode))
{
var ex = new BindException("BindSetEntry got an interface that resolved to " + n + "; expected a NamedParameter");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
Type setType = ReflectionUtilities.GetInterfaceTarget(typeof(Name<>), iface);
// if (!ReflectionUtilities.GetRawClass(setType).Equals(typeof(ISet<>)))
if (!ReflectionUtilities.IsGenericTypeof(typeof(ISet<>), setType))
{
var ex = new BindException("BindSetEntry got a NamedParameter that takes a " + setType + "; expected Set<...>");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
Type valType = ReflectionUtilities.GetInterfaceTarget(typeof(ISet<>), setType);
//// if (!ReflectionUtilities.GetRawClass(valType).IsAssignableFrom(impl))
if (!valType.IsAssignableFrom(impl))
{
var ex = new BindException("BindSetEntry got implementation " + impl + " that is incompatible with expected type " + valType);
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
BindSetEntry((INamedParameterNode)n, m);
return this;
}
ICsInternalConfigurationBuilder ICsInternalConfigurationBuilder.BindList(Type iface, IList<string> implList)
{
INode n = GetNode(iface);
if (!(n is INamedParameterNode))
{
var ex = new BindException("BindList got an interface that resolved to " + n + "; expected a NamedParameter");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
Type listType = ReflectionUtilities.GetInterfaceTarget(typeof(Name<>), iface);
if (!ReflectionUtilities.IsGenericTypeof(typeof(IList<>), listType))
{
var ex = new BindException("BindList got a NamedParameter that takes a " + listType + "; expected List<...>");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
BindList((INamedParameterNode)n, implList);
return this;
}
//// public <T> void bindConstructor(Class<T> c, Class<? extends ExternalConstructor<? extends T>> v) throws BindException;
/// <summary>
/// Binds an external constructor.
/// </summary>
/// <param name="c">The c.</param>
/// <param name="v">The v.</param>
/// <returns></returns>
/// <exception cref="BindException">BindConstructor got class that resolved to + n + ; expected ClassNode</exception>
ICsInternalConfigurationBuilder ICsInternalConfigurationBuilder.BindConstructor(Type c, Type v)
{
INode n = GetNode(c);
INode m = GetNode(v);
if (!(n is IClassNode))
{
var ex = new BindException("BindConstructor got class that resolved to " + n + "; expected ClassNode");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
if (!(m is IClassNode))
{
var ex = new BindException("BindConstructor got class that resolved to " + m + "; expected ClassNode");
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
BindConstructor((IClassNode)n, (IClassNode)m);
return this;
}
#endregion ICsInternalConfigurationBuilder
#region extension methods
public ICsConfigurationBuilder BindNamedParam<TName, TType>(string str) where TName : Name<TType>
{
return BindNamedParameter<TName, TType>(GenericType<TName>.Class, str);
}
public ICsConfigurationBuilder BindStringNamedParam<T>(string str) where T : Name<string>
{
return BindNamedParameter<T, string>(GenericType<T>.Class, str);
}
public ICsConfigurationBuilder BindIntNamedParam<T>(string str) where T : Name<int>
{
return BindNamedParameter<T, int>(GenericType<T>.Class, str);
}
public ICsConfigurationBuilder BindNamedParameter<U, V, T>()
where U : Name<T>
where V : T
{
return BindNamedParameter<U, V, T>(GenericType<U>.Class, GenericType<V>.Class);
}
public ICsConfigurationBuilder BindSetEntry<T1, T2, T3>()
where T1 : Name<ISet<T3>>
where T2 : T3
{
return BindSetEntry<T1, T2, T3>(GenericType<T1>.Class, GenericType<T2>.Class);
}
public ICsConfigurationBuilder BindSetEntry<U, T>(string value) where U : Name<ISet<T>>
{
return BindSetEntry<U, T>(GenericType<U>.Class, value);
}
public ICsConfigurationBuilder BindImplementation<T1, T2>() where T2 : T1
{
return BindImplementation(GenericType<T1>.Class, GenericType<T2>.Class);
}
public ICsConfigurationBuilder BindList<U, T>(IList<string> impl) where U : Name<IList<T>>
{
return BindList<U, T>(GenericType<U>.Class, impl);
}
public ICsConfigurationBuilder BindConstructor<T, U>() where U : IExternalConstructor<T>
{
return BindConstructor<T, U>(GenericType<T>.Class, GenericType<U>.Class);
}
#endregion extension methods
private INode GetNode(Type c)
{
return ((ICsClassHierarchy)ClassHierarchy).GetNode(c);
}
}
}