/**
 * Copyright 2017 Pivotal Software, Inc.
 * <p>
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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 io.micrometer.spring.autoconfigure;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.util.Assert;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * {@link ConfigurationProperties} for configuring Micrometer-based metrics.
 *
 * @author Jon Schneider
 */
@ConfigurationProperties("management.metrics")
public class MetricsProperties {

    private Web web = new Web();
    private Distribution distribution = new Distribution();

    /**
     * If {@code false}, the matching meter(s) are no-op.
     */
    private Map<String, Boolean> enable = new HashMap<>();

    /**
     * Whether or not auto-configured MeterRegistry implementations should be bound to the
     * global static registry on Metrics. For testing, set this to 'false' to maximize
     * test independence.
     */
    private boolean useGlobalRegistry = true;

    public boolean isUseGlobalRegistry() {
        return this.useGlobalRegistry;
    }

    public void setUseGlobalRegistry(boolean useGlobalRegistry) {
        this.useGlobalRegistry = useGlobalRegistry;
    }

    public Web getWeb() {
        return this.web;
    }

    public Map<String, Boolean> getEnable() {
        return enable;
    }

    public Distribution getDistribution() {
        return distribution;
    }

    public static class Web {

        private Client client = new Client();

        private Server server = new Server();

        public Client getClient() {
            return this.client;
        }

        public Server getServer() {
            return this.server;
        }

        public static class Client {
            /**
             * Name of the metric for sent requests.
             */
            private String requestsMetricName = "http.client.requests";

            /**
             * Maximum number of unique URI tag values allowed. After the max number of tag values is reached,
             * metrics with additional tag values are denied by filter.
             */
            private int maxUriTags = 100;

            public String getRequestsMetricName() {
                return this.requestsMetricName;
            }

            public void setRequestsMetricName(String requestsMetricName) {
                this.requestsMetricName = requestsMetricName;
            }

            public int getMaxUriTags() {
                return maxUriTags;
            }

            public void setMaxUriTags(int maxUriTags) {
                this.maxUriTags = maxUriTags;
            }
        }

        public static class Server {

            /**
             * Whether or not requests handled by Spring MVC or WebFlux should be
             * automatically timed. If the number of time series emitted grows too large
             * on account of request mapping timings, disable this and use 'Timed' on a
             * per request mapping basis as needed.
             */
            private boolean autoTimeRequests = true;

            /**
             * Name of the metric for received requests.
             */
            private String requestsMetricName = "http.server.requests";

            public boolean isAutoTimeRequests() {
                return this.autoTimeRequests;
            }

            public void setAutoTimeRequests(boolean autoTimeRequests) {
                this.autoTimeRequests = autoTimeRequests;
            }

            public String getRequestsMetricName() {
                return this.requestsMetricName;
            }

            public void setRequestsMetricName(String requestsMetricName) {
                this.requestsMetricName = requestsMetricName;
            }
        }
    }

    public static class Distribution {

        /**
         * Whether meter IDs starting-with the specified name should be publish percentile
         * histograms. Monitoring systems that support aggregable percentile calculation
         * based on a histogram be set to true. For other systems, this has no effect. The
         * longest match wins, the key `all` can also be used to configure all meters.
         */
        private Map<String, Boolean> percentilesHistogram = new LinkedHashMap<>();

        /**
         * Specific computed non-aggregable percentiles to ship to the backend for meter
         * IDs starting-with the specified name. The longest match wins, the key `all` can
         * also be used to configure all meters.
         */
        private Map<String, double[]> percentiles = new LinkedHashMap<>();

        /**
         * Specific SLA boundaries for meter IDs starting-with the specified name. The
         * longest match wins, the key `all` can also be used to configure all meters.
         * Counters will be published for each specified boundary. Values can be
         * specified as a long or as a Duration value (for timer meters, defaulting to ms
         * if no unit specified).
         */
        private Map<String, ServiceLevelAgreementBoundary[]> sla = new LinkedHashMap<>();

        public Map<String, Boolean> getPercentilesHistogram() {
            return this.percentilesHistogram;
        }

        public void setPercentilesHistogram(Map<String, Boolean> percentilesHistogram) {
            Assert.notNull(percentilesHistogram, "PercentilesHistogram must not be null");
            this.percentilesHistogram = percentilesHistogram;
        }

        public Map<String, double[]> getPercentiles() {
            return this.percentiles;
        }

        public void setPercentiles(Map<String, double[]> percentiles) {
            Assert.notNull(percentiles, "Percentiles must not be null");
            this.percentiles = percentiles;
        }

        public Map<String, ServiceLevelAgreementBoundary[]> getSla() {
            return this.sla;
        }

        public void setSla(Map<String, ServiceLevelAgreementBoundary[]> sla) {
            Assert.notNull(sla, "SLA must not be null");
            this.sla = sla;
        }

    }
}

@@ -732,48 +732,8 @@
 ies;
-%0Aimport org.springframework.util.Assert;
 %0A%0Aim
@@ -1017,16 +1017,22 @@
 private 
+final 
 Web web 
@@ -1056,16 +1056,22 @@
 private 
+final 
 Distribu
@@ -1189,32 +1189,38 @@
  */%0A    private 
+final 
 Map%3CString, Bool
@@ -1993,16 +1993,22 @@
 private 
+final 
 Client c
@@ -2046,16 +2046,22 @@
 private 
+final 
 Server s
@@ -4745,32 +4745,38 @@
         private 
+final 
 Map%3CString, Bool
@@ -5088,32 +5088,38 @@
         private 
+final 
 Map%3CString, doub
@@ -5581,16 +5581,22 @@
 private 
+final 
 Map%3CStri
@@ -5802,820 +5802,192 @@
 lic 
-void setPercentilesHistogram(Map%3CString, Boolean%3E percentilesHistogram) %7B%0A            Assert.notNull(percentilesHistogram, %22PercentilesHistogram must not be null%22);%0A            this.percentilesHistogram = percentilesHistogram;%0A        %7D%0A%0A        public Map%3CString, double%5B%5D%3E getPercentiles() %7B%0A            return this.percentiles;%0A        %7D%0A%0A        public void setPercentiles(Map%3CString, double%5B%5D%3E percentiles) %7B%0A            Assert.notNull(percentiles, %22Percentiles must not be null%22);%0A            this.percentiles = percentiles;%0A        %7D%0A%0A        public Map%3CString, ServiceLevelAgreementBoundary%5B%5D%3E getSla() %7B%0A            return this.sla;%0A        %7D%0A%0A        public void setSla(Map%3CString, ServiceLevelAgreementBoundary%5B%5D%3E sla) %7B%0A            Assert.notNull(sla, %22SLA must not be null%22);%0A            this.sla = 
+Map%3CString, double%5B%5D%3E getPercentiles() %7B%0A            return this.percentiles;%0A        %7D%0A%0A        public Map%3CString, ServiceLevelAgreementBoundary%5B%5D%3E getSla() %7B%0A            return this.
 sla;

Make MetricsProperties fields final if possible