You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@reef.apache.org by we...@apache.org on 2015/01/23 00:46:48 UTC

[15/51] [partial] incubator-reef git commit: [REEF-93] Move java sources to lang/java

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/NameResolutionException.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/NameResolutionException.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/NameResolutionException.java
new file mode 100644
index 0000000..e40ab94
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/NameResolutionException.java
@@ -0,0 +1,40 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.exceptions;
+
+/**
+ * Thrown when Tang encounters an unknown (to the current classloader) class
+ * or configuration option.  NameResolutionExceptions can only be encountered
+ * if:
+ * <ol>
+ * <li> Tang is processing a configuration file from an external source </li>
+ * <li> Classes / NamedParameters are passed to Tang in String form </li>
+ * <li> Class objects are passed directly to Tang, but it is using a different
+ * classloader than the calling code.</li>
+ * <li> Tang is processing Configurations using a ClassHierarchy produced by
+ * another process </li>
+ * </ol>
+ */
+public class NameResolutionException extends BindException {
+  private static final long serialVersionUID = 1L;
+
+  public NameResolutionException(String name, String longestPrefix) {
+    super("Could not resolve " + name + ".  Search ended at prefix " + longestPrefix + " This can happen due to typos in class names that are passed as strings, or because Tang is configured to use a classloader other than the one that generated the class reference (check your classpath and the code that instantiated Tang)");
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/ParseException.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/ParseException.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/ParseException.java
new file mode 100644
index 0000000..8c22e81
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/ParseException.java
@@ -0,0 +1,36 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.exceptions;
+
+/**
+ * Thrown when a string fails to parse as the requested type.
+ *
+ * @see ParameterParser for more information about string parsing.
+ */
+public class ParseException extends BindException {
+  private static final long serialVersionUID = 1L;
+
+  public ParseException(String msg, Throwable cause) {
+    super(msg, cause);
+  }
+
+  public ParseException(String msg) {
+    super(msg);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/package-info.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/package-info.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/package-info.java
new file mode 100644
index 0000000..0fca070
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/exceptions/package-info.java
@@ -0,0 +1,28 @@
+/**
+ * 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.
+ */
+/**
+ * Exceptions thrown by Tang, including runtime exceptions that reflect
+ * compile-time inconsistencies and other problems that can't be
+ * meaningfully handled by application code.  The non-runtime exceptions
+ * in this package are thrown when an incorrect configuration file, or
+ * other post-compilation problems are detected.
+ *
+ */
+package org.apache.reef.tang.exceptions;
+

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/AvroConfigurationSerializer.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/AvroConfigurationSerializer.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/AvroConfigurationSerializer.java
new file mode 100644
index 0000000..98f455a
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/AvroConfigurationSerializer.java
@@ -0,0 +1,313 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+import org.apache.avro.file.DataFileReader;
+import org.apache.avro.file.DataFileWriter;
+import org.apache.avro.io.*;
+import org.apache.avro.specific.SpecificDatumReader;
+import org.apache.avro.specific.SpecificDatumWriter;
+import org.apache.commons.lang.StringUtils;
+import org.apache.reef.tang.ClassHierarchy;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.ConfigurationBuilder;
+import org.apache.reef.tang.Tang;
+import org.apache.reef.tang.exceptions.BindException;
+import org.apache.reef.tang.exceptions.ClassHierarchyException;
+import org.apache.reef.tang.formats.avro.AvroConfiguration;
+import org.apache.reef.tang.formats.avro.ConfigurationEntry;
+import org.apache.reef.tang.implementation.ConfigurationBuilderImpl;
+import org.apache.reef.tang.types.ClassNode;
+import org.apache.reef.tang.types.NamedParameterNode;
+import org.apache.reef.tang.types.Node;
+import org.apache.reef.tang.util.ReflectionUtilities;
+
+import javax.inject.Inject;
+import java.io.*;
+import java.util.*;
+
+/**
+ * (De-)Serializing Configuration to and from AvroConfiguration.
+ * <p/>
+ * This class is stateless and is therefore safe to reuse.
+ */
+public final class AvroConfigurationSerializer implements ConfigurationSerializer {
+
+  /**
+   * The Charset used for the JSON encoding.
+   * <p/>
+   * Copied from <code>org.apache.avro.io.JsonDecoder.CHARSET</code>
+   */
+  private static final String JSON_CHARSET = "ISO-8859-1";
+
+  @Inject
+  public AvroConfigurationSerializer() {
+  }
+
+  private static void fromAvro(final AvroConfiguration avroConfiguration, final ConfigurationBuilder configurationBuilder) throws BindException {
+    // Note: This code is an adapted version of ConfigurationFile.processConfigFile();
+    // TODO: This method should implement list deserialization. Implement it when C# side is ready.
+    final Map<String, String> importedNames = new HashMap<>();
+
+    for (final ConfigurationEntry entry : avroConfiguration.getBindings()) {
+
+      final String longName = importedNames.get(entry.getKey().toString());
+      final String key;
+      if (null == longName) {
+        key = entry.getKey().toString();
+      } else {
+        key = longName;
+      }
+
+      // entry.getValue()'s type can be either string or array of string
+      final Object rawValue = entry.getValue();
+
+      try {
+        // TODO: Implement list deserialization
+        // rawValue is String.
+        String value = rawValue.toString();
+        if (key.equals(ConfigurationBuilderImpl.IMPORT)) {
+          configurationBuilder.getClassHierarchy().getNode(value);
+          final String[] tok = value.split(ReflectionUtilities.regexp);
+          final String lastTok = tok[tok.length - 1];
+          try {
+            configurationBuilder.getClassHierarchy().getNode(lastTok);
+            throw new IllegalArgumentException("Conflict on short name: " + lastTok);
+          } catch (final BindException e) {
+            final String oldValue = importedNames.put(lastTok, value);
+            if (oldValue != null) {
+              throw new IllegalArgumentException("Name conflict: "
+                  + lastTok + " maps to " + oldValue + " and " + value);
+            }
+          }
+        } else if (value.startsWith(ConfigurationBuilderImpl.INIT)) {
+          final String[] classes = value.substring(ConfigurationBuilderImpl.INIT.length(), value.length())
+              .replaceAll("^[\\s\\(]+", "")
+              .replaceAll("[\\s\\)]+$", "")
+              .split("[\\s\\-]+");
+          configurationBuilder.registerLegacyConstructor(key, classes);
+        } else {
+          configurationBuilder.bind(key, value);
+        }
+      } catch (final BindException | ClassHierarchyException e) {
+        throw new BindException("Failed to process configuration tuple: [" + key + "=" + rawValue + "]", e);
+      }
+    }
+  }
+
+  private static AvroConfiguration avroFromFile(final File file) throws IOException {
+    final AvroConfiguration avroConfiguration;
+    try (final DataFileReader<AvroConfiguration> dataFileReader =
+             new DataFileReader<>(file, new SpecificDatumReader<>(AvroConfiguration.class))) {
+      avroConfiguration = dataFileReader.next();
+    }
+    return avroConfiguration;
+  }
+
+  private static AvroConfiguration avroFromBytes(final byte[] theBytes) throws IOException {
+    final BinaryDecoder decoder = DecoderFactory.get().binaryDecoder(theBytes, null);
+    final SpecificDatumReader<AvroConfiguration> reader = new SpecificDatumReader<>(AvroConfiguration.class);
+    return reader.read(null, decoder);
+  }
+
+  private static AvroConfiguration avroFromString(final String theString) throws IOException {
+    final JsonDecoder decoder = DecoderFactory.get().jsonDecoder(AvroConfiguration.getClassSchema(), theString);
+    final SpecificDatumReader<AvroConfiguration> reader = new SpecificDatumReader<>(AvroConfiguration.class);
+    return reader.read(null, decoder);
+  }
+
+  public AvroConfiguration toAvro(final Configuration configuration) {
+    // Note: This code is an adapted version of ConfiurationFile.toConfigurationStringList();
+    // TODO: This method should implement list serialization. Implement it when C# side is ready.
+
+    final List<ConfigurationEntry> configurationEntries = new ArrayList<>();
+
+    for (final ClassNode<?> opt : configuration.getBoundImplementations()) {
+      configurationEntries.add(new ConfigurationEntry().newBuilder()
+          .setKey(opt.getFullName())
+          .setValue(configuration.getBoundImplementation(opt).getFullName())
+          .build());
+    }
+
+    for (final ClassNode<?> opt : configuration.getBoundConstructors()) {
+      configurationEntries.add(new ConfigurationEntry().newBuilder()
+          .setKey(opt.getFullName())
+          .setValue(configuration.getBoundConstructor(opt).getFullName())
+          .build());
+    }
+    for (final NamedParameterNode<?> opt : configuration.getNamedParameters()) {
+      configurationEntries.add(new ConfigurationEntry().newBuilder()
+          .setKey(opt.getFullName())
+          .setValue(configuration.getNamedParameter(opt))
+          .build());
+    }
+    for (final ClassNode<?> cn : configuration.getLegacyConstructors()) {
+      final String legacyConstructors = StringUtils.join(configuration.getLegacyConstructor(cn).getArgs(), "-");
+      configurationEntries.add(new ConfigurationEntry().newBuilder()
+          .setKey(cn.getFullName())
+          .setValue("" + ConfigurationBuilderImpl.INIT + "(" + legacyConstructors + ")")
+          .build());
+    }
+    for (final Map.Entry<NamedParameterNode<Set<?>>, Object> e : configuration.getBoundSets()) {
+      final String val;
+      if (e.getValue() instanceof String) {
+        val = (String) e.getValue();
+      } else if (e.getValue() instanceof Node) {
+        val = ((Node) e.getValue()).getFullName();
+      } else {
+        throw new IllegalStateException();
+      }
+      configurationEntries.add(new ConfigurationEntry().newBuilder()
+          .setKey(e.getKey().getFullName())
+          .setValue(val)
+          .build());
+    }
+    // TODO: Implement list serialization
+
+    return AvroConfiguration.newBuilder().setBindings(configurationEntries).build();
+  }
+
+  @Override
+  public void toFile(final Configuration conf, final File file) throws IOException {
+    final AvroConfiguration avroConfiguration = toAvro(conf);
+    final DatumWriter<AvroConfiguration> configurationWriter = new SpecificDatumWriter<>(AvroConfiguration.class);
+    try (DataFileWriter<AvroConfiguration> dataFileWriter = new DataFileWriter<>(configurationWriter)) {
+      dataFileWriter.create(avroConfiguration.getSchema(), file);
+      dataFileWriter.append(avroConfiguration);
+    }
+  }
+
+  @Override
+  public void toTextFile(final Configuration conf, final File file) throws IOException {
+    try (final Writer w = new FileWriter(file)) {
+      w.write(this.toString(conf));
+    }
+  }
+
+  @Override
+  public byte[] toByteArray(final Configuration conf) throws IOException {
+    final DatumWriter<AvroConfiguration> configurationWriter = new SpecificDatumWriter<>(AvroConfiguration.class);
+    final byte[] theBytes;
+    try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+      final BinaryEncoder encoder = EncoderFactory.get().binaryEncoder(out, null);
+      configurationWriter.write(toAvro(conf), encoder);
+      encoder.flush();
+      out.flush();
+      theBytes = out.toByteArray();
+    }
+    return theBytes;
+  }
+
+  @Override
+  public String toString(final Configuration configuration) {
+    final DatumWriter<AvroConfiguration> configurationWriter = new SpecificDatumWriter<>(AvroConfiguration.class);
+    final String result;
+    try (final ByteArrayOutputStream out = new ByteArrayOutputStream()) {
+      final JsonEncoder encoder = EncoderFactory.get().jsonEncoder(AvroConfiguration.SCHEMA$, out);
+      configurationWriter.write(toAvro(configuration), encoder);
+      encoder.flush();
+      out.flush();
+      result = out.toString(JSON_CHARSET);
+    } catch (final IOException e) {
+      throw new RuntimeException(e);
+    }
+    return result;
+  }
+
+  /**
+   * Converts a given AvroConfiguration to Configuration
+   *
+   * @param avroConfiguration
+   * @return a Configuration version of the given AvroConfiguration
+   */
+  public Configuration fromAvro(final AvroConfiguration avroConfiguration) throws BindException {
+    final ConfigurationBuilder configurationBuilder = Tang.Factory.getTang().newConfigurationBuilder();
+    fromAvro(avroConfiguration, configurationBuilder);
+    return configurationBuilder.build();
+  }
+
+  /**
+   * Converts a given AvroConfiguration to Configuration
+   *
+   * @param avroConfiguration
+   * @param classHierarchy    the class hierarchy used for validation.
+   * @return a Configuration version of the given AvroConfiguration
+   */
+  public Configuration fromAvro(final AvroConfiguration avroConfiguration, final ClassHierarchy classHierarchy)
+      throws BindException {
+    final ConfigurationBuilder configurationBuilder = Tang.Factory.getTang().newConfigurationBuilder(classHierarchy);
+    fromAvro(avroConfiguration, configurationBuilder);
+    return configurationBuilder.build();
+  }
+
+  @Override
+  public Configuration fromFile(final File file) throws IOException, BindException {
+    return fromAvro(avroFromFile(file));
+  }
+
+  @Override
+  public Configuration fromFile(final File file, final ClassHierarchy classHierarchy) throws IOException, BindException {
+    return fromAvro(avroFromFile(file), classHierarchy);
+  }
+
+  @Override
+  public Configuration fromTextFile(final File file) throws IOException, BindException {
+    final StringBuilder result = readFromTextFile(file);
+    return this.fromString(result.toString());
+  }
+
+  @Override
+  public Configuration fromTextFile(final File file, final ClassHierarchy classHierarchy) throws IOException, BindException {
+    final StringBuilder result = readFromTextFile(file);
+    return this.fromString(result.toString(), classHierarchy);
+  }
+
+  private StringBuilder readFromTextFile(final File file) throws IOException {
+    final StringBuilder result = new StringBuilder();
+    try (final BufferedReader reader = new BufferedReader(new FileReader(file))) {
+      String line = reader.readLine();
+      while (line != null) {
+        result.append(line);
+        line = reader.readLine();
+      }
+    }
+    return result;
+  }
+
+  @Override
+  public Configuration fromByteArray(final byte[] theBytes) throws IOException, BindException {
+    return fromAvro(avroFromBytes(theBytes));
+  }
+
+  @Override
+  public Configuration fromByteArray(final byte[] theBytes, final ClassHierarchy classHierarchy) throws IOException, BindException {
+    return fromAvro(avroFromBytes(theBytes), classHierarchy);
+  }
+
+  @Override
+  public Configuration fromString(final String theString) throws IOException, BindException {
+    return fromAvro(avroFromString(theString));
+  }
+
+  @Override
+  public Configuration fromString(final String theString, final ClassHierarchy classHierarchy) throws IOException, BindException {
+    return fromAvro(avroFromString(theString), classHierarchy);
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/CommandLine.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/CommandLine.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/CommandLine.java
new file mode 100644
index 0000000..a299958
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/CommandLine.java
@@ -0,0 +1,218 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+import org.apache.commons.cli.*;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.ConfigurationBuilder;
+import org.apache.reef.tang.JavaConfigurationBuilder;
+import org.apache.reef.tang.Tang;
+import org.apache.reef.tang.annotations.Name;
+import org.apache.reef.tang.exceptions.BindException;
+import org.apache.reef.tang.exceptions.NameResolutionException;
+import org.apache.reef.tang.types.NamedParameterNode;
+import org.apache.reef.tang.types.Node;
+import org.apache.reef.tang.util.MonotonicTreeMap;
+import org.apache.reef.tang.util.ReflectionUtilities;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class CommandLine {
+
+  final Map<Option, CommandLineCallback> applicationOptions = new HashMap<>();
+  private final ConfigurationBuilder conf;
+  private final Map<String, String> shortNames = new MonotonicTreeMap<>();
+
+  public CommandLine() {
+    this.conf = Tang.Factory.getTang().newConfigurationBuilder();
+  }
+
+  public CommandLine(final ConfigurationBuilder conf) {
+    this.conf = conf;
+  }
+
+  public ConfigurationBuilder getBuilder() {
+    return this.conf;
+  }
+
+  public CommandLine registerShortNameOfClass(final String s) throws BindException {
+
+    final Node n;
+    try {
+      n = conf.getClassHierarchy().getNode(s);
+    } catch (final NameResolutionException e) {
+      throw new BindException("Problem loading class " + s, e);
+    }
+
+    if (n instanceof NamedParameterNode) {
+      final NamedParameterNode<?> np = (NamedParameterNode<?>) n;
+      final String shortName = np.getShortName();
+      final String longName = np.getFullName();
+      if (shortName == null) {
+        throw new BindException(
+            "Can't register non-existent short name of named parameter: " + longName);
+      }
+      shortNames.put(shortName, longName);
+    } else {
+      throw new BindException("Can't register short name for non-NamedParameterNode: " + n);
+    }
+
+    return this;
+  }
+
+  public CommandLine registerShortNameOfClass(
+      final Class<? extends Name<?>> c) throws BindException {
+    return registerShortNameOfClass(ReflectionUtilities.getFullName(c));
+  }
+
+  @SuppressWarnings("static-access")
+  private Options getCommandLineOptions() {
+
+    final Options opts = new Options();
+    for (final String shortName : shortNames.keySet()) {
+      final String longName = shortNames.get(shortName);
+      try {
+        opts.addOption(OptionBuilder
+            .withArgName(conf.classPrettyDefaultString(longName)).hasArg()
+            .withDescription(conf.classPrettyDescriptionString(longName))
+            .create(shortName));
+      } catch (final BindException e) {
+        throw new IllegalStateException(
+            "Could not process " + shortName + " which is the short name of " + longName, e);
+      }
+    }
+
+    for (final Option o : applicationOptions.keySet()) {
+      opts.addOption(o);
+    }
+
+    return opts;
+  }
+
+  public CommandLine addCommandLineOption(final Option option, final CommandLineCallback cb) {
+    // TODO: Check for conflicting options.
+    applicationOptions.put(option, cb);
+    return this;
+  }
+
+  /**
+   * @param args
+   * @return Selfie if the command line parsing succeeded, null (or exception) otherwise.
+   * @throws IOException
+   * @throws NumberFormatException
+   * @throws ParseException
+   */
+  @SafeVarargs
+  final public <T> CommandLine processCommandLine(
+      final String[] args, Class<? extends Name<?>>... argClasses)
+      throws IOException, BindException {
+
+    for (final Class<? extends Name<?>> c : argClasses) {
+      registerShortNameOfClass(c);
+    }
+
+    final Options o = getCommandLineOptions();
+    o.addOption(new Option("?", "help"));
+    final Parser g = new GnuParser();
+
+    final org.apache.commons.cli.CommandLine cl;
+    try {
+      cl = g.parse(o, args);
+    } catch (final ParseException e) {
+      throw new IOException("Could not parse config file", e);
+    }
+
+    if (cl.hasOption("?")) {
+      new HelpFormatter().printHelp("reef", o);
+      return null;
+    }
+
+    for (final Option option : cl.getOptions()) {
+
+      final String shortName = option.getOpt();
+      final String value = option.getValue();
+
+      if (applicationOptions.containsKey(option)) {
+        applicationOptions.get(option).process(option);
+      } else {
+        try {
+          conf.bind(shortNames.get(shortName), value);
+        } catch (final BindException e) {
+          throw new BindException("Could not bind shortName " + shortName + " to value " + value, e);
+        }
+      }
+    }
+
+    return this;
+  }
+
+  /**
+   * Utility method to quickly parse a command line to a Configuration.
+   * <p/>
+   * This is equivalent to
+   * <code>parseToConfigurationBuilder(args, argClasses).build()</code>
+   *
+   * @param args       the command line parameters to parse.
+   * @param argClasses the named parameters to look for.
+   * @return a Configuration with the parsed parameters
+   * @throws ParseException if the parsing  of the commandline fails.
+   */
+  public static Configuration parseToConfiguration(final String[] args,
+                                                   final Class<? extends Name<?>>... argClasses)
+      throws ParseException {
+    return parseToConfigurationBuilder(args, argClasses).build();
+  }
+
+  /**
+   * Utility method to quickly parse a command line to a ConfigurationBuilder.
+   * <p/>
+   * This is equivalent to
+   * <code>new CommandLine().processCommandLine(args, argClasses).getBuilder()</code>, but with additional checks.
+   *
+   * @param args       the command line parameters to parse.
+   * @param argClasses the named parameters to look for.
+   * @return a ConfigurationBuilder with the parsed parameters
+   * @throws ParseException if the parsing  of the commandline fails.
+   */
+  public static ConfigurationBuilder parseToConfigurationBuilder(final String[] args,
+                                                                 final Class<? extends Name<?>>... argClasses)
+      throws ParseException {
+    final CommandLine commandLine;
+    try {
+      commandLine = new CommandLine().processCommandLine(args, argClasses);
+    } catch (final IOException e) {
+      // processCommandLine() converts ParseException into IOException. This reverts that to make exception handling
+      // more straight forward.
+      throw new ParseException(e.getMessage());
+    }
+
+    // processCommandLine() indicates that it might return null. We need to guard users of this one from that
+    if (commandLine == null) {
+      throw new ParseException("Unable to parse the command line and the parser returned null.");
+    } else {
+      return commandLine.getBuilder();
+    }
+  }
+
+  public interface CommandLineCallback {
+    public void process(final Option option);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationFile.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationFile.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationFile.java
new file mode 100644
index 0000000..91568d1
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationFile.java
@@ -0,0 +1,253 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.PropertiesConfiguration;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.ConfigurationBuilder;
+import org.apache.reef.tang.exceptions.BindException;
+import org.apache.reef.tang.exceptions.ClassHierarchyException;
+import org.apache.reef.tang.implementation.ConfigurationBuilderImpl;
+import org.apache.reef.tang.implementation.ConfigurationImpl;
+import org.apache.reef.tang.types.ClassNode;
+import org.apache.reef.tang.types.ConstructorArg;
+import org.apache.reef.tang.types.NamedParameterNode;
+import org.apache.reef.tang.types.Node;
+import org.apache.reef.tang.util.ReflectionUtilities;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.*;
+import java.util.Map.Entry;
+
+/**
+ * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead.
+ */
+@Deprecated
+public class ConfigurationFile {
+
+  /**
+   * Write Configuration to the given File.
+   *
+   * @throws IOException
+   * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead.
+   */
+  @Deprecated
+  public static void writeConfigurationFile(
+      final Configuration conf, final File confFile) throws IOException {
+    try (final PrintStream printStream = new PrintStream(new FileOutputStream(confFile))) {
+      printStream.print(toConfigurationString(conf));
+    }
+  }
+
+  /**
+   * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead.
+   */
+  @Deprecated
+  public static void addConfiguration(final ConfigurationBuilder conf,
+                                      final File tmpConfFile) throws IOException, BindException {
+    final PropertiesConfiguration confFile;
+    try {
+      confFile = new PropertiesConfiguration(tmpConfFile);
+    } catch (final ConfigurationException e) {
+      throw new BindException("Problem parsing config file: " + tmpConfFile, e);
+    }
+    processConfigFile(conf, confFile);
+  }
+
+  /**
+   * @param conf     This configuration builder will be modified to incorporate the
+   *                 contents of the configuration file.
+   * @param contents A string containing the contents of the configuration file.
+   * @throws BindException
+   * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead.
+   */
+  @Deprecated
+  public static void addConfiguration(final ConfigurationBuilder conf,
+                                      final String contents) throws BindException {
+    File tmpConfFile = null;
+    try {
+      tmpConfFile = File.createTempFile("tang", "tmp");
+      try (final FileOutputStream outStream = new FileOutputStream(tmpConfFile)) {
+        outStream.write(contents.getBytes());
+      }
+      addConfiguration(conf, tmpConfFile);
+    } catch (final IOException ex) {
+      throw new BindException("Error writing config file: " + tmpConfFile, ex);
+    } finally {
+      if (tmpConfFile != null) {
+        tmpConfFile.delete();
+      }
+    }
+  }
+
+  private static void processConfigFile(ConfigurationBuilder conf,
+                                        PropertiesConfiguration confFile) throws IOException, BindException {
+    ConfigurationBuilderImpl ci = (ConfigurationBuilderImpl) conf;
+    Iterator<String> it = confFile.getKeys();
+    Map<String, String> importedNames = new HashMap<>();
+
+    while (it.hasNext()) {
+      String key = it.next();
+      String longName = importedNames.get(key);
+      String[] values = confFile.getStringArray(key);
+      if (longName != null) {
+        // System.err.println("Mapped " + key + " to " + longName);
+        key = longName;
+      }
+      for (String value : values) {
+        try {
+          if (key.equals(ConfigurationBuilderImpl.IMPORT)) {
+            ci.getClassHierarchy().getNode(value);
+            final String[] tok = value.split(ReflectionUtilities.regexp);
+            final String lastTok = tok[tok.length - 1];
+            try {
+              // ci.namespace.getNode(lastTok);
+              ci.getClassHierarchy().getNode(lastTok);
+              throw new IllegalArgumentException("Conflict on short name: " + lastTok);
+            } catch (BindException e) {
+              String oldValue = importedNames.put(lastTok, value);
+              if (oldValue != null) {
+                throw new IllegalArgumentException("Name conflict: "
+                    + lastTok + " maps to " + oldValue + " and " + value);
+              }
+            }
+          } else if (value.startsWith(ConfigurationBuilderImpl.INIT)) {
+            String parseValue = value.substring(
+                ConfigurationBuilderImpl.INIT.length(), value.length());
+            parseValue = parseValue.replaceAll("^[\\s\\(]+", "");
+            parseValue = parseValue.replaceAll("[\\s\\)]+$", "");
+            String[] classes = parseValue.split("[\\s\\-]+");
+            ci.registerLegacyConstructor(key, classes);
+          } else {
+            ci.bind(key, value);
+          }
+        } catch (BindException e) {
+          throw new BindException("Failed to process configuration tuple: [" + key + "=" + value + "]", e);
+        } catch (ClassHierarchyException e) {
+          throw new ClassHierarchyException("Failed to process configuration tuple: [" + key + "=" + value + "]", e);
+        }
+      }
+    }
+  }
+
+  /**
+   * Replace any \'s in the input string with \\. and any "'s with \".
+   *
+   * @param in
+   * @return
+   */
+  private static String escape(String in) {
+    // After regexp escaping \\\\ = 1 slash, \\\\\\\\ = 2 slashes.
+
+    // Also, the second args of replaceAll are neither strings nor regexps, and
+    // are instead a special DSL used by Matcher. Therefore, we need to double
+    // escape slashes (4 slashes) and quotes (3 slashes + ") in those strings.
+    // Since we need to write \\ and \", we end up with 8 and 7 slashes,
+    // respectively.
+    return in.replaceAll("\\\\", "\\\\\\\\").replaceAll("\"", "\\\\\\\"");
+  }
+
+  /**
+   * Obtain the effective configuration of this ConfigurationBuilderImpl
+   * instance. This consists of string-string pairs that could be written
+   * directly to a Properties file, for example. Currently, this method does not
+   * return information about default parameter values that were specified by
+   * parameter annotations, or about the auto-discovered stuff in TypeHierarchy.
+   * All of that should be automatically imported as these keys are parsed on
+   * the other end.
+   *
+   * @return A string containing enough information to rebuild this
+   * configuration object (assuming the same classes / jars are
+   * available when the string is parsed by Tang).
+   * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead.
+   */
+  @Deprecated
+  public static String toConfigurationString(final Configuration c) {
+    StringBuilder sb = new StringBuilder();
+    for (String s : toConfigurationStringList(c)) {
+      sb.append(s);
+      sb.append('\n');
+    }
+    return sb.toString();
+  }
+
+  /**
+   * @deprecated in Tang 0.2 Use AvroConfigurationSerializer instead.
+   */
+  @Deprecated
+  static List<String> toConfigurationStringList(final Configuration c) {
+    ConfigurationImpl conf = (ConfigurationImpl) c;
+    List<String> l = new ArrayList<>();
+    for (ClassNode<?> opt : conf.getBoundImplementations()) {
+      l.add(opt.getFullName()
+          + '='
+          + escape(conf.getBoundImplementation(opt).getFullName()));
+    }
+    for (ClassNode<?> opt : conf.getBoundConstructors()) {
+      l.add(opt.getFullName()
+          + '='
+          + escape(conf.getBoundConstructor(opt).getFullName()));
+    }
+    for (NamedParameterNode<?> opt : conf.getNamedParameters()) {
+      l.add(opt.getFullName()
+          + '='
+          + escape(conf.getNamedParameter(opt)));
+    }
+    for (ClassNode<?> cn : conf.getLegacyConstructors()) {
+      StringBuilder sb = new StringBuilder();
+      join(sb, "-", conf.getLegacyConstructor(cn).getArgs());
+      l.add(cn.getFullName()
+          + escape('='
+              + ConfigurationBuilderImpl.INIT
+              + '('
+              + sb.toString()
+              + ')'
+      ));
+      //s.append(cn.getFullName()).append('=').append(ConfigurationBuilderImpl.INIT).append('(');
+//      .append(")\n");
+    }
+    for (Entry<NamedParameterNode<Set<?>>, Object> e : conf.getBoundSets()) {
+      final String val;
+      if (e.getValue() instanceof String) {
+        val = (String) e.getValue();
+      } else if (e.getValue() instanceof Node) {
+        val = ((Node) e.getValue()).getFullName();
+      } else {
+        throw new IllegalStateException();
+      }
+      l.add(e.getKey().getFullName() + '=' + escape(val));
+//      s.append(e.getKey().getFullName()).append('=').append(val).append("\n");
+    }
+    return l;//s.toString();
+  }
+
+  private static StringBuilder join(final StringBuilder sb, final String sep, final ConstructorArg[] types) {
+    if (types.length > 0) {
+      sb.append(types[0].getType());
+      for (int i = 1; i < types.length; i++) {
+        sb.append(sep).append(types[i].getType());
+      }
+    }
+    return sb;
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationModule.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationModule.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationModule.java
new file mode 100644
index 0000000..5b749ce
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationModule.java
@@ -0,0 +1,299 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.annotations.Name;
+import org.apache.reef.tang.exceptions.BindException;
+import org.apache.reef.tang.exceptions.ClassHierarchyException;
+import org.apache.reef.tang.exceptions.NameResolutionException;
+import org.apache.reef.tang.types.NamedParameterNode;
+import org.apache.reef.tang.util.*;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * Allows applications to bundle sets of configuration options together into
+ * discrete packages.  Unlike more conventional approaches,
+ * ConfigurationModules store such information in static data structures that
+ * can be statically discovered and sanity-checked.
+ *
+ * @see org.apache.reef.tang.formats.TestConfigurationModule for more information and examples.
+ */
+public class ConfigurationModule {
+  final ConfigurationModuleBuilder builder;
+  // Set of required unset parameters. Must be empty before build.
+  private final Set<Field> reqSet = new MonotonicHashSet<>();
+  private final Map<Impl<?>, Class<?>> setImpls = new MonotonicHashMap<>();
+  private final MonotonicMultiHashMap<Impl<?>, Class<?>> setImplSets = new MonotonicMultiHashMap<>();
+  private final MonotonicMultiHashMap<Impl<?>, String> setLateImplSets = new MonotonicMultiHashMap<>();
+  private final MonotonicMultiHashMap<Param<?>, String> setParamSets = new MonotonicMultiHashMap<>();
+  private final Map<Impl<?>, String> setLateImpls = new MonotonicHashMap<>();
+  private final Map<Param<?>, String> setParams = new MonotonicHashMap<>();
+  private final Map<Impl<List>, List<?>> setImplLists = new MonotonicHashMap<>();
+  private final Map<Param<List>, List<?>> setParamLists = new MonotonicHashMap<>();
+
+  protected ConfigurationModule(ConfigurationModuleBuilder builder) {
+    this.builder = builder.deepCopy();
+  }
+
+  private ConfigurationModule deepCopy() {
+    ConfigurationModule cm = new ConfigurationModule(builder.deepCopy());
+    cm.setImpls.putAll(setImpls);
+    cm.setImplSets.addAll(setImplSets);
+    cm.setLateImplSets.addAll(setLateImplSets);
+    cm.setParamSets.addAll(setParamSets);
+    cm.setLateImpls.putAll(setLateImpls);
+    cm.setParams.putAll(setParams);
+    cm.reqSet.addAll(reqSet);
+    cm.setImplLists.putAll(setImplLists);
+    cm.setParamLists.putAll(setParamLists);
+    return cm;
+  }
+
+  private final <T> void processSet(Object impl) {
+    Field f = builder.map.get(impl);
+    if (f == null) { /* throw */
+      throw new ClassHierarchyException("Unknown Impl/Param when setting " + ReflectionUtilities.getSimpleName(impl.getClass()) + ".  Did you pass in a field from some other module?");
+    }
+    if (!reqSet.contains(f)) {
+      reqSet.add(f);
+    }
+  }
+
+  public final <T> ConfigurationModule set(Impl<T> opt, Class<? extends T> impl) {
+    ConfigurationModule c = deepCopy();
+    c.processSet(opt);
+    if (c.builder.setOpts.contains(opt)) {
+      c.setImplSets.put(opt, impl);
+    } else {
+      c.setImpls.put(opt, impl);
+    }
+    return c;
+  }
+
+  public final <T> ConfigurationModule set(Impl<T> opt, String impl) {
+    ConfigurationModule c = deepCopy();
+    c.processSet(opt);
+    if (c.builder.setOpts.contains(opt)) {
+      c.setLateImplSets.put(opt, impl);
+    } else {
+      c.setLateImpls.put(opt, impl);
+    }
+    return c;
+  }
+
+  /**
+   * Binds a list to a specific optional/required Impl using ConfigurationModule.
+   *
+   * @param opt      Target optional/required Impl
+   * @param implList List object to be injected
+   * @param <T>
+   * @return
+   */
+  public final <T> ConfigurationModule set(Impl<List> opt, List implList) {
+    ConfigurationModule c = deepCopy();
+    c.processSet(opt);
+    c.setImplLists.put(opt, implList);
+    return c;
+  }
+
+  public final <T> ConfigurationModule set(Param<T> opt, Class<? extends T> val) {
+    return set(opt, ReflectionUtilities.getFullName(val));
+  }
+
+  public final ConfigurationModule set(Param<Boolean> opt, boolean val) {
+    return set(opt, "" + val);
+  }
+
+  public final ConfigurationModule set(Param<? extends Number> opt, Number val) {
+    return set(opt, "" + val);
+  }
+
+  public final <T> ConfigurationModule set(Param<T> opt, String val) {
+    ConfigurationModule c = deepCopy();
+    c.processSet(opt);
+    if (c.builder.setOpts.contains(opt)) {
+      c.setParamSets.put(opt, val);
+    } else {
+      c.setParams.put(opt, val);
+    }
+    return c;
+  }
+
+  /**
+   * Binds a list to a specfici optional/required Param using ConfigurationModule.
+   *
+   * @param opt      target optional/required Param
+   * @param implList List object to be injected
+   * @param <T>
+   * @return
+   */
+  public final <T> ConfigurationModule set(Param<List> opt, List implList) {
+    ConfigurationModule c = deepCopy();
+    c.processSet(opt);
+    c.setParamLists.put(opt, implList);
+    return c;
+  }
+
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  public Configuration build() throws BindException {
+    ConfigurationModule c = deepCopy();
+
+    if (!c.reqSet.containsAll(c.builder.reqDecl)) {
+      Set<Field> missingSet = new MonotonicHashSet<>();
+      for (Field f : c.builder.reqDecl) {
+        if (!c.reqSet.contains(f)) {
+          missingSet.add(f);
+        }
+      }
+      throw new BindException(
+          "Attempt to build configuration before setting required option(s): "
+              + builder.toString(missingSet));
+    }
+
+    for (Class<?> clazz : c.builder.freeImpls.keySet()) {
+      Impl<?> i = c.builder.freeImpls.get(clazz);
+      if (c.setImpls.containsKey(i)) {
+        c.builder.b.bind(clazz, c.setImpls.get(i));
+      } else if (c.setLateImpls.containsKey(i)) {
+        c.builder.b.bind(ReflectionUtilities.getFullName(clazz), c.setLateImpls.get(i));
+      } else if (c.setImplSets.containsKey(i) || c.setLateImplSets.containsKey(i)) {
+        for (Class<?> clz : c.setImplSets.getValuesForKey(i)) {
+          c.builder.b.bindSetEntry((Class) clazz, (Class) clz);
+        }
+        for (String s : c.setLateImplSets.getValuesForKey(i)) {
+          c.builder.b.bindSetEntry((Class) clazz, s);
+        }
+      } else if (c.setImplLists.containsKey(i)) {
+        c.builder.b.bindList((Class) clazz, c.setImplLists.get(i));
+      }
+    }
+    for (Class<? extends Name<?>> clazz : c.builder.freeParams.keySet()) {
+      Param<?> p = c.builder.freeParams.get(clazz);
+      String s = c.setParams.get(p);
+      boolean foundOne = false;
+      if (s != null) {
+        c.builder.b.bindNamedParameter(clazz, s);
+        foundOne = true;
+      }
+      // Find the bound list for the NamedParameter
+      List list = c.setParamLists.get(p);
+      if (list != null) {
+        c.builder.b.bindList((Class) clazz, list);
+        foundOne = true;
+      }
+      for (String paramStr : c.setParamSets.getValuesForKey(p)) {
+        c.builder.b.bindSetEntry((Class) clazz, paramStr);
+        foundOne = true;
+      }
+      if (!foundOne) {
+        if (!(p instanceof OptionalParameter)) {
+          throw new IllegalStateException();
+        }
+      }
+    }
+    return c.builder.b.build();
+
+  }
+
+  public Set<NamedParameterNode<?>> getBoundNamedParameters() {
+    Configuration c = this.builder.b.build();
+    Set<NamedParameterNode<?>> nps = new MonotonicSet<>();
+    nps.addAll(c.getNamedParameters());
+    for (Class<?> np : this.builder.freeParams.keySet()) {
+      try {
+        nps.add((NamedParameterNode<?>) builder.b.getClassHierarchy().getNode(ReflectionUtilities.getFullName(np)));
+      } catch (NameResolutionException e) {
+        throw new IllegalStateException(e);
+      }
+    }
+    return nps;
+  }
+
+  public List<Entry<String, String>> toStringPairs() {
+    List<Entry<String, String>> ret = new ArrayList<>();
+    class MyEntry implements Entry<String, String> {
+      final String k;
+      final String v;
+
+      public MyEntry(String k, String v) {
+        this.k = k;
+        this.v = v;
+      }
+
+      @Override
+      public String getKey() {
+        return k;
+      }
+
+      @Override
+      public String getValue() {
+        return v;
+      }
+
+      @Override
+      public String setValue(String value) {
+        throw new UnsupportedOperationException();
+      }
+
+    }
+    for (Class<?> c : this.builder.freeParams.keySet()) {
+      ret.add(new MyEntry(ReflectionUtilities.getFullName(c), this.builder.map.get(this.builder.freeParams.get(c)).getName()));
+    }
+    for (Class<?> c : this.builder.freeImpls.keySet()) {
+      ret.add(new MyEntry(ReflectionUtilities.getFullName(c), this.builder.map.get(this.builder.freeImpls.get(c)).getName()));
+    }
+    for (String s : ConfigurationFile.toConfigurationStringList(builder.b.build())) {
+      String[] tok = s.split("=", 2);
+      ret.add(new MyEntry(tok[0], tok[1]));
+    }
+
+    return ret;
+  }
+
+  public String toPrettyString() {
+    StringBuilder sb = new StringBuilder();
+
+    for (Entry<String, String> l : toStringPairs()) {
+      sb.append(l.getKey() + "=" + l.getValue() + "\n");
+    }
+    return sb.toString();
+  }
+
+  public void assertStaticClean() throws ClassHierarchyException {
+    if (!(
+        setImpls.isEmpty() &&
+            setImplSets.isEmpty() &&
+            setLateImplSets.isEmpty() &&
+            setParamSets.isEmpty() &&
+            setLateImpls.isEmpty() &&
+            setParams.isEmpty() &&
+            setImplLists.isEmpty() &&
+            setParamLists.isEmpty()
+    )) {
+      throw new ClassHierarchyException("Detected statically set ConfigurationModule Parameter / Implementation.  set() should only be used dynamically.  Use bind...() instead.");
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationModuleBuilder.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationModuleBuilder.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationModuleBuilder.java
new file mode 100644
index 0000000..38359c0
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationModuleBuilder.java
@@ -0,0 +1,385 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+import org.apache.reef.tang.ExternalConstructor;
+import org.apache.reef.tang.JavaConfigurationBuilder;
+import org.apache.reef.tang.Tang;
+import org.apache.reef.tang.annotations.Name;
+import org.apache.reef.tang.exceptions.BindException;
+import org.apache.reef.tang.exceptions.ClassHierarchyException;
+import org.apache.reef.tang.exceptions.NameResolutionException;
+import org.apache.reef.tang.util.MonotonicHashMap;
+import org.apache.reef.tang.util.MonotonicHashSet;
+import org.apache.reef.tang.util.ReflectionUtilities;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public abstract class ConfigurationModuleBuilder {
+
+  private final static Set<Class<?>> paramBlacklist = new MonotonicHashSet<Class<?>>(
+      Param.class, Impl.class);
+  private final static Set<Class<?>> paramTypes = new MonotonicHashSet<Class<?>>(
+      RequiredImpl.class, OptionalImpl.class, RequiredParameter.class,
+      OptionalParameter.class);
+  final JavaConfigurationBuilder b = Tang.Factory.getTang()
+      .newConfigurationBuilder();
+  // Sets of things that have been declared
+  final Set<Field> reqDecl = new MonotonicHashSet<>();
+  final Set<Object> setOpts = new MonotonicHashSet<>();
+  // Maps from field instance variables to the fields that they
+  // are assigned to. These better be unique!
+  final Map<Object, Field> map = new MonotonicHashMap<>();
+  final Map<Class<?>, Impl<?>> freeImpls = new MonotonicHashMap<>();
+  final Map<Class<? extends Name<?>>, Param<?>> freeParams = new MonotonicHashMap<>();
+  private final Set<Field> optDecl = new MonotonicHashSet<>();
+  // Set of things that have been used in a bind. These must be equal
+  // to the decl counterparts before build() is called.
+  private final Set<Field> reqUsed = new MonotonicHashSet<>();
+  private final Set<Field> optUsed = new MonotonicHashSet<>();
+  private final Map<Class<?>, String> lateBindClazz = new MonotonicHashMap<>();
+
+  protected ConfigurationModuleBuilder() {
+    for (Field f : getClass().getDeclaredFields()) {
+      Class<?> t = f.getType();
+      if (paramBlacklist.contains(t)) {
+        throw new ClassHierarchyException(
+            "Found a field of type " + t + " which should be a Required/Optional Parameter/Implementation instead"
+        );
+      }
+      if (paramTypes.contains(t)) {
+        if (!Modifier.isPublic(f.getModifiers())) {
+          throw new ClassHierarchyException(
+              "Found a non-public configuration option in " + getClass() + ": "
+                  + f);
+        }
+        if (!Modifier.isStatic(f.getModifiers())) {
+          throw new ClassHierarchyException(
+              "Found a non-static configuration option in " + getClass() + ": "
+                  + f);
+        }
+        if (!Modifier.isFinal(f.getModifiers())) {
+          throw new ClassHierarchyException(
+              "Found a non-final configuration option in " + getClass() + ": "
+                  + f);
+        }
+        final Object o;
+        try {
+          o = f.get(null);
+        } catch (IllegalArgumentException | IllegalAccessException e) {
+          throw new ClassHierarchyException(
+              "Could not look up field instance in " + getClass() + " field: "
+                  + f, e);
+        }
+        if (map.containsKey(o)) {
+          throw new ClassHierarchyException(
+              "Detected aliased instances in class " + getClass()
+                  + " for fields " + map.get(o) + " and " + f);
+        }
+        if (t == RequiredImpl.class || t == RequiredParameter.class) {
+          reqDecl.add(f);
+        } else {
+          optDecl.add(f);
+        }
+        map.put(o, f);
+      }
+    }
+  }
+
+  private ConfigurationModuleBuilder(ConfigurationModuleBuilder c) {
+    try {
+      b.addConfiguration(c.b.build());
+    } catch (BindException e) {
+      throw new ClassHierarchyException(e);
+    }
+    reqDecl.addAll(c.reqDecl);
+    optDecl.addAll(c.optDecl);
+    reqUsed.addAll(c.reqUsed);
+    optUsed.addAll(c.optUsed);
+    setOpts.addAll(c.setOpts);
+    map.putAll(c.map);
+    freeImpls.putAll(c.freeImpls);
+    freeParams.putAll(c.freeParams);
+    lateBindClazz.putAll(c.lateBindClazz);
+
+  }
+
+  /**
+   * TODO: It would be nice if this incorporated d by reference so that static analysis / documentation tools
+   * could document the dependency between c and d.
+   */
+  public final ConfigurationModuleBuilder merge(ConfigurationModule d) {
+    if (d == null) {
+      throw new NullPointerException("If merge() was passed a static final field that is initialized to non-null, then this is almost certainly caused by a circular class dependency.");
+    }
+    try {
+      d.assertStaticClean();
+    } catch (ClassHierarchyException e) {
+      throw new ClassHierarchyException(ReflectionUtilities.getFullName(getClass()) + ": detected attempt to merge with ConfigurationModule that has had set() called on it", e);
+    }
+    ConfigurationModuleBuilder c = deepCopy();
+    try {
+      c.b.addConfiguration(d.builder.b.build());
+    } catch (BindException e) {
+      throw new ClassHierarchyException(e);
+    }
+    c.reqDecl.addAll(d.builder.reqDecl);
+    c.optDecl.addAll(d.builder.optDecl);
+    c.reqUsed.addAll(d.builder.reqUsed);
+    c.optUsed.addAll(d.builder.optUsed);
+    c.setOpts.addAll(d.builder.setOpts);
+    c.map.putAll(d.builder.map);
+    c.freeImpls.putAll(d.builder.freeImpls);
+    c.freeParams.putAll(d.builder.freeParams);
+    c.lateBindClazz.putAll(d.builder.lateBindClazz);
+
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bind(Class<?> iface, Impl<?> opt) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.processUse(opt);
+    c.freeImpls.put(iface, opt);
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindSetEntry(Class<? extends Name<Set<T>>> iface, String impl) {
+    ConfigurationModuleBuilder c = deepCopy();
+    try {
+      c.b.bindSetEntry(iface, impl);
+    } catch (BindException e) {
+      throw new ClassHierarchyException(e);
+    }
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindSetEntry(Class<? extends Name<Set<T>>> iface, Class<? extends T> impl) {
+    ConfigurationModuleBuilder c = deepCopy();
+    try {
+      c.b.bindSetEntry(iface, impl);
+    } catch (BindException e) {
+      throw new ClassHierarchyException(e);
+    }
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindSetEntry(Class<? extends Name<Set<T>>> iface, Impl<? extends T> opt) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.processUse(opt);
+    c.freeImpls.put(iface, opt);
+    if (!setOpts.contains(opt)) {
+      c.setOpts.add(opt);
+    }
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindSetEntry(Class<? extends Name<Set<T>>> iface, Param<? extends T> opt) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.processUse(opt);
+    c.freeParams.put(iface, opt);
+    if (!setOpts.contains(opt)) {
+      c.setOpts.add(opt);
+    }
+    return c;
+  }
+
+
+  public final <T> ConfigurationModuleBuilder bindImplementation(Class<T> iface,
+                                                                 Class<? extends T> impl) {
+    ConfigurationModuleBuilder c = deepCopy();
+    try {
+      c.b.bindImplementation(iface, impl);
+    } catch (BindException e) {
+      throw new ClassHierarchyException(e);
+    }
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindImplementation(Class<T> iface,
+                                                                 String impl) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.lateBindClazz.put(iface, impl);
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindImplementation(Class<T> iface,
+                                                                 Impl<? extends T> opt) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.processUse(opt);
+    c.freeImpls.put(iface, opt);
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindNamedParameter(
+      Class<? extends Name<T>> name, String value) {
+    ConfigurationModuleBuilder c = deepCopy();
+    try {
+      c.b.bindNamedParameter(name, value);
+    } catch (BindException e) {
+      throw new ClassHierarchyException(e);
+    }
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindNamedParameter(
+      Class<? extends Name<T>> name, Param<T> opt) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.processUse(opt);
+    c.freeParams.put(name, opt);
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindNamedParameter(
+      Class<? extends Name<T>> iface, Class<? extends T> impl) {
+    ConfigurationModuleBuilder c = deepCopy();
+    try {
+      c.b.bindNamedParameter(iface, impl);
+    } catch (BindException e) {
+      throw new ClassHierarchyException(e);
+    }
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindNamedParameter(
+      Class<? extends Name<T>> iface, Impl<? extends T> opt) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.processUse(opt);
+    c.freeImpls.put(iface, opt);
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindConstructor(Class<T> clazz,
+                                                              Class<? extends ExternalConstructor<? extends T>> constructor) {
+    ConfigurationModuleBuilder c = deepCopy();
+    try {
+      c.b.bindConstructor(clazz, constructor);
+    } catch (BindException e) {
+      throw new ClassHierarchyException(e);
+    }
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindConstructor(Class<T> cons,
+                                                              Impl<? extends ExternalConstructor<? extends T>> v) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.processUse(v);
+    c.freeImpls.put(cons, v);
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindList(Class<? extends Name<List<T>>> iface,
+                                                       Impl<List> opt) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.processUse(opt);
+    c.freeImpls.put(iface, opt);
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindList(Class<? extends Name<List<T>>> iface,
+                                                       Param<List> opt) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.processUse(opt);
+    c.freeParams.put(iface, opt);
+    return c;
+  }
+
+  public final <T> ConfigurationModuleBuilder bindList(Class<? extends Name<List<T>>> iface, List list) {
+    ConfigurationModuleBuilder c = deepCopy();
+    c.b.bindList(iface, list);
+    return c;
+  }
+
+  private final <T> void processUse(Object impl) {
+    Field f = map.get(impl);
+    if (f == null) { /* throw */
+      throw new ClassHierarchyException("Unknown Impl/Param when binding " + ReflectionUtilities.getSimpleName(impl.getClass()) + ".  Did you pass in a field from some other module?");
+    }
+    if (!reqUsed.contains(f)) {
+      reqUsed.add(f);
+    }
+    if (!optUsed.contains(f)) {
+      optUsed.add(f);
+    }
+  }
+
+  public final ConfigurationModule build() throws ClassHierarchyException {
+    ConfigurationModuleBuilder c = deepCopy();
+
+    if (!(c.reqUsed.containsAll(c.reqDecl) && c.optUsed.containsAll(c.optDecl))) {
+      Set<Field> fset = new MonotonicHashSet<>();
+      for (Field f : c.reqDecl) {
+        if (!c.reqUsed.contains(f)) {
+          fset.add(f);
+        }
+      }
+      for (Field f : c.optDecl) {
+        if (!c.optUsed.contains(f)) {
+          fset.add(f);
+        }
+      }
+      throw new ClassHierarchyException(
+          "Found declared options that were not used in binds: "
+              + toString(fset));
+    }
+    for (Class<?> clz : c.lateBindClazz.keySet()) {
+      try {
+        c.b.bind(ReflectionUtilities.getFullName(clz), c.lateBindClazz.get(clz));
+      } catch (NameResolutionException e) {
+        throw new ClassHierarchyException("ConfigurationModule refers to unknown class: " + c.lateBindClazz.get(clz), e);
+      } catch (BindException e) {
+        throw new ClassHierarchyException("bind failed while initializing ConfigurationModuleBuilder", e);
+      }
+    }
+    return new ConfigurationModule(c);
+  }
+
+/*  public final <T> ConfigurationModuleBuilder bind(Class<T> iface, Class<?> impl) {
+    ConfigurationModuleBuilder c = deepCopy();
+    try {
+      c.b.bind(iface, impl);
+    } catch (BindException e) {
+      throw new ClassHierarchyException(e);
+    }
+    return c;
+  } */
+
+  final ConfigurationModuleBuilder deepCopy() {
+    // ooh... this is a dirty trick --- we strip this's type off here,
+    // fortunately, we've all ready looked at the root object's class's
+    // fields, and we copy the information we extracted from them, so
+    // everything works out OK w.r.t. field detection.
+    return new ConfigurationModuleBuilder(this) {
+    };
+  }
+
+  final String toString(Set<Field> s) {
+    StringBuilder sb = new StringBuilder("{");
+    boolean first = true;
+    for (Field f : s) {
+      sb.append((first ? " " : ", ") + f.getName());
+      first = false;
+    }
+    sb.append(" }");
+    return sb.toString();
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationSerializer.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationSerializer.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationSerializer.java
new file mode 100644
index 0000000..46fcaff
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ConfigurationSerializer.java
@@ -0,0 +1,154 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+import org.apache.reef.tang.ClassHierarchy;
+import org.apache.reef.tang.Configuration;
+import org.apache.reef.tang.annotations.DefaultImplementation;
+import org.apache.reef.tang.exceptions.BindException;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * A base interface for Configuration serializers.
+ */
+@DefaultImplementation(AvroConfigurationSerializer.class)
+public interface ConfigurationSerializer {
+
+
+  /**
+   * Stores the given Configuration in the given File.
+   *
+   * @param conf the Configuration to store
+   * @param file the file to store the Configuration in
+   * @throws java.io.IOException if there is an IO error in the process.
+   */
+  public void toFile(final Configuration conf, final File file) throws IOException;
+
+  /**
+   * Stores the given Configuration in the given Text File.
+   *
+   * @param conf the Configuration to store
+   * @param file the file to store the Configuration in
+   * @throws java.io.IOException if there is an IO error in the process.
+   */
+  public void toTextFile(final Configuration conf, final File file) throws IOException;
+
+  /**
+   * Writes the Configuration to a byte[].
+   *
+   * @param conf
+   * @return
+   * @throws IOException
+   */
+  public byte[] toByteArray(final Configuration conf) throws IOException;
+
+  /**
+   * Writes the Configuration as a String.
+   *
+   * @param configuration
+   * @return a String representation of the Configuration
+   */
+  public String toString(final Configuration configuration);
+
+
+  /**
+   * Loads a Configuration from a File created with toFile().
+   *
+   * @param file the File to read from.
+   * @return the Configuration stored in the file.
+   * @throws IOException   if the File can't be read or parsed
+   * @throws BindException if the file contains an illegal Configuration
+   */
+  public Configuration fromFile(final File file) throws IOException, BindException;
+
+  /**
+   * Loads a Configuration from a File created with toFile().
+   *
+   * @param file the File to read from.
+   * @return the Configuration stored in the file.
+   * @throws IOException   if the File can't be read or parsed
+   * @throws BindException if the file contains an illegal Configuration
+   */
+  public Configuration fromTextFile(final File file) throws IOException, BindException;
+
+  /**
+   * Loads a Configuration from a File created with toFile() with ClassHierarchy
+   *
+   * @param file
+   * @param classHierarchy
+   * @return
+   * @throws IOException
+   */
+  public Configuration fromTextFile(final File file, final ClassHierarchy classHierarchy) throws IOException;
+
+  /**
+   * Loads a Configuration from a File created with toFile().
+   *
+   * @param file           the File to read from.
+   * @param classHierarchy used to validate the configuration against
+   * @return the Configuration stored in the file.
+   * @throws IOException   if the File can't be read or parsed
+   * @throws BindException if the file contains an illegal Configuration
+   */
+  public Configuration fromFile(final File file, final ClassHierarchy classHierarchy) throws IOException, BindException;
+
+  /**
+   * Loads a Configuration from a byte[] created with toByteArray().
+   *
+   * @param theBytes the bytes to deserialize.
+   * @return the Configuration stored.
+   * @throws IOException   if the byte[] can't be deserialized
+   * @throws BindException if the byte[] contains an illegal Configuration.
+   */
+  public Configuration fromByteArray(final byte[] theBytes) throws IOException, BindException;
+
+  /**
+   * Loads a Configuration from a byte[] created with toByteArray().
+   *
+   * @param theBytes       the bytes to deserialize.
+   * @param classHierarchy used to validate the configuration against
+   * @return the Configuration stored.
+   * @throws IOException   if the byte[] can't be deserialized
+   * @throws BindException if the byte[] contains an illegal Configuration.
+   */
+  public Configuration fromByteArray(final byte[] theBytes, final ClassHierarchy classHierarchy) throws IOException, BindException;
+
+  /**
+   * Decodes a String generated via toString()
+   *
+   * @param theString to be parsed
+   * @return the Configuration stored in theString.
+   * @throws IOException   if theString can't be parsed.
+   * @throws BindException if theString contains an illegal Configuration.
+   */
+  public Configuration fromString(final String theString) throws IOException, BindException;
+
+  /**
+   * Decodes a String generated via toString()
+   *
+   * @param theString      to be parsed
+   * @param classHierarchy used to validate the configuration against
+   * @return the Configuration stored in theString.
+   * @throws IOException   if theString can't be parsed.
+   * @throws BindException if theString contains an illegal Configuration.
+   */
+  public Configuration fromString(final String theString, final ClassHierarchy classHierarchy) throws IOException, BindException;
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Impl.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Impl.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Impl.java
new file mode 100644
index 0000000..f3426fb
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Impl.java
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+public interface Impl<T> {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/OptionalImpl.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/OptionalImpl.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/OptionalImpl.java
new file mode 100644
index 0000000..b730feb
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/OptionalImpl.java
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+public final class OptionalImpl<T> implements Impl<T> {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/OptionalParameter.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/OptionalParameter.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/OptionalParameter.java
new file mode 100644
index 0000000..26d597b
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/OptionalParameter.java
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+public final class OptionalParameter<T> implements Param<T> {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Param.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Param.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Param.java
new file mode 100644
index 0000000..355030f
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Param.java
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+public interface Param<T> {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ParameterParser.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ParameterParser.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ParameterParser.java
new file mode 100644
index 0000000..be73444
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/ParameterParser.java
@@ -0,0 +1,150 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+import org.apache.reef.tang.ExternalConstructor;
+import org.apache.reef.tang.exceptions.BindException;
+import org.apache.reef.tang.util.MonotonicTreeMap;
+import org.apache.reef.tang.util.ReflectionUtilities;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Type;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class ParameterParser {
+  private static final Set<String> BUILTIN_NAMES = new HashSet<String>() {
+    private static final long serialVersionUID = 1L;
+
+    {
+      Collections.addAll(this,
+          String.class.getName(),
+          Byte.class.getName(),
+          Character.class.getName(),
+          Short.class.getName(),
+          Integer.class.getName(),
+          Long.class.getName(),
+          Float.class.getName(),
+          Double.class.getName(),
+          Boolean.class.getName(),
+          Void.class.getName());
+    }
+  };
+  MonotonicTreeMap<String, Constructor<? extends ExternalConstructor<?>>> parsers = new MonotonicTreeMap<>();
+
+  @SuppressWarnings({"unchecked", "rawtypes"})
+  public void addParser(Class<? extends ExternalConstructor<?>> ec) throws BindException {
+    Class<?> tc = (Class<?>) ReflectionUtilities.getInterfaceTarget(
+        ExternalConstructor.class, ec);
+    addParser((Class) tc, (Class) ec);
+  }
+
+  public <T, U extends T> void addParser(Class<U> clazz, Class<? extends ExternalConstructor<T>> ec) throws BindException {
+    Constructor<? extends ExternalConstructor<T>> c;
+    try {
+      c = ec.getDeclaredConstructor(String.class);
+      c.setAccessible(true);
+    } catch (NoSuchMethodException e) {
+      throw new BindException("Constructor "
+          + ReflectionUtilities.getFullName(ec) + "(String) does not exist!", e);
+    }
+    c.setAccessible(true);
+    parsers.put(ReflectionUtilities.getFullName(clazz), c);
+  }
+
+  public void mergeIn(ParameterParser p) {
+    for (String s : p.parsers.keySet()) {
+      if (!parsers.containsKey(s)) {
+        parsers.put(s, p.parsers.get(s));
+      } else {
+        if (!parsers.get(s).equals(p.parsers.get(s))) {
+          throw new IllegalArgumentException(
+              "Conflict detected when merging parameter parsers! To parse " + s
+                  + " I have a: " + ReflectionUtilities.getFullName(parsers.get(s).getDeclaringClass())
+                  + " the other instance has a: " + ReflectionUtilities.getFullName(p.parsers.get(s).getDeclaringClass()));
+        }
+      }
+    }
+  }
+
+  public <T> T parse(Class<T> c, String s) {
+    Class<?> d = ReflectionUtilities.boxClass(c);
+    for (Type e : ReflectionUtilities.classAndAncestors(d)) {
+      String name = ReflectionUtilities.getFullName(e);
+      if (parsers.containsKey(name)) {
+        T ret = parse(name, s);
+        if (c.isAssignableFrom(ret.getClass())) {
+          return ret;
+        } else {
+          throw new ClassCastException("Cannot cast from " + ret.getClass() + " to " + c);
+        }
+      }
+    }
+    return parse(ReflectionUtilities.getFullName(d), s);
+  }
+
+  @SuppressWarnings("unchecked")
+  public <T> T parse(String name, String value) {
+    if (parsers.containsKey(name)) {
+      try {
+        return (T) (parsers.get(name).newInstance(value).newInstance());
+      } catch (ReflectiveOperationException e) {
+        throw new IllegalArgumentException("Error invoking constructor for "
+            + name, e);
+      }
+    } else {
+      if (name.equals(String.class.getName())) {
+        return (T) value;
+      }
+      if (name.equals(Byte.class.getName())) {
+        return (T) (Byte) Byte.parseByte(value);
+      }
+      if (name.equals(Character.class.getName())) {
+        return (T) (Character) value.charAt(0);
+      }
+      if (name.equals(Short.class.getName())) {
+        return (T) (Short) Short.parseShort(value);
+      }
+      if (name.equals(Integer.class.getName())) {
+        return (T) (Integer) Integer.parseInt(value);
+      }
+      if (name.equals(Long.class.getName())) {
+        return (T) (Long) Long.parseLong(value);
+      }
+      if (name.equals(Float.class.getName())) {
+        return (T) (Float) Float.parseFloat(value);
+      }
+      if (name.equals(Double.class.getName())) {
+        return (T) (Double) Double.parseDouble(value);
+      }
+      if (name.equals(Boolean.class.getName())) {
+        return (T) (Boolean) Boolean.parseBoolean(value);
+      }
+      if (name.equals(Void.class.getName())) {
+        throw new ClassCastException("Can't instantiate void");
+      }
+      throw new UnsupportedOperationException("Don't know how to parse a " + name);
+    }
+  }
+
+  public boolean canParse(String name) {
+    return parsers.containsKey(name) || BUILTIN_NAMES.contains(name);
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Provides.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Provides.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Provides.java
new file mode 100644
index 0000000..a98f081
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/Provides.java
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+public final class Provides<T> {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/RequiredImpl.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/RequiredImpl.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/RequiredImpl.java
new file mode 100644
index 0000000..6355af0
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/RequiredImpl.java
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+public final class RequiredImpl<T> implements Impl<T> {
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-reef/blob/53ea32cc/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/RequiredParameter.java
----------------------------------------------------------------------
diff --git a/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/RequiredParameter.java b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/RequiredParameter.java
new file mode 100644
index 0000000..f0fa97f
--- /dev/null
+++ b/lang/java/reef-tang/tang/src/main/java/org/apache/reef/tang/formats/RequiredParameter.java
@@ -0,0 +1,22 @@
+/**
+ * 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.
+ */
+package org.apache.reef.tang.formats;
+
+public final class RequiredParameter<T> implements Param<T> {
+}
\ No newline at end of file