001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*- 002 * 003 * Copyright © 2018–2019 microBean™. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * 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 014 * implied. See the License for the specific language governing 015 * permissions and limitations under the License. 016 */ 017package org.microbean.microprofile.config; 018 019import java.util.Comparator; 020 021import org.eclipse.microprofile.config.spi.ConfigSource; 022 023/** 024 * A {@link Comparator} of {@link ConfigSource}s that considers only 025 * their {@linkplain ConfigSource#getOrdinal() ordinals} and 026 * {@linkplain ConfigSource#getName() names} in accordance with the 027 * minimal requirements of the MicroProfile Config specification as 028 * spelled out (only) in the {@linkplain ConfigSource 029 * <code>ConfigSource</code> API documentation}. 030 * 031 * <p><strong>This {@link Comparator} implementation is, and must be, 032 * inconsistent with {@link Object#equals(Object) equals()}</strong>, 033 * as implied by the same specification.</p> 034 * 035 * <p>Note that the requirement to use a {@link ConfigSource}'s 036 * {@linkplain ConfigSource#getName() name} as a secondary sorting key 037 * is defined only in the {@linkplain ConfigSource#getOrdinal() 038 * javadocs of the <code>ConfigSource.getOrdinal()</code> method}.</p> 039 * 040 * <p>Note further that there are no guidelines or requirements about 041 * what format a {@link ConfigSource}'s {@linkplain 042 * ConfigSource#getName() name} must take, so in effect the ordering 043 * of two {@link ConfigSource}s that have a common {@linkplain 044 * ConfigSource#getOrdinal() ordinal} is undefined.</p> 045 * 046 * @author <a href="https://about.me/lairdnelson" 047 * target="_parent">Laird Nelson</a> 048 * 049 * @see #compare(ConfigSource, ConfigSource) 050 * 051 * @see ConfigSource 052 * 053 * @see ConfigSource#getOrdinal() 054 * 055 * @see ConfigSource#getName() 056 */ 057public final class ConfigSourceComparator implements Comparator<ConfigSource> { 058 059 060 /* 061 * Static fields. 062 */ 063 064 065 /** 066 * The sole instance of this class. 067 */ 068 public static final ConfigSourceComparator INSTANCE = new ConfigSourceComparator(); 069 070 071 /* 072 * Constructors. 073 */ 074 075 076 /** 077 * Creates a new {@link ConfigSourceComparator}. 078 */ 079 private ConfigSourceComparator() { 080 super(); 081 } 082 083 084 /* 085 * Instance methods. 086 */ 087 088 089 /** 090 * Compares two {@link ConfigSource}s, returning {@code -1} if the 091 * first has an {@linkplain ConfigSource#getOrdinal() ordinal} 092 * greater than that of the second and {@code 1} if the second has 093 * an {@linkplain ConfigSource#getOrdinal() ordinal} greater than 094 * that of the first, and then the result of invoking {@link 095 * String#compareTo(String)} on the return values of the {@link 096 * ConfigSource}s' respective {@link ConfigSource#getName()} 097 * methods. 098 * 099 * <p><strong>This method may return {@code 0} when both {@link 100 * ConfigSource}s are not otherwise semantically equal.</strong></p> 101 * 102 * @param firstConfigSource the first of two {@link ConfigSource}s; 103 * may be {@code null} 104 * 105 * @param secondConfigSource the second of two {@link 106 * ConfigSource}s; may be {@code null} 107 * 108 * @return {@code -1} if the first {@link ConfigSource} has an 109 * {@linkplain ConfigSource#getOrdinal() ordinal} greater than that 110 * of the second, {@code 1} if the second {@link ConfigSource} has 111 * an {@linkplain ConfigSource#getOrdinal() ordinal} greater than 112 * that of the first, and the result of invoking {@link 113 * String#compareTo(String)} on the return values of the {@link 114 * ConfigSource}s' respective {@link ConfigSource#getName()} methods 115 * otherwise 116 * 117 * @see ConfigSource 118 * 119 * @see ConfigSource#getName() 120 * 121 * @see ConfigSource#getOrdinal() 122 */ 123 @Override 124 public final int compare(final ConfigSource firstConfigSource, final ConfigSource secondConfigSource) { 125 final int returnValue; 126 if (firstConfigSource == secondConfigSource) { 127 returnValue = 0; 128 } else if (firstConfigSource == null) { 129 returnValue = 1; 130 } else if (secondConfigSource == null) { 131 returnValue = -1; 132 } else { 133 final int firstOrdinal = firstConfigSource.getOrdinal(); 134 final int secondOrdinal = secondConfigSource.getOrdinal(); 135 if (firstOrdinal > secondOrdinal) { 136 returnValue = -1; 137 } else if (firstOrdinal < secondOrdinal) { 138 returnValue = 1; 139 } else { 140 final String firstName = firstConfigSource.getName(); 141 String secondName = secondConfigSource.getName(); 142 if (firstName == null) { 143 if (secondName == null) { 144 returnValue = 0; 145 } else { 146 returnValue = 1; 147 } 148 } else if (secondName == null) { 149 returnValue = -1; 150 } else { 151 returnValue = firstName.compareTo(secondName); 152 } 153 } 154 } 155 return returnValue; 156 } 157 158}