001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019 package org.apache.felix.framework.util; 020 021 import org.osgi.framework.Version; 022 023 public class VersionRange 024 { 025 private final Version m_low; 026 private final boolean m_isLowInclusive; 027 private final Version m_high; 028 private final boolean m_isHighInclusive; 029 public static final VersionRange infiniteRange = new VersionRange(Version.emptyVersion, true, null, true); 030 031 public VersionRange( 032 Version low, boolean isLowInclusive, 033 Version high, boolean isHighInclusive) 034 { 035 m_low = low; 036 m_isLowInclusive = isLowInclusive; 037 m_high = high; 038 m_isHighInclusive = isHighInclusive; 039 } 040 041 public Version getLow() 042 { 043 return m_low; 044 } 045 046 public boolean isLowInclusive() 047 { 048 return m_isLowInclusive; 049 } 050 051 public Version getHigh() 052 { 053 return m_high; 054 } 055 056 public boolean isHighInclusive() 057 { 058 return m_isHighInclusive; 059 } 060 061 public boolean isInRange(Version version) 062 { 063 // We might not have an upper end to the range. 064 if (m_high == null) 065 { 066 return (version.compareTo(m_low) >= 0); 067 } 068 else if (isLowInclusive() && isHighInclusive()) 069 { 070 return (version.compareTo(m_low) >= 0) && (version.compareTo(m_high) <= 0); 071 } 072 else if (isHighInclusive()) 073 { 074 return (version.compareTo(m_low) > 0) && (version.compareTo(m_high) <= 0); 075 } 076 else if (isLowInclusive()) 077 { 078 return (version.compareTo(m_low) >= 0) && (version.compareTo(m_high) < 0); 079 } 080 return (version.compareTo(m_low) > 0) && (version.compareTo(m_high) < 0); 081 } 082 083 public boolean intersects(VersionRange vr) 084 { 085 // Check to see if the passed in floor is less than or equal to 086 // this ceiling and the passed in ceiling is greater than or 087 // equal to this floor. 088 boolean isFloorLessThanCeiling = false; 089 if ((m_high == null) 090 || (m_high.compareTo(vr.getLow()) > 0) 091 || ((m_high.compareTo(vr.getLow()) == 0) 092 && m_isHighInclusive && vr.isLowInclusive())) 093 { 094 isFloorLessThanCeiling = true; 095 } 096 boolean isCeilingGreaterThanFloor = false; 097 if ((vr.getHigh() == null) 098 || (m_low.compareTo(vr.getHigh()) < 0) 099 || ((m_low.compareTo(vr.getHigh()) == 0) 100 && m_isLowInclusive && vr.isHighInclusive())) 101 { 102 isCeilingGreaterThanFloor = true; 103 } 104 return isFloorLessThanCeiling && isCeilingGreaterThanFloor; 105 } 106 107 public VersionRange intersection(VersionRange vr) 108 { 109 if (!intersects(vr)) 110 { 111 return null; 112 } 113 114 VersionRange floor = (m_low.compareTo(vr.getLow()) > 0) ? this : vr; 115 boolean floorInclusive = (getLow().equals(vr.getLow())) 116 ? (isLowInclusive() & vr.isLowInclusive()) 117 : floor.isLowInclusive(); 118 119 VersionRange ceiling; 120 boolean ceilingInclusive; 121 if (vr.getHigh() == null) 122 { 123 ceiling = this; 124 ceilingInclusive = ceiling.isHighInclusive(); 125 } 126 else if (m_high == null) 127 { 128 ceiling = vr; 129 ceilingInclusive = ceiling.isHighInclusive(); 130 } 131 else if (m_high.compareTo(vr.getHigh()) > 0) 132 { 133 ceiling = vr; 134 ceilingInclusive = ceiling.isHighInclusive(); 135 } 136 else if (m_high.compareTo(vr.getHigh()) < 0) 137 { 138 ceiling = this; 139 ceilingInclusive = ceiling.isHighInclusive(); 140 } 141 else 142 { 143 ceiling = this; 144 ceilingInclusive = (isHighInclusive() & vr.isHighInclusive()); 145 } 146 147 return new VersionRange( 148 floor.getLow(), floorInclusive, ceiling.getHigh(), ceilingInclusive); 149 } 150 151 public static VersionRange parse(String range) 152 { 153 // Check if the version is an interval. 154 if (range.indexOf(',') >= 0) 155 { 156 String s = range.substring(1, range.length() - 1); 157 String vlo = s.substring(0, s.indexOf(',')).trim(); 158 String vhi = s.substring(s.indexOf(',') + 1, s.length()).trim(); 159 return new VersionRange ( 160 new Version(vlo), (range.charAt(0) == '['), 161 new Version(vhi), (range.charAt(range.length() - 1) == ']')); 162 } 163 else 164 { 165 return new VersionRange(new Version(range), true, null, false); 166 } 167 } 168 169 public boolean equals(Object obj) 170 { 171 if (obj == null) 172 { 173 return false; 174 } 175 if (getClass() != obj.getClass()) 176 { 177 return false; 178 } 179 final VersionRange other = (VersionRange) obj; 180 if (m_low != other.m_low && (m_low == null || !m_low.equals(other.m_low))) 181 { 182 return false; 183 } 184 if (m_isLowInclusive != other.m_isLowInclusive) 185 { 186 return false; 187 } 188 if (m_high != other.m_high && (m_high == null || !m_high.equals(other.m_high))) 189 { 190 return false; 191 } 192 if (m_isHighInclusive != other.m_isHighInclusive) 193 { 194 return false; 195 } 196 return true; 197 } 198 199 public int hashCode() 200 { 201 int hash = 5; 202 hash = 97 * hash + (m_low != null ? m_low.hashCode() : 0); 203 hash = 97 * hash + (m_isLowInclusive ? 1 : 0); 204 hash = 97 * hash + (m_high != null ? m_high.hashCode() : 0); 205 hash = 97 * hash + (m_isHighInclusive ? 1 : 0); 206 return hash; 207 } 208 209 public String toString() 210 { 211 if (m_high != null) 212 { 213 StringBuffer sb = new StringBuffer(); 214 sb.append(m_isLowInclusive ? '[' : '('); 215 sb.append(m_low.toString()); 216 sb.append(','); 217 sb.append(m_high.toString()); 218 sb.append(m_isHighInclusive ? ']' : ')'); 219 return sb.toString(); 220 } 221 else 222 { 223 return m_low.toString(); 224 } 225 } 226 }