| 1 | package org.europa.together.domain; | |
| 2 | ||
| 3 | import java.util.Objects; | |
| 4 | import org.europa.together.application.LogbackLogger; | |
| 5 | import org.europa.together.business.Logger; | |
| 6 | import org.europa.together.exceptions.MisconfigurationException; | |
| 7 | import org.europa.together.utils.StringUtils; | |
| 8 | import org.europa.together.utils.Validator; | |
| 9 | ||
| 10 | /** | |
| 11 | * Data class for program version numbers, based on semantic versioning. This | |
| 12 | * implementation allwos to compare and sort version numbers.<br> | |
| 13 | * Pattern: Major.Minor.Patch-Label (Patch and Label are optional)<br> | |
| 14 | * <code> | |
| 15 | * true: equals(1.2.3-SNAPSHOT : 1.2.3-SNAPSHOT); | |
| 16 | * true: equals(1.2.3-LABLE : 1.2.3-SNAPSHOT); | |
| 17 | * true: equals(1.0 : 1.0.0); | |
| 18 | * false: equals(1.0 : 1.0.1); | |
| 19 | * false: equals(1.0-LABEL : 1.0); | |
| 20 | * A greater B: compareTo(2.0 : 1.0); | |
| 21 | * A greater B: compareTo(1.1 : 1.0); | |
| 22 | * A greater B: compareTo(1.0.1 : 1.0.0); | |
| 23 | * A greater B: compareTo(2.1 : 1.1); | |
| 24 | * A equal B: compareTo(2.1.1 : 2.1.1-SNAPSHOT); | |
| 25 | * </code> The only recomennded label is SNAPSHOT, because labels are not part | |
| 26 | * of comparing. | |
| 27 | * | |
| 28 | * <b>Definition:</b><br> | |
| 29 | * A version of a software artifact is always uniqe. Artifacts can have | |
| 30 | * different versions (1:n relation). That means when an artifact a exist two | |
| 31 | * times and both are not identical, the first artifact has a different version | |
| 32 | * than the second artifact. Both artifacts can not have the same version. If | |
| 33 | * both artifacts with the same name have the same version it is impossible to | |
| 34 | * distinguish them. | |
| 35 | */ | |
| 36 | public final class Version implements Comparable<Version> { | |
| 37 | ||
| 38 | private static final Logger LOGGER = new LogbackLogger(Version.class); | |
| 39 | ||
| 40 | private int major = -1; | |
| 41 | private int minor = -1; | |
| 42 | private int patch = -1; | |
| 43 | private String label = ""; | |
| 44 | ||
| 45 | /** | |
| 46 | * Constructor. | |
| 47 | * | |
| 48 | * @param version as String | |
| 49 | * @throws org.europa.together.exceptions.MisconfigurationException | |
| 50 | */ | |
| 51 | public Version(final String version) | |
| 52 | throws MisconfigurationException { | |
| 53 | ||
| 54 |
1
1. <init> : negated conditional → KILLED |
if (!Validator.validate(version, Validator.SEMANTIC_VERSION_NUMBER)) { |
| 55 | String msg = "The version number " + version | |
| 56 | + " do not match the Pattern: [1].[2].[3]-[LABEL]."; | |
| 57 | throw new MisconfigurationException(msg); | |
| 58 | } else { | |
| 59 | String[] fragments = version.split("\\."); | |
| 60 | LOGGER.log("Fragments: " + fragments.length, LogLevel.DEBUG); | |
| 61 | ||
| 62 | major = Integer.parseInt(fragments[0]); | |
| 63 |
2
1. <init> : changed conditional boundary → KILLED 2. <init> : negated conditional → KILLED |
if (fragments.length > 1) { |
| 64 |
1
1. <init> : negated conditional → KILLED |
if (!fragments[1].contains("-")) { |
| 65 | minor = Integer.parseInt(fragments[1]); | |
| 66 | } else { | |
| 67 | LOGGER.log("Lable after minor.", LogLevel.DEBUG); | |
| 68 | String[] optional = fragments[1].split("-"); | |
| 69 | minor = Integer.parseInt(optional[0]); | |
| 70 | label = optional[1]; | |
| 71 | } | |
| 72 | } | |
| 73 |
2
1. <init> : changed conditional boundary → KILLED 2. <init> : negated conditional → KILLED |
if (fragments.length > 2) { |
| 74 | String[] optional = fragments[2].split("-"); | |
| 75 | ||
| 76 | patch = Integer.parseInt(optional[0]); | |
| 77 |
1
1. <init> : negated conditional → KILLED |
if (optional.length == 2) { //prevent index out of bound exception |
| 78 | label = optional[1]; | |
| 79 | } | |
| 80 | } | |
| 81 | LOGGER.log("Version: " + toString(), LogLevel.DEBUG); | |
| 82 | } | |
| 83 | } | |
| 84 | ||
| 85 | //<editor-fold defaultstate="collapsed" desc="Getter / Setter"> | |
| 86 | /** | |
| 87 | * Return the Major section of a version number as int. MANDANTORY. | |
| 88 | * | |
| 89 | * @return Major as int | |
| 90 | */ | |
| 91 | public int getMajor() { | |
| 92 |
1
1. getMajor : replaced int return with 0 for org/europa/together/domain/Version::getMajor → KILLED |
return major; |
| 93 | } | |
| 94 | ||
| 95 | /** | |
| 96 | * Return the Minor section of a version number as int. MANDANTORY. | |
| 97 | * | |
| 98 | * @return Minor as int | |
| 99 | */ | |
| 100 | public int getMinor() { | |
| 101 |
1
1. getMinor : replaced int return with 0 for org/europa/together/domain/Version::getMinor → KILLED |
return minor; |
| 102 | } | |
| 103 | ||
| 104 | /** | |
| 105 | * Return the Patch level section of a version number as int. OPTIONAL. If | |
| 106 | * the patch level not exist the method return -1. | |
| 107 | * | |
| 108 | * @return Patch as int | |
| 109 | */ | |
| 110 | public int getPatch() { | |
| 111 |
1
1. getPatch : replaced int return with 0 for org/europa/together/domain/Version::getPatch → KILLED |
return patch; |
| 112 | } | |
| 113 | ||
| 114 | /** | |
| 115 | * Return the Label section of a version number as String. OPTIONAL. If the | |
| 116 | * label not exist the method return an empty String. | |
| 117 | * | |
| 118 | * @return Label as String | |
| 119 | */ | |
| 120 | public String getLabel() { | |
| 121 |
1
1. getLabel : replaced return value with "" for org/europa/together/domain/Version::getLabel → KILLED |
return label; |
| 122 | } | |
| 123 | ||
| 124 | /** | |
| 125 | * Return the whole version number as String. | |
| 126 | * | |
| 127 | * @return version as String | |
| 128 | */ | |
| 129 | public String getVersion() { | |
| 130 | String version = Integer.toString(major); | |
| 131 |
1
1. getVersion : negated conditional → KILLED |
if (minor != -1) { |
| 132 | version = version + "." + minor; | |
| 133 | } | |
| 134 |
1
1. getVersion : negated conditional → KILLED |
if (patch != -1) { |
| 135 | version = version + "." + patch; | |
| 136 | } | |
| 137 |
1
1. getVersion : negated conditional → KILLED |
if (!StringUtils.isEmpty(label)) { |
| 138 | version = version + "-" + label; | |
| 139 | } | |
| 140 |
1
1. getVersion : replaced return value with "" for org/europa/together/domain/Version::getVersion → KILLED |
return version; |
| 141 | } | |
| 142 | //</editor-fold> | |
| 143 | ||
| 144 | @Override | |
| 145 | public int compareTo(final Version o) { | |
| 146 | // -1:smaller | 0:equal | 1:greater | |
| 147 | int compare; | |
| 148 |
2
1. compareTo : negated conditional → KILLED 2. compareTo : changed conditional boundary → KILLED |
if (this.major > o.major) { |
| 149 | compare = 1; | |
| 150 |
2
1. compareTo : negated conditional → KILLED 2. compareTo : changed conditional boundary → KILLED |
} else if (this.major < o.major) { |
| 151 | compare = -1; | |
| 152 | } else { | |
| 153 |
2
1. compareTo : changed conditional boundary → KILLED 2. compareTo : negated conditional → KILLED |
if (this.minor > o.minor) { |
| 154 | compare = 1; | |
| 155 |
2
1. compareTo : changed conditional boundary → KILLED 2. compareTo : negated conditional → KILLED |
} else if (this.minor < o.minor) { |
| 156 | compare = -1; | |
| 157 | } else { | |
| 158 | ||
| 159 |
2
1. compareTo : negated conditional → KILLED 2. compareTo : changed conditional boundary → KILLED |
if (this.patch > o.patch) { |
| 160 | compare = 1; | |
| 161 |
2
1. compareTo : changed conditional boundary → KILLED 2. compareTo : negated conditional → KILLED |
} else if (this.patch < o.patch) { |
| 162 | compare = -1; | |
| 163 | } else { | |
| 164 | compare = 0; | |
| 165 | } | |
| 166 | } | |
| 167 | } | |
| 168 |
1
1. compareTo : replaced int return with 0 for org/europa/together/domain/Version::compareTo → KILLED |
return compare; |
| 169 | } | |
| 170 | ||
| 171 | @Override | |
| 172 | public boolean equals(final Object object) { | |
| 173 | boolean success = false; | |
| 174 |
2
1. equals : negated conditional → KILLED 2. equals : negated conditional → KILLED |
if (object != null && object instanceof Version) { |
| 175 |
1
1. equals : negated conditional → KILLED |
if (this == object) { |
| 176 | success = true; | |
| 177 | } else { | |
| 178 | final Version other = (Version) object; | |
| 179 |
1
1. equals : negated conditional → KILLED |
if (Objects.equals(this.major, other.major) |
| 180 |
5
1. equals : negated conditional → KILLED 2. equals : negated conditional → KILLED 3. equals : negated conditional → KILLED 4. equals : negated conditional → KILLED 5. equals : negated conditional → KILLED |
&& Objects.equals(this.minor, other.minor) |
| 181 | && ((this.patch == -1 || this.patch == 0) | |
| 182 | && (other.patch == -1 || other.patch == 0) | |
| 183 |
1
1. equals : negated conditional → KILLED |
|| Objects.equals(this.patch, other.patch))) { |
| 184 | success = true; | |
| 185 | } | |
| 186 | } | |
| 187 | } | |
| 188 |
2
1. equals : replaced boolean return with true for org/europa/together/domain/Version::equals → KILLED 2. equals : replaced boolean return with false for org/europa/together/domain/Version::equals → KILLED |
return success; |
| 189 | } | |
| 190 | ||
| 191 | @Override | |
| 192 | public int hashCode() { | |
| 193 | int hash = Objects.hashCode(this.major); | |
| 194 |
1
1. hashCode : Replaced integer addition with subtraction → KILLED |
hash += Objects.hashCode(this.minor); |
| 195 |
1
1. hashCode : Replaced integer addition with subtraction → KILLED |
hash += Objects.hashCode(this.patch); |
| 196 |
1
1. hashCode : replaced int return with 0 for org/europa/together/domain/Version::hashCode → KILLED |
return hash; |
| 197 | } | |
| 198 | ||
| 199 | @Override | |
| 200 | public String toString() { | |
| 201 |
1
1. toString : replaced return value with "" for org/europa/together/domain/Version::toString → KILLED |
return "Version{" + getVersion() + "}"; |
| 202 | } | |
| 203 | } | |
Mutations | ||
| 54 |
1.1 |
|
| 63 |
1.1 2.2 |
|
| 64 |
1.1 |
|
| 73 |
1.1 2.2 |
|
| 77 |
1.1 |
|
| 92 |
1.1 |
|
| 101 |
1.1 |
|
| 111 |
1.1 |
|
| 121 |
1.1 |
|
| 131 |
1.1 |
|
| 134 |
1.1 |
|
| 137 |
1.1 |
|
| 140 |
1.1 |
|
| 148 |
1.1 2.2 |
|
| 150 |
1.1 2.2 |
|
| 153 |
1.1 2.2 |
|
| 155 |
1.1 2.2 |
|
| 159 |
1.1 2.2 |
|
| 161 |
1.1 2.2 |
|
| 168 |
1.1 |
|
| 174 |
1.1 2.2 |
|
| 175 |
1.1 |
|
| 179 |
1.1 |
|
| 180 |
1.1 2.2 3.3 4.4 5.5 |
|
| 183 |
1.1 |
|
| 188 |
1.1 2.2 |
|
| 194 |
1.1 |
|
| 195 |
1.1 |
|
| 196 |
1.1 |
|
| 201 |
1.1 |