/*
 * 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.
 */

// DO NOT EDIT IT MANUALLY. This file is generated by opendal/dev/generate/java.rs.

package org.apache.opendal;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Data;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;

/**
 * Service configurations that are mapped from
 * <a href="https://docs.rs/opendal/latest/opendal/services/index.html">OpenDAL's services</a>.
 */
@SuppressWarnings("unused") // intended to be used by users
public interface ServiceConfig {
    /**
     * The scheme of the service.
     *
     * @return the scheme
     */
    String scheme();

    /**
     * Convert the structured config to a type erased config map.
     *
     * @return the config map
     */
    Map<String, String> configMap();
{% for srv in srvs %}
    /**
     * Configuration for service {{srv}}.
     */
    @Builder
    @Data
    @RequiredArgsConstructor(access = AccessLevel.PRIVATE)
    class {{srv | case_java_class_name}} implements ServiceConfig {
        {%- for field in srvs[srv].config %}
        {{make_field(field) | indent(8)}}
        {%- endfor %}

        @Override
        public String scheme() {
            return "{{srv}}";
        }

        @Override
        public Map<String, String> configMap() {
            final HashMap<String, String> map = new HashMap<>();
            {% for field in srvs[srv].config -%}
            {{make_populate_map(field) | indent(12)}}
            {% endfor -%}
            return map;
        }
    }
{% endfor -%}
}
