/**
 * Copyright 2015 Palantir Technologies
 *
 * Licensed under the BSD-3 License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://opensource.org/licenses/BSD-3-Clause
 *
 * 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 com.palantir.atlasdb.config;

import java.io.File;
import java.io.IOException;

import com.fasterxml.jackson.core.JsonPointer;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.datatype.guava.GuavaModule;
import com.google.common.base.Strings;

import io.dropwizard.jackson.DiscoverableSubtypeResolver;

public final class AtlasDbConfigs {

    public static final String ATLASDB_CONFIG_ROOT = "/atlasdb";

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(new YAMLFactory());

    static {
        OBJECT_MAPPER.setSubtypeResolver(new DiscoverableSubtypeResolver());
        OBJECT_MAPPER.registerModule(new GuavaModule());
    }

    private AtlasDbConfigs() {
        // uninstantiable
    }

    public static AtlasDbConfig load(File configFile) throws IOException {
        return load(configFile, ATLASDB_CONFIG_ROOT);
    }

    public static AtlasDbConfig load(File configFile, String configRoot) throws IOException {
        JsonNode rootNode = getConfigNode(configFile, configRoot);
        return OBJECT_MAPPER.treeToValue(rootNode, AtlasDbConfig.class);
    }

    public static AtlasDbConfig loadFromString(String fileContents, String configRoot) throws IOException {
        JsonNode rootNode = getConfigNode(fileContents, configRoot);
        return OBJECT_MAPPER.treeToValue(rootNode, AtlasDbConfig.class);
    }

    private static JsonNode getConfigNode(File configFile, String configRoot) throws IOException {
        JsonNode node = OBJECT_MAPPER.readTree(configFile);
        JsonNode configNode = findRoot(node, configRoot);

        if (configNode == null) {
            throw new IllegalArgumentException("Could not find " + configRoot + " in yaml file " + configFile);
        }

        return configNode;
    }

    private static JsonNode getConfigNode(String fileContents, String configRoot) throws IOException {
        JsonNode node = OBJECT_MAPPER.readTree(fileContents);
        JsonNode configNode = findRoot(node, configRoot);

        if (configNode == null) {
            throw new IllegalArgumentException("Could not find " + configRoot + " in given string");
        }

        return configNode;
    }

    private static JsonNode findRoot(JsonNode node, String configRoot) {
        if (Strings.isNullOrEmpty(configRoot)) {
            return node;
        }

        JsonNode root = node.at(JsonPointer.valueOf(configRoot));
        if (root.isMissingNode()) {
            return null;
        }
        return root;
    }
}

@@ -670,16 +670,51 @@
 ption;%0A%0A
+import javax.annotation.Nullable;%0A%0A
 import c
@@ -748,24 +748,24 @@
 sonPointer;%0A
-
 import com.f
@@ -1660,32 +1660,42 @@
 File configFile,
+ @Nullable
  String configRo
@@ -1925,32 +1925,42 @@
 ng fileContents,
+ @Nullable
  String configRo
@@ -2191,16 +2191,26 @@
 figFile,
+ @Nullable
  String 
@@ -2614,16 +2614,26 @@
 ontents,
+ @Nullable
  String 
@@ -2958,32 +2958,32 @@
 figNode;%0A    %7D%0A%0A
-
     private stat
@@ -3017,16 +3017,26 @@
 de node,
+ @Nullable
  String 

Add @Nullable to AtlasDbConfigs