1 /* 2 * ==================================================================== 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * ==================================================================== 20 * 21 * This software consists of voluntary contributions made by many 22 * individuals on behalf of the Apache Software Foundation. For more 23 * information on the Apache Software Foundation, please see 24 * <http://www.apache.org/>. 25 * 26 */ 27 28 package org.apache.hc.core5.http; 29 30 import java.io.Serializable; 31 32 import org.apache.hc.core5.annotation.Contract; 33 import org.apache.hc.core5.annotation.ThreadingBehavior; 34 import org.apache.hc.core5.util.Args; 35 36 /** 37 * Represents a protocol version. The "major.minor" numbering 38 * scheme is used to indicate versions of the protocol. 39 * <p> 40 * This class defines a protocol version as a combination of 41 * protocol name, major version number, and minor version number. 42 * Note that {@link #equals} and {@link #hashCode} are defined as 43 * final here, they cannot be overridden in derived classes. 44 * </p> 45 * 46 * @since 4.0 47 */ 48 @Contract(threading = ThreadingBehavior.IMMUTABLE) 49 public class ProtocolVersion implements Serializable { 50 51 private static final long serialVersionUID = 8950662842175091068L; 52 53 54 /** Name of the protocol. */ 55 private final String protocol; 56 57 /** Major version number of the protocol */ 58 private final int major; 59 60 /** Minor version number of the protocol */ 61 private final int minor; 62 63 /** 64 * Create a protocol version designator. 65 * 66 * @param protocol the name of the protocol, for example "HTTP" 67 * @param major the major version number of the protocol 68 * @param minor the minor version number of the protocol 69 */ 70 public ProtocolVersion(final String protocol, final int major, final int minor) { 71 this.protocol = Args.notNull(protocol, "Protocol name"); 72 this.major = Args.notNegative(major, "Protocol minor version"); 73 this.minor = Args.notNegative(minor, "Protocol minor version"); 74 } 75 76 /** 77 * Returns the name of the protocol. 78 * 79 * @return the protocol name 80 */ 81 public final String getProtocol() { 82 return protocol; 83 } 84 85 /** 86 * Returns the major version number of the protocol. 87 * 88 * @return the major version number. 89 */ 90 public final int getMajor() { 91 return major; 92 } 93 94 /** 95 * Returns the minor version number of the HTTP protocol. 96 * 97 * @return the minor version number. 98 */ 99 public final int getMinor() { 100 return minor; 101 } 102 103 104 /** 105 * Obtains a hash code consistent with {@link #equals}. 106 * 107 * @return the hashcode of this protocol version 108 */ 109 @Override 110 public final int hashCode() { 111 return this.protocol.hashCode() ^ (this.major * 100000) ^ this.minor; 112 } 113 114 /** 115 * Checks whether this instance has the same major and minor version as the arguments. 116 * 117 * @param major the major version to check. 118 * @param minor the minor version to check. 119 * @return whether this instance has the same major and minor version as the arguments. 120 * @since 5.0 121 */ 122 public final boolean equals(final int major, final int minor) { 123 return this.major == major && this.minor == minor; 124 } 125 126 /** 127 * Checks equality of this protocol version with an object. 128 * The object is equal if it is a protocol version with the same 129 * protocol name, major version number, and minor version number. 130 * The specific class of the object is <i>not</i> relevant, 131 * instances of derived classes with identical attributes are 132 * equal to instances of the base class and vice versa. 133 * 134 * @param obj the object to compare with 135 * 136 * @return {@code true} if the argument is the same protocol version, 137 * {@code false} otherwise 138 */ 139 @Override 140 public final boolean equals(final Object obj) { 141 if (this == obj) { 142 return true; 143 } 144 if (!(obj instanceof ProtocolVersion)) { 145 return false; 146 } 147 final ProtocolVersion./../../org/apache/hc/core5/http/ProtocolVersion.html#ProtocolVersion">ProtocolVersion that = (ProtocolVersion) obj; 148 149 return (this.protocol.equals(that.protocol) && 150 (this.major == that.major) && 151 (this.minor == that.minor)); 152 } 153 154 /** 155 * Formats this protocol version as a string. 156 * 157 * @return a protocol version string, like "HTTP/1.1" 158 * @since 5.0 159 */ 160 public String format() { 161 final StringBuilder buffer = new StringBuilder(); 162 buffer.append(this.protocol); 163 buffer.append('/'); 164 buffer.append(this.major); 165 buffer.append('.'); 166 buffer.append(this.minor); 167 return buffer.toString(); 168 } 169 170 /** 171 * Checks whether this protocol can be compared to another one. 172 * Only protocol versions with the same protocol name can be 173 * {@link #compareToVersion compared}. 174 * 175 * @param that the protocol version to consider 176 * 177 * @return {@code true} if {@link #compareToVersion compareToVersion} 178 * can be called with the argument, {@code false} otherwise 179 */ 180 public boolean isComparable(final ProtocolVersion that) { 181 return (that != null) && this.protocol.equals(that.protocol); 182 } 183 184 185 /** 186 * Compares this protocol version with another one. 187 * Only protocol versions with the same protocol name can be compared. 188 * This method does <i>not</i> define a total ordering, as it would be 189 * required for {@link java.lang.Comparable}. 190 * 191 * @param that the protocol version to compare with 192 * 193 * @return a negative integer, zero, or a positive integer 194 * as this version is less than, equal to, or greater than 195 * the argument version. 196 * 197 * @throws IllegalArgumentException 198 * if the argument has a different protocol name than this object, 199 * or if the argument is {@code null} 200 */ 201 public int compareToVersion(final ProtocolVersion that) { 202 Args.notNull(that, "Protocol version"); 203 Args.check(this.protocol.equals(that.protocol), 204 "Versions for different protocols cannot be compared: %s %s", this, that); 205 int delta = getMajor() - that.getMajor(); 206 if (delta == 0) { 207 delta = getMinor() - that.getMinor(); 208 } 209 return delta; 210 } 211 212 213 /** 214 * Tests if this protocol version is greater or equal to the given one. 215 * 216 * @param version the version against which to check this version 217 * 218 * @return {@code true} if this protocol version is 219 * {@link #isComparable comparable} to the argument 220 * and {@link #compareToVersion compares} as greater or equal, 221 * {@code false} otherwise 222 */ 223 public final boolean greaterEquals(final ProtocolVersion version) { 224 return isComparable(version) && (compareToVersion(version) >= 0); 225 } 226 227 228 /** 229 * Tests if this protocol version is less or equal to the given one. 230 * 231 * @param version the version against which to check this version 232 * 233 * @return {@code true} if this protocol version is 234 * {@link #isComparable comparable} to the argument 235 * and {@link #compareToVersion compares} as less or equal, 236 * {@code false} otherwise 237 */ 238 public final boolean lessEquals(final ProtocolVersion version) { 239 return isComparable(version) && (compareToVersion(version) <= 0); 240 } 241 242 243 /** 244 * Converts this protocol version to a string. 245 * 246 * @return a protocol version string, like "HTTP/1.1" 247 */ 248 @Override 249 public String toString() { 250 return format(); 251 } 252 253 }