blob: fe3a099c841a5dc424f6925c06acf29319cf7cb1 [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 System.Text;
using Org.Apache.REEF.Tang.Exceptions;
using Org.Apache.REEF.Tang.Implementations.ClassHierarchy;
using Org.Apache.REEF.Tang.Implementations.Tang;
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 class ConfigurationBuilderImpl : IConfigurationBuilder
{
public IClassHierarchy ClassHierarchy;
public readonly IDictionary<IClassNode, IClassNode> BoundImpls = new MonotonicTreeMap<IClassNode, IClassNode>();
public readonly IDictionary<IClassNode, IClassNode> BoundConstructors = new MonotonicTreeMap<IClassNode, IClassNode>();
public readonly IDictionary<INamedParameterNode, string> NamedParameters = new MonotonicTreeMap<INamedParameterNode, string>();
public readonly IDictionary<IClassNode, IConstructorDef> LegacyConstructors = new MonotonicTreeMap<IClassNode, IConstructorDef>();
public readonly MonotonicMultiMap<INamedParameterNode, object> BoundSetEntries = new MonotonicMultiMap<INamedParameterNode, object>();
public readonly IDictionary<INamedParameterNode, IList<object>> BoundLists = new MonotonicTreeMap<INamedParameterNode, IList<object>>();
public readonly static string INIT = "<init>";
public const string DuplicatedEntryForNamedParamater = "Duplicated entries: ";
private static readonly Logger LOGGER = Logger.GetLogger(typeof(ConfigurationBuilderImpl));
protected ConfigurationBuilderImpl()
{
this.ClassHierarchy = TangFactory.GetTang().GetDefaultClassHierarchy();
}
public ConfigurationBuilderImpl(IClassHierarchy classHierarchy)
{
this.ClassHierarchy = classHierarchy;
}
protected ConfigurationBuilderImpl(string[] assemblies, IConfiguration[] confs, Type[] parsers)
{
this.ClassHierarchy = TangFactory.GetTang().GetDefaultClassHierarchy(assemblies, parsers);
foreach (IConfiguration tc in confs)
{
AddConfiguration((ConfigurationImpl)tc);
}
}
public ConfigurationBuilderImpl(ConfigurationBuilderImpl t)
{
this.ClassHierarchy = t.GetClassHierarchy();
try
{
AddConfiguration(t.GetClassHierarchy(), t);
}
catch (BindException e)
{
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Caught(e, Level.Error, LOGGER);
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(new IllegalStateException("Could not copy builder", e), LOGGER);
}
}
protected ConfigurationBuilderImpl(string[] assemblies) : this(assemblies, new IConfiguration[0], new Type[0])
{
}
protected ConfigurationBuilderImpl(IConfiguration[] confs) : this(new string[0], confs, new Type[0])
{
}
public void AddConfiguration(IConfiguration conf)
{
AddConfiguration(conf.GetClassHierarchy(), ((ConfigurationImpl)conf).Builder);
}
private void AddConfiguration(IClassHierarchy ns, ConfigurationBuilderImpl builder)
{
this.ClassHierarchy = this.ClassHierarchy.Merge(ns);
if (ClassHierarchy is ClassHierarchyImpl || builder.ClassHierarchy is ClassHierarchyImpl)
{
if (ClassHierarchy is ClassHierarchyImpl && builder.ClassHierarchy is ClassHierarchyImpl)
{
((ClassHierarchyImpl)ClassHierarchy).Parameterparser.MergeIn(((ClassHierarchyImpl)builder.ClassHierarchy).Parameterparser);
}
else
{
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(new ArgumentException("Attempt to merge Java and non-Java class hierarchy! Not supported."), LOGGER);
}
}
foreach (IClassNode cn in builder.BoundImpls.Keys)
{
IClassNode n = null;
builder.BoundImpls.TryGetValue(cn, out n);
if (n != null)
{
Bind(cn.GetFullName(), n.GetFullName());
}
}
foreach (IClassNode cn in builder.BoundConstructors.Keys)
{
IClassNode n = null;
builder.BoundConstructors.TryGetValue(cn, out n);
if (n != null)
{
Bind(cn.GetFullName(), n.GetFullName());
}
}
// The namedParameters set contains the strings that can be used to
// instantiate new
// named parameter instances. Create new ones where we can.
foreach (INamedParameterNode np in builder.NamedParameters.Keys)
{
string v = null;
builder.NamedParameters.TryGetValue(np, out v);
Bind(np.GetFullName(), v);
}
foreach (IClassNode cn in builder.LegacyConstructors.Keys)
{
IConstructorDef cd = null;
builder.LegacyConstructors.TryGetValue(cn, out cd);
RegisterLegacyConstructor(cn, cd.GetArgs());
}
foreach (KeyValuePair<INamedParameterNode, object> e in builder.BoundSetEntries)
{
string name = ((INamedParameterNode)e.Key).GetFullName();
if (e.Value is INode)
{
BindSetEntry(name, (INode)e.Value);
}
else if (e.Value is string)
{
BindSetEntry(name, (string)e.Value);
}
else
{
var ex = new IllegalStateException(string.Format(CultureInfo.CurrentCulture, "The value {0} set to the named parameter {1} is illegel.", e.Value, name));
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
}
foreach (var p in builder.BoundLists)
{
BoundLists.Add(p.Key, p.Value);
}
}
public IClassHierarchy GetClassHierarchy()
{
return this.ClassHierarchy;
}
public void RegisterLegacyConstructor(IClassNode cn, IList<IClassNode> args)
{
LegacyConstructors.Add(cn, cn.GetConstructorDef(args));
}
public void RegisterLegacyConstructor(string s, IList<string> args)
{
IClassNode cn = (IClassNode)this.ClassHierarchy.GetNode(s);
IList<IClassNode> cnArgs = new List<IClassNode>();
for (int i = 0; i < args.Count; i++)
{
cnArgs.Add((IClassNode)ClassHierarchy.GetNode(args[i]));
}
RegisterLegacyConstructor(cn, cnArgs);
}
public void RegisterLegacyConstructor(IClassNode c, IList<IConstructorArg> args)
{
string[] cn = new string[args.Count];
for (int i = 0; i < args.Count; i++)
{
cn[i] = args[i].Gettype();
}
RegisterLegacyConstructor(c.GetFullName(), cn);
}
public IConfiguration Build()
{
return new ConfigurationImpl(new ConfigurationBuilderImpl(this));
}
public void Bind(string key, string value)
{
INode n = this.ClassHierarchy.GetNode(key);
BindNode(n, value);
}
private void BindNode(INode n, string value)
{
if (n is INamedParameterNode)
{
BindParameter((INamedParameterNode)n, value);
}
else if (n is IClassNode)
{
INode m = this.ClassHierarchy.GetNode(value);
Bind((IClassNode)n, (IClassNode)m);
}
else
{
var ex = new IllegalStateException(string.Format("getNode() returned {0} which is neither a ClassNode nor a NamedParameterNode", n));
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
}
public void Bind(string key, string value, string aliasLanguage)
{
INode n = ClassHierarchy.GetNode(key, aliasLanguage);
BindNode(n, value);
}
public void Bind(Types.INode key, Types.INode value)
{
if (key is INamedParameterNode)
{
BindParameter((INamedParameterNode)key, value.GetFullName());
}
else if (key is IClassNode)
{
IClassNode k = (IClassNode)key;
if (value is IClassNode)
{
IClassNode val = (IClassNode)value;
if (val.IsExternalConstructor() && !k.IsExternalConstructor())
{
BindConstructor(k, (IClassNode)val);
}
else
{
BindImplementation(k, (IClassNode)val);
}
}
}
}
public void BindParameter(INamedParameterNode name, string value)
{
/* Parse and discard value; this is just for type checking, skip for now*/
if (this.ClassHierarchy is ICsClassHierarchy)
{
((ICsClassHierarchy)ClassHierarchy).Parse(name, value);
}
if (name.IsSet())
{
BindSetEntry((INamedParameterNode)name, value);
}
else
{
try
{
NamedParameters.Add(name, value);
}
catch (ArgumentException e)
{
var msg = string.Format(CultureInfo.InvariantCulture, DuplicatedEntryForNamedParamater + "try to bind [{0}] to [{1}], but the configuration has been set for it.", value, name.GetFullName());
Utilities.Diagnostics.Exceptions.Throw(new ArgumentException(msg + e.Message), LOGGER);
}
}
}
public void BindImplementation(IClassNode n, IClassNode m)
{
if (this.ClassHierarchy.IsImplementation(n, m))
{
BoundImpls.Add(n, m);
}
else
{
var ex = new ArgumentException(string.Format("Class {0} does not extend {1}.", m, n));
Org.Apache.REEF.Utilities.Diagnostics.Exceptions.Throw(ex, LOGGER);
}
}
public void BindSetEntry(string iface, string impl)
{
BoundSetEntries.Add((INamedParameterNode)this.ClassHierarchy.GetNode(iface), impl);
}
public void BindSetEntry(string iface, INode impl)
{
BoundSetEntries.Add((INamedParameterNode)ClassHierarchy.GetNode(iface), impl);
}
public void BindSetEntry(INamedParameterNode iface, string impl)
{
BoundSetEntries.Add(iface, impl);
}
public void BindSetEntry(INamedParameterNode iface, INode impl)
{
BoundSetEntries.Add(iface, impl);
}
public void BindList(INamedParameterNode iface, IList<INode> impl)
{
IList<object> l = new List<object>();
foreach (var n in impl)
{
l.Add((object)n);
}
BoundLists.Add(iface, l);
}
public void BindList(INamedParameterNode iface, IList<string> impl)
{
IList<object> l = new List<object>();
foreach (var n in impl)
{
l.Add((object)n);
}
BoundLists.Add(iface, l);
}
public void BindList(string iface, IList<INode> impl)
{
BindList((INamedParameterNode)ClassHierarchy.GetNode(iface), impl);
}
public void BindList(string iface, IList<string> impl)
{
BindList((INamedParameterNode)ClassHierarchy.GetNode(iface), impl);
}
public void BindConstructor(Types.IClassNode k, Types.IClassNode v)
{
BoundConstructors.Add(k, v);
}
public string ClassPrettyDefaultString(string longName)
{
INamedParameterNode param = (INamedParameterNode)this.ClassHierarchy.GetNode(longName);
return param.GetSimpleArgName() + "=" + Join(",", param.GetDefaultInstanceAsStrings());
}
private string Join(string sep, string[] s)
{
if (s.Length == 0)
{
return null;
}
else
{
StringBuilder sb = new StringBuilder(s[0]);
for (int i = 1; i < s.Length; i++)
{
sb.Append(sep);
sb.Append(s[i]);
}
return sb.ToString();
}
}
public string ClassPrettyDescriptionString(string fullName)
{
INamedParameterNode param = (INamedParameterNode)this.ClassHierarchy.GetNode(fullName);
return param.GetDocumentation() + "\n" + param.GetFullName();
}
}
}