alluxio-master-2.x/table/server/common/src/main/java/alluxio/table/common/udb/UdbConfiguration.java
/*
 * The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
 * (the "License"). You may not use this work except in compliance with the License, which is
 * available at www.apache.org/licenses/LICENSE-2.0
 *
 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
 * either express or implied, as more fully set forth in the License.
 *
 * See the NOTICE file distributed with this work for information regarding copyright ownership.
 */

package alluxio.table.common.udb;

import alluxio.table.common.BaseConfiguration;
import alluxio.table.common.ConfigurationUtils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * This represents a configuration of the UDB.
 */
public class UdbConfiguration extends BaseConfiguration<UdbProperty> {
  private static final Logger LOG = LoggerFactory.getLogger(UdbConfiguration.class);

  // {...} group the scheme/authority, and are not special to various shells
  private static final Pattern CONFIG_PATTERN = Pattern.compile("(\\{.*\\})\\.(.+?)");
  public static final String READ_ONLY_OPTION = "readonly";
  public static final String SHARED_OPTION = "shared";
  public static final String REGEX_PREFIX = "regex:";

  protected final Map<String, Map<String, String>> mMountOptions;

  /**
   * Creates an instance.
   *
   * @param values the map of values
   */
  public UdbConfiguration(Map<String, String> values) {
    super(values);
    mMountOptions = new HashMap<>(values.size());
    for (Map.Entry<String, String> entry : values.entrySet()) {
      if (entry.getKey().startsWith(ConfigurationUtils.MOUNT_PREFIX)) {
        String key = entry.getKey().substring(ConfigurationUtils.MOUNT_PREFIX.length());
        Matcher m = CONFIG_PATTERN.matcher(key);
        if (m.matches()) {
          // templateSchemeAuthority can be a regex string.
          String templateSchemeAuthority = m.group(1);
          String option = m.group(2);

          // remove the bracket around the scheme://authority
          templateSchemeAuthority =
              templateSchemeAuthority.substring(1, templateSchemeAuthority.length() - 1);
          if (!templateSchemeAuthority.endsWith("/")) {
            // include the trailing '/'
            templateSchemeAuthority += "/";
          }

          Map<String, String> optionMap = mMountOptions.get(templateSchemeAuthority);
          if (optionMap == null) {
            optionMap = new HashMap<>();
            optionMap.put(option, entry.getValue());
            mMountOptions.put(templateSchemeAuthority, optionMap);
          } else {
            optionMap.put(option, entry.getValue());
          }
        }
      }
    }
  }

  /**
   * Returns the mount option for a particular scheme and authority URL.
   *
   * @param concreteSchemeAuthority scheme://authority/ (expected to have a trailing '/')
   * @return mount options in a map of or matched given concreteSchemeAuthority
   */
  public Map<String, String> getMountOption(String concreteSchemeAuthority) {
    if (!concreteSchemeAuthority.endsWith("/")) {
      // include the trailing '/'
      concreteSchemeAuthority += "/";
    }
    Map<String, String> map =
        mMountOptions.getOrDefault(concreteSchemeAuthority, Collections.emptyMap());
    if (map.equals(Collections.emptyMap())) {
      for (Entry<String, Map<String, String>> entry : mMountOptions.entrySet()) {
        if (entry.getKey().startsWith(REGEX_PREFIX)
            && concreteSchemeAuthority.matches(entry.getKey().substring(REGEX_PREFIX.length()))) {
          return entry.getValue();
        }
      }
    }
    return map;
  }
}
