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.commons.lang; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020 021/** 022 * Represents an OSGi-style version range like <js>"1.2"</js> or <js>"[1.0,2.0)"</js>. 023 * 024 * <p> 025 * The range can be any of the following formats: 026 * <ul> 027 * <li><js>"[0,1.0)"</js> = Less than 1.0. 1.0 and 1.0.0 does not match. 028 * <li><js>"[0,1.0]"</js> = Less than or equal to 1.0. Note that 1.0.1 will match. 029 * <li><js>"1.0"</js> = At least 1.0. 1.0 and 2.0 will match. 030 * </ul> 031 * 032 */ 033public class VersionRange { 034 035 /** 036 * Static creator. 037 * 038 * @param range The range string to parse (e.g. <js>"1.2"</js> or <js>"[1.0,2.0)"</js>). Must not be <jk>null</jk>. 039 * @return A new {@link VersionRange} object. 040 */ 041 public static VersionRange of(String range) { 042 return new VersionRange(range); 043 } 044 045 private final Version minVersion; 046 private final Version maxVersion; 047 private final boolean minExclusive; 048 private final boolean maxExclusive; 049 050 /** 051 * Constructor. 052 * 053 * @param range The range string to parse. Must not be <jk>null</jk>. 054 */ 055 public VersionRange(String range) { 056 range = range.trim(); 057 if (! range.isEmpty()) { 058 char c1 = range.charAt(0); 059 char c2 = range.charAt(range.length() - 1); 060 var c = range.indexOf(','); 061 if (c > -1 && (c1 == '[' || c1 == '(') && (c2 == ']' || c2 == ')')) { 062 var v1 = range.substring(1, c); 063 var v2 = range.substring(c + 1, range.length() - 1); 064 minVersion = new Version(v1); 065 maxVersion = new Version(v2); 066 minExclusive = c1 == '('; 067 maxExclusive = c2 == ')'; 068 } else { 069 minVersion = new Version(range); 070 maxVersion = null; 071 minExclusive = maxExclusive = false; 072 } 073 } else { 074 minVersion = maxVersion = null; 075 minExclusive = maxExclusive = false; 076 } 077 } 078 079 /** 080 * Returns <jk>true</jk> if the specified version string matches this version range. 081 * 082 * @param v The version string (e.g. <js>"1.2.3"</js>). Can be <jk>null</jk> or empty. 083 * @return <jk>true</jk> if the specified version string matches this version range. 084 */ 085 public boolean matches(String v) { 086 if (ie(v)) 087 return (minVersion == null && maxVersion == null); 088 var ver = new Version(v); 089 return (minVersion == null || ver.isAtLeast(minVersion, minExclusive)) 090 && (maxVersion == null || ver.isAtMost(maxVersion, maxExclusive)); 091 } 092 093 @Override /* Overridden from Object */ 094 public String toString() { 095 return (minExclusive ? "(" : "[") + minVersion + ',' + maxVersion + (maxExclusive ? ")" : "]"); 096 } 097}