001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software GmbH & Co. KG, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.module; 029 030import org.opencms.main.CmsIllegalArgumentException; 031import org.opencms.main.CmsRuntimeException; 032import org.opencms.util.CmsStringUtil; 033 034import java.io.Serializable; 035 036/** 037 * A version number for an OpenCms module.<p> 038 * 039 * A module version number has the form <code>n1.n2.n3.n4</code>. 040 * Only <code>n1</code> is required, <code>n2 - n4</code> are optional.<p> 041 * 042 * The valid range for each <code>n</code> is 0 - 999. 043 * Examples for valid version numbers are <code>0.9</code>, <code>1.0.0.5</code> 044 * or <code>5</code>. 045 * The maximum version number is <code>999.999.999.999</code>.<p> 046 * 047 * The comparison is started with <code>n1</code> being the most important value, 048 * followed by <code>n2 - n4</code>. 049 * For example <code>5.0.0.1 > 4.999.999.999</code> since <code>5 > 4</code>.<p> 050 * 051 * For any <code>n1 - n4</code>, if <code>n > 0</code> leading zeros are ignored. 052 * So <code>001.002.004.004 = 1.2.3.4</code>. Unrequired leading zeros are automatically 053 * stripped from version numbers.<p> 054 * 055 * @since 6.0.0 056 */ 057public class CmsModuleVersion implements Comparable<Object>, Serializable { 058 059 /** Default version for new modules. */ 060 public static final String DEFAULT_VERSION = "0.1"; 061 062 /** The serial version id. */ 063 private static final long serialVersionUID = 5871716904011659917L; 064 065 /** The dot count of the version. */ 066 private int m_dots; 067 068 /** The version number (for comparisons). */ 069 private long m_number; 070 071 /** Indicates if the module version was already updated. */ 072 private boolean m_updated; 073 074 /** The version String. */ 075 private String m_version; 076 077 /** 078 * Creates a new module version based on a String.<p> 079 * 080 * @param version the version to set 081 */ 082 public CmsModuleVersion(String version) { 083 084 setVersion(version); 085 } 086 087 /** 088 * @see java.lang.Comparable#compareTo(java.lang.Object) 089 */ 090 public int compareTo(Object obj) { 091 092 if (obj == this) { 093 return 0; 094 } 095 if (obj instanceof CmsModuleVersion) { 096 if (m_version == null) { 097 return 0; 098 } 099 CmsModuleVersion other = (CmsModuleVersion)obj; 100 if (m_number == other.m_number) { 101 return 0; 102 } 103 return (m_number > other.m_number) ? 1 : -1; 104 } 105 return 0; 106 } 107 108 /** 109 * @see java.lang.Object#equals(java.lang.Object) 110 */ 111 @Override 112 public boolean equals(Object obj) { 113 114 if (obj == this) { 115 return true; 116 } 117 if (obj instanceof CmsModuleVersion) { 118 CmsModuleVersion other = (CmsModuleVersion)obj; 119 if (m_version == null) { 120 return (other.m_version == null); 121 } 122 return m_version.equals(other.m_version); 123 } 124 return false; 125 } 126 127 /** 128 * Returns the current version String.<p> 129 * 130 * @return the current version String 131 */ 132 public String getVersion() { 133 134 return m_version; 135 } 136 137 /** 138 * @see java.lang.Object#hashCode() 139 */ 140 @Override 141 public int hashCode() { 142 143 if (m_version == null) { 144 return 0; 145 } 146 147 return m_version.hashCode(); 148 } 149 150 /** 151 * Sets the version as a String.<p> 152 * 153 * @param version the version String to set 154 */ 155 public void setVersion(String version) { 156 157 m_number = 0L; 158 if ((version == null) || (version.charAt(0) == '.') || (version.charAt(version.length() - 1) == '.')) { 159 throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_NOT_NUMBER_0)); 160 } 161 String[] split = CmsStringUtil.splitAsArray(version, '.'); 162 m_dots = split.length; 163 if (m_dots > 4) { 164 throw new CmsIllegalArgumentException( 165 Messages.get().container(Messages.ERR_INVALID_VERSION_LENGTH_1, version)); 166 } 167 String[] numbers = new String[5]; 168 System.arraycopy(split, 0, numbers, 1, m_dots); 169 numbers[0] = "1"; 170 for (int i = 1 + m_dots; i < 5; i++) { 171 numbers[i] = "0"; 172 } 173 for (int i = numbers.length - 1; i >= 0; i--) { 174 try { 175 int number = Integer.valueOf(numbers[numbers.length - i - 1]).intValue(); 176 177 if ((number > 999) || (number < 0)) { 178 throw new CmsIllegalArgumentException( 179 Messages.get().container(Messages.ERR_INVALID_VERSION_SUBNUMBER_1, Integer.valueOf(number))); 180 } 181 m_number = ((long)Math.pow(1000.0, i) * number) + m_number; 182 } catch (NumberFormatException e) { 183 // no valid version provided 184 throw new CmsIllegalArgumentException(Messages.get().container(Messages.ERR_NOT_NUMBER_0)); 185 } 186 } 187 188 setVersion(m_number); 189 } 190 191 /** 192 * @see java.lang.Object#toString() 193 */ 194 @Override 195 public String toString() { 196 197 return getVersion(); 198 } 199 200 /** 201 * Increments this version number by 1 in the last digit.<p> 202 */ 203 protected void increment() { 204 205 if (m_number < 1999999999999L) { 206 m_number += (long)Math.pow(1000.0, (4 - m_dots)); 207 setVersion(m_number); 208 } else { 209 throw new CmsRuntimeException(Messages.get().container(Messages.ERR_MODULE_VERSION_NUMBER_0)); 210 } 211 } 212 213 /** 214 * Returns the updated status.<p> 215 * 216 * @return the updated status 217 */ 218 protected boolean isUpdated() { 219 220 return m_updated; 221 } 222 223 /** 224 * Sets the updated status.<p> 225 * 226 * @param updated the updated status to set 227 */ 228 protected void setUpdated(boolean updated) { 229 230 m_updated = updated; 231 } 232 233 /** 234 * Sets the version as a number.<p> 235 * 236 * @param number the version number to set 237 */ 238 private void setVersion(long number) { 239 240 String result = ""; 241 for (int i = 0; i < 4; i++) { 242 long mod = number % 1000L; 243 number = number / 1000L; 244 if (m_dots >= (4 - i)) { 245 if (m_dots > (4 - i)) { 246 result = '.' + result; 247 } 248 result = "" + mod + result; 249 } 250 } 251 252 m_version = result; 253 } 254}