001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.internal;
014
015import static org.apache.juneau.internal.StringUtils.*;
016
017/**
018 * Represents an OSGi-style version range like <js>"1.2"</js> or <js>"[1.0,2.0)"</js>.
019 *
020 * <p>
021 * The range can be any of the following formats:
022 * <ul>
023 *    <li><js>"[0,1.0)"</js> = Less than 1.0.  1.0 and 1.0.0 does not match.
024 *    <li><js>"[0,1.0]"</js> = Less than or equal to 1.0.  Note that 1.0.1 will match.
025 *    <li><js>"1.0"</js> = At least 1.0.  1.0 and 2.0 will match.
026 * </ul>
027 */
028public class VersionRange {
029
030   private final Version minVersion, maxVersion;
031   private final boolean minExclusive, maxExclusive;
032
033   /**
034    * Constructor.
035    *
036    * @param range The range string to parse.
037    */
038   public VersionRange(String range) {
039      range = range.trim();
040      if (! range.isEmpty()) {
041         char c1 = range.charAt(0), c2 = range.charAt(range.length()-1);
042         int c = range.indexOf(',');
043         if (c > -1 && (c1 == '[' || c1 == '(') && (c2 == ']' || c2 == ')')) {
044            String v1 = range.substring(1, c), v2 = range.substring(c+1, range.length()-1);
045            minVersion = new Version(v1);
046            maxVersion = new Version(v2);
047            minExclusive = c1 == '(';
048            maxExclusive = c2 == ')';
049         } else {
050            minVersion = new Version(range);
051            maxVersion = null;
052            minExclusive = maxExclusive = false;
053         }
054      } else {
055         minVersion = maxVersion = null;
056         minExclusive = maxExclusive = false;
057      }
058   }
059
060   /**
061    * Returns <jk>true</jk> if the specified version string matches this version range.
062    *
063    * @param v The version string (e.g. <js>"1.2.3"</js>)
064    * @return <jk>true</jk> if the specified version string matches this version range.
065    */
066   public boolean matches(String v) {
067      if (isEmpty(v))
068         return (minVersion == null && maxVersion == null);
069      Version ver = new Version(v);
070      if (minVersion != null && ! ver.isAtLeast(minVersion, minExclusive))
071         return false;
072      if (maxVersion != null && ! ver.isAtMost(maxVersion, maxExclusive))
073         return false;
074      return true;
075   }
076
077   @Override /* Object */
078   public String toString() {
079      return (minExclusive ? "(" : "[") + minVersion + ',' + maxVersion + (maxExclusive ? ")" : "]");
080   }
081}