Merge branch 'v6' into feature/v6/json

# Conflicts:
#	Core/src/main/java/com/plotsquared/core/util/MainUtil.java
#	Core/src/main/java/com/plotsquared/core/util/OperationUtil.java
This commit is contained in:
Alexander Söderberg 2020-07-21 13:13:10 +02:00
commit 20e9d13f60
No known key found for this signature in database
GPG Key ID: C0207FF7EA146678
10 changed files with 172 additions and 421 deletions

View File

@ -36,7 +36,6 @@ import com.plotsquared.core.plot.PlotArea;
import com.plotsquared.core.plot.world.PlotAreaManager; import com.plotsquared.core.plot.world.PlotAreaManager;
import com.plotsquared.core.queue.ScopedLocalBlockQueue; import com.plotsquared.core.queue.ScopedLocalBlockQueue;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.util.MainUtil;
import com.sk89q.worldedit.math.BlockVector2; import com.sk89q.worldedit.math.BlockVector2;
import org.bukkit.World; import org.bukkit.World;
import org.bukkit.block.Biome; import org.bukkit.block.Biome;
@ -73,7 +72,6 @@ public class BukkitPlotGenerator extends ChunkGenerator
this.populators = new ArrayList<>(); this.populators = new ArrayList<>();
this.populators.add(new BlockStatePopulator(this.plotGenerator, this.plotAreaManager)); this.populators.add(new BlockStatePopulator(this.plotGenerator, this.plotAreaManager));
this.full = true; this.full = true;
MainUtil.initCache();
} }
public BukkitPlotGenerator(final String world, final ChunkGenerator cg, @Nonnull final PlotAreaManager plotAreaManager) { public BukkitPlotGenerator(final String world, final ChunkGenerator cg, @Nonnull final PlotAreaManager plotAreaManager) {
@ -86,7 +84,6 @@ public class BukkitPlotGenerator extends ChunkGenerator
this.full = false; this.full = false;
this.platformGenerator = cg; this.platformGenerator = cg;
this.plotGenerator = new DelegatePlotGenerator(cg, world); this.plotGenerator = new DelegatePlotGenerator(cg, world);
MainUtil.initCache();
} }
@Override public void augment(PlotArea area) { @Override public void augment(PlotArea area) {

View File

@ -31,7 +31,7 @@ import com.plotsquared.bukkit.util.BukkitUtil;
import com.plotsquared.core.location.ChunkWrapper; import com.plotsquared.core.location.ChunkWrapper;
import com.plotsquared.core.location.Location; import com.plotsquared.core.location.Location;
import com.plotsquared.core.queue.ScopedLocalBlockQueue; import com.plotsquared.core.queue.ScopedLocalBlockQueue;
import com.plotsquared.core.util.MainUtil; import com.plotsquared.core.util.ChunkUtil;
import com.plotsquared.core.util.PatternUtil; import com.plotsquared.core.util.PatternUtil;
import com.sk89q.worldedit.bukkit.BukkitAdapter; import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.function.pattern.Pattern; import com.sk89q.worldedit.function.pattern.Pattern;
@ -149,12 +149,12 @@ public class GenChunk extends ScopedLocalBlockQueue {
} }
private void storeCache(final int x, final int y, final int z, final BlockState id) { private void storeCache(final int x, final int y, final int z, final BlockState id) {
int i = MainUtil.CACHE_I[y][x][z]; int i = y >> 4;
BlockState[] v = this.result[i]; BlockState[] v = this.result[i];
if (v == null) { if (v == null) {
this.result[i] = v = new BlockState[4096]; this.result[i] = v = new BlockState[4096];
} }
int j = MainUtil.CACHE_J[y][x][z]; int j = ChunkUtil.getJ(x, y, z);
v[j] = id; v[j] = id;
} }
@ -169,7 +169,7 @@ public class GenChunk extends ScopedLocalBlockQueue {
} }
@Override public BlockState getBlock(int x, int y, int z) { @Override public BlockState getBlock(int x, int y, int z) {
int i = MainUtil.CACHE_I[y][x][z]; int i = y >> 4;
if (result == null) { if (result == null) {
return BukkitBlockUtil.get(chunkData.getType(x, y, z)); return BukkitBlockUtil.get(chunkData.getType(x, y, z));
} }
@ -177,7 +177,7 @@ public class GenChunk extends ScopedLocalBlockQueue {
if (array == null) { if (array == null) {
return BlockTypes.AIR.getDefaultState(); return BlockTypes.AIR.getDefaultState();
} }
int j = MainUtil.CACHE_J[y][x][z]; int j = ChunkUtil.getJ(x, y, z);
return array[j]; return array[j];
} }

View File

@ -45,7 +45,6 @@ import com.plotsquared.core.queue.ChunkBlockQueue;
import com.plotsquared.core.queue.GlobalBlockQueue; import com.plotsquared.core.queue.GlobalBlockQueue;
import com.plotsquared.core.queue.LocalBlockQueue; import com.plotsquared.core.queue.LocalBlockQueue;
import com.plotsquared.core.util.ChunkManager; import com.plotsquared.core.util.ChunkManager;
import com.plotsquared.core.util.MainUtil;
import com.plotsquared.core.util.MathMan; import com.plotsquared.core.util.MathMan;
import com.plotsquared.core.util.RegionManager; import com.plotsquared.core.util.RegionManager;
import com.plotsquared.core.util.RegionUtil; import com.plotsquared.core.util.RegionUtil;
@ -141,7 +140,6 @@ public class HybridUtils {
final int cbz = bz >> 4; final int cbz = bz >> 4;
final int ctx = tx >> 4; final int ctx = tx >> 4;
final int ctz = tz >> 4; final int ctz = tz >> 4;
MainUtil.initCache();
final int width = tx - bx + 1; final int width = tx - bx + 1;
final int length = tz - bz + 1; final int length = tz - bz + 1;
@ -251,7 +249,6 @@ public class HybridUtils {
whenDone.run(); whenDone.run();
}); });
System.gc(); System.gc();
MainUtil.initCache();
Location botLoc = Location.at(world, bot.getX(), bot.getY(), bot.getZ()); Location botLoc = Location.at(world, bot.getX(), bot.getY(), bot.getZ());
Location topLoc = Location.at(world, top.getX(), top.getY(), top.getZ()); Location topLoc = Location.at(world, top.getX(), top.getY(), top.getZ());
ChunkManager.chunkTask(botLoc, topLoc, new RunnableVal<int[]>() { ChunkManager.chunkTask(botLoc, topLoc, new RunnableVal<int[]>() {

View File

@ -0,0 +1,93 @@
package com.plotsquared.core.util;
import lombok.experimental.UtilityClass;
import org.jetbrains.annotations.Range;
/**
* This cache is used for world generation and just saves a bit of calculation time when checking if something is in the plot area.
*/
@UtilityClass
public class ChunkUtil {
/**
* Cache of mapping x,y,z coordinates to the chunk array<br>
* - Used for efficient world generation<br>
*/
private static short[] x_loc;
private static short[][] y_loc;
private static short[] z_loc;
private static short[][][] CACHE_J = null;
static {
x_loc = new short[4096];
y_loc = new short[16][4096];
z_loc = new short[4096];
for (int i = 0; i < 16; i++) {
int i4 = i << 4;
for (int j = 0; j < 4096; j++) {
int y = i4 + (j >> 8);
int a = j - ((y & 0xF) << 8);
int z1 = a >> 4;
int x1 = a - (z1 << 4);
x_loc[j] = (short) x1;
y_loc[i][j] = (short) y;
z_loc[j] = (short) z1;
}
}
CACHE_J = new short[256][16][16];
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
for (int y = 0; y < 256; y++) {
short j = (short) ((y & 0xF) << 8 | z << 4 | x);
CACHE_J[y][x][z] = j;
}
}
}
}
/**
* Get the J value for Chunk block storage from the chunk xyz coordinates.
* J is in the range 0 to 4095 where it represents a position in an array of 16x16x16 xyz (ChunkSection Array[4096]).
*
* @param x Relative x coordinate
* @param y Relative y coordinate
* @param z Relative z coordinate
* @return J value for xyz position in Array[4096].
*/
public static int getJ(@Range(from = 0, to = 15) int x, @Range(from = 0, to = 255) int y,
@Range(from = 0, to = 15) int z) {
return CACHE_J[y][x][z];
}
/**
* Gets the x coordinate for a specific J value for a ChunkSection 16x16x16 xyz Array[4096].
*
* @param j Position in the xyz Array[4096].
* @return x coordinate within the chunk
*/
public static int getX(@Range(from = 0, to = 4095) int j) {
return x_loc[j];
}
/**
* Gets the y coordinate for specific I and J values for a Chunk 16x16x16x16 layerxyz Array[16][4096].
*
* @param i Relative layer of the position in the layerxyz Array[16][4096].
* @param j Position in the xyz Array[4096].
* @return x coordinate within the chunk
*/
public static int getY(@Range(from = 0, to = 15) int i, @Range(from = 0, to = 4095) int j) {
return y_loc[i][j];
}
/**
* Gets the z coordinate for a specific J value for a ChunkSection 16x16x16 xyz Array[4096].
*
* @param j Position in the xyz Array[4096].
* @return z coordinate within the chunk
*/
public static int getZ(@Range(from = 0, to = 4095) int j) {
return z_loc[j];
}
}

View File

@ -1,37 +0,0 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.util;
import com.sk89q.worldedit.world.block.BlockState;
public abstract class LazyBlock {
public abstract BlockState getBlockState();
public String getId() {
return getBlockState().toString();
}
}

View File

@ -1,44 +0,0 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.util;
public abstract class LazyResult<T> {
private T result;
public T get() {
return this.result;
}
public T getOrCreate() {
if (this.result == null) {
return this.result = create();
}
return this.result;
}
public abstract T create();
}

View File

@ -25,9 +25,16 @@
*/ */
package com.plotsquared.core.util; package com.plotsquared.core.util;
import com.plotsquared.core.configuration.Caption;
import com.plotsquared.core.configuration.CaptionUtility;
import com.plotsquared.core.configuration.Captions;
import com.plotsquared.core.player.PlotPlayer;
import com.plotsquared.core.util.task.TaskManager;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import javax.annotation.Nonnull;
/** /**
* plot functions * plot functions
* @deprecated Do not use * @deprecated Do not use
@ -38,50 +45,80 @@ import org.slf4j.LoggerFactory;
LoggerFactory.getLogger("P2/" + MainUtil.class.getSimpleName()); LoggerFactory.getLogger("P2/" + MainUtil.class.getSimpleName());
/** /**
* Cache of mapping x,y,z coordinates to the chunk array<br> * Send a message to the player.
* - Used for efficient world generation<br> *
* @param player Player to receive message
* @param message Message to send
* @return true Can be used in things such as commands (return PlayerFunctions.sendMessage(...))
*/ */
public static short[][] x_loc; @Deprecated public static boolean sendMessage(PlotPlayer<?> player, String message) {
public static short[][] y_loc; return sendMessage(player, message, true);
public static short[][] z_loc; }
public static short[][][] CACHE_I = null;
public static short[][][] CACHE_J = null;
/** /**
* This cache is used for world generation and just saves a bit of calculation time when checking if something is in the plot area. * Send a message to console.
*
* @param caption
* @param args
*/ */
public static void initCache() { @Deprecated public static void sendConsoleMessage(Captions caption, String... args) {
if (x_loc == null) { sendMessage(null, caption, args);
x_loc = new short[16][4096]; }
y_loc = new short[16][4096];
z_loc = new short[16][4096]; /**
for (int i = 0; i < 16; i++) { * Send a message to a player.
int i4 = i << 4; *
for (int j = 0; j < 4096; j++) { * @param player Can be null to represent console, or use ConsolePlayer.getConsole()
int y = i4 + (j >> 8); * @param msg
int a = j - ((y & 0xF) << 8); * @param prefix If the message should be prefixed with the configured prefix
int z1 = a >> 4; * @return
int x1 = a - (z1 << 4); */
x_loc[i][j] = (short) x1; @Deprecated public static boolean sendMessage(PlotPlayer<?> player, @Nonnull String msg, boolean prefix) {
y_loc[i][j] = (short) y; if (!msg.isEmpty()) {
z_loc[i][j] = (short) z1; if (player == null) {
} String message = CaptionUtility
.format(null, (prefix ? Captions.PREFIX.getTranslated() : "") + msg);
logger.info(message);
} else {
player.sendMessage(CaptionUtility.format(player,
(prefix ? Captions.PREFIX.getTranslated() : "") + Captions.color(msg)));
} }
} }
if (CACHE_I == null) { return true;
CACHE_I = new short[256][16][16]; }
CACHE_J = new short[256][16][16];
for (int x = 0; x < 16; x++) { /**
for (int z = 0; z < 16; z++) { * Send a message to the player.
for (int y = 0; y < 256; y++) { *
short i = (short) (y >> 4); * @param player the recipient of the message
short j = (short) ((y & 0xF) << 8 | z << 4 | x); * @param caption the message to send
CACHE_I[y][x][z] = i; * @return boolean success
CACHE_J[y][x][z] = j; */
} @Deprecated public static boolean sendMessage(PlotPlayer<?> player, Caption caption, String... args) {
} return sendMessage(player, caption, (Object[]) args);
} }
/**
* Send a message to the player
*
* @param player the recipient of the message
* @param caption the message to send
* @return boolean success
*/
@Deprecated public static boolean sendMessage(final PlotPlayer<?> player, final Caption caption,
final Object... args) {
if (caption.getTranslated().isEmpty()) {
return true;
} }
TaskManager.runTaskAsync(() -> {
String m = CaptionUtility.format(player, caption, args);
if (player == null) {
logger.info(m);
} else {
player.sendMessage(m);
}
});
return true;
} }
} }

View File

@ -1,141 +0,0 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.util;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.plotsquared.core.location.Location;
import com.plotsquared.core.player.PlotPlayer;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.concurrent.Future;
import java.util.function.Consumer;
public class OperationUtil {
private static final boolean ASYNC;
static {
boolean hasFawe = true;
try {
Class.forName("com.boydti.fawe.Fawe");
} catch (ClassNotFoundException ignore) {
hasFawe = false;
}
ASYNC = hasFawe;
}
private static World getWorld(String worldName) {
Platform platform =
WorldEdit.getInstance().getPlatformManager().queryCapability(Capability.WORLD_EDITING);
List<? extends World> worlds = platform.getWorlds();
for (World current : worlds) {
if (current.getName().equals(worldName)) {
return current;
}
}
return null;
}
private static World getWorld(PlotPlayer plotPlayer, Actor actor) {
World weWorld;
if (actor instanceof Player) {
weWorld = ((Player) actor).getWorld();
} else {
@Nonnull Location loc = plotPlayer.getLocation();
String world = loc.getWorldName();
weWorld = getWorld(world);
}
return weWorld;
}
private static EditSession createEditSession(PlotPlayer plotPlayer) {
Actor actor = plotPlayer.toActor();
World weWorld = getWorld(plotPlayer, actor);
return createEditSession(weWorld, actor);
}
private static LocalSession getSession(Actor actor) {
return WorldEdit.getInstance().getSessionManager().get(actor);
}
private static EditSession createEditSession(World world, Actor actor) {
return createEditSession(world, actor, getSession(actor));
}
private static EditSession createEditSession(World world, Actor actor, LocalSession session) {
EditSession editSession;
Player player = actor.isPlayer() ? (Player) actor : null;
editSession =
WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, null, player);
editSession.setFastMode(!actor.isPlayer());
editSession.setReorderMode(EditSession.ReorderMode.FAST);
return editSession;
}
public Future<?> withEditSession(@Nonnull PlotPlayer plotPlayer,
@Nonnull Consumer<EditSession> consumer, @Nullable Consumer<Throwable> exceptionHandler) {
if (ASYNC) {
ListeningExecutorService exec = WorldEdit.getInstance().getExecutorService();
return exec
.submit(() -> withEditSessionOnThread(plotPlayer, consumer, exceptionHandler));
} else {
withEditSessionOnThread(plotPlayer, consumer, exceptionHandler);
}
return Futures.immediateFuture(true);
}
private void withEditSessionOnThread(PlotPlayer plotPlayer, Consumer<EditSession> consumer,
Consumer<Throwable> exceptionHandler) {
Actor actor = plotPlayer.toActor();
World weWorld = getWorld(plotPlayer, actor);
LocalSession session = getSession(actor);
try (EditSession ess = createEditSession(weWorld, actor, session)) {
try {
consumer.accept(ess);
} finally {
ess.close();
session.remember(ess);
}
} catch (Throwable e) {
if (exceptionHandler != null) {
exceptionHandler.accept(e);
} else {
e.printStackTrace();
}
}
}
}

View File

@ -1,54 +0,0 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.util;
public class PseudoRandom {
public static final PseudoRandom random = new PseudoRandom();
public long state = System.nanoTime();
public long nextLong() {
long a = this.state;
this.state = xorShift64(a);
return a;
}
public long xorShift64(long a) {
a ^= a << 21;
a ^= a >>> 35;
a ^= a << 4;
return a;
}
public int random(int n) {
if (n == 1) {
return 0;
}
long r = ((nextLong() >>> 32) * n) >> 32;
return (int) r;
}
}

View File

@ -1,97 +0,0 @@
/*
* _____ _ _ _____ _
* | __ \| | | | / ____| | |
* | |__) | | ___ | |_| (___ __ _ _ _ __ _ _ __ ___ __| |
* | ___/| |/ _ \| __|\___ \ / _` | | | |/ _` | '__/ _ \/ _` |
* | | | | (_) | |_ ____) | (_| | |_| | (_| | | | __/ (_| |
* |_| |_|\___/ \__|_____/ \__, |\__,_|\__,_|_| \___|\__,_|
* | |
* |_|
* PlotSquared plot management system for Minecraft
* Copyright (C) 2020 IntellectualSites
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.plotsquared.core.util;
/**
*
*/
public class StringWrapper {
public final String value;
private int hash;
/**
* Constructor
*
* @param value to wrap
*/
public StringWrapper(String value) {
this.value = value;
}
/**
* Check if a wrapped string equals another one
*
* @param obj to compare
* @return true if obj equals the stored value
*/
@Override public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
if (obj.getClass() == String.class) {
return obj.toString().equalsIgnoreCase(this.value);
}
return false;
}
if (obj.hashCode() != hashCode()) {
return false;
}
StringWrapper other = (StringWrapper) obj;
if ((other.value == null) || (this.value == null)) {
return false;
}
return other.value.equalsIgnoreCase(this.value);
}
/**
* Get the string value.
*
* @return string value
*/
@Override public String toString() {
return this.value;
}
/**
* Get the hash value.
*
* @return has value
*/
@Override public int hashCode() {
if (this.value == null) {
return 0;
}
if (this.hash == 0) {
this.hash = this.value.toLowerCase().hashCode();
}
return this.hash;
}
}