001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.juneau.rest.server.health;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020
021import java.util.*;
022
023/**
024 * Component health result returned from a {@link HealthIndicator}.
025 *
026 * @since 10.0.0
027 */
028public final class Health {
029
030   private final String name;
031   private final HealthStatus status;
032   private final Map<String,Object> details;
033   private final Throwable error;
034
035   private Health(Builder b) {
036      this.name = b.name;
037      this.status = b.status;
038      this.details = u(cp(b.details));
039      this.error = b.error;
040   }
041
042   /**
043    * Creates an {@link HealthStatus#UP} builder.
044    *
045    * @param name Component name. Must not be <jk>null</jk> or empty.
046    * @return A new builder.
047    */
048   public static Builder up(String name) {
049      return new Builder(name, HealthStatus.UP, null);
050   }
051
052   /**
053    * Creates an {@link HealthStatus#DOWN} builder.
054    *
055    * @param name Component name. Must not be <jk>null</jk> or empty.
056    * @param error Optional error causing the down state. Can be <jk>null</jk> (no error is recorded).
057    * @return A new builder.
058    */
059   public static Builder down(String name, Throwable error) {
060      return new Builder(name, HealthStatus.DOWN, error);
061   }
062
063   /**
064    * Creates an {@link HealthStatus#UNKNOWN} builder.
065    *
066    * @param name Component name. Must not be <jk>null</jk> or empty.
067    * @return A new builder.
068    */
069   public static Builder unknown(String name) {
070      return new Builder(name, HealthStatus.UNKNOWN, null);
071   }
072
073   /** @return Component name. */
074   public String getName() { return name; }
075   /** @return Health status. */
076   public HealthStatus getStatus() { return status; }
077   /** @return Structured details map. */
078   public Map<String,Object> getDetails() { return details; }
079   /** @return Optional error. */
080   public Throwable getError() { return error; }
081
082   /**
083    * Builder for {@link Health}.
084    */
085   public static final class Builder {
086      private final String name;
087      private final HealthStatus status;
088      private final Map<String,Object> details = m();
089      private Throwable error;
090
091      private Builder(String name, HealthStatus status, Throwable error) {
092         reqnn("name", name);
093         if (name.isEmpty())
094            throw new IllegalArgumentException("Argument 'name' cannot be empty.");
095         this.name = name;
096         this.status = Objects.requireNonNull(status, "status");
097         this.error = error;
098      }
099
100      /**
101       * Adds a structured detail.
102       *
103       * @param key Detail key. Must not be <jk>null</jk> or empty.
104       * @param value Detail value. Can be <jk>null</jk> (the detail is recorded with a <jk>null</jk> value).
105       * @return This builder.
106       */
107      public Builder detail(String key, Object value) {
108         reqnn("key", key);
109         if (key.isEmpty())
110            throw new IllegalArgumentException("Argument 'key' cannot be empty.");
111         details.put(key, value);
112         return this;
113      }
114
115      /**
116       * Overrides the error attached to this result.
117       *
118       * @param value The throwable. Can be <jk>null</jk> (clears the error).
119       * @return This builder.
120       */
121      public Builder error(Throwable value) {
122         error = value;
123         return this;
124      }
125
126      /**
127       * Builds a health result.
128       *
129       * @return A new health result.
130       */
131      public Health build() {
132         return new Health(this);
133      }
134   }
135}