reduce 'return null'

This commit is contained in:
huangyuhui 2018-02-07 21:01:09 +08:00
parent 35047477fe
commit 5607298898
25 changed files with 111 additions and 105 deletions

View File

@ -39,6 +39,7 @@ import java.net.Proxy;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
public final class AccountHelper {
public static final AccountHelper INSTANCE = new AccountHelper();
@ -155,9 +156,9 @@ public final class AccountHelper {
if (profile == null) return;
String name = profile.getName();
if (name == null) return;
ProfileTexture texture = account.getSkin(profile);
if (texture == null) return;
String url = texture.getUrl();
Optional<ProfileTexture> texture = account.getSkin(profile);
if (!texture.isPresent()) return;
String url = texture.get().getUrl();
File file = getSkinFile(name);
if (!refresh && file.exists())
return;

View File

@ -135,6 +135,11 @@ public class HMCLGameRepository extends DefaultGameRepository {
}
}
/**
* Create new version setting if version id has no version setting.
* @param id the version id.
* @return new version setting, null if given version does not exist.
*/
public VersionSetting createVersionSetting(String id) {
if (!hasVersion(id))
return null;

View File

@ -86,9 +86,8 @@ public class HMCLModpackExportTask extends TaskResult<ZipEngine> {
});
Version mv = repository.getVersion(version).resolve(repository);
String gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version));
if (gameVersion == null)
throw new IllegalStateException("Cannot parse the version of " + version);
String gameVersion = GameVersion.minecraftVersion(repository.getVersionJar(version))
.orElseThrow(() -> new IllegalStateException("Cannot parse the version of " + version));
zip.putTextFile(Constants.GSON.toJson(mv.setJar(gameVersion)), "minecraft/pack.json"); // Making "jar" to gameVersion is to be compatible with old HMCL.
zip.putTextFile(Constants.GSON.toJson(modpack.setGameVersion(gameVersion)), "modpack.json"); // Newer HMCL only reads 'gameVersion' field.
}

View File

@ -156,7 +156,7 @@ public final class LauncherHelper {
private static void checkGameState(Profile profile, VersionSetting setting, Version version, Runnable onAccept) throws InterruptedException {
boolean flag = false, suggest = true;
VersionNumber gameVersion = VersionNumber.asVersion(GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)));
VersionNumber gameVersion = VersionNumber.asVersion(GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version)).orElse("Unknown"));
JavaVersion java = setting.getJavaVersion();
if (java == null) {
Controllers.dialog(Main.i18n("launch.wrong_javadir"), Main.i18n("message.error"), MessageBox.ERROR_MESSAGE, onAccept);

View File

@ -27,6 +27,7 @@ import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.Pair;
import java.util.Map;
import java.util.Optional;
/**
* @author huangyuhui
@ -52,14 +53,19 @@ public final class Accounts {
account.getProperties().put("character", character);
}
public static String getCurrentCharacter(Account account) {
return Lang.get(account.getProperties(), "character", String.class, null);
public static boolean hasCurrentCharacter(Account account) {
return Lang.get(account.getProperties(), "character", String.class, null) != null;
}
public static String getCurrentCharacter(Map<Object, Object> storage) {
Map properties = Lang.get(storage, "properties", Map.class, null);
if (properties == null) return null;
return Lang.get(properties, "character", String.class, null);
public static String getCurrentCharacter(Account account) {
return Lang.get(account.getProperties(), "character", String.class)
.orElseThrow(() -> new IllegalArgumentException("Account " + account + " has not set current character."));
}
public static Optional<String> getCurrentCharacter(Map<Object, Object> storage) {
Optional<Map> properties = Lang.get(storage, "properties", Map.class);
if (!properties.isPresent()) return Optional.empty();
return Lang.get(properties.get(), "character", String.class);
}
static String getAccountId(Account account) {

View File

@ -126,6 +126,11 @@ public final class Profile {
return vs == null || vs.isUsesGlobal();
}
/**
* Make version use self version settings instead of the global one.
* @param id the version id.
* @return specialized version setting, null if given version does not exist.
*/
public VersionSetting specializeVersionSetting(String id) {
VersionSetting vs = repository.getVersionSetting(id);
if (vs == null)

View File

@ -66,9 +66,9 @@ public class Settings {
{
for (Map<Object, Object> settings : SETTINGS.getAccounts()) {
String characterName = Accounts.getCurrentCharacter(settings);
Optional<String> characterName = Accounts.getCurrentCharacter(settings);
AccountFactory factory = Accounts.ACCOUNT_FACTORY.get(Lang.get(settings, "type", String.class, ""));
if (factory == null || characterName == null) {
if (factory == null || !characterName.isPresent()) {
// unrecognized account type, so remove it.
SETTINGS.getAccounts().remove(settings);
continue;

View File

@ -488,7 +488,7 @@ public final class VersionSetting {
.setJavaArgs(getJavaArgs())
.setMaxMemory(getMaxMemory())
.setMinMemory(getMinMemory())
.setMetaspace(StringUtils.parseInt(getPermSize()))
.setMetaspace(Lang.toIntOrNull(getPermSize()))
.setWidth(getWidth())
.setHeight(getHeight())
.setFullscreen(isFullscreen())

View File

@ -20,6 +20,7 @@ package org.jackhuang.hmcl.ui;
import com.jfoenix.concurrency.JFXUtilities;
import org.jackhuang.hmcl.auth.Account;
import org.jackhuang.hmcl.auth.AuthInfo;
import org.jackhuang.hmcl.auth.MultiCharacterSelector;
import org.jackhuang.hmcl.auth.yggdrasil.YggdrasilAccount;
import org.jackhuang.hmcl.task.SilentException;
@ -47,6 +48,6 @@ public final class DialogController {
latch.await();
return Optional.ofNullable(res.get()).orElseThrow(SilentException::new);
}
return null;
return account.logIn(MultiCharacterSelector.DEFAULT);
}
}

View File

@ -31,6 +31,7 @@ import org.jackhuang.hmcl.task.Task;
import org.jackhuang.hmcl.ui.download.InstallerWizardProvider;
import java.util.LinkedList;
import java.util.Optional;
import java.util.function.Consumer;
public class InstallerController {
@ -85,11 +86,11 @@ public class InstallerController {
@FXML
private void onAdd() {
String gameVersion = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version));
Optional<String> gameVersion = GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version));
if (gameVersion == null)
if (!gameVersion.isPresent())
Controllers.dialog("version.cannot_read");
else
Controllers.getDecorator().startWizard(new InstallerWizardProvider(profile, gameVersion, version, forge, liteLoader, optiFine));
Controllers.getDecorator().startWizard(new InstallerWizardProvider(profile, gameVersion.get(), version, forge, liteLoader, optiFine));
}
}

View File

@ -184,7 +184,7 @@ public final class MainPage extends StackPane implements DecoratorPage {
List<Node> children = new LinkedList<>();
List<Version> versions = new LinkedList<>(profile.getRepository().getVersions());
for (Version version : versions) {
children.add(buildNode(profile, version.getId(), Lang.nonNull(GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version.getId())), "Unknown")));
children.add(buildNode(profile, version.getId(), GameVersion.minecraftVersion(profile.getRepository().getVersionJar(version.getId())).orElse("Unknown")));
}
FXUtils.resetChildren(masonryPane, children);
}

View File

@ -144,8 +144,10 @@ public final class YggdrasilAccount extends Account {
}
private void logIn1(URL url, Object input, Proxy proxy) throws AuthenticationException {
AuthenticationResponse response = makeRequest(url, input, proxy);
if (response == null || !clientToken.equals(response.getClientToken()))
AuthenticationResponse response = makeRequest(url, input, proxy)
.orElseThrow(() -> new AuthenticationException("Server response empty"));
if (!clientToken.equals(response.getClientToken()))
throw new AuthenticationException("Client token changed");
if (response.getSelectedProfile() != null)
@ -205,12 +207,12 @@ public final class YggdrasilAccount extends Account {
return result;
}
private AuthenticationResponse makeRequest(URL url, Object input, Proxy proxy) throws AuthenticationException {
private Optional<AuthenticationResponse> makeRequest(URL url, Object input, Proxy proxy) throws AuthenticationException {
try {
String jsonResult = input == null ? NetworkUtils.doGet(url, proxy) : NetworkUtils.doPost(url, GSON.toJson(input), "application/json", proxy);
AuthenticationResponse response = GSON.fromJson(jsonResult, AuthenticationResponse.class);
if (response == null)
return null;
return Optional.empty();
if (!StringUtils.isBlank(response.getError())) {
if (response.getErrorMessage() != null)
if (response.getErrorMessage().contains("Invalid credentials"))
@ -222,7 +224,7 @@ public final class YggdrasilAccount extends Account {
throw new AuthenticationException(response.getError() + ": " + response.getErrorMessage());
}
return response;
return Optional.of(response);
} catch (IOException e) {
throw new ServerDisconnectException(e);
} catch (JsonParseException e) {
@ -242,22 +244,22 @@ public final class YggdrasilAccount extends Account {
}
}
public ProfileTexture getSkin(GameProfile profile) throws IOException, JsonParseException {
public Optional<ProfileTexture> getSkin(GameProfile profile) throws IOException, JsonParseException {
if (StringUtils.isBlank(userId))
throw new IllegalStateException("Not logged in");
ProfileResponse response = GSON.fromJson(NetworkUtils.doGet(NetworkUtils.toURL(BASE_PROFILE + UUIDTypeAdapter.fromUUID(profile.getId()))), ProfileResponse.class);
if (response.getProperties() == null) return null;
if (response.getProperties() == null) return Optional.empty();
Property textureProperty = response.getProperties().get("textures");
if (textureProperty == null) return null;
if (textureProperty == null) return Optional.empty();
TextureResponse texture;
String json = new String(Base64.getDecoder().decode(textureProperty.getValue()), Charsets.UTF_8);
texture = GSON.fromJson(json, TextureResponse.class);
if (texture == null || texture.getTextures() == null)
return null;
return Optional.empty();
return texture.getTextures().get(ProfileTexture.Type.SKIN);
return Optional.ofNullable(texture.getTextures().get(ProfileTexture.Type.SKIN));
}
@Override

View File

@ -27,10 +27,7 @@ import org.jackhuang.hmcl.util.NetworkUtils;
import org.jackhuang.hmcl.util.StringUtils;
import org.jackhuang.hmcl.util.VersionNumber;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
*
@ -62,8 +59,8 @@ public final class ForgeVersionList extends VersionList<Void> {
versions.clear();
for (Map.Entry<String, int[]> entry : root.getGameVersions().entrySet()) {
String gameVersion = VersionNumber.parseVersion(entry.getKey());
if (gameVersion == null)
Optional<String> gameVersion = VersionNumber.parseVersion(entry.getKey());
if (!gameVersion.isPresent())
continue;
for (int v : entry.getValue()) {
ForgeVersion version = root.getNumber().get(v);
@ -80,7 +77,7 @@ public final class ForgeVersionList extends VersionList<Void> {
if (jar == null)
continue;
versions.put(gameVersion, new RemoteVersion<>(
versions.put(gameVersion.get(), new RemoteVersion<>(
version.getGameVersion(), version.getVersion(), jar, null
));
}

View File

@ -28,6 +28,7 @@ import org.jackhuang.hmcl.util.VersionNumber;
import java.util.Collection;
import java.util.Collections;
import java.util.Optional;
/**
*
@ -55,10 +56,10 @@ public final class GameVersionList extends VersionList<GameRemoteVersionTag> {
GameRemoteVersions root = Constants.GSON.fromJson(task.getResult(), GameRemoteVersions.class);
for (GameRemoteVersion remoteVersion : root.getVersions()) {
String gameVersion = VersionNumber.parseVersion(remoteVersion.getGameVersion());
if (gameVersion == null)
Optional<String> gameVersion = VersionNumber.parseVersion(remoteVersion.getGameVersion());
if (!gameVersion.isPresent())
continue;
versions.put(gameVersion, new RemoteVersion<>(
versions.put(gameVersion.get(), new RemoteVersion<>(
remoteVersion.getGameVersion(),
remoteVersion.getGameVersion(),
remoteVersion.getUrl(),

View File

@ -64,10 +64,7 @@ public final class LiteLoaderInstallTask extends TaskResult<Version> {
if (!liteLoaderVersionList.isLoaded())
dependents.add(liteLoaderVersionList.refreshAsync(dependencyManager.getDownloadProvider())
.then(s -> {
doRemote();
return null;
}));
.then(Task.of(this::doRemote)));
else
doRemote();
}

View File

@ -38,6 +38,7 @@ import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
/**
*
@ -67,11 +68,11 @@ public final class LiteLoaderVersionList extends VersionList<LiteLoaderRemoteVer
for (Map.Entry<String, LiteLoaderGameVersions> entry : root.getVersions().entrySet()) {
String gameVersion = entry.getKey();
LiteLoaderGameVersions liteLoader = entry.getValue();
String gg = VersionNumber.parseVersion(gameVersion);
if (gg == null)
Optional<String> gg = VersionNumber.parseVersion(gameVersion);
if (!gg.isPresent())
continue;
doBranch(gg, gameVersion, liteLoader.getRepoitory(), liteLoader.getArtifacts(), false);
doBranch(gg, gameVersion, liteLoader.getRepoitory(), liteLoader.getSnapshots(), true);
doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getArtifacts(), false);
doBranch(gg.get(), gameVersion, liteLoader.getRepoitory(), liteLoader.getSnapshots(), true);
}
}

View File

@ -66,8 +66,8 @@ public final class OptiFineBMCLVersionList extends VersionList<Void> {
if (StringUtils.isBlank(element.getGameVersion()))
continue;
String gameVersion = VersionNumber.parseVersion(element.getGameVersion());
versions.put(gameVersion, new RemoteVersion<>(gameVersion, version, mirror, null));
VersionNumber.parseVersion(element.getGameVersion())
.ifPresent(gameVersion -> versions.put(gameVersion, new RemoteVersion<>(gameVersion, version, mirror, null)));
}
}
};

View File

@ -62,10 +62,7 @@ public final class OptiFineInstallTask extends TaskResult<Version> {
if (!optiFineVersionList.isLoaded())
dependents.add(optiFineVersionList.refreshAsync(dependencyManager.getDownloadProvider())
.then(s -> {
doRemote();
return null;
}));
.then(Task.of(this::doRemote)));
else
doRemote();
}

View File

@ -19,10 +19,7 @@ package org.jackhuang.hmcl.game;
import org.jackhuang.hmcl.util.Immutable;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.*;
/**
*
@ -49,20 +46,20 @@ public final class CompatibilityRule {
this.features = features;
}
public Action getAppliedAction(Map<String, Boolean> supportedFeatures) {
public Optional<Action> getAppliedAction(Map<String, Boolean> supportedFeatures) {
if (os != null && !os.allow())
return null;
return Optional.empty();
if (features != null)
for (Map.Entry<String, Boolean> entry : features.entrySet())
if (!Objects.equals(supportedFeatures.get(entry.getKey()), entry.getValue()))
return null;
return Optional.empty();
return action;
return Optional.ofNullable(action);
}
public static boolean appliesToCurrentEnvironment(Collection<CompatibilityRule> rules) {
return appliesToCurrentEnvironment(rules, Collections.EMPTY_MAP);
return appliesToCurrentEnvironment(rules, Collections.emptyMap());
}
public static boolean appliesToCurrentEnvironment(Collection<CompatibilityRule> rules, Map<String, Boolean> features) {
@ -71,9 +68,9 @@ public final class CompatibilityRule {
Action action = Action.DISALLOW;
for (CompatibilityRule rule : rules) {
Action thisAction = rule.getAppliedAction(features);
if (thisAction != null)
action = thisAction;
Optional<Action> thisAction = rule.getAppliedAction(features);
if (thisAction.isPresent())
action = thisAction.get();
}
return action == Action.ALLOW;

View File

@ -24,6 +24,7 @@ import org.jackhuang.hmcl.util.IOUtils;
import java.io.File;
import java.io.IOException;
import java.util.Optional;
/**
* @author huangyuhui
@ -51,31 +52,31 @@ public final class GameVersion {
return -1;
}
private static String getVersionOfOldMinecraft(ZipFile file, ZipArchiveEntry entry) throws IOException {
private static Optional<String> getVersionOfOldMinecraft(ZipFile file, ZipArchiveEntry entry) throws IOException {
byte[] tmp = IOUtils.readFullyAsByteArray(file.getInputStream(entry));
byte[] bytes = "Minecraft Minecraft ".getBytes(Charsets.US_ASCII);
int j = matchArray(tmp, bytes);
if (j < 0)
return null;
return Optional.empty();
int i = j + bytes.length;
if ((j = lessThan32(tmp, i)) < 0)
return null;
return Optional.empty();
return new String(tmp, i, j - i, Charsets.US_ASCII);
return Optional.of(new String(tmp, i, j - i, Charsets.US_ASCII));
}
private static String getVersionOfNewMinecraft(ZipFile file, ZipArchiveEntry entry) throws IOException {
private static Optional<String> getVersionOfNewMinecraft(ZipFile file, ZipArchiveEntry entry) throws IOException {
byte[] tmp = IOUtils.readFullyAsByteArray(file.getInputStream(entry));
byte[] str = "-server.txt".getBytes(Charsets.US_ASCII);
int j = matchArray(tmp, str);
if (j < 0) return null;
if (j < 0) return Optional.empty();
int i = j + str.length;
i += 11;
j = lessThan32(tmp, i);
if (j < 0) return null;
if (j < 0) return Optional.empty();
String result = new String(tmp, i, j - i, Charsets.US_ASCII);
char ch = result.charAt(0);
@ -83,7 +84,7 @@ public final class GameVersion {
if (ch < '0' || ch > '9') {
str = "Can't keep up! Did the system time change, or is the server overloaded?".getBytes(Charsets.US_ASCII);
j = matchArray(tmp, str);
if (j < 0) return null;
if (j < 0) return Optional.empty();
i = -1;
while (j > 0) {
if (tmp[j] >= 48 && tmp[j] <= 57) {
@ -92,21 +93,21 @@ public final class GameVersion {
}
j--;
}
if (i == -1) return null;
if (i == -1) return Optional.empty();
int k = i;
if (tmp[i + 1] >= (int) 'a' && tmp[i + 1] <= (int) 'z')
i++;
while (tmp[k] >= 48 && tmp[k] <= 57 || tmp[k] == (int) '-' || tmp[k] == (int) '.' || tmp[k] >= 97 && tmp[k] <= (int) 'z')
k--;
k++;
return new String(tmp, k, i - k + 1, Charsets.US_ASCII);
return Optional.of(new String(tmp, k, i - k + 1, Charsets.US_ASCII));
}
return result;
return Optional.of(result);
}
public static String minecraftVersion(File file) {
public static Optional<String> minecraftVersion(File file) {
if (file == null || !file.exists() || !file.isFile() || !file.canRead())
return null;
return Optional.empty();
ZipFile f = null;
try {
@ -119,9 +120,9 @@ public final class GameVersion {
ZipArchiveEntry minecraftserver = f.getEntry("net/minecraft/server/MinecraftServer.class");
if ((main != null) && (minecraftserver != null))
return getVersionOfNewMinecraft(f, minecraftserver);
return null;
return Optional.empty();
} catch (IOException e) {
return null;
return Optional.empty();
} finally {
IOUtils.closeQuietly(f);
}

View File

@ -123,7 +123,7 @@ public final class CurseManifest {
if (manifest == null)
throw new JsonParseException("`manifest.json` not found. Not a valid Curse modpack.");
return new Modpack(manifest.getName(), manifest.getAuthor(), manifest.getVersion(), manifest.getMinecraft().getGameVersion(),
Optional.ofNullable(CompressingUtils.readTextZipEntryQuietly(f, "modlist.html")).orElse( "No description"), manifest);
CompressingUtils.readTextZipEntryQuietly(f, "modlist.html").orElse( "No description"), manifest);
}
public static final String MINECRAFT_MODPACK = "minecraftModpack";

View File

@ -19,6 +19,7 @@ package org.jackhuang.hmcl.mod;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
import org.jackhuang.hmcl.util.Lang;
import org.jackhuang.hmcl.util.StringUtils;
import java.io.File;
@ -66,17 +67,17 @@ public final class MultiMCInstanceConfiguration {
javaPath = p.getProperty("JavaPath");
jvmArgs = p.getProperty("JvmArgs");
fullscreen = Boolean.parseBoolean(p.getProperty("LaunchMaximized"));
maxMemory = StringUtils.parseInt(p.getProperty("MaxMemAlloc"));
minMemory = StringUtils.parseInt(p.getProperty("MinMemAlloc"));
height = StringUtils.parseInt(p.getProperty("MinecraftWinHeight"));
width = StringUtils.parseInt(p.getProperty("MinecraftWinWidth"));
maxMemory = Lang.toIntOrNull(p.getProperty("MaxMemAlloc"));
minMemory = Lang.toIntOrNull(p.getProperty("MinMemAlloc"));
height = Lang.toIntOrNull(p.getProperty("MinecraftWinHeight"));
width = Lang.toIntOrNull(p.getProperty("MinecraftWinWidth"));
overrideCommands = Boolean.parseBoolean(p.getProperty("OverrideCommands"));
overrideConsole = Boolean.parseBoolean(p.getProperty("OverrideConsole"));
overrideJavaArgs = Boolean.parseBoolean(p.getProperty("OverrideJavaArgs"));
overrideJavaLocation = Boolean.parseBoolean(p.getProperty("OverrideJavaLocation"));
overrideMemory = Boolean.parseBoolean(p.getProperty("OverrideMemory"));
overrideWindow = Boolean.parseBoolean(p.getProperty("OverrideWindow"));
permGen = StringUtils.parseInt(p.getProperty("PermGen"));
permGen = Lang.toIntOrNull(p.getProperty("PermGen"));
postExitCommand = p.getProperty("PostExitCommand");
preLaunchCommand = p.getProperty("PreLaunchCommand");
showConsole = Boolean.parseBoolean(p.getProperty("ShowConsole"));

View File

@ -24,6 +24,7 @@ import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipFile;
import java.io.*;
import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.Predicate;
@ -217,11 +218,11 @@ public final class CompressingUtils {
* @param name the location of the text in zip file, something like A/B/C/D.txt
* @return the content of given file.
*/
public static String readTextZipEntryQuietly(File file, String name) {
public static Optional<String> readTextZipEntryQuietly(File file, String name) {
try {
return readTextZipEntry(file, name);
return Optional.of(readTextZipEntry(file, name));
} catch (IOException e) {
return null;
return Optional.empty();
}
}
}

View File

@ -207,14 +207,4 @@ public final class StringUtils {
return result;
}
public static Integer parseInt(String str) {
if (str == null)
return null;
try {
return Integer.parseInt(str);
} catch (NumberFormatException ex) {
return null;
}
}
}

View File

@ -19,6 +19,8 @@ package org.jackhuang.hmcl.util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Objects;
import java.util.Optional;
/**
* The formatted version number represents a version string.
@ -53,6 +55,7 @@ public abstract class VersionNumber implements Comparable<VersionNumber> {
}
public static VersionNumber asVersion(String version) {
Objects.requireNonNull(version);
try {
return asIntVersionNumber(version);
} catch (IllegalArgumentException e) {
@ -60,13 +63,13 @@ public abstract class VersionNumber implements Comparable<VersionNumber> {
}
}
public static String parseVersion(String str) {
public static Optional<String> parseVersion(String str) {
if (str.chars().anyMatch(it -> it != '.' && (it < '0' || it > '9')) || StringUtils.isBlank(str))
return null;
return Optional.empty();
String[] s = str.split("\\.");
for (String i : s)
if (StringUtils.isBlank(i))
return null;
return Optional.empty();
StringBuilder builder = new StringBuilder();
int last = s.length - 1;
for (int i = s.length - 1; i >= 0; --i)
@ -74,6 +77,6 @@ public abstract class VersionNumber implements Comparable<VersionNumber> {
last = i;
for (int i = 0; i < last; ++i)
builder.append(s[i]).append(".");
return builder.append(s[last]).toString();
return Optional.of(builder.append(s[last]).toString());
}
}