/*
* 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 gobblin.config;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import com.typesafe.config.ConfigValueFactory;
/** A helper class to create {@link Config} objects */
public class ConfigBuilder {
private final Map<String, Object> primitiveProps = new HashMap<>();
private final Optional<String> originDestription;
private Config currentConfig;
ConfigBuilder(Optional<String> originDescription) {
this.originDestription = originDescription;
this.currentConfig =
originDescription.isPresent() ? ConfigFactory.empty(this.originDestription.get()) : ConfigFactory.empty();
}
/**
* Loads properties which have a given name prefix into the config. The following restrictions
* apply:
* <ul>
* <li>No property can have a name that is equal to the prefix
* <li>After removal of the prefix, the remaining property name should start with a letter.
* </ul>
*
* @param props the collection from where to load the properties
* @param scopePrefix only properties with this prefix will be considered. The prefix will be
* removed from the names of the keys added to the {@link Config} object.
* The prefix can be an empty string but cannot be null.
*/
public ConfigBuilder loadProps(Properties props, String scopePrefix) {
Preconditions.checkNotNull(props);
Preconditions.checkNotNull(scopePrefix);
int scopePrefixLen = scopePrefix.length();
for (Map.Entry<Object, Object> propEntry : props.entrySet()) {
String propName = propEntry.getKey().toString();
if (propName.startsWith(scopePrefix)) {
String scopedName = propName.substring(scopePrefixLen);
if (scopedName.isEmpty()) {
throw new RuntimeException("Illegal scoped property:" + propName);
}
if (!Character.isAlphabetic(scopedName.charAt(0))) {
throw new RuntimeException(
"Scoped name for property " + propName + " should start with a character: " + scopedName);
}
this.primitiveProps.put(scopedName, propEntry.getValue());
}
}
return this;
}
public ConfigBuilder addPrimitive(String name, Object value) {
this.primitiveProps.put(name, value);
return this;
}
public ConfigBuilder addList(String name, Iterable<? extends Object> values) {
this.currentConfig = this.originDestription.isPresent()
? this.currentConfig.withValue(name, ConfigValueFactory.fromIterable(values, this.originDestription.get()))
: this.currentConfig.withValue(name, ConfigValueFactory.fromIterable(values));
return this;
}
public static ConfigBuilder create() {
return new ConfigBuilder(Optional.<String> absent());
}
public static ConfigBuilder create(String originDescription) {
return new ConfigBuilder(Optional.of(originDescription));
}
public Config build() {
return ConfigFactory.parseMap(this.primitiveProps).withFallback(this.currentConfig);
}
}