/*
* Copyright 2016-present Facebook, Inc.
*
* Licensed 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 com.facebook.buck.config;
import com.facebook.buck.util.immutables.BuckStyleTuple;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import java.util.Map;
import java.util.Optional;
import org.immutables.value.Value;
/**
* Hierarcical configuration of section/key/value triples.
*
* <p>This class only implements the simple construction/storage/retrieval of these values. Other
* classes like {@link Config} implements accessors that interpret the values as other types.
*/
@Value.Immutable
@BuckStyleTuple
abstract class AbstractRawConfig {
public abstract ImmutableMap<String, ImmutableMap<String, String>> getValues();
/**
* Retrieve a section by name.
*
* @return The contents of the named section. If the section does not exist, the empty map.
*/
public ImmutableMap<String, String> getSection(String sectionName) {
return Optional.ofNullable(getValues().get(sectionName)).orElse(ImmutableMap.of());
}
/** Retrieve a value from a named section. */
public Optional<String> getValue(String sectionName, String key) {
return Optional.ofNullable(getSection(sectionName).get(key));
}
/** Returns an empty config. */
public static RawConfig of() {
return RawConfig.of(ImmutableMap.of());
}
public static Builder builder() {
return new Builder();
}
/**
* A builder for {@link RawConfig}s.
*
* <p>Unless otherwise stated, duplicate keys overwrites earlier ones.
*/
public static class Builder {
private Map<String, Map<String, String>> values = Maps.newLinkedHashMap();
/** Merge raw config values into this config. */
public <M extends Map<String, String>> Builder putAll(Map<String, M> config) {
for (Map.Entry<String, M> entry : config.entrySet()) {
requireSection(entry.getKey()).putAll(entry.getValue());
}
return this;
}
/** Merge the values from another {@code RawConfig}. */
public Builder putAll(RawConfig config) {
return putAll(config.getValues());
}
/** Put a single value. */
public Builder put(String section, String key, String value) {
requireSection(section).put(key, value);
return this;
}
public RawConfig build() {
ImmutableMap.Builder<String, ImmutableMap<String, String>> builder = ImmutableMap.builder();
for (Map.Entry<String, Map<String, String>> entry : values.entrySet()) {
builder.put(entry.getKey(), ImmutableMap.copyOf(entry.getValue()));
}
return RawConfig.of(builder.build());
}
/** Get a section or create it if it doesn't exist. */
private Map<String, String> requireSection(String sectionName) {
Map<String, String> section = values.get(sectionName);
if (section == null) {
section = Maps.newLinkedHashMap();
values.put(sectionName, section);
}
return section;
}
}
}