changed namespace to com.massivecraft

This commit is contained in:
Olof Larsson
2011-07-18 22:06:02 +02:00
parent 60603892c6
commit 8aefae5679
151 changed files with 988 additions and 949 deletions

View File

@ -0,0 +1,346 @@
package com.massivecraft.factions;
import java.io.*;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
import org.bukkit.ChatColor;
import com.massivecraft.factions.gson.JsonArray;
import com.massivecraft.factions.gson.JsonElement;
import com.massivecraft.factions.gson.JsonObject;
import com.massivecraft.factions.gson.JsonParser;
import com.massivecraft.factions.gson.reflect.TypeToken;
import com.massivecraft.factions.util.AsciiCompass;
import com.massivecraft.factions.util.DiscUtil;
import com.massivecraft.factions.util.TextUtil;
public class Board {
private static transient File file = new File(Factions.instance.getDataFolder(), "board.json");
private static transient HashMap<FLocation, Integer> flocationIds = new HashMap<FLocation, Integer>();
//----------------------------------------------//
// Get and Set
//----------------------------------------------//
public static int getIdAt(FLocation flocation) {
if ( ! flocationIds.containsKey(flocation)) {
return 0;
}
return flocationIds.get(flocation);
}
public static Faction getFactionAt(FLocation flocation) {
return Faction.get(getIdAt(flocation));
}
public static void setIdAt(int id, FLocation flocation) {
if (id == 0) {
removeAt(flocation);
}
flocationIds.put(flocation, id);
}
public static void setFactionAt(Faction faction, FLocation flocation) {
setIdAt(faction.getId(), flocation);
}
public static void removeAt(FLocation flocation) {
flocationIds.remove(flocation);
}
public static void unclaimAll(int factionId) {
Iterator<Entry<FLocation, Integer>> iter = flocationIds.entrySet().iterator();
while (iter.hasNext()) {
Entry<FLocation, Integer> entry = iter.next();
if (entry.getValue().equals(factionId)) {
iter.remove();
}
}
}
// Is this coord NOT completely surrounded by coords claimed by the same faction?
// Simpler: Is there any nearby coord with a faction other than the faction here?
public static boolean isBorderLocation(FLocation flocation) {
Faction faction = getFactionAt(flocation);
FLocation a = flocation.getRelative(1, 0);
FLocation b = flocation.getRelative(-1, 0);
FLocation c = flocation.getRelative(0, 1);
FLocation d = flocation.getRelative(0, -1);
return faction != getFactionAt(a) || faction != getFactionAt(b) || faction != getFactionAt(c) || faction != getFactionAt(d);
}
// Is this coord connected to any coord claimed by the specified faction?
public static boolean isConnectedLocation(FLocation flocation, Faction faction) {
FLocation a = flocation.getRelative(1, 0);
FLocation b = flocation.getRelative(-1, 0);
FLocation c = flocation.getRelative(0, 1);
FLocation d = flocation.getRelative(0, -1);
return faction == getFactionAt(a) || faction == getFactionAt(b) || faction == getFactionAt(c) || faction == getFactionAt(d);
}
//----------------------------------------------//
// Cleaner. Remove orphaned foreign keys
//----------------------------------------------//
public static void clean() {
Iterator<Entry<FLocation, Integer>> iter = flocationIds.entrySet().iterator();
while (iter.hasNext()) {
Entry<FLocation, Integer> entry = iter.next();
if ( ! Faction.exists(entry.getValue())) {
Factions.log("Board cleaner removed "+entry.getValue()+" from "+entry.getKey());
iter.remove();
}
}
}
//----------------------------------------------//
// Coord count
//----------------------------------------------//
public static int getFactionCoordCount(int factionId) {
int ret = 0;
for (int thatFactionId : flocationIds.values()) {
if(thatFactionId == factionId) {
ret += 1;
}
}
return ret;
}
public static int getFactionCoordCount(Faction faction) {
return getFactionCoordCount(faction.getId());
}
public static int getFactionCoordCountInWorld(Faction faction, String worldName) {
int factionId = faction.getId();
int ret = 0;
Iterator<Entry<FLocation, Integer>> iter = flocationIds.entrySet().iterator();
while (iter.hasNext()) {
Entry<FLocation, Integer> entry = iter.next();
if (entry.getValue() == factionId && entry.getKey().getWorldName().equals(worldName)) {
ret += 1;
}
}
return ret;
}
//----------------------------------------------//
// Map generation
//----------------------------------------------//
/**
* The map is relative to a coord and a faction
* north is in the direction of decreasing x
* east is in the direction of decreasing z
*/
public static ArrayList<String> getMap(Faction faction, FLocation flocation, double inDegrees) {
ArrayList<String> ret = new ArrayList<String>();
ret.add(TextUtil.titleize("("+flocation.getCoordString()+") "+getFactionAt(flocation).getTag(faction)));
int halfWidth = Conf.mapWidth / 2;
int halfHeight = Conf.mapHeight / 2;
FLocation topLeft = flocation.getRelative(-halfHeight, halfWidth);
int width = halfWidth * 2 + 1;
int height = halfHeight * 2 + 1;
if (Conf.showMapFactionKey) {
height--;
}
Map<String, Character> fList = new HashMap<String, Character>();
int chrIdx = 0;
// For each row
for (int dx = 0; dx < height; dx++) {
// Draw and add that row
String row = "";
for (int dz = 0; dz > -width; dz--) {
if(dz == -(halfWidth) && dx == halfHeight) {
row += ChatColor.AQUA+"+";
} else {
FLocation flocationHere = topLeft.getRelative(dx, dz);
Faction factionHere = getFactionAt(flocationHere);
if (factionHere.isNone()) {
row += ChatColor.GRAY+"-";
} else if (factionHere.isSafeZone()) {
row += ChatColor.GOLD+"+";
} else if (factionHere.isWarZone()) {
row += ChatColor.DARK_RED+"+";
} else {
if (!fList.containsKey(factionHere.getTag()))
fList.put(factionHere.getTag(), Conf.mapKeyChrs[chrIdx++]);
char tag = fList.get(factionHere.getTag());
row += factionHere.getRelation(faction).getColor() + "" + tag;
}
}
}
ret.add(row);
}
// Get the compass
ArrayList<String> asciiCompass = AsciiCompass.getAsciiCompass(inDegrees, ChatColor.RED, Conf.colorChrome);
// Add the compass
ret.set(1, asciiCompass.get(0)+ret.get(1).substring(3*3));
ret.set(2, asciiCompass.get(1)+ret.get(2).substring(3*3));
ret.set(3, asciiCompass.get(2)+ret.get(3).substring(3*3));
// Add the faction key
if (Conf.showMapFactionKey) {
String fRow = "";
for(String key : fList.keySet()) {
fRow += String.format("%s%s: %s ", ChatColor.GRAY, fList.get(key), key);
}
ret.add(fRow);
}
return ret;
}
// -------------------------------------------- //
// Persistance
// -------------------------------------------- //
public static Map<String,Map<String,Integer>> dumpAsSaveFormat() {
Map<String,Map<String,Integer>> worldCoordIds = new HashMap<String,Map<String,Integer>>();
for (Entry<FLocation, Integer> entry : flocationIds.entrySet()) {
String worldName = entry.getKey().getWorldName();
String coords = entry.getKey().getCoordString();
Integer id = entry.getValue();
if ( ! worldCoordIds.containsKey(worldName)) {
worldCoordIds.put(worldName, new TreeMap<String,Integer>());
}
worldCoordIds.get(worldName).put(coords, id);
}
return worldCoordIds;
}
public static void loadFromSaveFormat(Map<String,Map<String,Integer>> worldCoordIds) {
flocationIds.clear();
for (Entry<String,Map<String,Integer>> entry : worldCoordIds.entrySet()) {
String worldName = entry.getKey();
for (Entry<String,Integer> entry2 : entry.getValue().entrySet()) {
String[] coords = entry2.getKey().trim().split("[,\\s]+");
int x = Integer.parseInt(coords[0]);
int z = Integer.parseInt(coords[1]);
int factionId = entry2.getValue();
flocationIds.put(new FLocation(worldName, x, z), factionId);
}
}
}
public static boolean save() {
//Factions.log("Saving board to disk");
try {
DiscUtil.write(file, Factions.gson.toJson(dumpAsSaveFormat()));
} catch (Exception e) {
e.printStackTrace();
Factions.log("Failed to save the board to disk.");
return false;
}
return true;
}
public static boolean load() {
Factions.log("Loading board from disk");
if ( ! file.exists()) {
if ( ! loadOld())
Factions.log("No board to load from disk. Creating new file.");
save();
return true;
}
try {
Type type = new TypeToken<Map<String,Map<String,Integer>>>(){}.getType();
Map<String,Map<String,Integer>> worldCoordIds = Factions.gson.fromJson(DiscUtil.read(file), type);
loadFromSaveFormat(worldCoordIds);
} catch (Exception e) {
e.printStackTrace();
Factions.log("Failed to load the board from disk.");
return false;
}
return true;
}
private static boolean loadOld() {
File folderBoard = new File(Factions.instance.getDataFolder(), "board");
if ( ! folderBoard.isDirectory())
return false;
Factions.log("Board file doesn't exist, attempting to load old pre-1.1 data.");
String ext = ".json";
class jsonFileFilter implements FileFilter {
@Override
public boolean accept(File file) {
return (file.getName().toLowerCase().endsWith(".json") && file.isFile());
}
}
File[] jsonFiles = folderBoard.listFiles(new jsonFileFilter());
for (File jsonFile : jsonFiles) {
// Extract the name from the filename. The name is filename minus ".json"
String name = jsonFile.getName();
name = name.substring(0, name.length() - ext.length());
try {
JsonParser parser = new JsonParser();
JsonObject json = (JsonObject) parser.parse(DiscUtil.read(jsonFile));
JsonArray coords = json.getAsJsonArray("coordFactionIds");
Iterator<JsonElement> coordSet = coords.iterator();
while(coordSet.hasNext()) {
JsonArray coordDat = (JsonArray) coordSet.next();
JsonObject coord = coordDat.get(0).getAsJsonObject();
int coordX = coord.get("x").getAsInt();
int coordZ = coord.get("z").getAsInt();
int factionId = coordDat.get(1).getAsInt();
flocationIds.put(new FLocation(name, coordX, coordZ), factionId);
}
Factions.log("loaded pre-1.1 board "+name);
} catch (Exception e) {
e.printStackTrace();
Factions.log(Level.WARNING, "failed to load board "+name);
}
}
return true;
}
}

View File

@ -0,0 +1,202 @@
package com.massivecraft.factions;
import java.io.File;
import java.util.*;
import org.bukkit.*;
import org.bukkit.entity.CreatureType;
import com.massivecraft.factions.util.DiscUtil;
public class Conf {
public static final transient File file = new File(Factions.instance.getDataFolder(), "conf.json");
// Colors
public static ChatColor colorMember = ChatColor.GREEN;
public static ChatColor colorAlly = ChatColor.LIGHT_PURPLE;
public static ChatColor colorNeutral = ChatColor.WHITE;
public static ChatColor colorEnemy = ChatColor.RED;
public static ChatColor colorSystem = ChatColor.YELLOW;
public static ChatColor colorChrome = ChatColor.GOLD;
public static ChatColor colorCommand = ChatColor.AQUA;
public static ChatColor colorParameter = ChatColor.DARK_AQUA;
// Power
public static double powerPlayerMax = 10;
public static double powerPlayerMin = -10;
public static double powerPerMinute = 0.2; // Default health rate... it takes 5 min to heal one power
public static double powerPerDeath = 4; // A death makes you lose 4 power
public static boolean powerRegenOffline = false; // does player power regenerate even while they're offline?
public static String prefixAdmin = "**";
public static String prefixMod = "*";
public static int factionTagLengthMin = 3;
public static int factionTagLengthMax = 10;
public static boolean factionTagForceUpperCase = false;
public static boolean newFactionsDefaultOpen = true;
public static boolean showMapFactionKey = true;
// Disallow joining/leaving/kicking while power is negative
public static boolean CanLeaveWithNegativePower = true;
// Configuration on the Faction tag in chat messages.
public static boolean chatTagEnabled = true;
public static transient boolean chatTagHandledByAnotherPlugin = false;
public static boolean chatTagRelationColored = true;
public static String chatTagReplaceString = "{FACTION}";
public static String chatTagInsertAfterString = "";
public static String chatTagInsertBeforeString = "";
public static int chatTagInsertIndex = 1;
public static boolean chatTagPadBefore = false;
public static boolean chatTagPadAfter = true;
public static String chatTagFormat = "%s"+ChatColor.WHITE;
public static String factionChatFormat = "%s"+ChatColor.WHITE+" %s";
public static boolean allowNoSlashCommand = true;
public static double autoLeaveAfterDaysOfInactivity = 14;
public static boolean homesEnabled = true;
public static boolean homesMustBeInClaimedTerritory = true;
public static boolean homesTeleportToOnDeath = true;
public static boolean homesRespawnFromNoPowerLossWorlds = true;
public static boolean homesTeleportCommandEnabled = true;
public static boolean homesTeleportAllowedFromEnemyTerritory = true;
public static boolean homesTeleportAllowedFromDifferentWorld = true;
public static double homesTeleportAllowedEnemyDistance = 32;
public static boolean disablePVPForFactionlessPlayers = false;
public static int noPVPDamageToOthersForXSecondsAfterLogin = 3;
public static boolean claimsMustBeConnected = false;
public static double considerFactionsReallyOfflineAfterXMinutes = 0;
public static double territoryShieldFactor = 0.3;
public static boolean territoryDenyBuild = true;
public static boolean territoryDenyBuildWhenOffline = true;
public static boolean territoryDenyUseage = true;
public static boolean territoryEnemyDenyBuild = true;
public static boolean territoryEnemyDenyBuildWhenOffline = true;
public static boolean territoryEnemyDenyUseage = true;
public static boolean territoryEnemyProtectMaterials = true;
public static boolean territoryBlockCreepers = false;
public static boolean territoryBlockCreepersWhenOffline = false;
public static boolean territoryBlockFireballs = false;
public static boolean territoryBlockFireballsWhenOffline = false;
public static boolean territoryBlockTNT = false;
public static boolean territoryBlockTNTWhenOffline = false;
public static boolean safeZoneDenyBuild = true;
public static boolean safeZoneDenyUseage = true;
public static boolean safeZoneBlockTNT = true;
public static boolean warZoneDenyBuild = true;
public static boolean warZoneDenyUseage = true;
public static boolean warZoneBlockCreepers = false;
public static boolean warZoneBlockFireballs = false;
public static boolean warZoneBlockTNT = true;
public static boolean warZonePowerLoss = true;
public static boolean warZoneFriendlyFire = false;
public static boolean wildernessDenyBuild = false;
public static boolean wildernessDenyUseage = false;
public static boolean wildernessBlockCreepers = false;
public static boolean wildernessBlockFireballs = false;
public static boolean wildernessBlockTNT = false;
public static boolean wildernessPowerLoss = true;
public static Set<Material> territoryProtectedMaterials = EnumSet.noneOf(Material.class);
public static Set<Material> territoryDenyUseageMaterials = EnumSet.noneOf(Material.class);
public static Set<Material> territoryProtectedMaterialsWhenOffline = EnumSet.noneOf(Material.class);
public static Set<Material> territoryDenyUseageMaterialsWhenOffline = EnumSet.noneOf(Material.class);
public static transient Set<CreatureType> safeZoneNerfedCreatureTypes = EnumSet.noneOf(CreatureType.class);
public static Set<String> worldsNoClaiming = new HashSet<String>();
public static Set<String> worldsNoPowerLoss = new HashSet<String>();
public static transient int mapHeight = 8;
public static transient int mapWidth = 39;
public static transient char[] mapKeyChrs = "\\/#?$%=&^ABCDEFGHJKLMNOPQRSTUVWXYZ1234567890abcdeghjmnopqrsuvwxyz".toCharArray();
static {
territoryProtectedMaterials.add(Material.WOODEN_DOOR);
territoryProtectedMaterials.add(Material.TRAP_DOOR);
territoryProtectedMaterials.add(Material.DISPENSER);
territoryProtectedMaterials.add(Material.CHEST);
territoryProtectedMaterials.add(Material.FURNACE);
territoryProtectedMaterials.add(Material.BURNING_FURNACE);
territoryDenyUseageMaterials.add(Material.FLINT_AND_STEEL);
territoryDenyUseageMaterials.add(Material.BUCKET);
territoryDenyUseageMaterials.add(Material.WATER_BUCKET);
territoryDenyUseageMaterials.add(Material.LAVA_BUCKET);
territoryProtectedMaterialsWhenOffline.add(Material.WOODEN_DOOR);
territoryProtectedMaterialsWhenOffline.add(Material.TRAP_DOOR);
territoryProtectedMaterialsWhenOffline.add(Material.DISPENSER);
territoryProtectedMaterialsWhenOffline.add(Material.CHEST);
territoryProtectedMaterialsWhenOffline.add(Material.FURNACE);
territoryProtectedMaterialsWhenOffline.add(Material.BURNING_FURNACE);
territoryDenyUseageMaterialsWhenOffline.add(Material.FLINT_AND_STEEL);
territoryDenyUseageMaterialsWhenOffline.add(Material.BUCKET);
territoryDenyUseageMaterialsWhenOffline.add(Material.WATER_BUCKET);
territoryDenyUseageMaterialsWhenOffline.add(Material.LAVA_BUCKET);
safeZoneNerfedCreatureTypes.add(CreatureType.CREEPER);
safeZoneNerfedCreatureTypes.add(CreatureType.GHAST);
safeZoneNerfedCreatureTypes.add(CreatureType.PIG_ZOMBIE);
safeZoneNerfedCreatureTypes.add(CreatureType.SKELETON);
safeZoneNerfedCreatureTypes.add(CreatureType.SPIDER);
safeZoneNerfedCreatureTypes.add(CreatureType.SLIME);
safeZoneNerfedCreatureTypes.add(CreatureType.ZOMBIE);
}
// track players with admin access who have enabled "admin bypass" mode, and should therefore be able to build anywhere
// not worth saving between server restarts, I think
public static transient Set<String> adminBypassPlayers = Collections.synchronizedSet(new HashSet<String>());
// -------------------------------------------- //
// Persistance
// -------------------------------------------- //
public static boolean save() {
//Factions.log("Saving config to disk.");
try {
DiscUtil.write(file, Factions.gson.toJson(new Conf()));
} catch (Exception e) {
e.printStackTrace();
Factions.log("Failed to save the config to disk.");
return false;
}
return true;
}
public static boolean load() {
Factions.log("Loading conf from disk");
if ( ! file.exists()) {
Factions.log("No conf to load from disk. Creating new file.");
save();
return true;
}
try {
Factions.gson.fromJson(DiscUtil.read(file), Conf.class);
} catch (Exception e) {
e.printStackTrace();
Factions.log("Failed to load the config from disk.");
return false;
}
return true;
}
}

View File

@ -0,0 +1,128 @@
package com.massivecraft.factions;
import java.util.HashSet;
import org.bukkit.Location;
import org.bukkit.block.Block;
import org.bukkit.entity.Player;
import com.massivecraft.factions.util.MiscUtil;
public class FLocation {
private String worldName = "world";
private int x = 0;
private int z = 0;
private final static transient double cellSize = 16;
//----------------------------------------------//
// Constructors
//----------------------------------------------//
public FLocation() {
}
public FLocation(String worldName, int x, int z) {
this.worldName = worldName;
this.x = x;
this.z = z;
}
public FLocation(Location location) {
this(location.getWorld().getName(), (int) Math.floor(location.getX() / cellSize) , (int) Math.floor(location.getZ() / cellSize));
}
public FLocation(Player player) {
this(player.getLocation());
}
public FLocation(FPlayer fplayer) {
this(fplayer.getPlayer());
}
public FLocation(Block block) {
this(block.getLocation());
}
//----------------------------------------------//
// Getters and Setters
//----------------------------------------------//
public String getWorldName() {
return worldName;
}
public void setWorldName(String worldName) {
this.worldName = worldName;
}
public long getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public long getZ() {
return z;
}
public void setZ(int z) {
this.z = z;
}
public String getCoordString() {
return ""+x+","+z;
}
@Override
public String toString() {
return "["+this.getWorldName()+","+this.getCoordString()+"]";
}
//----------------------------------------------//
// Misc Geometry
//----------------------------------------------//
public FLocation getRelative(int dx, int dz) {
return new FLocation(this.worldName, this.x + dx, this.z + dz);
}
public static HashSet<FLocation> getArea(FLocation from, FLocation to) {
HashSet<FLocation> ret = new HashSet<FLocation>();
for (long x : MiscUtil.range(from.getX(), to.getX())) {
for (long z : MiscUtil.range(from.getZ(), to.getZ())) {
ret.add(new FLocation(from.getWorldName(), (int)x, (int)z));
}
}
return ret;
}
//----------------------------------------------//
// Comparison
//----------------------------------------------//
public int hashCode() {
int hash = 3;
hash = 19 * hash + (this.worldName != null ? this.worldName.hashCode() : 0);
hash = 19 * hash + this.x;
hash = 19 * hash + this.z;
return hash;
};
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (!(obj instanceof FLocation))
return false;
FLocation that = (FLocation) obj;
return this.x == that.x && this.z == that.z && ( this.worldName==null ? that.worldName==null : this.worldName.equals(that.worldName) );
}
}

View File

@ -0,0 +1,708 @@
package com.massivecraft.factions;
import java.io.*;
import java.lang.reflect.Type;
import java.util.*;
import java.util.logging.Level;
import java.util.Map.Entry;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import com.massivecraft.factions.gson.reflect.TypeToken;
import com.massivecraft.factions.struct.Relation;
import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.DiscUtil;
/**
* Logged in players always have exactly one FPlayer instance.
* Logged out players may or may not have an FPlayer instance. They will always have one if they are part of a faction.
* This is because only players with a faction are saved to disk (in order to not waste disk space).
*
* The FPlayer is linked to a minecraft player using the player name.
*
* The same instance is always returned for the same player.
* This means you can use the == operator. No .equals method necessary.
*/
public class FPlayer {
// -------------------------------------------- //
// Fields
// -------------------------------------------- //
private static transient TreeMap<String, FPlayer> instances = new TreeMap<String, FPlayer>(String.CASE_INSENSITIVE_ORDER);
private static transient File file = new File(Factions.instance.getDataFolder(), "players.json");
private transient String playerName;
private transient FLocation lastStoodAt = new FLocation(); // Where did this player stand the last time we checked?
private int factionId;
private Role role;
private String title;
private double power;
private long lastPowerUpdateTime;
private long lastLoginTime;
private transient boolean mapAutoUpdating;
private transient boolean autoClaimEnabled;
private transient boolean autoSafeZoneEnabled;
private transient boolean autoWarZoneEnabled;
private transient boolean loginPvpDisabled;
private boolean factionChatting;
// -------------------------------------------- //
// Construct
// -------------------------------------------- //
// GSON need this noarg constructor.
public FPlayer() {
this.resetFactionData();
this.power = this.getPowerMax();
this.lastPowerUpdateTime = System.currentTimeMillis();
this.lastLoginTime = System.currentTimeMillis();
this.mapAutoUpdating = false;
this.autoClaimEnabled = false;
this.autoSafeZoneEnabled = false;
this.autoWarZoneEnabled = false;
this.loginPvpDisabled = (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) ? true : false;
}
public void resetFactionData() {
this.factionId = 0; // The default neutral faction
this.factionChatting = false;
this.role = Role.NORMAL;
this.title = "";
}
// -------------------------------------------- //
// Minecraft Player
// -------------------------------------------- //
public Player getPlayer() {
return Factions.instance.getServer().getPlayer(playerName);
}
public String getPlayerName() {
return this.playerName;
}
public boolean isOnline() {
return Factions.instance.getServer().getPlayer(playerName) != null;
}
public boolean isOffline() {
return ! isOnline();
}
// -------------------------------------------- //
// Getters And Setters
// -------------------------------------------- //
public Faction getFaction() {
return Faction.get(factionId);
}
private int getFactionId() {
return factionId;
}
public void setFaction(Faction faction) {
this.factionId = faction.getId();
}
public boolean hasFaction() {
return factionId != 0;
}
public Role getRole() {
return this.role;
}
public void setRole(Role role) {
this.role = role;
}
public boolean isFactionChatting() {
if (this.factionId == 0) {
return false;
}
return factionChatting;
}
public void setFactionChatting(boolean factionChatting) {
this.factionChatting = factionChatting;
}
public long getLastLoginTime() {
return lastLoginTime;
}
public boolean autoClaimEnabled() {
if (this.factionId == 0)
return false;
return autoClaimEnabled;
}
public void enableAutoClaim(boolean enabled) {
this.autoClaimEnabled = enabled;
if (enabled) {
this.autoSafeZoneEnabled = false;
this.autoWarZoneEnabled = false;
}
}
public boolean autoSafeZoneEnabled() {
return autoSafeZoneEnabled;
}
public void enableAutoSafeZone(boolean enabled) {
this.autoSafeZoneEnabled = enabled;
if (enabled) {
this.autoClaimEnabled = false;
this.autoWarZoneEnabled = false;
}
}
public boolean autoWarZoneEnabled() {
return autoWarZoneEnabled;
}
public void enableAutoWarZone(boolean enabled) {
this.autoWarZoneEnabled = enabled;
if (enabled) {
this.autoClaimEnabled = false;
this.autoSafeZoneEnabled = false;
}
}
public void setLastLoginTime(long lastLoginTime) {
this.lastLoginTime = lastLoginTime;
this.lastPowerUpdateTime = lastLoginTime;
if (Conf.noPVPDamageToOthersForXSecondsAfterLogin > 0) {
this.loginPvpDisabled = true;
}
}
public boolean isMapAutoUpdating() {
return mapAutoUpdating;
}
public void setMapAutoUpdating(boolean mapAutoUpdating) {
this.mapAutoUpdating = mapAutoUpdating;
}
public boolean hasLoginPvpDisabled() {
if (!loginPvpDisabled) {
return false;
}
if (this.lastLoginTime + (Conf.noPVPDamageToOthersForXSecondsAfterLogin * 1000) < System.currentTimeMillis()) {
this.loginPvpDisabled = false;
return false;
}
return true;
}
public FLocation getLastStoodAt() {
return this.lastStoodAt;
}
public void setLastStoodAt(FLocation flocation) {
this.lastStoodAt = flocation;
}
//----------------------------------------------//
// Title, Name, Faction Tag and Chat
//----------------------------------------------//
// Base:
public String getTitle() {
return this.title;
}
public void setTitle(String title) {
this.title = title;
}
public String getName() {
return this.playerName;
}
public String getTag() {
if ( ! this.hasFaction()) {
return "";
}
return this.getFaction().getTag();
}
// Base concatenations:
public String getNameAndSomething(String something) {
String ret = this.role.getPrefix();
if (something.length() > 0) {
ret += something+" ";
}
ret += this.getName();
return ret;
}
public String getNameAndTitle() {
return this.getNameAndSomething(this.getTitle());
}
public String getNameAndTag() {
return this.getNameAndSomething(this.getTag());
}
// Colored concatenations:
// These are used in information messages
public String getNameAndTitle(Faction faction) {
return this.getRelationColor(faction)+this.getNameAndTitle();
}
public String getNameAndTitle(FPlayer fplayer) {
return this.getRelationColor(fplayer)+this.getNameAndTitle();
}
public String getNameAndTag(Faction faction) {
return this.getRelationColor(faction)+this.getNameAndTag();
}
public String getNameAndTag(FPlayer fplayer) {
return this.getRelationColor(fplayer)+this.getNameAndTag();
}
public String getNameAndRelevant(Faction faction) {
// Which relation?
Relation rel = this.getRelation(faction);
// For member we show title
if (rel == Relation.MEMBER) {
return rel.getColor() + this.getNameAndTitle();
}
// For non members we show tag
return rel.getColor() + this.getNameAndTag();
}
public String getNameAndRelevant(FPlayer fplayer) {
return getNameAndRelevant(fplayer.getFaction());
}
// Chat Tag:
// These are injected into the format of global chat messages.
public String getChatTag() {
if ( ! this.hasFaction()) {
return "";
}
return String.format(Conf.chatTagFormat, this.role.getPrefix()+this.getTag());
}
// Colored Chat Tag
public String getChatTag(Faction faction) {
if ( ! this.hasFaction()) {
return "";
}
return this.getRelation(faction).getColor()+getChatTag();
}
public String getChatTag(FPlayer fplayer) {
if ( ! this.hasFaction()) {
return "";
}
return this.getRelation(fplayer).getColor()+getChatTag();
}
// -------------------------------
// Relation and relation colors
// -------------------------------
public Relation getRelation(Faction faction) {
return faction.getRelation(this);
}
public Relation getRelation(FPlayer fplayer) {
return this.getFaction().getRelation(fplayer);
}
public ChatColor getRelationColor(Faction faction) {
return faction.getRelationColor(this);
}
public ChatColor getRelationColor(FPlayer fplayer) {
return this.getRelation(fplayer).getColor();
}
//----------------------------------------------//
// Health
//----------------------------------------------//
public void heal(int amnt) {
Player player = this.getPlayer();
if (player == null) {
return;
}
player.setHealth(player.getHealth() + amnt);
}
//----------------------------------------------//
// Power
//----------------------------------------------//
public double getPower() {
this.updatePower();
return this.power;
}
protected void alterPower(double delta) {
this.power += delta;
if (this.power > this.getPowerMax()) {
this.power = this.getPowerMax();
} else if (this.power < this.getPowerMin()) {
this.power = this.getPowerMin();
}
//Log.debug("Power of "+this.getName()+" is now: "+this.power);
}
public double getPowerMax() {
return Conf.powerPlayerMax;
}
public double getPowerMin() {
return Conf.powerPlayerMin;
}
public int getPowerRounded() {
return (int) Math.round(this.getPower());
}
public int getPowerMaxRounded() {
return (int) Math.round(this.getPowerMax());
}
public int getPowerMinRounded() {
return (int) Math.round(this.getPowerMin());
}
protected void updatePower() {
if (this.isOffline() && !Conf.powerRegenOffline) {
return;
}
long now = System.currentTimeMillis();
long millisPassed = now - this.lastPowerUpdateTime;
this.lastPowerUpdateTime = now;
int millisPerMinute = 60*1000;
this.alterPower(millisPassed * Conf.powerPerMinute / millisPerMinute);
}
public void onDeath() {
this.updatePower();
this.alterPower(-Conf.powerPerDeath);
}
//----------------------------------------------//
// Territory
//----------------------------------------------//
public boolean isInOwnTerritory() {
return Board.getFactionAt(new FLocation(this)) == this.getFaction();
}
public boolean isInOthersTerritory() {
int idHere = Board.getIdAt(new FLocation(this));
return idHere > 0 && idHere != this.factionId;
}
public boolean isInEnemyTerritory() {
return Board.getFactionAt(new FLocation(this)).getRelation(this) == Relation.ENEMY;
}
public void sendFactionHereMessage() {
Faction factionHere = Board.getFactionAt(new FLocation(this));
String msg = Conf.colorSystem+" ~ "+factionHere.getTag(this);
if (factionHere.getDescription().length() > 0) {
msg += " - "+factionHere.getDescription();
}
this.sendMessage(msg);
}
// -------------------------------
// Actions
// -------------------------------
public void leave() {
Faction myFaction = this.getFaction();
if (this.getRole() == Role.ADMIN && myFaction.getFPlayers().size() > 1) {
sendMessage("You must give the admin role to someone else first.");
return;
}
if (!Conf.CanLeaveWithNegativePower && this.getPower() < 0) {
sendMessage("You cannot leave until your power is positive.");
return;
}
if (myFaction.isNormal()) {
myFaction.sendMessage(this.getNameAndRelevant(myFaction) + Conf.colorSystem + " left your faction.");
}
this.resetFactionData();
if (myFaction.isNormal() && myFaction.getFPlayers().size() == 0) {
// Remove this faction
for (FPlayer fplayer : FPlayer.getAllOnline()) {
fplayer.sendMessage("The faction "+myFaction.getTag(fplayer)+Conf.colorSystem+" was disbanded.");
}
Faction.delete(myFaction.getId());
}
}
public boolean attemptClaim(boolean notifyFailure) {
// notifyFailure is false if called by auto-claim; not need to notify on every failure for it
// return value is false on failure, true on success
Faction myFaction = getFaction();
FLocation flocation = new FLocation(this);
Faction otherFaction = Board.getFactionAt(flocation);
if (myFaction == otherFaction) {
if (notifyFailure)
sendMessage("You already own this land.");
return false;
}
if (this.getRole().value < Role.MODERATOR.value) {
sendMessage("You must be "+Role.MODERATOR+" to claim land.");
return false;
}
if (Conf.worldsNoClaiming.contains(flocation.getWorldName())) {
sendMessage("Sorry, this world has land claiming disabled.");
return false;
}
if (otherFaction.isSafeZone()) {
if (notifyFailure)
sendMessage("You can not claim a Safe Zone.");
return false;
}
else if (otherFaction.isWarZone()) {
if (notifyFailure)
sendMessage("You can not claim a War Zone.");
return false;
}
if (myFaction.getLandRounded() >= myFaction.getPowerRounded()) {
sendMessage("You can't claim more land! You need more power!");
return false;
}
if (otherFaction.getRelation(this) == Relation.ALLY) {
if (notifyFailure)
sendMessage("You can't claim the land of your allies.");
return false;
}
if (Conf.claimsMustBeConnected && myFaction.getLandRoundedInWorld(flocation.getWorldName()) > 0 && !Board.isConnectedLocation(flocation, myFaction)) {
sendMessage("You can only claim additional land which is connected to your first claim!");
return false;
}
if (otherFaction.isNone()) {
myFaction.sendMessage(this.getNameAndRelevant(myFaction)+Conf.colorSystem+" claimed some new land :D");
} else { //if (otherFaction.isNormal()) {
if ( ! otherFaction.hasLandInflation()) {
// TODO more messages WARN current faction most importantly
sendMessage(this.getRelationColor(otherFaction)+otherFaction.getTag()+Conf.colorSystem+" owns this land and is strong enough to keep it.");
return false;
}
if ( ! Board.isBorderLocation(flocation)) {
sendMessage("You must start claiming land at the border of the territory.");
return false;
}
// ASDF claimed some of your land 450 blocks NNW of you.
// ASDf claimed some land from FACTION NAME
otherFaction.sendMessage(this.getNameAndRelevant(otherFaction)+Conf.colorSystem+" stole some of your land :O");
myFaction.sendMessage(this.getNameAndRelevant(myFaction)+Conf.colorSystem+" claimed some land from "+otherFaction.getTag(myFaction));
}
Board.setFactionAt(myFaction, flocation);
return true;
}
// -------------------------------------------- //
// Messages
// -------------------------------------------- //
public void sendMessage(String message) {
if (this.getPlayer() != null)
this.getPlayer().sendMessage(Conf.colorSystem + message);
}
public void sendMessage(List<String> messages) {
for(String message : messages) {
this.sendMessage(message);
}
}
// -------------------------------------------- //
// Get and search
// -------------------------------------------- //
// You should use this one to be sure you do not spell the player name wrong.
public static FPlayer get(Player player) {
return get(player.getName());
}
private static FPlayer get(String playerName) {
if (instances.containsKey(playerName)) {
return instances.get(playerName);
}
FPlayer vplayer = new FPlayer();
vplayer.playerName = playerName;
instances.put(playerName, vplayer);
return vplayer;
}
public static Set<FPlayer> getAllOnline() {
Set<FPlayer> fplayers = new HashSet<FPlayer>();
for (Player player : Factions.instance.getServer().getOnlinePlayers()) {
fplayers.add(FPlayer.get(player));
}
return fplayers;
}
public static Collection<FPlayer> getAll() {
return instances.values();
}
public static FPlayer find(String playername) {
for (Entry<String, FPlayer> entry : instances.entrySet()) {
if (entry.getKey().equalsIgnoreCase(playername) || entry.getKey().startsWith(playername)) {
return entry.getValue();
}
}
return null;
}
// -------------------------------------------- //
// Persistance
// -------------------------------------------- //
public boolean shouldBeSaved() {
return this.factionId != 0;
}
public static boolean save() {
//Factions.log("Saving players to disk");
// We only wan't to save the players with non default values
Map<String, FPlayer> playersToSave = new HashMap<String, FPlayer>();
for (Entry<String, FPlayer> entry : instances.entrySet()) {
if (entry.getValue().shouldBeSaved()) {
playersToSave.put(entry.getKey(), entry.getValue());
}
}
try {
DiscUtil.write(file, Factions.gson.toJson(playersToSave));
} catch (Exception e) {
e.printStackTrace();
Factions.log("Failed to save the players to disk.");
return false;
}
return true;
}
public static boolean load() {
Factions.log("Loading players from disk");
if ( ! file.exists()) {
if ( ! loadOld())
Factions.log("No players to load from disk. Creating new file.");
save();
return true;
}
try {
Type type = new TypeToken<Map<String, FPlayer>>(){}.getType();
Map<String, FPlayer> instancesFromFile = Factions.gson.fromJson(DiscUtil.read(file), type);
instances.clear();
instances.putAll(instancesFromFile);
} catch (Exception e) {
e.printStackTrace();
Factions.log("Failed to load the players from disk.");
return false;
}
fillPlayernames();
return true;
}
public static void fillPlayernames() {
for(Entry<String, FPlayer> entry : instances.entrySet()) {
entry.getValue().playerName = entry.getKey();
}
}
public static void clean() {
for (FPlayer fplayer : instances.values()) {
if ( ! Faction.exists(fplayer.getFactionId())) {
Factions.log("Reset faction data (invalid faction) for player "+fplayer.getName());
fplayer.resetFactionData();
}
}
}
public static void autoLeaveOnInactivityRoutine() {
long now = System.currentTimeMillis();
double toleranceMillis = Conf.autoLeaveAfterDaysOfInactivity * 24 * 60 * 60 * 1000;
for (FPlayer fplayer : FPlayer.getAll()) {
if (now - fplayer.getLastLoginTime() > toleranceMillis) {
fplayer.leave();
}
}
}
private static boolean loadOld() {
File folderFollower = new File(Factions.instance.getDataFolder(), "follower");
if ( ! folderFollower.isDirectory())
return false;
Factions.log("Players file doesn't exist, attempting to load old pre-1.1 data.");
String ext = ".json";
class jsonFileFilter implements FileFilter {
@Override
public boolean accept(File file) {
return (file.getName().toLowerCase().endsWith(".json") && file.isFile());
}
}
File[] jsonFiles = folderFollower.listFiles(new jsonFileFilter());
for (File jsonFile : jsonFiles) {
// Extract the name from the filename. The name is filename minus ".json"
String name = jsonFile.getName();
name = name.substring(0, name.length() - ext.length());
try {
FPlayer follower = Factions.gson.fromJson(DiscUtil.read(jsonFile), FPlayer.class);
follower.playerName = name;
follower.lastLoginTime = System.currentTimeMillis();
instances.put(follower.playerName, follower);
Factions.log("loaded pre-1.1 follower "+name);
} catch (Exception e) {
e.printStackTrace();
Factions.log(Level.WARNING, "failed to load follower "+name);
}
}
return true;
}
}

View File

@ -0,0 +1,568 @@
package com.massivecraft.factions;
import java.io.*;
import java.lang.reflect.Type;
import java.util.*;
import java.util.Map.Entry;
import java.util.logging.Level;
import org.bukkit.ChatColor;
import org.bukkit.Location;
import org.bukkit.entity.Player;
import com.massivecraft.factions.gson.reflect.TypeToken;
import com.massivecraft.factions.struct.Relation;
import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.*;
public class Faction {
// -------------------------------------------- //
// Fields
// -------------------------------------------- //
private static transient Map<Integer, Faction> instances = new HashMap<Integer, Faction>();
private static transient File file = new File(Factions.instance.getDataFolder(), "factions.json");
private static transient int nextId;
private transient int id;
private Map<Integer, Relation> relationWish;
private Set<String> invites; // Where string is a lowercase player name
private boolean open;
private String tag;
private String description;
private Location home;
private transient long lastPlayerLoggedOffTime;
// -------------------------------------------- //
// Construct
// -------------------------------------------- //
public Faction() {
this.relationWish = new HashMap<Integer, Relation>();
this.invites = new HashSet<String>();
this.open = Conf.newFactionsDefaultOpen;
this.tag = "???";
this.description = "Default faction description :(";
this.lastPlayerLoggedOffTime = 0;
}
// -------------------------------------------- //
// Getters And Setters
// -------------------------------------------- //
public int getId() {
return this.id;
}
public boolean getOpen() {
return open;
}
public void setOpen(boolean isOpen) {
open = isOpen;
}
public String getTag() {
return this.getTag("");
}
public String getTag(String prefix) {
return prefix+this.tag;
}
public String getTag(Faction otherFaction) {
if (otherFaction == null)
return getTag();
else
return this.getTag(otherFaction.getRelationColor(this).toString());
}
public String getTag(FPlayer otherFplayer) {
if (otherFplayer == null)
return getTag();
else
return this.getTag(otherFplayer.getRelationColor(this).toString());
}
public void setTag(String str) {
if (Conf.factionTagForceUpperCase) {
str = str.toUpperCase();
}
this.tag = str;
}
public String getDescription() {
return this.description;
}
public void setDescription(String value) {
this.description = value;
}
public void setHome(Location home) {
this.home = home;
}
public Location getHome() {
confirmValidHome();
return home;
}
public boolean hasHome() {
confirmValidHome();
return this.home != null;
}
public void confirmValidHome() {
if (!Conf.homesMustBeInClaimedTerritory || this.home == null || Board.getFactionAt(new FLocation(this.home)) == this) {
return;
}
sendMessage("Your faction home has been un-set since it is no longer in your territory.");
this.home = null;
}
// -------------------------------
// Understand the types
// -------------------------------
public boolean isNormal() {
return this.getId() > 0;
}
public boolean isNone() {
return this.getId() == 0;
}
public boolean isSafeZone() {
return this.getId() == -1;
}
public boolean isWarZone() {
return this.getId() == -2;
}
// -------------------------------
// Invites - uses lowercase name
// -------------------------------
public void invite(FPlayer fplayer) {
this.invites.add(fplayer.getName().toLowerCase());
}
public void deinvite(FPlayer fplayer) {
this.invites.remove(fplayer.getName().toLowerCase());
}
public boolean isInvited(FPlayer fplayer) {
return this.invites.contains(fplayer.getName().toLowerCase());
}
// -------------------------------
// Relation and relation colors TODO
// -------------------------------
public Relation getRelationWish(Faction otherFaction) {
if (this.relationWish.containsKey(otherFaction.getId())){
return this.relationWish.get(otherFaction.getId());
}
return Relation.NEUTRAL;
}
public void setRelationWish(Faction otherFaction, Relation relation) {
if (this.relationWish.containsKey(otherFaction.getId()) && relation.equals(Relation.NEUTRAL)){
this.relationWish.remove(otherFaction.getId());
} else {
this.relationWish.put(otherFaction.getId(), relation);
}
}
public Relation getRelation(Faction otherFaction) {
if (!otherFaction.isNormal() || !this.isNormal()) {
return Relation.NEUTRAL;
}
if (otherFaction.equals(this)) {
return Relation.MEMBER;
}
if(this.getRelationWish(otherFaction).value >= otherFaction.getRelationWish(this).value) {
return otherFaction.getRelationWish(this);
}
return this.getRelationWish(otherFaction);
}
public Relation getRelation(FPlayer fplayer) {
if (fplayer == null)
return Relation.NEUTRAL;
else
return getRelation(fplayer.getFaction());
}
//----------------------------------------------//
// Power
//----------------------------------------------//
public double getPower() {
double ret = 0;
for (FPlayer fplayer : this.getFPlayers()) {
ret += fplayer.getPower();
}
return ret;
}
public double getPowerMax() {
double ret = 0;
for (FPlayer fplayer : this.getFPlayers()) {
ret += fplayer.getPowerMax();
}
return ret;
}
public int getPowerRounded() {
return (int) Math.round(this.getPower());
}
public int getPowerMaxRounded() {
return (int) Math.round(this.getPowerMax());
}
public int getLandRounded() {
return Board.getFactionCoordCount(this);
}
public int getLandRoundedInWorld(String worldName) {
return Board.getFactionCoordCountInWorld(this, worldName);
}
public boolean hasLandInflation() {
return this.getLandRounded() > this.getPowerRounded();
}
// -------------------------------
// Fplayers
// -------------------------------
public ArrayList<FPlayer> getFPlayers() {
ArrayList<FPlayer> ret = new ArrayList<FPlayer>();
if (id < 0)
return ret;
for (FPlayer fplayer : FPlayer.getAll()) {
if (fplayer.getFaction() == this) {
ret.add(fplayer);
}
}
return ret;
}
public ArrayList<FPlayer> getFPlayersWhereOnline(boolean online) {
ArrayList<FPlayer> ret = new ArrayList<FPlayer>();
if (id < 0)
return ret;
for (FPlayer fplayer : FPlayer.getAll()) {
if (fplayer.getFaction() == this && fplayer.isOnline() == online) {
ret.add(fplayer);
}
}
return ret;
}
public ArrayList<FPlayer> getFPlayersWhereRole(Role role) {
ArrayList<FPlayer> ret = new ArrayList<FPlayer>();
if (id <= 0)
return ret;
for (FPlayer fplayer : FPlayer.getAll()) {
if (fplayer.getFaction() == this && fplayer.getRole() == role) {
ret.add(fplayer);
}
}
return ret;
}
public ArrayList<Player> getOnlinePlayers() {
ArrayList<Player> ret = new ArrayList<Player>();
if (id < 0)
return ret;
for (Player player: Factions.instance.getServer().getOnlinePlayers()) {
FPlayer fplayer = FPlayer.get(player);
if (fplayer.getFaction() == this) {
ret.add(player);
}
}
return ret;
}
// slightly faster check than getOnlinePlayers() if you just want to see if there are any players online
public boolean hasPlayersOnline() {
// only real factions can have players online, not safe zone / war zone
if (id < 0)
return false;
for (Player player: Factions.instance.getServer().getOnlinePlayers()) {
FPlayer fplayer = FPlayer.get(player);
if (fplayer.getFaction() == this) {
return true;
}
}
// even if all players are technically logged off, maybe someone was on recently enough to not consider them officially offline yet
if (Conf.considerFactionsReallyOfflineAfterXMinutes > 0 &&
System.currentTimeMillis() < lastPlayerLoggedOffTime + (Conf.considerFactionsReallyOfflineAfterXMinutes * 60000)) {
return true;
}
return false;
}
public void memberLoggedOff() {
if (this.isNormal()) {
lastPlayerLoggedOffTime = System.currentTimeMillis();
}
}
//----------------------------------------------//
// Faction tag
//----------------------------------------------//
public String getComparisonTag() {
return TextUtil.getComparisonString(this.tag);
}
public static ArrayList<String> validateTag(String str) {
ArrayList<String> errors = new ArrayList<String>();
if(TextUtil.getComparisonString(str).length() < Conf.factionTagLengthMin) {
errors.add(Conf.colorSystem+"The faction tag can't be shorter than "+Conf.factionTagLengthMin+ " chars.");
}
if(str.length() > Conf.factionTagLengthMax) {
errors.add(Conf.colorSystem+"The faction tag can't be longer than "+Conf.factionTagLengthMax+ " chars.");
}
for (char c : str.toCharArray()) {
if ( ! TextUtil.substanceChars.contains(String.valueOf(c))) {
errors.add(Conf.colorSystem+"Faction tag must be alphanumeric. \""+c+"\" is not allowed.");
}
}
return errors;
}
public static Faction findByTag(String str) {
String compStr = TextUtil.getComparisonString(str);
for (Faction faction : Faction.getAll()) {
if (faction.getComparisonTag().equals(compStr)) {
return faction;
}
}
return null;
}
public static boolean isTagTaken(String str) {
return Faction.findByTag(str) != null;
}
//----------------------------------------------//
// Messages
//----------------------------------------------//
public void sendMessage(String message) {
for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) {
fplayer.sendMessage(message);
}
}
public void sendMessage(List<String> messages) {
for (FPlayer fplayer : this.getFPlayersWhereOnline(true)) {
fplayer.sendMessage(messages);
}
}
//----------------------------------------------//
// Mudd TODO
//----------------------------------------------//
public ChatColor getRelationColor(Faction otherFaction) {
return this.getRelation(otherFaction).getColor();
}
public ChatColor getRelationColor(FPlayer fplayer) {
return this.getRelation(fplayer).getColor();
}
//----------------------------------------------//
// Persistance and entity management
//----------------------------------------------//
public static boolean save() {
//Factions.log("Saving factions to disk");
try {
DiscUtil.write(file, Factions.gson.toJson(instances));
} catch (IOException e) {
e.printStackTrace();
Factions.log("Failed to save the factions to disk due to I/O exception.");
return false;
} catch (Exception e) {
e.printStackTrace();
Factions.log("Failed to save the factions to disk.");
return false;
}
return true;
}
public static boolean load() {
Factions.log("Loading factions from disk");
if ( ! file.exists()) {
if ( ! loadOld())
Factions.log("No factions to load from disk. Creating new file.");
save();
}
try {
Type type = new TypeToken<Map<Integer, Faction>>(){}.getType();
Map<Integer, Faction> instancesFromFile = Factions.gson.fromJson(DiscUtil.read(file), type);
instances.clear();
instances.putAll(instancesFromFile);
} catch (Exception e) {
e.printStackTrace();
Factions.log("Failed to load the factions from disk.");
return false;
}
fillIds();
// Make sure the default neutral faction exists
if ( ! instances.containsKey(0)) {
Faction faction = new Faction();
faction.tag = ChatColor.DARK_GREEN+"Wilderness";
faction.description = "";
faction.id = 0;
instances.put(faction.id, faction);
}
// Make sure the safe zone faction exists
if ( ! instances.containsKey(-1)) {
Faction faction = new Faction();
faction.tag = ChatColor.GOLD+"Safe Zone";
faction.description = "Free from PVP and monsters";
faction.id = -1;
instances.put(faction.id, faction);
}
// Make sure the war zone faction exists
if ( ! instances.containsKey(-2)) {
Faction faction = new Faction();
faction.tag = ChatColor.DARK_RED+"War Zone";
faction.description = "Not the safest place to be";
faction.id = -2;
instances.put(faction.id, faction);
}
return true;
}
public static void fillIds() {
nextId = 1;
for(Entry<Integer, Faction> entry : instances.entrySet()) {
entry.getValue().id = entry.getKey();
if (nextId < entry.getKey()) {
nextId = entry.getKey();
}
}
nextId += 1; // make it the next id and not the current highest.
}
public static Faction get(Integer factionId) {
if ( ! instances.containsKey(factionId)) {
Factions.log(Level.WARNING, "Non existing factionId "+factionId+" requested! Issuing cleaning!");
Board.clean();
FPlayer.clean();
}
return instances.get(factionId);
}
public static Faction getNone() {
return instances.get(0);
}
public static Faction getSafeZone() {
return instances.get(-1);
}
public static Faction getWarZone() {
return instances.get(-2);
}
public static boolean exists(Integer factionId) {
return instances.containsKey(factionId);
}
public static Collection<Faction> getAll() {
return instances.values();
}
//TODO ta parametrar här. All info som behövs ska matas in här och så sparar vi i denna method.
public static Faction create() {
Faction faction = new Faction();
faction.id = nextId;
nextId += 1;
instances.put(faction.id, faction);
Factions.log("created new faction "+faction.id);
//faction.save();
return faction;
}
public static void delete(Integer id) {
// Remove the faction
instances.remove(id);
// Clean the board
Board.clean();
// Clean the fplayers
FPlayer.clean();
}
private static boolean loadOld() {
File folderFaction = new File(Factions.instance.getDataFolder(), "faction");
if ( ! folderFaction.isDirectory())
return false;
Factions.log("Factions file doesn't exist, attempting to load old pre-1.1 data.");
String ext = ".json";
class jsonFileFilter implements FileFilter {
@Override
public boolean accept(File file) {
return (file.getName().toLowerCase().endsWith(".json") && file.isFile());
}
}
File[] jsonFiles = folderFaction.listFiles(new jsonFileFilter());
for (File jsonFile : jsonFiles) {
// Extract the name from the filename. The name is filename minus ".json"
String name = jsonFile.getName();
name = name.substring(0, name.length() - ext.length());
int id = Integer.parseInt(name);
try {
Faction faction = Factions.gson.fromJson(DiscUtil.read(jsonFile), Faction.class);
faction.id = id;
instances.put(faction.id, faction);
Factions.log("loaded pre-1.1 faction "+id);
} catch (Exception e) {
e.printStackTrace();
Factions.log(Level.WARNING, "Failed to load faction "+id);
}
}
return true;
}
}

View File

@ -0,0 +1,382 @@
package com.massivecraft.factions;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Location;
import org.bukkit.command.Command;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import org.bukkit.event.Event;
import org.bukkit.event.player.PlayerChatEvent;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import org.bukkit.plugin.java.JavaPlugin;
import com.massivecraft.factions.commands.*;
import com.massivecraft.factions.gson.Gson;
import com.massivecraft.factions.gson.GsonBuilder;
import com.massivecraft.factions.listeners.FactionsBlockListener;
import com.massivecraft.factions.listeners.FactionsEntityListener;
import com.massivecraft.factions.listeners.FactionsPlayerListener;
import com.nijiko.permissions.PermissionHandler;
import com.nijikokun.bukkit.Permissions.Permissions;
/**
* The data is saved to disk every 30min and on plugin disable.
*/
public class Factions extends JavaPlugin {
// -------------------------------------------- //
// Fields
// -------------------------------------------- //
public static Factions instance;
private Integer saveTask = null;
public final static Gson gson = new GsonBuilder()
.setPrettyPrinting()
.excludeFieldsWithModifiers(Modifier.TRANSIENT, Modifier.VOLATILE)
.registerTypeAdapter(Location.class, new MyLocationTypeAdapter())
.create();
private final FactionsPlayerListener playerListener = new FactionsPlayerListener();
private final FactionsEntityListener entityListener = new FactionsEntityListener();
private final FactionsBlockListener blockListener = new FactionsBlockListener();
public static PermissionHandler Permissions;
// Commands
public List<FBaseCommand> commands = new ArrayList<FBaseCommand>();
private String baseCommand;
public Factions() {
Factions.instance = this;
}
@Override
public void onEnable() {
log("=== INIT START ===");
long timeInitStart = System.currentTimeMillis();
// Add the commands
commands.add(new FCommandHelp());
commands.add(new FCommandAdmin());
commands.add(new FCommandAutoClaim());
commands.add(new FCommandAutoSafeclaim());
commands.add(new FCommandAutoWarclaim());
commands.add(new FCommandBypass());
commands.add(new FCommandChat());
commands.add(new FCommandClaim());
commands.add(new FCommandCreate());
commands.add(new FCommandDeinvite());
commands.add(new FCommandDescription());
commands.add(new FCommandDisband());
commands.add(new FCommandHome());
commands.add(new FCommandInvite());
commands.add(new FCommandJoin());
commands.add(new FCommandKick());
commands.add(new FCommandLeave());
commands.add(new FCommandList());
commands.add(new FCommandLock());
commands.add(new FCommandMap());
commands.add(new FCommandMod());
commands.add(new FCommandOpen());
commands.add(new FCommandRelationAlly());
commands.add(new FCommandRelationEnemy());
commands.add(new FCommandRelationNeutral());
commands.add(new FCommandReload());
commands.add(new FCommandSafeclaim());
commands.add(new FCommandSafeunclaimall());
commands.add(new FCommandSaveAll());
commands.add(new FCommandSethome());
commands.add(new FCommandShow());
commands.add(new FCommandTag());
commands.add(new FCommandTitle());
commands.add(new FCommandUnclaim());
commands.add(new FCommandUnclaimall());
commands.add(new FCommandVersion());
commands.add(new FCommandWarclaim());
commands.add(new FCommandWarunclaimall());
commands.add(new FCommandWorldNoClaim());
commands.add(new FCommandWorldNoPowerLoss());
// Ensure base folder exists!
this.getDataFolder().mkdirs();
Conf.load();
FPlayer.load();
Faction.load();
Board.load();
setupPermissions();
// preload could apparently cause issues; removed since "softdepend" is now available
// Register events
PluginManager pm = this.getServer().getPluginManager();
pm.registerEvent(Event.Type.PLAYER_CHAT, this.playerListener, Event.Priority.Highest, this);
pm.registerEvent(Event.Type.PLAYER_INTERACT, this.playerListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_MOVE, this.playerListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_JOIN, this.playerListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_QUIT, this.playerListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_RESPAWN, this.playerListener, Event.Priority.High, this);
pm.registerEvent(Event.Type.PLAYER_BUCKET_EMPTY, this.playerListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.PLAYER_BUCKET_FILL, this.playerListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_DEATH, this.entityListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_DAMAGE, this.entityListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_EXPLODE, this.entityListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.CREATURE_SPAWN, this.entityListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.ENTITY_TARGET, this.entityListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.PAINTING_BREAK, this.entityListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.PAINTING_PLACE, this.entityListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.BLOCK_BREAK, this.blockListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.BLOCK_DAMAGE, this.blockListener, Event.Priority.Normal, this);
pm.registerEvent(Event.Type.BLOCK_PLACE, this.blockListener, Event.Priority.Normal, this);
// Register recurring tasks
long saveTicks = 20 * 60 * 30; // Approximately every 30 min
if (saveTask == null)
saveTask = this.getServer().getScheduler().scheduleSyncRepeatingTask(this, new SaveTask(), saveTicks, saveTicks);
log("=== INIT DONE (Took "+(System.currentTimeMillis()-timeInitStart)+"ms) ===");
}
@Override
public void onDisable() {
if (saveTask != null) {
this.getServer().getScheduler().cancelTask(saveTask);
saveTask = null;
}
saveAll();
log("Disabled");
}
// -------------------------------------------- //
// Integration with other plugins
// -------------------------------------------- //
private void setupPermissions() {
if (Permissions != null) {
return;
}
Plugin test = this.getServer().getPluginManager().getPlugin("Permissions");
if (test != null) {
Permissions = ((Permissions)test).getHandler();
Factions.log("Found and will use plugin "+((Permissions)test).getDescription().getFullName());
} else {
Factions.log("Permission system not detected, defaulting to OP");
}
}
// -------------------------------------------- //
// Functions for other plugins to hook into
// -------------------------------------------- //
// This value will be updated whenever new hooks are added
public int hookSupportVersion() {
return 1;
}
// If another plugin is handling insertion of chat tags, this should be used to notify Factions
public void handleFactionTagExternally(boolean notByFactions) {
Conf.chatTagHandledByAnotherPlugin = notByFactions;
}
// Simply put, should this chat event be left for Factions to handle? For now, that means players with Faction Chat
// enabled or use of the Factions f command without a slash; combination of isPlayerFactionChatting() and isFactionsCommand()
public boolean shouldLetFactionsHandleThisChat(PlayerChatEvent event) {
if (event == null)
return false;
return (isPlayerFactionChatting(event.getPlayer()) || isFactionsCommand(event.getMessage()));
}
// Does player have Faction Chat enabled? If so, chat plugins should preferably not do channels,
// local chat, or anything else which targets individual recipients, so Faction Chat can be done
public boolean isPlayerFactionChatting(Player player) {
if (player == null)
return false;
FPlayer me = FPlayer.get(player);
if (me == null)
return false;
return me.isFactionChatting();
}
// Is this chat message actually a Factions command, and thus should be left alone by other plugins?
public boolean isFactionsCommand(String check) {
if (check == null || check.isEmpty())
return false;
return (Conf.allowNoSlashCommand && (check.startsWith(instance.getBaseCommand()+" ") || check.equals(instance.getBaseCommand())));
}
// Get a player's faction tag (faction name), mainly for usage by chat plugins for local/channel chat
public String getPlayerFactionTag(Player player) {
return getPlayerFactionTagRelation(player, null);
}
// Same as above, but with relation (enemy/neutral/ally) coloring potentially added to the tag
public String getPlayerFactionTagRelation(Player speaker, Player listener) {
String tag = "~";
if (speaker == null)
return tag;
FPlayer me = FPlayer.get(speaker);
if (me == null)
return tag;
// if listener isn't set, or config option is disabled, give back uncolored tag
if (listener == null || !Conf.chatTagRelationColored) {
tag = me.getChatTag().trim();
} else {
FPlayer you = FPlayer.get(listener);
if (you == null)
tag = me.getChatTag().trim();
else // everything checks out, give the colored tag
tag = me.getChatTag(you).trim();
}
if (tag.isEmpty())
tag = "~";
return tag;
}
// Get a player's title within their faction, mainly for usage by chat plugins for local/channel chat
public String getPlayerTitle(Player player) {
if (player == null)
return "";
FPlayer me = FPlayer.get(player);
if (me == null)
return "";
return me.getTitle().trim();
}
// -------------------------------------------- //
// Test rights
// -------------------------------------------- //
public static boolean hasPermParticipate(CommandSender sender) {
return hasPerm(sender, "factions.participate");
}
public static boolean hasPermCreate(CommandSender sender) {
return hasPerm(sender, "factions.create");
}
public static boolean hasPermManageSafeZone(CommandSender sender) {
return hasPerm(sender, "factions.manageSafeZone");
}
public static boolean hasPermManageWarZone(CommandSender sender) {
return hasPerm(sender, "factions.manageWarZone");
}
public static boolean hasPermAdminBypass(CommandSender sender) {
return hasPerm(sender, "factions.adminBypass");
}
public static boolean hasPermReload(CommandSender sender) {
return hasPerm(sender, "factions.reload");
}
public static boolean hasPermSaveAll(CommandSender sender) {
return hasPerm(sender, "factions.saveall");
}
public static boolean hasPermLock(CommandSender sender) {
return hasPerm(sender, "factions.lock");
}
public static boolean hasPermDisband(CommandSender sender) {
return hasPerm(sender, "factions.disband");
}
public static boolean hasPermWorlds(CommandSender sender) {
return hasPerm(sender, "factions.worldOptions");
}
private static boolean hasPerm(CommandSender sender, String permNode) {
if (Factions.Permissions == null || ! (sender instanceof Player)) {
return sender.isOp() || sender.hasPermission(permNode);
}
Player player = (Player)sender;
return Factions.Permissions.has(player, permNode);
}
// -------------------------------------------- //
// Commands
// -------------------------------------------- //
@SuppressWarnings("unchecked")
public String getBaseCommand() {
if (this.baseCommand != null) {
return this.baseCommand;
}
Map<String, Object> Commands = (Map<String, Object>)this.getDescription().getCommands();
this.baseCommand = Commands.keySet().iterator().next();
return this.baseCommand;
}
@Override
public boolean onCommand(CommandSender sender, Command cmd, String commandLabel, String[] args) {
List<String> parameters = new ArrayList<String>(Arrays.asList(args));
this.handleCommand(sender, parameters);
return true;
}
public void handleCommand(CommandSender sender, List<String> parameters) {
if (parameters.size() == 0) {
this.commands.get(0).execute(sender, parameters);
return;
}
String commandName = parameters.get(0).toLowerCase();
parameters.remove(0);
for (FBaseCommand fcommand : this.commands) {
if (fcommand.getAliases().contains(commandName)) {
fcommand.execute(sender, parameters);
return;
}
}
sender.sendMessage(Conf.colorSystem+"Unknown faction command \""+commandName+"\". Try "+Conf.colorCommand+"/"+this.getBaseCommand()+" help");
}
// -------------------------------------------- //
// Logging
// -------------------------------------------- //
public static void log(String msg) {
log(Level.INFO, msg);
}
public static void log(Level level, String msg) {
Logger.getLogger("Minecraft").log(level, "["+instance.getDescription().getFullName()+"] "+msg);
}
// -------------------------------------------- //
// Save all
// -------------------------------------------- //
public static void saveAll() {
FPlayer.save();
Faction.save();
Board.save();
Conf.save();
}
}

View File

@ -0,0 +1,79 @@
package com.massivecraft.factions;
import java.lang.reflect.Type;
import java.util.logging.Level;
import org.bukkit.Location;
import org.bukkit.World;
import com.massivecraft.factions.gson.JsonDeserializationContext;
import com.massivecraft.factions.gson.JsonDeserializer;
import com.massivecraft.factions.gson.JsonElement;
import com.massivecraft.factions.gson.JsonObject;
import com.massivecraft.factions.gson.JsonParseException;
import com.massivecraft.factions.gson.JsonSerializationContext;
import com.massivecraft.factions.gson.JsonSerializer;
public class MyLocationTypeAdapter implements JsonDeserializer<Location>, JsonSerializer<Location> {
private static final String WORLD = "world";
private static final String X = "x";
private static final String Y = "y";
private static final String Z = "z";
private static final String YAW = "yaw";
private static final String PITCH = "pitch";
@Override
public Location deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
try {
JsonObject obj = json.getAsJsonObject();
String worldname = obj.get(WORLD).getAsString();
World world = Factions.instance.getServer().getWorld(worldname);
if (world == null) {
Factions.log(Level.WARNING, "Stored location's world \"" + worldname + "\" not found on server; dropping the location.");
return null;
}
double x = obj.get(X).getAsDouble();
double y = obj.get(Y).getAsDouble();
double z = obj.get(Z).getAsDouble();
float yaw = obj.get(YAW).getAsFloat();
float pitch = obj.get(PITCH).getAsFloat();
return new Location(world, x, y, z, yaw, pitch);
} catch (Exception ex) {
ex.printStackTrace();
Factions.log(Level.WARNING, "Error encountered while deserializing a location.");
return null;
}
}
@Override
public JsonElement serialize(Location src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject obj = new JsonObject();
try {
if (src.getWorld() == null)
{
Factions.log(Level.WARNING, "Passed location's world was not found on the server. Dropping the location.");
return obj;
}
obj.addProperty(WORLD, src.getWorld().getName());
obj.addProperty(X, src.getX());
obj.addProperty(Y, src.getY());
obj.addProperty(Z, src.getZ());
obj.addProperty(YAW, src.getYaw());
obj.addProperty(PITCH, src.getPitch());
return obj;
} catch (Exception ex) {
ex.printStackTrace();
Factions.log(Level.WARNING, "Error encountered while serializing a location.");
return obj;
}
}
}

View File

@ -0,0 +1,12 @@
package com.massivecraft.factions;
public class SaveTask implements Runnable {
//TODO are they removed on disable?
@Override
public void run() {
Factions.saveAll();
}
}

View File

@ -0,0 +1,255 @@
package com.massivecraft.factions.commands;
import java.util.ArrayList;
import java.util.List;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.TextUtil;
public class FBaseCommand {
public List<String> aliases;
public List<String> requiredParameters;
public List<String> optionalParameters;
public String helpNameAndParams;
public String helpDescription;
public CommandSender sender;
public boolean senderMustBePlayer;
public Player player;
public FPlayer me;
public List<String> parameters;
private static boolean lock = false;
public FBaseCommand() {
aliases = new ArrayList<String>();
requiredParameters = new ArrayList<String>();
optionalParameters = new ArrayList<String>();
senderMustBePlayer = true;
helpNameAndParams = "fail!";
helpDescription = "no description";
}
public List<String> getAliases() {
return aliases;
}
public void execute(CommandSender sender, List<String> parameters) {
this.sender = sender;
this.parameters = parameters;
if ( ! validateCall()) {
return;
}
if (sender instanceof Player) {
this.player = (Player)sender;
this.me = FPlayer.get(this.player);
}
perform();
}
public void perform() {
}
public void sendMessage(String message) {
sender.sendMessage(Conf.colorSystem+message);
}
public void sendMessage(List<String> messages) {
for(String message : messages) {
this.sendMessage(message);
}
}
public boolean validateCall() {
if ( this.senderMustBePlayer && ! (sender instanceof Player)) {
sendMessage("This command can only be used by ingame players.");
return false;
}
if( ! hasPermission(sender)) {
sendMessage("You lack the permissions to "+this.helpDescription.toLowerCase()+".");
return false;
}
if (parameters.size() < requiredParameters.size()) {
sendMessage("Usage: "+this.getUseageTemplate(false));
return false;
}
return true;
}
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermParticipate(sender);
}
// -------------------------------------------- //
// Help and usage description
// -------------------------------------------- //
public String getUseageTemplate(boolean withDescription) {
String ret = "";
ret += Conf.colorCommand;
ret += Factions.instance.getBaseCommand()+ " " +TextUtil.implode(this.getAliases(), ",")+" ";
List<String> parts = new ArrayList<String>();
for (String requiredParameter : this.requiredParameters) {
parts.add("["+requiredParameter+"]");
}
for (String optionalParameter : this.optionalParameters) {
parts.add("*["+optionalParameter+"]");
}
ret += Conf.colorParameter;
ret += TextUtil.implode(parts, " ");
if (withDescription) {
ret += " "+Conf.colorSystem + this.helpDescription;
}
return ret;
}
public String getUseageTemplate() {
return getUseageTemplate(true);
}
// -------------------------------------------- //
// Assertions
// -------------------------------------------- //
public boolean assertHasFaction() {
if ( ! me.hasFaction()) {
sendMessage("You are not member of any faction.");
return false;
}
return true;
}
public boolean assertMinRole(Role role) {
if (me.getRole().value < role.value) {
sendMessage("You must be "+role+" to "+this.helpDescription+".");
return false;
}
return true;
}
// -------------------------------------------- //
// Commonly used logic
// -------------------------------------------- //
public FPlayer findFPlayer(String playerName, boolean defaultToMe) {
FPlayer fp = FPlayer.find(playerName);
if (fp == null) {
if (defaultToMe) {
return me;
}
sendMessage("The player \""+playerName+"\" could not be found");
}
return fp;
}
public FPlayer findFPlayer(String playerName) {
return findFPlayer(playerName, false);
}
public Faction findFaction(String factionName, boolean defaultToMine) {
// First we search player names
FPlayer fp = FPlayer.find(factionName);
if (fp != null) {
return fp.getFaction();
}
// Secondly we search faction names
Faction faction = Faction.findByTag(factionName);
if (faction != null) {
return faction;
}
if (defaultToMine && sender instanceof Player) {
return me.getFaction();
}
sendMessage(Conf.colorSystem+"No faction or player \""+factionName+"\" was found");
return null;
}
public Faction findFaction(String factionName) {
return findFaction(factionName, false);
}
public boolean canIAdministerYou(FPlayer i, FPlayer you) {
if ( ! i.getFaction().equals(you.getFaction())) {
i.sendMessage(you.getNameAndRelevant(i)+Conf.colorSystem+" is not in the same faction as you.");
return false;
}
if (i.getRole().value > you.getRole().value || i.getRole().equals(Role.ADMIN) ) {
return true;
}
if (you.getRole().equals(Role.ADMIN)) {
i.sendMessage(Conf.colorSystem+"Only the faction admin can do that.");
} else if (i.getRole().equals(Role.MODERATOR)) {
i.sendMessage(Conf.colorSystem+"Moderators can't control each other...");
} else {
i.sendMessage(Conf.colorSystem+"You must be a faction moderator to do that.");
}
return false;
}
public boolean parseBool(String str) {
List<String> aliasTrue = new ArrayList<String>();
aliasTrue.add("true");
aliasTrue.add("yes");
aliasTrue.add("y");
aliasTrue.add("ok");
aliasTrue.add("on");
aliasTrue.add("+");
return aliasTrue.contains(str.toLowerCase());
}
public void setLock(boolean newLock) {
if( newLock ) {
sendMessage("Factions is now locked");
} else {
sendMessage("Factions in now unlocked");
}
lock = newLock;
}
public boolean isLocked() {
return lock;
}
public void sendLockMessage() {
me.sendMessage("Factions is locked. Please try again later");
}
}

View File

@ -0,0 +1,66 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
public class FCommandAdmin extends FBaseCommand {
public FCommandAdmin() {
aliases.add("admin");
requiredParameters.add("player name");
helpDescription = "Hand over your admin rights";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
if ( ! assertMinRole(Role.ADMIN)) {
return;
}
String playerName = parameters.get(0);
FPlayer you = findFPlayer(playerName, false);
if (you == null) {
return;
}
Faction myFaction = me.getFaction();
if (you.getFaction() != myFaction) {
sendMessage(you.getNameAndRelevant(me)+Conf.colorSystem+" is not a member in your faction.");
return;
}
if (you == me) {
sendMessage("The target player musn't be yourself.");
return;
}
me.setRole(Role.MODERATOR);
you.setRole(Role.ADMIN);
// Inform all players
for (FPlayer fplayer : FPlayer.getAllOnline()) {
if (fplayer.getFaction() == me.getFaction()) {
fplayer.sendMessage(me.getNameAndRelevant(me)+Conf.colorSystem+" gave "+you.getNameAndRelevant(me)+Conf.colorSystem+" the leadership of your faction.");
} else {
fplayer.sendMessage(me.getNameAndRelevant(fplayer)+Conf.colorSystem+" gave "+you.getNameAndRelevant(fplayer)+Conf.colorSystem+" the leadership of "+myFaction.getTag(fplayer));
}
}
}
}

View File

@ -0,0 +1,67 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FLocation;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
public class FCommandAutoClaim extends FBaseCommand {
public FCommandAutoClaim() {
aliases.add("autoclaim");
optionalParameters.add("on|off");
helpDescription = "Auto-claim land as you walk around";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
// default: toggle existing value
boolean enable = !me.autoClaimEnabled();
// if on|off is specified, use that instead
if (parameters.size() > 0)
enable = parseBool(parameters.get(0));
me.enableAutoClaim(enable);
if (!enable) {
sendMessage("Auto-claiming of land disabled.");
return;
}
Faction myFaction = me.getFaction();
FLocation flocation = new FLocation(me);
if ( ! assertMinRole(Role.MODERATOR)) {
me.enableAutoClaim(false);
return;
}
if (Conf.worldsNoClaiming.contains(flocation.getWorldName())) {
sendMessage("Sorry, this world has land claiming disabled.");
me.enableAutoClaim(false);
return;
}
if (myFaction.getLandRounded() >= myFaction.getPowerRounded()) {
sendMessage("You can't claim more land! You need more power!");
me.enableAutoClaim(false);
return;
}
sendMessage("Auto-claiming of land enabled.");
me.attemptClaim(false);
}
}

View File

@ -0,0 +1,55 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.FLocation;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
public class FCommandAutoSafeclaim extends FBaseCommand {
public FCommandAutoSafeclaim() {
aliases.add("autosafe");
optionalParameters.add("on|off");
helpDescription = "Auto-claim land for the safezone";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermManageSafeZone(sender);
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
boolean enable = !me.autoSafeZoneEnabled();
if (parameters.size() > 0)
enable = parseBool(parameters.get(0));
me.enableAutoSafeZone(enable);
if (!enable) {
sendMessage("Auto-claiming of safe zone disabled.");
return;
}
sendMessage("Auto-claiming of safe zone enabled.");
FLocation playerFlocation = new FLocation(me);
if (!Board.getFactionAt(playerFlocation).isSafeZone()) {
Board.setFactionAt(Faction.getSafeZone(), playerFlocation);
sendMessage("This land is now a safe zone.");
}
}
}

View File

@ -0,0 +1,55 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.FLocation;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
public class FCommandAutoWarclaim extends FBaseCommand {
public FCommandAutoWarclaim() {
aliases.add("autowar");
optionalParameters.add("on|off");
helpDescription = "Auto-claim land for the warzone";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermManageWarZone(sender);
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
boolean enable = !me.autoWarZoneEnabled();
if (parameters.size() > 0)
enable = parseBool(parameters.get(0));
me.enableAutoWarZone(enable);
if (!enable) {
sendMessage("Auto-claiming of war zone disabled.");
return;
}
sendMessage("Auto-claiming of war zone enabled.");
FLocation playerFlocation = new FLocation(me);
if (!Board.getFactionAt(playerFlocation).isWarZone()) {
Board.setFactionAt(Faction.getWarZone(), playerFlocation);
sendMessage("This land is now a war zone.");
}
}
}

View File

@ -0,0 +1,32 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Factions;
public class FCommandBypass extends FBaseCommand {
public FCommandBypass() {
aliases.add("bypass");
helpDescription = "Enable admin bypass mode; build/destroy anywhere";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermAdminBypass(sender);
}
@Override
public void perform() {
if ( ! Conf.adminBypassPlayers.contains(player.getName())) {
Conf.adminBypassPlayers.add(player.getName());
me.sendMessage("You have enabled admin bypass mode. You will be able to build or destroy anywhere.");
} else {
Conf.adminBypassPlayers.remove(player.getName());
me.sendMessage("You have disabled admin bypass mode.");
}
}
}

View File

@ -0,0 +1,29 @@
package com.massivecraft.factions.commands;
public class FCommandChat extends FBaseCommand {
public FCommandChat() {
aliases.add("chat");
aliases.add("c");
helpDescription = "Switch faction only chat on and off";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if ( ! me.isFactionChatting()) {
// Turn on
me.setFactionChatting(true);
sendMessage("Faction-only chat ENABLED.");
} else {
// Turn off
me.setFactionChatting(false);
sendMessage("Faction-only chat DISABLED.");
}
}
}

View File

@ -0,0 +1,25 @@
package com.massivecraft.factions.commands;
public class FCommandClaim extends FBaseCommand {
public FCommandClaim() {
aliases.add("claim");
helpDescription = "Claim the land where you are standing";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
me.attemptClaim(true);
}
}

View File

@ -0,0 +1,67 @@
package com.massivecraft.factions.commands;
import java.util.ArrayList;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
import com.massivecraft.factions.struct.Role;
public class FCommandCreate extends FBaseCommand {
public FCommandCreate() {
aliases.add("create");
requiredParameters.add("faction tag");
helpDescription = "Create a new faction";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermCreate(sender);
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
String tag = parameters.get(0);
if (me.hasFaction()) {
sendMessage("You must leave your current faction first.");
return;
}
if (Faction.isTagTaken(tag)) {
sendMessage("That tag is already in use.");
return;
}
ArrayList<String> tagValidationErrors = Faction.validateTag(tag);
if (tagValidationErrors.size() > 0) {
sendMessage(tagValidationErrors);
return;
}
Faction faction = Faction.create();
faction.setTag(tag);
me.setRole(Role.ADMIN);
me.setFaction(faction);
for (FPlayer follower : FPlayer.getAllOnline()) {
follower.sendMessage(me.getNameAndRelevant(follower)+Conf.colorSystem+" created a new faction "+faction.getTag(follower));
}
sendMessage("You should now: " + new FCommandDescription().getUseageTemplate());
}
}

View File

@ -0,0 +1,55 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
public class FCommandDeinvite extends FBaseCommand {
public FCommandDeinvite() {
aliases.add("deinvite");
aliases.add("deinv");
requiredParameters.add("player name");
helpDescription = "Remove a pending invitation";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
String playerName = parameters.get(0);
FPlayer you = findFPlayer(playerName, false);
if (you == null) {
return;
}
Faction myFaction = me.getFaction();
if ( ! assertMinRole(Role.MODERATOR)) {
return;
}
if (you.getFaction() == myFaction) {
sendMessage(you.getName()+" is already a member of "+myFaction.getTag());
sendMessage("You might want to: " + new FCommandKick().getUseageTemplate(false));
return;
}
myFaction.deinvite(you);
you.sendMessage(me.getNameAndRelevant(you)+Conf.colorSystem+" revoked your invitation to "+myFaction.getTag(you));
myFaction.sendMessage(me.getNameAndRelevant(me)+Conf.colorSystem+" revoked "+you.getNameAndRelevant(me)+"'s"+Conf.colorSystem+" invitation.");
}
}

View File

@ -0,0 +1,42 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.TextUtil;
public class FCommandDescription extends FBaseCommand {
public FCommandDescription() {
aliases.add("desc");
requiredParameters.add("desc");
helpDescription = "Change the faction description";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
if ( ! assertMinRole(Role.MODERATOR)) {
return;
}
me.getFaction().setDescription(TextUtil.implode(parameters));
// Broadcast the description to everyone
for (FPlayer fplayer : FPlayer.getAllOnline()) {
fplayer.sendMessage("The faction "+fplayer.getRelationColor(me)+me.getFaction().getTag()+Conf.colorSystem+" changed their description to:");
fplayer.sendMessage(me.getFaction().getDescription());
}
}
}

View File

@ -0,0 +1,39 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
public class FCommandDisband extends FBaseCommand {
public FCommandDisband() {
aliases.add("disband");
senderMustBePlayer = false;
requiredParameters.add("faction tag");
helpDescription = "Disband a faction";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermDisband(sender);
}
@Override
public void perform() {
if( parameters.size() > 0) {
Faction faction = Faction.findByTag(parameters.get(0));
if( faction != null && faction.getId() > 0 ) {
sendMessage("Faction " + faction.getTag() + " got disbanded");
Faction.delete( faction.getId() );
} else {
sendMessage("Faction " + parameters.get(0) + "not found");
}
}
}
}

View File

@ -0,0 +1,154 @@
package com.massivecraft.factions.commands;
import java.util.ArrayList;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.util.TextUtil;
public class FCommandHelp extends FBaseCommand {
public FCommandHelp() {
aliases.add("help");
aliases.add("h");
aliases.add("?");
optionalParameters.add("page");
helpDescription = "Display a help page";
}
@Override
public boolean hasPermission(CommandSender sender) {
return true;
}
@Override
public void perform() {
int page = 1;
if (parameters.size() > 0) {
try {
page = Integer.parseInt(parameters.get(0));
} catch (NumberFormatException e) {
// wasn't an integer
}
}
sendMessage(TextUtil.titleize("Factions Help ("+page+"/"+helpPages.size()+")"));
page -= 1;
if (page < 0 || page >= helpPages.size()) {
sendMessage("This page does not exist");
return;
}
sendMessage(helpPages.get(page));
}
//----------------------------------------------//
// Build the help pages
//----------------------------------------------//
public static final ArrayList<ArrayList<String>> helpPages;
static {
helpPages = new ArrayList<ArrayList<String>>();
ArrayList<String> pageLines;
pageLines = new ArrayList<String>();
pageLines.add( new FCommandHelp().getUseageTemplate() );
pageLines.add( new FCommandList().getUseageTemplate() );
pageLines.add( new FCommandShow().getUseageTemplate() );
pageLines.add( new FCommandMap().getUseageTemplate() );
pageLines.add( new FCommandJoin().getUseageTemplate() );
pageLines.add( new FCommandLeave().getUseageTemplate() );
pageLines.add( new FCommandChat().getUseageTemplate() );
pageLines.add( new FCommandHome().getUseageTemplate() );
pageLines.add( "Learn how to create a faction on the next page." );
helpPages.add(pageLines);
pageLines = new ArrayList<String>();
pageLines.add( new FCommandCreate().getUseageTemplate() );
pageLines.add( new FCommandDescription().getUseageTemplate() );
pageLines.add( new FCommandTag().getUseageTemplate() );
pageLines.add( "You might want to close it and use invitations:" );
pageLines.add( new FCommandOpen().getUseageTemplate() );
pageLines.add( new FCommandInvite().getUseageTemplate() );
pageLines.add( new FCommandDeinvite().getUseageTemplate() );
pageLines.add( "And don't forget to set your home:" );
pageLines.add( new FCommandSethome().getUseageTemplate() );
helpPages.add(pageLines);
pageLines = new ArrayList<String>();
pageLines.add( new FCommandClaim().getUseageTemplate() );
pageLines.add( new FCommandAutoClaim().getUseageTemplate() );
pageLines.add( new FCommandUnclaim().getUseageTemplate() );
pageLines.add( new FCommandUnclaimall().getUseageTemplate() );
pageLines.add( new FCommandKick().getUseageTemplate() );
pageLines.add( new FCommandMod().getUseageTemplate() );
pageLines.add( new FCommandAdmin().getUseageTemplate() );
pageLines.add( new FCommandTitle().getUseageTemplate() );
pageLines.add( "Player titles are just for fun. No rules connected to them." );
helpPages.add(pageLines);
pageLines = new ArrayList<String>();
pageLines.add( new FCommandRelationAlly().getUseageTemplate() );
pageLines.add( new FCommandRelationNeutral().getUseageTemplate() );
pageLines.add( new FCommandRelationEnemy().getUseageTemplate() );
pageLines.add("");
pageLines.add("Set the relation you WISH to have with another faction.");
pageLines.add("Your default relation with other factions will be neutral.");
pageLines.add("");
pageLines.add("If BOTH factions choose \"ally\" you will be allies.");
pageLines.add("If ONE faction chooses \"enemy\" you will be enemies.");
helpPages.add(pageLines);
pageLines = new ArrayList<String>();
pageLines.add("You can never hurt members or allies.");
pageLines.add("You can not hurt neutrals in their own territory.");
pageLines.add("You can always hurt enemies and players without faction.");
pageLines.add("");
pageLines.add("Damage from enemies is reduced in your own territory.");
pageLines.add("When you die you lose power. It is restored over time.");
pageLines.add("The power of a faction is the sum of all member power.");
pageLines.add("The power of a faction determines how much land it can hold.");
pageLines.add("You can claim land from factions with too little power.");
helpPages.add(pageLines);
pageLines = new ArrayList<String>();
pageLines.add("Only faction members can build and destroy in their own");
pageLines.add("territory. Usage of the following items is also restricted:");
pageLines.add("Door, Chest, Furnace and Dispenser.");
pageLines.add("");
pageLines.add("Make sure to put pressure plates in front of doors for your");
pageLines.add("guest visitors. Otherwise they can't get through. You can");
pageLines.add("also use this to create member only areas.");
pageLines.add("As dispensers are protected, you can create traps without");
pageLines.add("worrying about those arrows getting stolen.");
helpPages.add(pageLines);
pageLines = new ArrayList<String>();
pageLines.add("Finally some commands for the server admins:");
pageLines.add( new FCommandDisband().getUseageTemplate() );
pageLines.add( new FCommandSafeclaim().getUseageTemplate() );
pageLines.add( new FCommandAutoSafeclaim().getUseageTemplate() );
pageLines.add( new FCommandSafeunclaimall().getUseageTemplate() );
pageLines.add( new FCommandWarclaim().getUseageTemplate() );
pageLines.add( new FCommandAutoWarclaim().getUseageTemplate() );
pageLines.add( new FCommandWarunclaimall().getUseageTemplate() );
pageLines.add("Note: " + Conf.colorCommand + "f unclaim" + Conf.colorSystem + " works on safe/war zones as well.");
helpPages.add(pageLines);
pageLines = new ArrayList<String>();
pageLines.add("More commands for server admins:");
pageLines.add( new FCommandBypass().getUseageTemplate() );
pageLines.add( new FCommandWorldNoClaim().getUseageTemplate() );
pageLines.add( new FCommandWorldNoPowerLoss().getUseageTemplate() );
pageLines.add( new FCommandLock().getUseageTemplate() );
pageLines.add( new FCommandReload().getUseageTemplate() );
pageLines.add( new FCommandSaveAll().getUseageTemplate() );
pageLines.add( new FCommandVersion().getUseageTemplate() );
helpPages.add(pageLines);
}
}

View File

@ -0,0 +1,94 @@
package com.massivecraft.factions.commands;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.entity.Player;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FLocation;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Relation;
import com.massivecraft.factions.struct.Role;
public class FCommandHome extends FBaseCommand {
public FCommandHome() {
aliases.add("home");
helpDescription = "Teleport to the faction home";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if ( ! Conf.homesEnabled) {
me.sendMessage("Sorry, Faction homes are disabled on this server.");
return;
}
if ( ! Conf.homesTeleportCommandEnabled) {
me.sendMessage("Sorry, the ability to teleport to Faction homes is disabled on this server.");
return;
}
Faction myFaction = me.getFaction();
if ( ! myFaction.hasHome()) {
me.sendMessage("You faction does not have a home. " + (me.getRole().value < Role.MODERATOR.value ? " Ask your leader to:" : "You should:"));
me.sendMessage(new FCommandSethome().getUseageTemplate());
return;
}
if (!Conf.homesTeleportAllowedFromEnemyTerritory && me.isInEnemyTerritory()) {
me.sendMessage("You cannot teleport to your faction home while in the territory of an enemy faction.");
return;
}
if (!Conf.homesTeleportAllowedFromDifferentWorld && player.getWorld().getUID() != myFaction.getHome().getWorld().getUID()) {
me.sendMessage("You cannot teleport to your faction home while in a different world.");
return;
}
Faction faction = Board.getFactionAt(new FLocation(player.getLocation()));
// if player is not in a safe zone or their own faction territory, only allow teleport if no enemies are nearby
if (Conf.homesTeleportAllowedEnemyDistance > 0 && ! faction.isSafeZone() && ! me.isInOwnTerritory()) {
Location loc = player.getLocation();
World w = loc.getWorld();
double x = loc.getX();
double y = loc.getY();
double z = loc.getZ();
for (Player p : player.getServer().getOnlinePlayers())
{
if (p == null || !p.isOnline() || p.isDead() || p == player || p.getWorld() != w)
continue;
FPlayer fp = FPlayer.get(p);
if (me.getRelation(fp) != Relation.ENEMY)
continue;
Location l = p.getLocation();
double dx = Math.abs(x - l.getX());
double dy = Math.abs(y - l.getY());
double dz = Math.abs(z - l.getZ());
double max = Conf.homesTeleportAllowedEnemyDistance;
// box-shaped distance check
if (dx > max || dy > max || dz > max)
continue;
me.sendMessage("You cannot teleport to your faction home while an enemy is within " + Conf.homesTeleportAllowedEnemyDistance + " blocks of you.");
return;
}
}
player.teleport(myFaction.getHome());
}
}

View File

@ -0,0 +1,55 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
public class FCommandInvite extends FBaseCommand {
public FCommandInvite() {
aliases.add("invite");
aliases.add("inv");
requiredParameters.add("player name");
helpDescription = "Invite a player";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
if ( ! assertMinRole(Role.MODERATOR)) {
return;
}
String playerName = parameters.get(0);
FPlayer you = findFPlayer(playerName, false);
if (you == null) {
return;
}
Faction myFaction = me.getFaction();
if (you.getFaction() == myFaction) {
sendMessage(you.getName()+" is already a member of "+myFaction.getTag());
sendMessage("You might want to: " + new FCommandKick().getUseageTemplate(false));
return;
}
myFaction.invite(you);
you.sendMessage(me.getNameAndRelevant(you)+Conf.colorSystem+" invited you to "+myFaction.getTag(you));
myFaction.sendMessage(me.getNameAndRelevant(me)+Conf.colorSystem+" invited "+you.getNameAndRelevant(me)+Conf.colorSystem+" to your faction.");
}
}

View File

@ -0,0 +1,65 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Faction;
public class FCommandJoin extends FBaseCommand {
public FCommandJoin() {
aliases.add("join");
requiredParameters.add("faction name");
helpDescription = "Join a faction";
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
String factionName = parameters.get(0);
Faction faction = findFaction(factionName);
if (faction == null) {
return;
}
if ( ! faction.isNormal()) {
sendMessage("You may only join normal factions. This is a system faction.");
return;
}
if (faction == me.getFaction()) {
sendMessage("You are already a member of "+faction.getTag(me));
return;
}
if (me.hasFaction()) {
sendMessage("You must leave your current faction first.");
return;
}
if (!Conf.CanLeaveWithNegativePower && me.getPower() < 0) {
sendMessage("You cannot join a faction until your power is positive.");
return;
}
if( ! faction.getOpen() && ! faction.isInvited(me)) {
sendMessage("This guild requires invitation.");
faction.sendMessage(me.getNameAndRelevant(faction)+Conf.colorSystem+" tried to join your faction.");
return;
}
me.sendMessage(Conf.colorSystem+"You successfully joined "+faction.getTag(me));
faction.sendMessage(me.getNameAndRelevant(faction)+Conf.colorSystem+" joined your faction.");
me.resetFactionData();
me.setFaction(faction);
faction.deinvite(me);
}
}

View File

@ -0,0 +1,78 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
public class FCommandKick extends FBaseCommand {
public FCommandKick() {
aliases.add("kick");
requiredParameters.add("player name");
helpDescription = "Kick a player from the faction";
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
String playerName = parameters.get(0);
FPlayer you = findFPlayer(playerName, false);
if (you == null) {
return;
}
if (me == you) {
sendMessage("You cannot kick yourself.");
sendMessage("You might want to: " + new FCommandLeave().getUseageTemplate(false));
return;
}
Faction yourFaction = you.getFaction();
Faction myFaction = me.getFaction();
// players with admin-level "disband" permission can bypass these requirements
if (!Factions.hasPermDisband(sender)) {
if (yourFaction != myFaction) {
sendMessage(you.getNameAndRelevant(me)+Conf.colorSystem+" is not a member of "+myFaction.getTag(me));
return;
}
if (you.getRole().value >= me.getRole().value) { // TODO add more informative messages.
sendMessage("Your rank is too low to kick this player.");
return;
}
if (!Conf.CanLeaveWithNegativePower && you.getPower() < 0) {
sendMessage("You cannot kick that member until their power is positive.");
return;
}
}
yourFaction.sendMessage(me.getNameAndRelevant(yourFaction)+Conf.colorSystem+" kicked "+you.getNameAndRelevant(yourFaction)+Conf.colorSystem+" from the faction! :O");
you.sendMessage(me.getNameAndRelevant(you)+Conf.colorSystem+" kicked you from "+yourFaction.getTag(you)+Conf.colorSystem+"! :O");
if (yourFaction != myFaction) {
me.sendMessage(Conf.colorSystem+"You kicked "+you.getNameAndRelevant(myFaction)+Conf.colorSystem+" from the faction "+yourFaction.getTag(me)+Conf.colorSystem+"!");
}
yourFaction.deinvite(you);
you.resetFactionData();
if (yourFaction.getFPlayers().isEmpty()) {
// Remove this faction
for (FPlayer fplayer : FPlayer.getAllOnline()) {
fplayer.sendMessage("The faction "+yourFaction.getTag(fplayer)+Conf.colorSystem+" was disbanded.");
}
Faction.delete(yourFaction.getId());
}
}
}

View File

@ -0,0 +1,32 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
public class FCommandLeave extends FBaseCommand {
public FCommandLeave() {
aliases.add("leave");
helpDescription = "Leave your faction";
}
@Override
public boolean hasPermission(CommandSender sender) {
return true;
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
me.leave();
}
}

View File

@ -0,0 +1,97 @@
package com.massivecraft.factions.commands;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.util.TextUtil;
public class FCommandList extends FBaseCommand {
public FCommandList() {
aliases.add("list");
aliases.add("ls");
senderMustBePlayer = false;
optionalParameters.add("page");
helpDescription = "Show a list of the factions";
}
@Override
public boolean hasPermission(CommandSender sender) {
return true;
}
@Override
public void perform() {
ArrayList<Faction> FactionList = new ArrayList<Faction>(Faction.getAll());
FactionList.remove(Faction.getNone());
FactionList.remove(Faction.getSafeZone());
FactionList.remove(Faction.getWarZone());
int page = 1;
if (parameters.size() > 0) {
try {
page = Integer.parseInt(parameters.get(0));
} catch (NumberFormatException e) {
// wasn't an integer
}
}
page -= 1;
// Sort by total followers first
Collections.sort(FactionList, new Comparator<Faction>(){
@Override
public int compare(Faction f1, Faction f2) {
if (f1.getFPlayers().size() < f2.getFPlayers().size())
return 1;
else if (f1.getFPlayers().size() > f2.getFPlayers().size())
return -1;
return 0;
}
});
// Then sort by how many members are online now
Collections.sort(FactionList, new Comparator<Faction>(){
@Override
public int compare(Faction f1, Faction f2) {
if (f1.getFPlayersWhereOnline(true).size() < f2.getFPlayersWhereOnline(true).size())
return 1;
else if (f1.getFPlayersWhereOnline(true).size() > f2.getFPlayersWhereOnline(true).size())
return -1;
return 0;
}
});
FactionList.add(0, Faction.getNone());
int maxPage = (int)Math.floor((double)FactionList.size() / 9D);
if (page < 0 || page > maxPage) {
sendMessage("The faction list is only " + (maxPage+1) + " page(s) long");
return;
}
String header = "Faction List";
if (maxPage > 1) header += " (page " + (page+1) + " of " + (maxPage+1) + ")";
sendMessage(TextUtil.titleize(header));
int maxPos = (page+1) * 9;
if (maxPos > FactionList.size()) maxPos = FactionList.size();
for (int pos = page * 9; pos < maxPos; pos++) {
Faction faction = FactionList.get(pos);
if (faction.getId() == 0) {
sendMessage("Factionless"+Conf.colorSystem+" "+faction.getFPlayersWhereOnline(true).size() + " online");
} else {
sendMessage(faction.getTag(me)+Conf.colorSystem+" "+faction.getFPlayersWhereOnline(true).size()+"/"+faction.getFPlayers().size()+" online, "+faction.getLandRounded()+"/"+faction.getPowerRounded()+"/"+faction.getPowerMaxRounded());
}
}
}
}

View File

@ -0,0 +1,37 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Factions;
public class FCommandLock extends FBaseCommand {
public FCommandLock() {
aliases.add("lock");
senderMustBePlayer = false;
optionalParameters.add("on|off");
helpDescription = "lock all write stuff";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermLock(sender);
}
@Override
public void perform() {
if( parameters.size() > 0 ) {
setLock( parseBool( parameters.get(0) ));
} else {
if( isLocked() ) {
sendMessage("Factions is locked");
} else {
sendMessage("Factions is not locked");
}
}
}
}

View File

@ -0,0 +1,49 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.FLocation;
public class FCommandMap extends FBaseCommand {
public FCommandMap() {
aliases.add("map");
optionalParameters.add("on|off");
helpDescription = "Show territory map, set optional auto update";
}
@Override
public boolean hasPermission(CommandSender sender) {
return true;
}
@Override
public void perform() {
if (parameters.size() > 0) {
String mapAutoUpdating = parameters.get(0);
if (parseBool(mapAutoUpdating)) {
// Turn on
me.setMapAutoUpdating(true);
sendMessage("Map auto update ENABLED.");
// And show the map once
showMap();
} else {
// Turn off
me.setMapAutoUpdating(false);
sendMessage("Map auto update DISABLED.");
}
} else {
showMap();
}
}
public void showMap() {
sendMessage(Board.getMap(me.getFaction(), new FLocation(me), me.getPlayer().getLocation().getYaw()));
}
}

View File

@ -0,0 +1,63 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
public class FCommandMod extends FBaseCommand {
public FCommandMod() {
aliases.add("mod");
requiredParameters.add("player name");
helpDescription = "Give or revoke moderator rights";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
if ( ! assertMinRole(Role.ADMIN)) {
return;
}
String playerName = parameters.get(0);
FPlayer you = findFPlayer(playerName, false);
if (you == null) {
return;
}
Faction myFaction = me.getFaction();
if (you.getFaction() != myFaction) {
sendMessage(you.getNameAndRelevant(me)+Conf.colorSystem+" is not a member in your faction.");
return;
}
if (you == me) {
sendMessage("The target player musn't be yourself.");
return;
}
if (you.getRole() == Role.MODERATOR) {
// Revoke
you.setRole(Role.NORMAL);
myFaction.sendMessage(you.getNameAndRelevant(myFaction)+Conf.colorSystem+" is no longer moderator in your faction.");
} else {
// Give
you.setRole(Role.MODERATOR);
myFaction.sendMessage(you.getNameAndRelevant(myFaction)+Conf.colorSystem+" was promoted to moderator in your faction.");
}
}
}

View File

@ -0,0 +1,46 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
public class FCommandOpen extends FBaseCommand {
public FCommandOpen() {
aliases.add("open");
aliases.add("close");
helpDescription = "Switch if invitation is required to join";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
if ( ! assertMinRole(Role.MODERATOR)) {
return;
}
Faction myFaction = me.getFaction();
myFaction.setOpen( ! me.getFaction().getOpen());
String open = myFaction.getOpen() ? "open" : "closed";
// Inform
myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" changed the faction to "+open);
for (Faction faction : Faction.getAll()) {
if (faction == me.getFaction()) {
continue;
}
faction.sendMessage(Conf.colorSystem+"The faction "+myFaction.getTag(faction)+Conf.colorSystem+" is now "+open);
}
}
}

View File

@ -0,0 +1,22 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.struct.Relation;
public class FCommandRelationAlly extends FRelationCommand {
public FCommandRelationAlly() {
aliases.add("ally");
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
relation(Relation.ALLY, parameters.get(0));
}
}

View File

@ -0,0 +1,22 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.struct.Relation;
public class FCommandRelationEnemy extends FRelationCommand {
public FCommandRelationEnemy() {
aliases.add("enemy");
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
relation(Relation.ENEMY, parameters.get(0));
}
}

View File

@ -0,0 +1,22 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.struct.Relation;
public class FCommandRelationNeutral extends FRelationCommand {
public FCommandRelationNeutral() {
aliases.add("neutral");
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
relation(Relation.NEUTRAL, parameters.get(0));
}
}

View File

@ -0,0 +1,77 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
public class FCommandReload extends FBaseCommand {
public FCommandReload() {
aliases.add("reload");
senderMustBePlayer = false;
optionalParameters.add("file");
helpDescription = "reloads all json files, or a specific one";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermReload(sender);
}
@Override
public void perform() {
Factions.log("=== RELOAD START ===");
long timeInitStart = System.currentTimeMillis();
String fileName = "s";
// Was a single file specified?
if (parameters.size() > 0) {
String file = parameters.get(0);
if (file.equalsIgnoreCase("conf") || file.equalsIgnoreCase("conf.json")) {
Factions.log("RELOADING CONF.JSON");
Conf.load();
fileName = " conf.json";
}
else if (file.equalsIgnoreCase("board") || file.equalsIgnoreCase("board.json")) {
Factions.log("RELOADING BOARD.JSON");
Board.load();
fileName = " board.json";
}
else if (file.equalsIgnoreCase("factions") || file.equalsIgnoreCase("factions.json")) {
Factions.log("RELOADING FACTIONS.JSON");
Faction.load();
fileName = " factions.json";
}
else if (file.equalsIgnoreCase("players") || file.equalsIgnoreCase("players.json")) {
Factions.log("RELOADING PLAYERS.JSON");
FPlayer.load();
fileName = " players.json";
}
else {
Factions.log("RELOAD CANCELLED - SPECIFIED FILE INVALID");
sendMessage("Invalid file specified. Valid files: conf, board, factions, players.");
return;
}
}
else {
Factions.log("RELOADING ALL FILES");
Conf.load();
FPlayer.load();
Faction.load();
Board.load();
}
long timeReload = (System.currentTimeMillis()-timeInitStart);
Factions.log("=== RELOAD DONE (Took "+timeReload+"ms) ===");
sendMessage("Factions file" + fileName + " reloaded from disk, took " + timeReload + "ms");
}
}

View File

@ -0,0 +1,56 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.FLocation;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
public class FCommandSafeclaim extends FBaseCommand {
public FCommandSafeclaim() {
aliases.add("safeclaim");
aliases.add("safe");
optionalParameters.add("radius");
helpDescription = "Claim land for the safezone";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermManageSafeZone(sender);
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
// The current location of the player
FLocation playerFlocation = new FLocation(me);
// Was a radius set?
if (parameters.size() > 0) {
int radius = Integer.parseInt(parameters.get(0));
FLocation from = playerFlocation.getRelative(radius, radius);
FLocation to = playerFlocation.getRelative(-radius, -radius);
for (FLocation locToClaim : FLocation.getArea(from, to)) {
Board.setFactionAt(Faction.getSafeZone(), locToClaim);
}
sendMessage("You claimed "+(1+radius*2)*(1+radius*2)+" chunks for the safe zone.");
} else {
Board.setFactionAt(Faction.getSafeZone(), playerFlocation);
sendMessage("This land is now a safe zone.");
}
}
}

View File

@ -0,0 +1,35 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
public class FCommandSafeunclaimall extends FBaseCommand {
public FCommandSafeunclaimall() {
aliases.add("safeunclaimall");
aliases.add("safedeclaimall");
helpDescription = "Unclaim all safezone land";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermManageSafeZone(sender);
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
Board.unclaimAll(Faction.getSafeZone().getId());
sendMessage("You unclaimed ALL safe zone land.");
}
}

View File

@ -0,0 +1,30 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Factions;
public class FCommandSaveAll extends FBaseCommand {
public FCommandSaveAll() {
aliases.add("saveall");
aliases.add("save");
senderMustBePlayer = false;
helpDescription = "save factions to disk";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermSaveAll(sender);
}
@Override
public void perform() {
Factions.saveAll();
sendMessage("Factions saved to disk!");
}
}

View File

@ -0,0 +1,47 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
public class FCommandSethome extends FBaseCommand {
public FCommandSethome() {
aliases.add("sethome");
helpDescription = "Set the faction home";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
if ( ! assertMinRole(Role.MODERATOR)) {
return;
}
if ( ! Conf.homesEnabled) {
me.sendMessage("Sorry, Faction homes are disabled on this server.");
return;
}
if (Conf.homesMustBeInClaimedTerritory && !me.isInOwnTerritory()) {
me.sendMessage("Sorry, your faction home can only be set inside your own claimed territory.");
return;
}
Faction myFaction = me.getFaction();
myFaction.setHome(player.getLocation());
myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" set the home for your faction. You can now use:");
myFaction.sendMessage(new FCommandHome().getUseageTemplate());
}
}

View File

@ -0,0 +1,131 @@
package com.massivecraft.factions.commands;
import java.util.Collection;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.TextUtil;
public class FCommandShow extends FBaseCommand {
public FCommandShow() {
aliases.add("show");
aliases.add("who");
senderMustBePlayer = false;
optionalParameters.add("faction tag");
helpDescription = "Show faction information";
}
@Override
public boolean hasPermission(CommandSender sender) {
return true;
}
@Override
public void perform() {
Faction faction;
if (parameters.size() > 0) {
faction = findFaction(parameters.get(0), true);
} else if (!(sender instanceof Player)) {
sendMessage("From the command line, you must specify a faction tag (f who <faction tag>).");
return;
} else {
faction = me.getFaction();
}
if (faction == null) {
return;
}
Collection<FPlayer> admins = faction.getFPlayersWhereRole(Role.ADMIN);
Collection<FPlayer> mods = faction.getFPlayersWhereRole(Role.MODERATOR);
Collection<FPlayer> normals = faction.getFPlayersWhereRole(Role.NORMAL);
sendMessage(TextUtil.titleize(faction.getTag(me)));
sendMessage(Conf.colorChrome+"Description: "+Conf.colorSystem+faction.getDescription());
if ( ! faction.isNormal()) {
return;
}
if(faction.getOpen()) {
sendMessage(Conf.colorChrome+"Joining: "+Conf.colorSystem+"no invitation is needed");
} else {
sendMessage(Conf.colorChrome+"Joining: "+Conf.colorSystem+"invitation is required");
}
sendMessage(Conf.colorChrome+"Land / Power / Maxpower: "+Conf.colorSystem+ faction.getLandRounded()+" / "+faction.getPowerRounded()+" / "+faction.getPowerMaxRounded());
String listpart;
// List relation
String allyList = Conf.colorChrome+"Allies: ";
String enemyList = Conf.colorChrome+"Enemies: ";
for (Faction otherFaction : Faction.getAll()) {
if (otherFaction == faction) {
continue;
}
listpart = otherFaction.getTag(me)+Conf.colorSystem+", ";
if (otherFaction.getRelation(faction).isAlly()) {
allyList += listpart;
} else if (otherFaction.getRelation(faction).isEnemy()) {
enemyList += listpart;
}
}
if (allyList.endsWith(", ")) {
allyList = allyList.substring(0, allyList.length()-2);
}
if (enemyList.endsWith(", ")) {
enemyList = enemyList.substring(0, enemyList.length()-2);
}
sendMessage(allyList);
sendMessage(enemyList);
// List the members...
String onlineList = Conf.colorChrome+"Members online: ";
String offlineList = Conf.colorChrome+"Members offline: ";
for (FPlayer follower : admins) {
listpart = follower.getNameAndTitle(me)+Conf.colorSystem+", ";
if (follower.isOnline()) {
onlineList += listpart;
} else {
offlineList += listpart;
}
}
for (FPlayer follower : mods) {
listpart = follower.getNameAndTitle(me)+Conf.colorSystem+", ";
if (follower.isOnline()) {
onlineList += listpart;
} else {
offlineList += listpart;
}
}
for (FPlayer follower : normals) {
listpart = follower.getNameAndTitle(me)+Conf.colorSystem+", ";
if (follower.isOnline()) {
onlineList += listpart;
} else {
offlineList += listpart;
}
}
if (onlineList.endsWith(", ")) {
onlineList = onlineList.substring(0, onlineList.length()-2);
}
if (offlineList.endsWith(", ")) {
offlineList = offlineList.substring(0, offlineList.length()-2);
}
sendMessage(onlineList);
sendMessage(offlineList);
}
}

View File

@ -0,0 +1,66 @@
package com.massivecraft.factions.commands;
import java.util.ArrayList;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
import com.massivecraft.factions.util.TextUtil;
public class FCommandTag extends FBaseCommand {
public FCommandTag() {
aliases.add("tag");
requiredParameters.add("faction tag");
helpDescription = "Change the faction tag";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
if ( ! assertMinRole(Role.MODERATOR)) {
return;
}
String tag = parameters.get(0);
// TODO does not first test cover selfcase?
if (Faction.isTagTaken(tag) && ! TextUtil.getComparisonString(tag).equals(me.getFaction().getComparisonTag())) {
sendMessage("That tag is already taken");
return;
}
ArrayList<String> errors = new ArrayList<String>();
errors.addAll(Faction.validateTag(tag));
if (errors.size() > 0) {
sendMessage(errors);
return;
}
Faction myFaction = me.getFaction();
String oldtag = myFaction.getTag();
myFaction.setTag(tag);
// Inform
myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" changed your faction tag to "+Conf.colorMember+myFaction.getTag());
for (Faction faction : Faction.getAll()) {
if (faction == me.getFaction()) {
continue;
}
faction.sendMessage(Conf.colorSystem+"The faction "+me.getRelationColor(faction)+oldtag+Conf.colorSystem+" changed their name to "+myFaction.getTag(faction));
}
}
}

View File

@ -0,0 +1,51 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FPlayer;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.util.TextUtil;
public class FCommandTitle extends FBaseCommand {
public FCommandTitle() {
aliases.add("title");
requiredParameters.add("player name");
optionalParameters.add("title");
helpDescription = "Set or remove a players title";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
String playerName = parameters.get(0);
parameters.remove(0);
String title = TextUtil.implode(parameters);
FPlayer you = findFPlayer(playerName, false);
if (you == null) {
return;
}
if ( ! canIAdministerYou(me, you)) {
return;
}
you.setTitle(title);
// Inform
Faction myFaction = me.getFaction();
myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" changed a title: "+you.getNameAndRelevant(myFaction));
}
}

View File

@ -0,0 +1,78 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.FLocation;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
import com.massivecraft.factions.struct.Role;
public class FCommandUnclaim extends FBaseCommand {
public FCommandUnclaim() {
aliases.add("unclaim");
aliases.add("declaim");
helpDescription = "Unclaim the land where you are standing";
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
FLocation flocation = new FLocation(me);
Faction otherFaction = Board.getFactionAt(flocation);
if (otherFaction.isSafeZone()) {
if (Factions.hasPermManageSafeZone(sender)) {
Board.removeAt(flocation);
sendMessage("Safe zone was unclaimed.");
} else {
sendMessage("This is a safe zone. You lack permissions to unclaim.");
}
return;
}
else if (otherFaction.isWarZone()) {
if (Factions.hasPermManageWarZone(sender)) {
Board.removeAt(flocation);
sendMessage("War zone was unclaimed.");
} else {
sendMessage("This is a war zone. You lack permissions to unclaim.");
}
return;
}
if (Conf.adminBypassPlayers.contains(player.getName())) {
Board.removeAt(flocation);
otherFaction.sendMessage(me.getNameAndRelevant(otherFaction)+Conf.colorSystem+" unclaimed some of your land.");
sendMessage("You unclaimed this land.");
return;
}
if ( ! assertHasFaction()) {
return;
}
if ( ! assertMinRole(Role.MODERATOR)) {
return;
}
Faction myFaction = me.getFaction();
if ( myFaction != otherFaction) {
sendMessage("You don't own this land.");
return;
}
Board.removeAt(flocation);
myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" unclaimed some land.");
}
}

View File

@ -0,0 +1,38 @@
package com.massivecraft.factions.commands;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.struct.Role;
public class FCommandUnclaimall extends FBaseCommand {
public FCommandUnclaimall() {
aliases.add("unclaimall");
aliases.add("declaimall");
helpDescription = "Unclaim all of your factions land";
}
@Override
public void perform() {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
if ( ! assertMinRole(Role.MODERATOR)) {
return;
}
Faction myFaction = me.getFaction();
Board.unclaimAll(myFaction.getId());
myFaction.sendMessage(me.getNameAndRelevant(myFaction)+Conf.colorSystem+" unclaimed ALL of your factions land.");
}
}

View File

@ -0,0 +1,28 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Factions;
public class FCommandVersion extends FBaseCommand {
public FCommandVersion() {
aliases.add("version");
senderMustBePlayer = false;
helpDescription = "Which version are you using?";
}
@Override
public boolean hasPermission(CommandSender sender) {
return true;
}
@Override
public void perform() {
sendMessage("You are running "+Factions.instance.getDescription().getFullName());
}
}

View File

@ -0,0 +1,55 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.FLocation;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
public class FCommandWarclaim extends FBaseCommand {
public FCommandWarclaim() {
aliases.add("warclaim");
aliases.add("war");
optionalParameters.add("radius");
helpDescription = "Claim land for the warzone";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermManageWarZone(sender);
}
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
// The current location of the player
FLocation playerFlocation = new FLocation(me);
// Was a radius set?
if (parameters.size() > 0) {
int radius = Integer.parseInt(parameters.get(0));
FLocation from = playerFlocation.getRelative(radius, radius);
FLocation to = playerFlocation.getRelative(-radius, -radius);
for (FLocation locToClaim : FLocation.getArea(from, to)) {
Board.setFactionAt(Faction.getWarZone(), locToClaim);
}
sendMessage("You claimed "+(1+radius*2)*(1+radius*2)+" chunks for the war zone.");
} else {
Board.setFactionAt(Faction.getWarZone(), playerFlocation);
sendMessage("This land is now a war zone.");
}
}
}

View File

@ -0,0 +1,35 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Board;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
public class FCommandWarunclaimall extends FBaseCommand {
public FCommandWarunclaimall() {
aliases.add("warunclaimall");
aliases.add("wardeclaimall");
helpDescription = "Unclaim all warzone land";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermManageWarZone(sender);
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
Board.unclaimAll(Faction.getWarZone().getId());
sendMessage("You unclaimed ALL war zone land.");
}
}

View File

@ -0,0 +1,40 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Factions;
public class FCommandWorldNoClaim extends FBaseCommand {
public FCommandWorldNoClaim() {
aliases.add("worldnoclaim");
helpDescription = "Disable claims in this world";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermWorlds(sender);
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
String worldName = me.getPlayer().getWorld().getName();
if ( ! Conf.worldsNoClaiming.contains(worldName)) {
Conf.worldsNoClaiming.add(worldName);
me.sendMessage("Faction land claiming is now DISALLOWED in this world (\"" + worldName + "\").");
} else {
Conf.worldsNoClaiming.remove(worldName);
me.sendMessage("Faction land claiming is now ALLOWED in this world (\"" + worldName + "\").");
}
}
}

View File

@ -0,0 +1,40 @@
package com.massivecraft.factions.commands;
import org.bukkit.command.CommandSender;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Factions;
public class FCommandWorldNoPowerLoss extends FBaseCommand {
public FCommandWorldNoPowerLoss() {
aliases.add("worldnopowerloss");
helpDescription = "Disable power loss in this world";
}
@Override
public boolean hasPermission(CommandSender sender) {
return Factions.hasPermWorlds(sender);
}
@Override
public void perform() {
if( isLocked() ) {
sendLockMessage();
return;
}
String worldName = me.getPlayer().getWorld().getName();
if ( ! Conf.worldsNoPowerLoss.contains(worldName)) {
Conf.worldsNoPowerLoss.add(worldName);
me.sendMessage("Power loss from death is now DISABLED in this world (\"" + worldName + "\").");
} else {
Conf.worldsNoPowerLoss.remove(worldName);
me.sendMessage("Power loss from death is now ENABLED in this world (\"" + worldName + "\").");
}
}
}

View File

@ -0,0 +1,62 @@
package com.massivecraft.factions.commands;
import org.bukkit.ChatColor;
import com.massivecraft.factions.Conf;
import com.massivecraft.factions.Faction;
import com.massivecraft.factions.Factions;
import com.massivecraft.factions.struct.Relation;
import com.massivecraft.factions.struct.Role;
public class FRelationCommand extends FBaseCommand {
public FRelationCommand() {
requiredParameters.add("faction tag");
helpDescription = "Set relation wish to another faction";
}
public void relation(Relation whishedRelation, String otherFactionName) {
if ( ! assertHasFaction()) {
return;
}
if( isLocked() ) {
sendLockMessage();
return;
}
if ( ! assertMinRole(Role.MODERATOR)) {
return;
}
Faction myFaction = me.getFaction();
Faction otherFaction = findFaction(otherFactionName, false);
if (otherFaction == null) {
return;
}
if (otherFaction.getId() == 0) {
sendMessage("Nope! You can't :) The default faction is not a real faction.");
return;
}
if (otherFaction == myFaction) {
sendMessage("Nope! You can't declare a relation to yourself :)");
return;
}
myFaction.setRelationWish(otherFaction, whishedRelation);
Relation currentRelation = myFaction.getRelation(otherFaction);
ChatColor currentRelationColor = currentRelation.getColor();
if (whishedRelation == currentRelation) {
otherFaction.sendMessage(Conf.colorSystem+"Your faction is now "+currentRelationColor+whishedRelation.toString()+Conf.colorSystem+" to "+currentRelationColor+myFaction.getTag());
myFaction.sendMessage(Conf.colorSystem+"Your faction is now "+currentRelationColor+whishedRelation.toString()+Conf.colorSystem+" to "+currentRelationColor+otherFaction.getTag());
} else {
otherFaction.sendMessage(currentRelationColor+myFaction.getTag()+Conf.colorSystem+ " wishes to be your "+whishedRelation.getColor()+whishedRelation.toString());
otherFaction.sendMessage(Conf.colorSystem+"Type "+Conf.colorCommand+Factions.instance.getBaseCommand()+" "+whishedRelation+" "+myFaction.getTag()+Conf.colorSystem+" to accept.");
myFaction.sendMessage(currentRelationColor+otherFaction.getTag()+Conf.colorSystem+ " were informed that you wish to be "+whishedRelation.getColor()+whishedRelation);
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* Strategy for excluding anonymous and local classes.
*
* @author Joel Leitch
*/
final class AnonymousAndLocalClassExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipField(FieldAttributes f) {
return isAnonymousOrLocal(f.getDeclaredClass());
}
public boolean shouldSkipClass(Class<?> clazz) {
return isAnonymousOrLocal(clazz);
}
private boolean isAnonymousOrLocal(Class<?> clazz) {
return !Enum.class.isAssignableFrom(clazz)
&& (clazz.isAnonymousClass() || clazz.isLocalClass());
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Type;
import java.util.Map;
/**
* Captures all the common/shared logic between the old, ({@link MapTypeAdapter}, and
* the new, {@link MapAsArrayTypeAdapter}, map type adapters.
*
* @author Joel Leitch
*/
abstract class BaseMapTypeAdapter
implements JsonSerializer<Map<?, ?>>, JsonDeserializer<Map<?, ?>> {
protected static final JsonElement serialize(JsonSerializationContext context,
Object src, Type srcType) {
JsonSerializationContextDefault contextImpl = (JsonSerializationContextDefault) context;
return contextImpl.serialize(src, srcType, false);
}
@SuppressWarnings("unchecked")
protected static final Map<Object, Object> constructMapType(
Type mapType, JsonDeserializationContext context) {
JsonDeserializationContextDefault contextImpl = (JsonDeserializationContextDefault) context;
ObjectConstructor objectConstructor = contextImpl.getObjectConstructor();
return (Map<Object, Object>) objectConstructor.construct(mapType);
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* Defines generic cache interface.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
interface Cache<K, V> {
/**
* Adds the new value object into the cache for the given key. If the key already
* exists, then this method will override the value for the key.
*
* @param key the key identifier for the {@code value} object
* @param value the value object to store in the cache
*/
void addElement(K key, V value);
/**
* Retrieve the cached value for the given {@code key}.
*
* @param key the key identifying the value
* @return the cached value for the given {@code key}
*/
V getElement(K key);
/**
* Removes the value from the cache for the given key.
*
* @param key the key identifying the value to remove
* @return the value for the given {@code key}
*/
V removeElement(K key);
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* Converts the field name that uses camel-case define word separation into separate words that
* are separated by the provided {@code separatorString}.
*
* <p>The following is an example:</p>
* <pre>
* class IntWrapper {
* public int integerField = 0;
* }
*
* CamelCaseSeparatorNamingPolicy policy = new CamelCaseSeparatorNamingPolicy("_");
* String translatedFieldName =
* policy.translateName(IntWrapper.class.getField("integerField"));
*
* assert("integer_Field".equals(translatedFieldName));
* </pre>
*
* @author Joel Leitch
*/
final class CamelCaseSeparatorNamingPolicy extends RecursiveFieldNamingPolicy {
private final String separatorString;
/**
* Constructs a new CamelCaseSeparatorNamingPolicy object that will add the
* {@code separatorString} between each of the words separated by camel case.
*
* @param separatorString the string value to place between words
* @throws IllegalArgumentException thrown if the {@code separatorString} parameter
* is null or empty.
*/
public CamelCaseSeparatorNamingPolicy(String separatorString) {
$Gson$Preconditions.checkNotNull(separatorString);
$Gson$Preconditions.checkArgument(!"".equals(separatorString));
this.separatorString = separatorString;
}
@Override
protected String translateName(String target, Type fieldType,
Collection<Annotation> annnotations) {
StringBuilder translation = new StringBuilder();
for (int i = 0; i < target.length(); i++) {
char character = target.charAt(i);
if (Character.isUpperCase(character) && translation.length() != 0) {
translation.append(separatorString);
}
translation.append(character);
}
return translation.toString();
}
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* Exception class to indicate a circular reference error.
* This class is not part of the public API and hence is not public.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class CircularReferenceException extends RuntimeException {
private static final long serialVersionUID = 7444343294106513081L;
private final Object offendingNode;
CircularReferenceException(Object offendingNode) {
super("circular reference error");
this.offendingNode = offendingNode;
}
public IllegalStateException createDetailedException(FieldAttributes offendingField) {
StringBuilder msg = new StringBuilder(getMessage());
if (offendingField != null) {
msg.append("\n ").append("Offending field: ").append(offendingField.getName() + "\n");
}
if (offendingNode != null) {
msg.append("\n ").append("Offending object: ").append(offendingNode);
}
return new IllegalStateException(msg.toString(), this);
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* Performs numerous field naming translations wrapped up as one object.
*
* @author Joel Leitch
*/
abstract class CompositionFieldNamingPolicy extends RecursiveFieldNamingPolicy {
private final RecursiveFieldNamingPolicy[] fieldPolicies;
public CompositionFieldNamingPolicy(RecursiveFieldNamingPolicy... fieldNamingPolicies) {
if (fieldNamingPolicies == null) {
throw new NullPointerException("naming policies can not be null.");
}
this.fieldPolicies = fieldNamingPolicies;
}
@Override
protected String translateName(String target, Type fieldType, Collection<Annotation> annotations) {
for (RecursiveFieldNamingPolicy policy : fieldPolicies) {
target = policy.translateName(target, fieldType, annotations);
}
return target;
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Constructor;
/**
* Use the default constructor on the class to instantiate an object.
*
* @author Joel Leitch
*/
final class DefaultConstructorAllocator {
private static final Constructor<Null> NULL_CONSTRUCTOR = createNullConstructor();
private final Cache<Class<?>, Constructor<?>> constructorCache;
public DefaultConstructorAllocator() {
this(200);
}
public DefaultConstructorAllocator(int cacheSize) {
constructorCache = new LruCache<Class<?>, Constructor<?>>(cacheSize);
}
// for testing purpose
final boolean isInCache(Class<?> cacheKey) {
return constructorCache.getElement(cacheKey) != null;
}
private static final Constructor<Null> createNullConstructor() {
try {
return getNoArgsConstructor(Null.class);
} catch (Exception e) {
return null;
}
}
public <T> T newInstance(Class<T> c) throws Exception {
Constructor<T> constructor = findConstructor(c);
return (constructor != null) ? constructor.newInstance() : null;
}
@SuppressWarnings("unchecked")
private <T> Constructor<T> findConstructor(Class<T> c) {
Constructor<T> cachedElement = (Constructor<T>) constructorCache.getElement(c);
if (cachedElement != null) {
if (cachedElement == NULL_CONSTRUCTOR) {
return null;
} else {
return cachedElement;
}
}
Constructor<T> noArgsConstructor = getNoArgsConstructor(c);
if (noArgsConstructor != null) {
constructorCache.addElement(c, noArgsConstructor);
} else {
constructorCache.addElement(c, NULL_CONSTRUCTOR);
}
return noArgsConstructor;
}
private static <T> Constructor<T> getNoArgsConstructor(Class<T> c) {
try {
Constructor<T> declaredConstructor = c.getDeclaredConstructor();
declaredConstructor.setAccessible(true);
return declaredConstructor;
} catch (Exception e) {
return null;
}
}
// placeholder class for Null constructor
private static final class Null {
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import java.io.IOException;
/**
* A simple implementation of the {@link JsonElementVisitor} that simply delegates the method
* invocation onto a {@code delegate} instance of the {@link JsonElementVisitor}. This object
* can be used to build a chain of visitors such that each Visitor instance can perform some
* operation on the {@link JsonElement} and then pass on the input to the delegate. This kind
* of pattern is sometimes referred as a "Chain of Responsibility".
*
* <p>The following is an example use case:
*
* <pre>
* class JsonEscapingVisitor extends DelegatingJsonElementVisitor {
* public JsonEscapingVisitor(JsonElementVisitor) {
* super(visitor);
* }
*
* public void visitPrimitive(JsonPrimitive primitive) {
* JsonPrimitive escapedPrimitive = escapePrimitiveObject(primitive);
* super.visitPrimitive(escapedPrimitive);
* }
* }
*
* JsonElementVisitor visitor = new JsonEscapingVisitor(new FormattingVisitor());
* </pre></p>
*
* @author Joel Leitch
*/
final class DelegatingJsonElementVisitor implements JsonElementVisitor {
private final JsonElementVisitor delegate;
protected DelegatingJsonElementVisitor(JsonElementVisitor delegate) {
this.delegate = $Gson$Preconditions.checkNotNull(delegate);
}
public void endArray(JsonArray array) throws IOException {
delegate.endArray(array);
}
public void endObject(JsonObject object) throws IOException {
delegate.endObject(object);
}
public void startArray(JsonArray array) throws IOException {
delegate.startArray(array);
}
public void startObject(JsonObject object) throws IOException {
delegate.startObject(object);
}
public void visitArrayMember(JsonArray parent, JsonPrimitive member,
boolean isFirst) throws IOException {
delegate.visitArrayMember(parent, member, isFirst);
}
public void visitArrayMember(JsonArray parent, JsonArray member,
boolean isFirst) throws IOException {
delegate.visitArrayMember(parent, member, isFirst);
}
public void visitArrayMember(JsonArray parent, JsonObject member,
boolean isFirst) throws IOException {
delegate.visitArrayMember(parent, member, isFirst);
}
public void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
boolean isFirst) throws IOException {
delegate.visitObjectMember(parent, memberName, member, isFirst);
}
public void visitObjectMember(JsonObject parent, String memberName, JsonArray member,
boolean isFirst) throws IOException {
delegate.visitObjectMember(parent, memberName, member, isFirst);
}
public void visitObjectMember(JsonObject parent, String memberName, JsonObject member,
boolean isFirst) throws IOException {
delegate.visitObjectMember(parent, memberName, member, isFirst);
}
public void visitNullObjectMember(JsonObject parent, String memberName,
boolean isFirst) throws IOException {
delegate.visitNullObjectMember(parent, memberName, isFirst);
}
public void visitPrimitive(JsonPrimitive primitive) throws IOException {
delegate.visitPrimitive(primitive);
}
public void visitNull() throws IOException {
delegate.visitNull();
}
public void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException {
delegate.visitNullArrayMember(parent, isFirst);
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import java.util.Collection;
/**
* A wrapper class used to collect numerous {@link ExclusionStrategy} objects
* and perform a short-circuited OR operation.
*
* @author Joel Leitch
*/
final class DisjunctionExclusionStrategy implements ExclusionStrategy {
private final Collection<ExclusionStrategy> strategies;
DisjunctionExclusionStrategy(Collection<ExclusionStrategy> strategies) {
this.strategies = $Gson$Preconditions.checkNotNull(strategies);
}
public boolean shouldSkipField(FieldAttributes f) {
for (ExclusionStrategy strategy : strategies) {
if (strategy.shouldSkipField(f)) {
return true;
}
}
return false;
}
public boolean shouldSkipClass(Class<?> clazz) {
for (ExclusionStrategy strategy : strategies) {
if (strategy.shouldSkipClass(clazz)) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,160 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.io.IOException;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
/**
* A utility class that is used to perform JSON escaping so that ", <, >, etc. characters are
* properly encoded in the JSON string representation before returning to the client code.
*
* <p>This class contains a single method to escape a passed in string value:
* <pre>
* String jsonStringValue = "beforeQuote\"afterQuote";
* String escapedValue = Escaper.escapeJsonString(jsonStringValue);
* </pre></p>
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class Escaper {
private static final char[] HEX_CHARS = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
private static final Set<Character> JS_ESCAPE_CHARS;
private static final Set<Character> HTML_ESCAPE_CHARS;
static {
Set<Character> mandatoryEscapeSet = new HashSet<Character>();
mandatoryEscapeSet.add('"');
mandatoryEscapeSet.add('\\');
JS_ESCAPE_CHARS = Collections.unmodifiableSet(mandatoryEscapeSet);
Set<Character> htmlEscapeSet = new HashSet<Character>();
htmlEscapeSet.add('<');
htmlEscapeSet.add('>');
htmlEscapeSet.add('&');
htmlEscapeSet.add('=');
htmlEscapeSet.add('\'');
// htmlEscapeSet.add('/'); -- Removing slash for now since it causes some incompatibilities
HTML_ESCAPE_CHARS = Collections.unmodifiableSet(htmlEscapeSet);
}
private final boolean escapeHtmlCharacters;
Escaper(boolean escapeHtmlCharacters) {
this.escapeHtmlCharacters = escapeHtmlCharacters;
}
public String escapeJsonString(CharSequence plainText) {
StringBuilder escapedString = new StringBuilder(plainText.length() + 20);
try {
escapeJsonString(plainText, escapedString);
} catch (IOException e) {
throw new RuntimeException(e);
}
return escapedString.toString();
}
private void escapeJsonString(CharSequence plainText, StringBuilder out) throws IOException {
int pos = 0; // Index just past the last char in plainText written to out.
int len = plainText.length();
for (int charCount, i = 0; i < len; i += charCount) {
int codePoint = Character.codePointAt(plainText, i);
charCount = Character.charCount(codePoint);
if (!isControlCharacter(codePoint) && !mustEscapeCharInJsString(codePoint)) {
continue;
}
out.append(plainText, pos, i);
pos = i + charCount;
switch (codePoint) {
case '\b':
out.append("\\b");
break;
case '\t':
out.append("\\t");
break;
case '\n':
out.append("\\n");
break;
case '\f':
out.append("\\f");
break;
case '\r':
out.append("\\r");
break;
case '\\':
out.append("\\\\");
break;
case '/':
out.append("\\/");
break;
case '"':
out.append("\\\"");
break;
default:
appendHexJavaScriptRepresentation(codePoint, out);
break;
}
}
out.append(plainText, pos, len);
}
private boolean mustEscapeCharInJsString(int codepoint) {
if (!Character.isSupplementaryCodePoint(codepoint)) {
char c = (char) codepoint;
return JS_ESCAPE_CHARS.contains(c)
|| (escapeHtmlCharacters && HTML_ESCAPE_CHARS.contains(c));
}
return false;
}
private static boolean isControlCharacter(int codePoint) {
// JSON spec defines these code points as control characters, so they must be escaped
return codePoint < 0x20
|| codePoint == 0x2028 // Line separator
|| codePoint == 0x2029 // Paragraph separator
|| (codePoint >= 0x7f && codePoint <= 0x9f);
}
private static void appendHexJavaScriptRepresentation(int codePoint, Appendable out)
throws IOException {
if (Character.isSupplementaryCodePoint(codePoint)) {
// Handle supplementary unicode values which are not representable in
// javascript. We deal with these by escaping them as two 4B sequences
// so that they will round-trip properly when sent from java to javascript
// and back.
char[] surrogates = Character.toChars(codePoint);
appendHexJavaScriptRepresentation(surrogates[0], out);
appendHexJavaScriptRepresentation(surrogates[1], out);
return;
}
out.append("\\u")
.append(HEX_CHARS[(codePoint >>> 12) & 0xf])
.append(HEX_CHARS[(codePoint >>> 8) & 0xf])
.append(HEX_CHARS[(codePoint >>> 4) & 0xf])
.append(HEX_CHARS[codePoint & 0xf]);
}
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* A strategy (or policy) definition that is used to decide whether or not a field or top-level
* class should be serialized or deserialized as part of the JSON output/input. For serialization,
* if the {@link #shouldSkipClass(Class)} method returns false then that class or field type
* will not be part of the JSON output. For deserialization, if {@link #shouldSkipClass(Class)}
* returns false, then it will not be set as part of the Java object structure.
*
* <p>The following are a few examples that shows how you can use this exclusion mechanism.
*
* <p><strong>Exclude fields and objects based on a particular class type:</strong>
* <pre class="code">
* private static class SpecificClassExclusionStrategy implements ExclusionStrategy {
* private final Class&lt;?&gt; excludedThisClass;
*
* public SpecificClassExclusionStrategy(Class&lt;?&gt; excludedThisClass) {
* this.excludedThisClass = excludedThisClass;
* }
*
* public boolean shouldSkipClass(Class&lt;?&gt; clazz) {
* return excludedThisClass.equals(clazz);
* }
*
* public boolean shouldSkipField(FieldAttributes f) {
* return excludedThisClass.equals(f.getDeclaredClass());
* }
* }
* </pre>
*
* <p><strong>Excludes fields and objects based on a particular annotation:</strong>
* <pre class="code">
* public &#64interface FooAnnotation {
* // some implementation here
* }
*
* // Excludes any field (or class) that is tagged with an "&#64FooAnnotation"
* private static class FooAnnotationExclusionStrategy implements ExclusionStrategy {
* public boolean shouldSkipClass(Class&lt;?&gt; clazz) {
* return clazz.getAnnotation(FooAnnotation.class) != null;
* }
*
* public boolean shouldSkipField(FieldAttributes f) {
* return f.getAnnotation(FooAnnotation.class) != null;
* }
* }
* </pre>
*
* <p>Now if you want to configure {@code Gson} to use a user defined exclusion strategy, then
* the {@code GsonBuilder} is required. The following is an example of how you can use the
* {@code GsonBuilder} to configure Gson to use one of the above sample:
* <pre class="code">
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
* Gson gson = new GsonBuilder()
* .setExclusionStrategies(excludeStrings)
* .create();
* </pre>
*
* <p>For certain model classes, you may only want to serialize a field, but exclude it for
* deserialization. To do that, you can write an {@code ExclusionStrategy} as per normal;
* however, you would register it with the
* {@link GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)} method.
* For example:
* <pre class="code">
* ExclusionStrategy excludeStrings = new UserDefinedExclusionStrategy(String.class);
* Gson gson = new GsonBuilder()
* .addDeserializationExclusionStrategy(excludeStrings)
* .create();
* </pre>
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @see GsonBuilder#setExclusionStrategies(ExclusionStrategy...)
* @see GsonBuilder#addDeserializationExclusionStrategy(ExclusionStrategy)
* @see GsonBuilder#addSerializationExclusionStrategy(ExclusionStrategy)
*
* @since 1.4
*/
public interface ExclusionStrategy {
/**
* @param f the field object that is under test
* @return true if the field should be ignored; otherwise false
*/
public boolean shouldSkipField(FieldAttributes f);
/**
* @param clazz the class object that is under test
* @return true if the class should be ignored; otherwise false
*/
public boolean shouldSkipClass(Class<?> clazz);
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.annotations.Expose;
/**
* Excludes fields that do not have the {@link Expose} annotation
*
* @author Joel Leitch
*/
final class ExposeAnnotationDeserializationExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
Expose annotation = f.getAnnotation(Expose.class);
if (annotation == null) {
return true;
}
return !annotation.deserialize();
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2011 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.annotations.Expose;
/**
* Excludes fields that do not have the {@link Expose} annotation
*
* @author Joel Leitch
*/
final class ExposeAnnotationSerializationExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
Expose annotation = f.getAnnotation(Expose.class);
if (annotation == null) {
return true;
}
return !annotation.serialize();
}
}

View File

@ -0,0 +1,255 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import com.massivecraft.factions.gson.internal.$Gson$Types;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
/**
* A data object that stores attributes of a field.
*
* <p>This class is immutable; therefore, it can be safely shared across threads.
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @since 1.4
*/
public final class FieldAttributes {
private static final String MAX_CACHE_PROPERTY_NAME =
"com.google.gson.annotation_cache_size_hint";
private static final Cache<Pair<Class<?>, String>, Collection<Annotation>> ANNOTATION_CACHE =
new LruCache<Pair<Class<?>,String>, Collection<Annotation>>(getMaxCacheSize());
private final Class<?> declaringClazz;
private final Field field;
private final Class<?> declaredType;
private final boolean isSynthetic;
private final int modifiers;
private final String name;
private final Type resolvedType;
// Fields used for lazy initialization
private Type genericType;
private Collection<Annotation> annotations;
/**
* Constructs a Field Attributes object from the {@code f}.
*
* @param f the field to pull attributes from
* @param declaringType The type in which the field is declared
*/
FieldAttributes(Class<?> declaringClazz, Field f, Type declaringType) {
this.declaringClazz = $Gson$Preconditions.checkNotNull(declaringClazz);
this.name = f.getName();
this.declaredType = f.getType();
this.isSynthetic = f.isSynthetic();
this.modifiers = f.getModifiers();
this.field = f;
this.resolvedType = getTypeInfoForField(f, declaringType);
}
private static int getMaxCacheSize() {
final int defaultMaxCacheSize = 2000;
try {
String propertyValue = System.getProperty(
MAX_CACHE_PROPERTY_NAME, String.valueOf(defaultMaxCacheSize));
return Integer.parseInt(propertyValue);
} catch (NumberFormatException e) {
return defaultMaxCacheSize;
}
}
/**
* @return the declaring class that contains this field
*/
public Class<?> getDeclaringClass() {
return declaringClazz;
}
/**
* @return the name of the field
*/
public String getName() {
return name;
}
/**
* <p>For example, assume the following class definition:
* <pre class="code">
* public class Foo {
* private String bar;
* private List&lt;String&gt; red;
* }
*
* Type listParmeterizedType = new TypeToken<List<String>>() {}.getType();
* </pre>
*
* <p>This method would return {@code String.class} for the {@code bar} field and
* {@code listParameterizedType} for the {@code red} field.
*
* @return the specific type declared for this field
*/
public Type getDeclaredType() {
if (genericType == null) {
genericType = field.getGenericType();
}
return genericType;
}
/**
* Returns the {@code Class<?>} object that was declared for this field.
*
* <p>For example, assume the following class definition:
* <pre class="code">
* public class Foo {
* private String bar;
* private List&lt;String&gt; red;
* }
* </pre>
*
* <p>This method would return {@code String.class} for the {@code bar} field and
* {@code List.class} for the {@code red} field.
*
* @return the specific class object that was declared for the field
*/
public Class<?> getDeclaredClass() {
return declaredType;
}
/**
* Return the {@code T} annotation object from this field if it exist; otherwise returns
* {@code null}.
*
* @param annotation the class of the annotation that will be retrieved
* @return the annotation instance if it is bound to the field; otherwise {@code null}
*/
public <T extends Annotation> T getAnnotation(Class<T> annotation) {
return getAnnotationFromArray(getAnnotations(), annotation);
}
/**
* Return the annotations that are present on this field.
*
* @return an array of all the annotations set on the field
* @since 1.4
*/
public Collection<Annotation> getAnnotations() {
if (annotations == null) {
Pair<Class<?>, String> key = new Pair<Class<?>, String>(declaringClazz, name);
annotations = ANNOTATION_CACHE.getElement(key);
if (annotations == null) {
annotations = Collections.unmodifiableCollection(
Arrays.asList(field.getAnnotations()));
ANNOTATION_CACHE.addElement(key, annotations);
}
}
return annotations;
}
/**
* Returns {@code true} if the field is defined with the {@code modifier}.
*
* <p>This method is meant to be called as:
* <pre class="code">
* boolean hasPublicModifier = fieldAttribute.hasModifier(java.lang.reflect.Modifier.PUBLIC);
* </pre>
*
* @see java.lang.reflect.Modifier
*/
public boolean hasModifier(int modifier) {
return (modifiers & modifier) != 0;
}
/**
* This is exposed internally only for the removing synthetic fields from the JSON output.
*
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
void set(Object instance, Object value) throws IllegalAccessException {
field.set(instance, value);
}
/**
* This is exposed internally only for the removing synthetic fields from the JSON output.
*
* @return true if the field is synthetic; otherwise false
* @throws IllegalAccessException
* @throws IllegalArgumentException
*/
Object get(Object instance) throws IllegalAccessException {
return field.get(instance);
}
/**
* This is exposed internally only for the removing synthetic fields from the JSON output.
*
* @return true if the field is synthetic; otherwise false
*/
boolean isSynthetic() {
return isSynthetic;
}
/**
* @deprecated remove this when {@link FieldNamingStrategy} is deleted.
*/
@Deprecated
Field getFieldObject() {
return field;
}
Type getResolvedType() {
return resolvedType;
}
@SuppressWarnings("unchecked")
private static <T extends Annotation> T getAnnotationFromArray(
Collection<Annotation> annotations, Class<T> annotation) {
for (Annotation a : annotations) {
if (a.annotationType() == annotation) {
return (T) a;
}
}
return null;
}
/**
* Evaluates the "actual" type for the field. If the field is a "TypeVariable" or has a
* "TypeVariable" in a parameterized type then it evaluates the real type.
*
* @param f the actual field object to retrieve the type from
* @param typeDefiningF the type that contains the field {@code f}
* @return the type information for the field
*/
static Type getTypeInfoForField(Field f, Type typeDefiningF) {
Class<?> rawType = $Gson$Types.getRawType(typeDefiningF);
if (!f.getDeclaringClass().isAssignableFrom(rawType)) {
// this field is unrelated to the type; the user probably omitted type information
return f.getGenericType();
}
return $Gson$Types.resolve(typeDefiningF, rawType, f.getGenericType());
}
}

View File

@ -0,0 +1,99 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* An enumeration that defines a few standard naming conventions for JSON field names.
* This enumeration should be used in conjunction with {@link com.massivecraft.factions.gson.GsonBuilder}
* to configure a {@link com.massivecraft.factions.gson.Gson} instance to properly translate Java field
* names into the desired JSON field names.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public enum FieldNamingPolicy {
/**
* Using this naming policy with Gson will ensure that the first "letter" of the Java
* field name is capitalized when serialized to its JSON form.
*
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
* <ul>
* <li>someFieldName ---> SomeFieldName</li>
* <li>_someFieldName ---> _SomeFieldName</li>
* </ul>
*/
UPPER_CAMEL_CASE(new ModifyFirstLetterNamingPolicy(
ModifyFirstLetterNamingPolicy.LetterModifier.UPPER)),
/**
* Using this naming policy with Gson will ensure that the first "letter" of the Java
* field name is capitalized when serialized to its JSON form and the words will be
* separated by a space.
*
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
* <ul>
* <li>someFieldName ---> Some Field Name</li>
* <li>_someFieldName ---> _Some Field Name</li>
* </ul>
*
* @since 1.4
*/
UPPER_CAMEL_CASE_WITH_SPACES(new UpperCamelCaseSeparatorNamingPolicy(" ")),
/**
* Using this naming policy with Gson will modify the Java Field name from its camel cased
* form to a lower case field name where each word is separated by an underscore (_).
*
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
* <ul>
* <li>someFieldName ---> some_field_name</li>
* <li>_someFieldName ---> _some_field_name</li>
* <li>aStringField ---> a_string_field</li>
* <li>aURL ---> a_u_r_l</li>
* </ul>
*/
LOWER_CASE_WITH_UNDERSCORES(new LowerCamelCaseSeparatorNamingPolicy("_")),
/**
* Using this naming policy with Gson will modify the Java Field name from its camel cased
* form to a lower case field name where each word is separated by a dash (-).
*
* <p>Here's a few examples of the form "Java Field Name" ---> "JSON Field Name":</p>
* <ul>
* <li>someFieldName ---> some-field-name</li>
* <li>_someFieldName ---> _some-field-name</li>
* <li>aStringField ---> a-string-field</li>
* <li>aURL ---> a-u-r-l</li>
* </ul>
* Using dashes in JavaScript is not recommended since dash is also used for a minus sign in
* expressions. This requires that a field named with dashes is always accessed as a quoted
* property like {@code myobject['my-field']}. Accessing it as an object field
* {@code myobject.my-field} will result in an unintended javascript expression.
* @since 1.4
*/
LOWER_CASE_WITH_DASHES(new LowerCamelCaseSeparatorNamingPolicy("-"));
private final FieldNamingStrategy2 namingPolicy;
private FieldNamingPolicy(FieldNamingStrategy2 namingPolicy) {
this.namingPolicy = namingPolicy;
}
FieldNamingStrategy2 getFieldNamingPolicy() {
return namingPolicy;
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Field;
/**
* A mechanism for providing custom field naming in Gson. This allows the client code to translate
* field names into a particular convention that is not supported as a normal Java field
* declaration rules. For example, Java does not support "-" characters in a field name.
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.3
*/
public interface FieldNamingStrategy {
/**
* Translates the field name into its JSON field name representation.
*
* @param f the field object that we are translating
* @return the translated field name.
* @since 1.3
*/
public String translateName(Field f);
}

View File

@ -0,0 +1,37 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* The new mechanism for providing custom field naming in Gson. This allows the client code
* to translate field names into a particular convention that is not supported as a normal
* Java field declaration rules. For example, Java does not support "-" characters in a
* field name.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
interface FieldNamingStrategy2 {
/**
* Translates the field name into its JSON field name representation.
*
* @param f the field that is being translated
* @return the translated field name.
*/
public String translateName(FieldAttributes f);
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
/**
* Adapts the old FieldNamingStrategy to the new {@link FieldNamingStrategy2}
* type.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class FieldNamingStrategy2Adapter implements FieldNamingStrategy2 {
private final FieldNamingStrategy adaptee;
FieldNamingStrategy2Adapter(FieldNamingStrategy adaptee) {
this.adaptee = $Gson$Preconditions.checkNotNull(adaptee);
}
public String translateName(FieldAttributes f) {
return adaptee.translateName(f.getFieldObject());
}
}

View File

@ -0,0 +1,570 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.stream.JsonReader;
import com.massivecraft.factions.gson.stream.JsonToken;
import com.massivecraft.factions.gson.stream.JsonWriter;
import com.massivecraft.factions.gson.stream.MalformedJsonException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* This is the main class for using Gson. Gson is typically used by first constructing a
* Gson instance and then invoking {@link #toJson(Object)} or {@link #fromJson(String, Class)}
* methods on it.
*
* <p>You can create a Gson instance by invoking {@code new Gson()} if the default configuration
* is all you need. You can also use {@link GsonBuilder} to build a Gson instance with various
* configuration options such as versioning support, pretty printing, custom
* {@link JsonSerializer}s, {@link JsonDeserializer}s, and {@link InstanceCreator}s.</p>
*
* <p>Here is an example of how Gson is used for a simple Class:
*
* <pre>
* Gson gson = new Gson(); // Or use new GsonBuilder().create();
* MyType target = new MyType();
* String json = gson.toJson(target); // serializes target to Json
* MyType target2 = gson.fromJson(json, MyType.class); // deserializes json into target2
* </pre></p>
*
* <p>If the object that your are serializing/deserializing is a {@code ParameterizedType}
* (i.e. contains at least one type parameter and may be an array) then you must use the
* {@link #toJson(Object, Type)} or {@link #fromJson(String, Type)} method. Here is an
* example for serializing and deserialing a {@code ParameterizedType}:
*
* <pre>
* Type listType = new TypeToken&lt;List&lt;String&gt;&gt;() {}.getType();
* List&lt;String&gt; target = new LinkedList&lt;String&gt;();
* target.add("blah");
*
* Gson gson = new Gson();
* String json = gson.toJson(target, listType);
* List&lt;String&gt; target2 = gson.fromJson(json, listType);
* </pre></p>
*
* <p>See the <a href="https://sites.google.com/site/gson/gson-user-guide">Gson User Guide</a>
* for a more complete set of examples.</p>
*
* @see com.massivecraft.factions.gson.reflect.TypeToken
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class Gson {
//TODO(inder): get rid of all the registerXXX methods and take all such parameters in the
// constructor instead. At the minimum, mark those methods private.
static final boolean DEFAULT_JSON_NON_EXECUTABLE = false;
// Default instances of plug-ins
static final AnonymousAndLocalClassExclusionStrategy DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY =
new AnonymousAndLocalClassExclusionStrategy();
static final SyntheticFieldExclusionStrategy DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY =
new SyntheticFieldExclusionStrategy(true);
static final ModifierBasedExclusionStrategy DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY =
new ModifierBasedExclusionStrategy(new int[] { Modifier.TRANSIENT, Modifier.STATIC });
static final FieldNamingStrategy2 DEFAULT_NAMING_POLICY =
new SerializedNameAnnotationInterceptingNamingPolicy(new JavaFieldNamingPolicy());
private static final ExclusionStrategy DEFAULT_EXCLUSION_STRATEGY = createExclusionStrategy();
private static final String JSON_NON_EXECUTABLE_PREFIX = ")]}'\n";
private final ExclusionStrategy deserializationExclusionStrategy;
private final ExclusionStrategy serializationExclusionStrategy;
private final FieldNamingStrategy2 fieldNamingPolicy;
private final MappedObjectConstructor objectConstructor;
/** Map containing Type or Class objects as keys */
private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers;
/** Map containing Type or Class objects as keys */
private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
private final boolean serializeNulls;
private final boolean htmlSafe;
private final boolean generateNonExecutableJson;
private final boolean prettyPrinting;
/**
* Constructs a Gson object with default configuration. The default configuration has the
* following settings:
* <ul>
* <li>The JSON generated by <code>toJson</code> methods is in compact representation. This
* means that all the unneeded white-space is removed. You can change this behavior with
* {@link GsonBuilder#setPrettyPrinting()}. </li>
* <li>The generated JSON omits all the fields that are null. Note that nulls in arrays are
* kept as is since an array is an ordered list. Moreover, if a field is not null, but its
* generated JSON is empty, the field is kept. You can configure Gson to serialize null values
* by setting {@link GsonBuilder#serializeNulls()}.</li>
* <li>Gson provides default serialization and deserialization for Enums, {@link Map},
* {@link java.net.URL}, {@link java.net.URI}, {@link java.util.Locale}, {@link java.util.Date},
* {@link java.math.BigDecimal}, and {@link java.math.BigInteger} classes. If you would prefer
* to change the default representation, you can do so by registering a type adapter through
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}. </li>
* <li>The default Date format is same as {@link java.text.DateFormat#DEFAULT}. This format
* ignores the millisecond portion of the date during serialization. You can change
* this by invoking {@link GsonBuilder#setDateFormat(int)} or
* {@link GsonBuilder#setDateFormat(String)}. </li>
* <li>By default, Gson ignores the {@link com.massivecraft.factions.gson.annotations.Expose} annotation.
* You can enable Gson to serialize/deserialize only those fields marked with this annotation
* through {@link GsonBuilder#excludeFieldsWithoutExposeAnnotation()}. </li>
* <li>By default, Gson ignores the {@link com.massivecraft.factions.gson.annotations.Since} annotation. You
* can enable Gson to use this annotation through {@link GsonBuilder#setVersion(double)}.</li>
* <li>The default field naming policy for the output Json is same as in Java. So, a Java class
* field <code>versionNumber</code> will be output as <code>&quot;versionNumber@quot;</code> in
* Json. The same rules are applied for mapping incoming Json to the Java classes. You can
* change this policy through {@link GsonBuilder#setFieldNamingPolicy(FieldNamingPolicy)}.</li>
* <li>By default, Gson excludes <code>transient</code> or <code>static</code> fields from
* consideration for serialization and deserialization. You can change this behavior through
* {@link GsonBuilder#excludeFieldsWithModifiers(int...)}.</li>
* </ul>
*/
public Gson() {
this(DEFAULT_EXCLUSION_STRATEGY, DEFAULT_EXCLUSION_STRATEGY, DEFAULT_NAMING_POLICY,
new MappedObjectConstructor(DefaultTypeAdapters.getDefaultInstanceCreators()),
false, DefaultTypeAdapters.getAllDefaultSerializers(),
DefaultTypeAdapters.getAllDefaultDeserializers(), DEFAULT_JSON_NON_EXECUTABLE, true, false);
}
Gson(ExclusionStrategy deserializationExclusionStrategy,
ExclusionStrategy serializationExclusionStrategy, FieldNamingStrategy2 fieldNamingPolicy,
MappedObjectConstructor objectConstructor, boolean serializeNulls,
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
boolean generateNonExecutableGson, boolean htmlSafe, boolean prettyPrinting) {
this.deserializationExclusionStrategy = deserializationExclusionStrategy;
this.serializationExclusionStrategy = serializationExclusionStrategy;
this.fieldNamingPolicy = fieldNamingPolicy;
this.objectConstructor = objectConstructor;
this.serializeNulls = serializeNulls;
this.serializers = serializers;
this.deserializers = deserializers;
this.generateNonExecutableJson = generateNonExecutableGson;
this.htmlSafe = htmlSafe;
this.prettyPrinting = prettyPrinting;
}
private static ExclusionStrategy createExclusionStrategy() {
List<ExclusionStrategy> strategies = new LinkedList<ExclusionStrategy>();
strategies.add(DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
strategies.add(DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
strategies.add(DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY);
return new DisjunctionExclusionStrategy(strategies);
}
/**
* This method serializes the specified object into its equivalent representation as a tree of
* {@link JsonElement}s. This method should be used when the specified object is not a generic
* type. This method uses {@link Class#getClass()} to get the type for the specified object, but
* the {@code getClass()} loses the generic type information because of the Type Erasure feature
* of Java. Note that this method works fine if the any of the object fields are of generic type,
* just the object itself should not be of a generic type. If the object is of generic type, use
* {@link #toJsonTree(Object, Type)} instead.
*
* @param src the object for which Json representation is to be created setting for Gson
* @return Json representation of {@code src}.
* @since 1.4
*/
public JsonElement toJsonTree(Object src) {
if (src == null) {
return JsonNull.createJsonNull();
}
return toJsonTree(src, src.getClass());
}
/**
* This method serializes the specified object, including those of generic types, into its
* equivalent representation as a tree of {@link JsonElement}s. This method must be used if the
* specified object is a generic type. For non-generic objects, use {@link #toJsonTree(Object)}
* instead.
*
* @param src the object for which JSON representation is to be created
* @param typeOfSrc The specific genericized type of src. You can obtain
* this type by using the {@link com.massivecraft.factions.gson.reflect.TypeToken} class. For example,
* to get the type for {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfSrc = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return Json representation of {@code src}
* @since 1.4
*/
public JsonElement toJsonTree(Object src, Type typeOfSrc) {
JsonSerializationContextDefault context = new JsonSerializationContextDefault(
new ObjectNavigator(serializationExclusionStrategy), fieldNamingPolicy,
serializeNulls, serializers);
return context.serialize(src, typeOfSrc);
}
/**
* This method serializes the specified object into its equivalent Json representation.
* This method should be used when the specified object is not a generic type. This method uses
* {@link Class#getClass()} to get the type for the specified object, but the
* {@code getClass()} loses the generic type information because of the Type Erasure feature
* of Java. Note that this method works fine if the any of the object fields are of generic type,
* just the object itself should not be of a generic type. If the object is of generic type, use
* {@link #toJson(Object, Type)} instead. If you want to write out the object to a
* {@link Writer}, use {@link #toJson(Object, Appendable)} instead.
*
* @param src the object for which Json representation is to be created setting for Gson
* @return Json representation of {@code src}.
*/
public String toJson(Object src) {
if (src == null) {
return toJson(JsonNull.createJsonNull());
}
return toJson(src, src.getClass());
}
/**
* This method serializes the specified object, including those of generic types, into its
* equivalent Json representation. This method must be used if the specified object is a generic
* type. For non-generic objects, use {@link #toJson(Object)} instead. If you want to write out
* the object to a {@link Appendable}, use {@link #toJson(Object, Type, Appendable)} instead.
*
* @param src the object for which JSON representation is to be created
* @param typeOfSrc The specific genericized type of src. You can obtain
* this type by using the {@link com.massivecraft.factions.gson.reflect.TypeToken} class. For example,
* to get the type for {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfSrc = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return Json representation of {@code src}
*/
public String toJson(Object src, Type typeOfSrc) {
StringWriter writer = new StringWriter();
toJson(toJsonTree(src, typeOfSrc), writer);
return writer.toString();
}
/**
* This method serializes the specified object into its equivalent Json representation.
* This method should be used when the specified object is not a generic type. This method uses
* {@link Class#getClass()} to get the type for the specified object, but the
* {@code getClass()} loses the generic type information because of the Type Erasure feature
* of Java. Note that this method works fine if the any of the object fields are of generic type,
* just the object itself should not be of a generic type. If the object is of generic type, use
* {@link #toJson(Object, Type, Appendable)} instead.
*
* @param src the object for which Json representation is to be created setting for Gson
* @param writer Writer to which the Json representation needs to be written
* @throws JsonIOException if there was a problem writing to the writer
* @since 1.2
*/
public void toJson(Object src, Appendable writer) throws JsonIOException {
if (src != null) {
toJson(src, src.getClass(), writer);
} else {
toJson(JsonNull.createJsonNull(), writer);
}
}
/**
* This method serializes the specified object, including those of generic types, into its
* equivalent Json representation. This method must be used if the specified object is a generic
* type. For non-generic objects, use {@link #toJson(Object, Appendable)} instead.
*
* @param src the object for which JSON representation is to be created
* @param typeOfSrc The specific genericized type of src. You can obtain
* this type by using the {@link com.massivecraft.factions.gson.reflect.TypeToken} class. For example,
* to get the type for {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfSrc = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @param writer Writer to which the Json representation of src needs to be written.
* @throws JsonIOException if there was a problem writing to the writer
* @since 1.2
*/
public void toJson(Object src, Type typeOfSrc, Appendable writer) throws JsonIOException {
JsonElement jsonElement = toJsonTree(src, typeOfSrc);
toJson(jsonElement, writer);
}
/**
* Writes the JSON representation of {@code src} of type {@code typeOfSrc} to
* {@code writer}.
* @throws JsonIOException if there was a problem writing to the writer
*/
public void toJson(Object src, Type typeOfSrc, JsonWriter writer) throws JsonIOException {
toJson(toJsonTree(src, typeOfSrc), writer);
}
/**
* Converts a tree of {@link JsonElement}s into its equivalent JSON representation.
*
* @param jsonElement root of a tree of {@link JsonElement}s
* @return JSON String representation of the tree
* @since 1.4
*/
public String toJson(JsonElement jsonElement) {
StringWriter writer = new StringWriter();
toJson(jsonElement, writer);
return writer.toString();
}
/**
* Writes out the equivalent JSON for a tree of {@link JsonElement}s.
*
* @param jsonElement root of a tree of {@link JsonElement}s
* @param writer Writer to which the Json representation needs to be written
* @throws JsonIOException if there was a problem writing to the writer
* @since 1.4
*/
public void toJson(JsonElement jsonElement, Appendable writer) throws JsonIOException {
try {
if (generateNonExecutableJson) {
writer.append(JSON_NON_EXECUTABLE_PREFIX);
}
JsonWriter jsonWriter = new JsonWriter(Streams.writerForAppendable(writer));
if (prettyPrinting) {
jsonWriter.setIndent(" ");
}
toJson(jsonElement, jsonWriter);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* Writes the JSON for {@code jsonElement} to {@code writer}.
* @throws JsonIOException if there was a problem writing to the writer
*/
public void toJson(JsonElement jsonElement, JsonWriter writer) throws JsonIOException {
boolean oldLenient = writer.isLenient();
writer.setLenient(true);
boolean oldHtmlSafe = writer.isHtmlSafe();
writer.setHtmlSafe(htmlSafe);
try {
Streams.write(jsonElement, serializeNulls, writer);
} catch (IOException e) {
throw new JsonIOException(e);
} finally {
writer.setLenient(oldLenient);
writer.setHtmlSafe(oldHtmlSafe);
}
}
/**
* This method deserializes the specified Json into an object of the specified class. It is not
* suitable to use if the specified class is a generic type since it will not have the generic
* type information because of the Type Erasure feature of Java. Therefore, this method should not
* be used if the desired type is a generic type. Note that this method works fine if the any of
* the fields of the specified object are generics, just the object itself should not be a
* generic type. For the cases when the object is of generic type, invoke
* {@link #fromJson(String, Type)}. If you have the Json in a {@link Reader} instead of
* a String, use {@link #fromJson(Reader, Class)} instead.
*
* @param <T> the type of the desired object
* @param json the string from which the object is to be deserialized
* @param classOfT the class of T
* @return an object of type T from the string
* @throws JsonSyntaxException if json is not a valid representation for an object of type
* classOfT
*/
public <T> T fromJson(String json, Class<T> classOfT) throws JsonSyntaxException {
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
/**
* This method deserializes the specified Json into an object of the specified type. This method
* is useful if the specified object is a generic type. For non-generic objects, use
* {@link #fromJson(String, Class)} instead. If you have the Json in a {@link Reader} instead of
* a String, use {@link #fromJson(Reader, Type)} instead.
*
* @param <T> the type of the desired object
* @param json the string from which the object is to be deserialized
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
* {@link com.massivecraft.factions.gson.reflect.TypeToken} class. For example, to get the type for
* {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return an object of type T from the string
* @throws JsonParseException if json is not a valid representation for an object of type typeOfT
* @throws JsonSyntaxException if json is not a valid representation for an object of type
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(String json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
StringReader reader = new StringReader(json);
T target = (T) fromJson(reader, typeOfT);
return target;
}
/**
* This method deserializes the Json read from the specified reader into an object of the
* specified class. It is not suitable to use if the specified class is a generic type since it
* will not have the generic type information because of the Type Erasure feature of Java.
* Therefore, this method should not be used if the desired type is a generic type. Note that
* this method works fine if the any of the fields of the specified object are generics, just the
* object itself should not be a generic type. For the cases when the object is of generic type,
* invoke {@link #fromJson(Reader, Type)}. If you have the Json in a String form instead of a
* {@link Reader}, use {@link #fromJson(String, Class)} instead.
*
* @param <T> the type of the desired object
* @param json the reader producing the Json from which the object is to be deserialized.
* @param classOfT the class of T
* @return an object of type T from the string
* @throws JsonIOException if there was a problem reading from the Reader
* @throws JsonSyntaxException if json is not a valid representation for an object of type
* @since 1.2
*/
public <T> T fromJson(Reader json, Class<T> classOfT) throws JsonSyntaxException, JsonIOException {
JsonReader jsonReader = new JsonReader(json);
Object object = fromJson(jsonReader, classOfT);
assertFullConsumption(object, jsonReader);
return Primitives.wrap(classOfT).cast(object);
}
/**
* This method deserializes the Json read from the specified reader into an object of the
* specified type. This method is useful if the specified object is a generic type. For
* non-generic objects, use {@link #fromJson(Reader, Class)} instead. If you have the Json in a
* String form instead of a {@link Reader}, use {@link #fromJson(String, Type)} instead.
*
* @param <T> the type of the desired object
* @param json the reader producing Json from which the object is to be deserialized
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
* {@link com.massivecraft.factions.gson.reflect.TypeToken} class. For example, to get the type for
* {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return an object of type T from the json
* @throws JsonIOException if there was a problem reading from the Reader
* @throws JsonSyntaxException if json is not a valid representation for an object of type
* @since 1.2
*/
public <T> T fromJson(Reader json, Type typeOfT) throws JsonIOException, JsonSyntaxException {
JsonReader jsonReader = new JsonReader(json);
T object = this.<T>fromJson(jsonReader, typeOfT);
assertFullConsumption(object, jsonReader);
return object;
}
private static void assertFullConsumption(Object obj, JsonReader reader) {
try {
if (obj != null && reader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonIOException("JSON document was not fully consumed.");
}
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
/**
* Reads the next JSON value from {@code reader} and convert it to an object
* of type {@code typeOfT}.
* Since Type is not parameterized by T, this method is type unsafe and should be used carefully
*
* @throws JsonIOException if there was a problem writing to the Reader
* @throws JsonSyntaxException if json is not a valid representation for an object of type
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(JsonReader reader, Type typeOfT) throws JsonIOException, JsonSyntaxException {
boolean oldLenient = reader.isLenient();
reader.setLenient(true);
try {
JsonElement root = Streams.parse(reader);
return (T) fromJson(root, typeOfT);
} finally {
reader.setLenient(oldLenient);
}
}
/**
* This method deserializes the Json read from the specified parse tree into an object of the
* specified type. It is not suitable to use if the specified class is a generic type since it
* will not have the generic type information because of the Type Erasure feature of Java.
* Therefore, this method should not be used if the desired type is a generic type. Note that
* this method works fine if the any of the fields of the specified object are generics, just the
* object itself should not be a generic type. For the cases when the object is of generic type,
* invoke {@link #fromJson(JsonElement, Type)}.
* @param <T> the type of the desired object
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
* be deserialized
* @param classOfT The class of T
* @return an object of type T from the json
* @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
* @since 1.3
*/
public <T> T fromJson(JsonElement json, Class<T> classOfT) throws JsonSyntaxException {
Object object = fromJson(json, (Type) classOfT);
return Primitives.wrap(classOfT).cast(object);
}
/**
* This method deserializes the Json read from the specified parse tree into an object of the
* specified type. This method is useful if the specified object is a generic type. For
* non-generic objects, use {@link #fromJson(JsonElement, Class)} instead.
*
* @param <T> the type of the desired object
* @param json the root of the parse tree of {@link JsonElement}s from which the object is to
* be deserialized
* @param typeOfT The specific genericized type of src. You can obtain this type by using the
* {@link com.massivecraft.factions.gson.reflect.TypeToken} class. For example, to get the type for
* {@code Collection<Foo>}, you should use:
* <pre>
* Type typeOfT = new TypeToken&lt;Collection&lt;Foo&gt;&gt;(){}.getType();
* </pre>
* @return an object of type T from the json
* @throws JsonSyntaxException if json is not a valid representation for an object of type typeOfT
* @since 1.3
*/
@SuppressWarnings("unchecked")
public <T> T fromJson(JsonElement json, Type typeOfT) throws JsonSyntaxException {
if (json == null) {
return null;
}
JsonDeserializationContext context = new JsonDeserializationContextDefault(
new ObjectNavigator(deserializationExclusionStrategy), fieldNamingPolicy,
deserializers, objectConstructor);
T target = (T) context.deserialize(json, typeOfT);
return target;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{")
.append("serializeNulls:").append(serializeNulls)
.append(",serializers:").append(serializers)
.append(",deserializers:").append(deserializers)
// using the name instanceCreator instead of ObjectConstructor since the users of Gson are
// more familiar with the concept of Instance Creators. Moreover, the objectConstructor is
// just a utility class around instance creators, and its toString() only displays them.
.append(",instanceCreators:").append(objectConstructor)
.append("}");
return sb.toString();
}
}

View File

@ -0,0 +1,715 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.DefaultTypeAdapters.DefaultDateTypeAdapter;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* <p>Use this builder to construct a {@link Gson} instance when you need to set configuration
* options other than the default. For {@link Gson} with default configuration, it is simpler to
* use {@code new Gson()}. {@code GsonBuilder} is best used by creating it, and then invoking its
* various configuration methods, and finally calling create.</p>
*
* <p>The following is an example shows how to use the {@code GsonBuilder} to construct a Gson
* instance:
*
* <pre>
* Gson gson = new GsonBuilder()
* .registerTypeAdapter(Id.class, new IdTypeAdapter())
* .enableComplexMapKeySerialization()
* .serializeNulls()
* .setDateFormat(DateFormat.LONG)
* .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
* .setPrettyPrinting()
* .setVersion(1.0)
* .create();
* </pre></p>
*
* <p>NOTES:
* <ul>
* <li> the order of invocation of configuration methods does not matter.</li>
* <li> The default serialization of {@link Date} and its subclasses in Gson does
* not contain time-zone information. So, if you are using date/time instances,
* use {@code GsonBuilder} and its {@code setDateFormat} methods.</li>
* </ul>
* </p>
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class GsonBuilder {
private static final MapAsArrayTypeAdapter COMPLEX_KEY_MAP_TYPE_ADAPTER =
new MapAsArrayTypeAdapter();
private static final InnerClassExclusionStrategy innerClassExclusionStrategy =
new InnerClassExclusionStrategy();
private static final ExposeAnnotationDeserializationExclusionStrategy
exposeAnnotationDeserializationExclusionStrategy =
new ExposeAnnotationDeserializationExclusionStrategy();
private static final ExposeAnnotationSerializationExclusionStrategy
exposeAnnotationSerializationExclusionStrategy =
new ExposeAnnotationSerializationExclusionStrategy();
private final Set<ExclusionStrategy> serializeExclusionStrategies =
new HashSet<ExclusionStrategy>();
private final Set<ExclusionStrategy> deserializeExclusionStrategies =
new HashSet<ExclusionStrategy>();
private double ignoreVersionsAfter;
private ModifierBasedExclusionStrategy modifierBasedExclusionStrategy;
private boolean serializeInnerClasses;
private boolean excludeFieldsWithoutExposeAnnotation;
private LongSerializationPolicy longSerializationPolicy;
private FieldNamingStrategy2 fieldNamingPolicy;
private final ParameterizedTypeHandlerMap<InstanceCreator<?>> instanceCreators;
private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers;
private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
private boolean serializeNulls;
private String datePattern;
private int dateStyle;
private int timeStyle;
private boolean serializeSpecialFloatingPointValues;
private boolean escapeHtmlChars;
private boolean prettyPrinting;
private boolean generateNonExecutableJson;
/**
* Creates a GsonBuilder instance that can be used to build Gson with various configuration
* settings. GsonBuilder follows the builder pattern, and it is typically used by first
* invoking various configuration methods to set desired options, and finally calling
* {@link #create()}.
*/
public GsonBuilder() {
// add default exclusion strategies
deserializeExclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
deserializeExclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
serializeExclusionStrategies.add(Gson.DEFAULT_ANON_LOCAL_CLASS_EXCLUSION_STRATEGY);
serializeExclusionStrategies.add(Gson.DEFAULT_SYNTHETIC_FIELD_EXCLUSION_STRATEGY);
// setup default values
ignoreVersionsAfter = VersionConstants.IGNORE_VERSIONS;
serializeInnerClasses = true;
prettyPrinting = false;
escapeHtmlChars = true;
modifierBasedExclusionStrategy = Gson.DEFAULT_MODIFIER_BASED_EXCLUSION_STRATEGY;
excludeFieldsWithoutExposeAnnotation = false;
longSerializationPolicy = LongSerializationPolicy.DEFAULT;
fieldNamingPolicy = Gson.DEFAULT_NAMING_POLICY;
instanceCreators = new ParameterizedTypeHandlerMap<InstanceCreator<?>>();
serializers = new ParameterizedTypeHandlerMap<JsonSerializer<?>>();
deserializers = new ParameterizedTypeHandlerMap<JsonDeserializer<?>>();
serializeNulls = false;
dateStyle = DateFormat.DEFAULT;
timeStyle = DateFormat.DEFAULT;
serializeSpecialFloatingPointValues = false;
generateNonExecutableJson = false;
}
/**
* Configures Gson to enable versioning support.
*
* @param ignoreVersionsAfter any field or type marked with a version higher than this value
* are ignored during serialization or deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder setVersion(double ignoreVersionsAfter) {
this.ignoreVersionsAfter = ignoreVersionsAfter;
return this;
}
/**
* Configures Gson to excludes all class fields that have the specified modifiers. By default,
* Gson will exclude all fields marked transient or static. This method will override that
* behavior.
*
* @param modifiers the field modifiers. You must use the modifiers specified in the
* {@link java.lang.reflect.Modifier} class. For example,
* {@link java.lang.reflect.Modifier#TRANSIENT},
* {@link java.lang.reflect.Modifier#STATIC}.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder excludeFieldsWithModifiers(int... modifiers) {
modifierBasedExclusionStrategy = new ModifierBasedExclusionStrategy(modifiers);
return this;
}
/**
* Makes the output JSON non-executable in Javascript by prefixing the generated JSON with some
* special text. This prevents attacks from third-party sites through script sourcing. See
* <a href="http://code.google.com/p/google-gson/issues/detail?id=42">Gson Issue 42</a>
* for details.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder generateNonExecutableJson() {
this.generateNonExecutableJson = true;
return this;
}
/**
* Configures Gson to exclude all fields from consideration for serialization or deserialization
* that do not have the {@link com.massivecraft.factions.gson.annotations.Expose} annotation.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder excludeFieldsWithoutExposeAnnotation() {
excludeFieldsWithoutExposeAnnotation = true;
return this;
}
/**
* Configure Gson to serialize null fields. By default, Gson omits all fields that are null
* during serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder serializeNulls() {
this.serializeNulls = true;
return this;
}
/**
* Enabling this feature will only change the serialized form if the map key is
* a complex type (i.e. non-primitive) in its <strong>serialized</strong> JSON
* form. The default implementation of map serialization uses {@code toString()}
* on the key; however, when this is called then one of the following cases
* apply:
*
* <h3>Maps as JSON objects</h3>
* For this case, assume that a type adapter is registered to serialize and
* deserialize some {@code Point} class, which contains an x and y coordinate,
* to/from the JSON Primitive string value {@code "(x,y)"}. The Java map would
* then be serialized as a {@link JsonObject}.
*
* <p>Below is an example:
* <pre> {@code
* Gson gson = new GsonBuilder()
* .register(Point.class, new MyPointTypeAdapter())
* .enableComplexMapKeySerialization()
* .create();
*
* Map<Point, String> original = new LinkedHashMap<Point, String>();
* original.put(new Point(5, 6), "a");
* original.put(new Point(8, 8), "b");
* System.out.println(gson.toJson(original, type));
* }</pre>
* The above code prints this JSON object:<pre> {@code
* {
* "(5,6)": "a",
* "(8,8)": "b"
* }
* }</pre>
*
* <h3>Maps as JSON arrays</h3>
* For this case, assume that a type adapter was NOT registered for some
* {@code Point} class, but rather the default Gson serialization is applied.
* In this case, some {@code new Point(2,3)} would serialize as {@code
* {"x":2,"y":5}}.
*
* <p>Given the assumption above, a {@code Map<Point, String>} will be
* serialize as an array of arrays (can be viewed as an entry set of pairs).
*
* <p>Below is an example of serializing complex types as JSON arrays:
* <pre> {@code
* Gson gson = new GsonBuilder()
* .enableComplexMapKeySerialization()
* .create();
*
* Map<Point, String> original = new LinkedHashMap<Point, String>();
* original.put(new Point(5, 6), "a");
* original.put(new Point(8, 8), "b");
* System.out.println(gson.toJson(original, type));
* }
*
* The JSON output would look as follows:
* <pre> {@code
* [
* [
* {
* "x": 5,
* "y": 6
* },
* "a"
* ],
* [
* {
* "x": 8,
* "y": 8
* },
* "b"
* ]
* ]
* }</pre>
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder enableComplexMapKeySerialization() {
registerTypeHierarchyAdapter(Map.class, COMPLEX_KEY_MAP_TYPE_ADAPTER);
return this;
}
/**
* Configures Gson to exclude inner classes during serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder disableInnerClassSerialization() {
serializeInnerClasses = false;
return this;
}
/**
* Configures Gson to apply a specific serialization policy for {@code Long} and {@code long}
* objects.
*
* @param serializationPolicy the particular policy to use for serializing longs.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder setLongSerializationPolicy(LongSerializationPolicy serializationPolicy) {
this.longSerializationPolicy = serializationPolicy;
return this;
}
/**
* Configures Gson to apply a specific naming policy to an object's field during serialization
* and deserialization.
*
* @param namingConvention the JSON field naming convention to use for serialization and
* deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder setFieldNamingPolicy(FieldNamingPolicy namingConvention) {
return setFieldNamingStrategy(namingConvention.getFieldNamingPolicy());
}
/**
* Configures Gson to apply a specific naming policy strategy to an object's field during
* serialization and deserialization.
*
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder setFieldNamingStrategy(FieldNamingStrategy fieldNamingStrategy) {
return setFieldNamingStrategy(new FieldNamingStrategy2Adapter(fieldNamingStrategy));
}
/**
* Configures Gson to apply a specific naming policy strategy to an object's field during
* serialization and deserialization.
*
* @param fieldNamingStrategy the actual naming strategy to apply to the fields
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
GsonBuilder setFieldNamingStrategy(FieldNamingStrategy2 fieldNamingStrategy) {
this.fieldNamingPolicy =
new SerializedNameAnnotationInterceptingNamingPolicy(fieldNamingStrategy);
return this;
}
/**
* Configures Gson to apply a set of exclusion strategies during both serialization and
* deserialization. Each of the {@code strategies} will be applied as a disjunction rule.
* This means that if one of the {@code strategies} suggests that a field (or class) should be
* skipped then that field (or object) is skipped during serializaiton/deserialization.
*
* @param strategies the set of strategy object to apply during object (de)serialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.4
*/
public GsonBuilder setExclusionStrategies(ExclusionStrategy... strategies) {
List<ExclusionStrategy> strategyList = Arrays.asList(strategies);
serializeExclusionStrategies.addAll(strategyList);
deserializeExclusionStrategies.addAll(strategyList);
return this;
}
/**
* Configures Gson to apply the passed in exclusion strategy during serialization.
* If this method is invoked numerous times with different exclusion strategy objects
* then the exclusion strategies that were added will be applied as a disjunction rule.
* This means that if one of the added exclusion strategies suggests that a field (or
* class) should be skipped then that field (or object) is skipped during its
* serialization.
*
* @param strategy an exclusion strategy to apply during serialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder addSerializationExclusionStrategy(ExclusionStrategy strategy) {
serializeExclusionStrategies.add(strategy);
return this;
}
/**
* Configures Gson to apply the passed in exclusion strategy during deserialization.
* If this method is invoked numerous times with different exclusion strategy objects
* then the exclusion strategies that were added will be applied as a disjunction rule.
* This means that if one of the added exclusion strategies suggests that a field (or
* class) should be skipped then that field (or object) is skipped during its
* deserialization.
*
* @param strategy an exclusion strategy to apply during deserialization.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder addDeserializationExclusionStrategy(ExclusionStrategy strategy) {
deserializeExclusionStrategies.add(strategy);
return this;
}
/**
* Configures Gson to output Json that fits in a page for pretty printing. This option only
* affects Json serialization.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder setPrettyPrinting() {
prettyPrinting = true;
return this;
}
/**
* By default, Gson escapes HTML characters such as &lt; &gt; etc. Use this option to configure
* Gson to pass-through HTML characters as is.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder disableHtmlEscaping() {
this.escapeHtmlChars = false;
return this;
}
/**
* Configures Gson to serialize {@code Date} objects according to the pattern provided. You can
* call this method or {@link #setDateFormat(int)} multiple times, but only the last invocation
* will be used to decide the serialization format.
*
* <p>The date format will be used to serialize and deserialize {@link java.util.Date}, {@link
* java.sql.Timestamp} and {@link java.sql.Date}.
*
* <p>Note that this pattern must abide by the convention provided by {@code SimpleDateFormat}
* class. See the documentation in {@link java.text.SimpleDateFormat} for more information on
* valid date and time patterns.</p>
*
* @param pattern the pattern that dates will be serialized/deserialized to/from
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(String pattern) {
// TODO(Joel): Make this fail fast if it is an invalid date format
this.datePattern = pattern;
return this;
}
/**
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
* information on the valid style constants.</p>
*
* @param style the predefined date style that date objects will be serialized/deserialized
* to/from
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(int style) {
this.dateStyle = style;
this.datePattern = null;
return this;
}
/**
* Configures Gson to to serialize {@code Date} objects according to the style value provided.
* You can call this method or {@link #setDateFormat(String)} multiple times, but only the last
* invocation will be used to decide the serialization format.
*
* <p>Note that this style value should be one of the predefined constants in the
* {@code DateFormat} class. See the documentation in {@link java.text.DateFormat} for more
* information on the valid style constants.</p>
*
* @param dateStyle the predefined date style that date objects will be serialized/deserialized
* to/from
* @param timeStyle the predefined style for the time portion of the date objects
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.2
*/
public GsonBuilder setDateFormat(int dateStyle, int timeStyle) {
this.dateStyle = dateStyle;
this.timeStyle = timeStyle;
this.datePattern = null;
return this;
}
/**
* Configures Gson for custom serialization or deserialization. This method combines the
* registration of an {@link InstanceCreator}, {@link JsonSerializer}, and a
* {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter} implements
* all the required interfaces for custom serialization with Gson. If an instance creator,
* serializer or deserializer was previously registered for the specified {@code type}, it is
* overwritten.
*
* @param type the type definition for the type adapter being registered
* @param typeAdapter This object must implement at least one of the {@link InstanceCreator},
* {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
public GsonBuilder registerTypeAdapter(Type type, Object typeAdapter) {
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?>);
if (typeAdapter instanceof InstanceCreator<?>) {
registerInstanceCreator(type, (InstanceCreator<?>) typeAdapter);
}
if (typeAdapter instanceof JsonSerializer<?>) {
registerSerializer(type, (JsonSerializer<?>) typeAdapter);
}
if (typeAdapter instanceof JsonDeserializer<?>) {
registerDeserializer(type, (JsonDeserializer<?>) typeAdapter);
}
return this;
}
/**
* Configures Gson to use a custom {@link InstanceCreator} for the specified type. If an instance
* creator was previously registered for the specified class, it is overwritten. Since this method
* takes a type instead of a Class object, it can be used to register a specific handler for a
* generic type corresponding to a raw type.
*
* @param <T> the type for which instance creator is being registered
* @param typeOfT The Type definition for T
* @param instanceCreator the instance creator for T
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
private <T> GsonBuilder registerInstanceCreator(Type typeOfT,
InstanceCreator<? extends T> instanceCreator) {
instanceCreators.register(typeOfT, instanceCreator);
return this;
}
/**
* Configures Gson to use a custom JSON serializer for the specified type. You should use this
* method if you want to register different serializers for different generic types corresponding
* to a raw type.
*
* @param <T> the type for which the serializer is being registered
* @param typeOfT The type definition for T
* @param serializer the custom serializer
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
private <T> GsonBuilder registerSerializer(Type typeOfT, final JsonSerializer<T> serializer) {
serializers.register(typeOfT, serializer);
return this;
}
/**
* Configures Gson to use a custom JSON deserializer for the specified type. You should use this
* method if you want to register different deserializers for different generic types
* corresponding to a raw type.
*
* @param <T> the type for which the deserializer is being registered
* @param typeOfT The type definition for T
* @param deserializer the custom deserializer
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
*/
private <T> GsonBuilder registerDeserializer(Type typeOfT, JsonDeserializer<T> deserializer) {
deserializers.register(typeOfT, new JsonDeserializerExceptionWrapper<T>(deserializer));
return this;
}
/**
* Configures Gson for custom serialization or deserialization for an inheritance type hierarchy.
* This method combines the registration of an {@link InstanceCreator}, {@link JsonSerializer},
* and a {@link JsonDeserializer}. It is best used when a single object {@code typeAdapter}
* implements all the required interfaces for custom serialization with Gson.
* If an instance creator, serializer or deserializer was previously registered for the specified
* type hierarchy, it is overwritten. If an instance creator, serializer or deserializer is
* registered for a specific type in the type hierarchy, it will be invoked instead of the one
* registered for the type hierarchy.
*
* @param baseType the class definition for the type adapter being registered for the base class
* or interface
* @param typeAdapter This object must implement at least one of the {@link InstanceCreator},
* {@link JsonSerializer}, and a {@link JsonDeserializer} interfaces.
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.7
*/
public GsonBuilder registerTypeHierarchyAdapter(Class<?> baseType, Object typeAdapter) {
$Gson$Preconditions.checkArgument(typeAdapter instanceof JsonSerializer<?>
|| typeAdapter instanceof JsonDeserializer<?> || typeAdapter instanceof InstanceCreator<?>);
if (typeAdapter instanceof InstanceCreator<?>) {
registerInstanceCreatorForTypeHierarchy(baseType, (InstanceCreator<?>) typeAdapter);
}
if (typeAdapter instanceof JsonSerializer<?>) {
registerSerializerForTypeHierarchy(baseType, (JsonSerializer<?>) typeAdapter);
}
if (typeAdapter instanceof JsonDeserializer<?>) {
registerDeserializerForTypeHierarchy(baseType, (JsonDeserializer<?>) typeAdapter);
}
return this;
}
private <T> GsonBuilder registerInstanceCreatorForTypeHierarchy(Class<?> classOfT,
InstanceCreator<? extends T> instanceCreator) {
instanceCreators.registerForTypeHierarchy(classOfT, instanceCreator);
return this;
}
private <T> GsonBuilder registerSerializerForTypeHierarchy(Class<?> classOfT,
final JsonSerializer<T> serializer) {
serializers.registerForTypeHierarchy(classOfT, serializer);
return this;
}
private <T> GsonBuilder registerDeserializerForTypeHierarchy(Class<?> classOfT,
JsonDeserializer<T> deserializer) {
deserializers.registerForTypeHierarchy(classOfT,
new JsonDeserializerExceptionWrapper<T>(deserializer));
return this;
}
/**
* Section 2.4 of <a href="http://www.ietf.org/rfc/rfc4627.txt">JSON specification</a> disallows
* special double values (NaN, Infinity, -Infinity). However,
* <a href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf">Javascript
* specification</a> (see section 4.3.20, 4.3.22, 4.3.23) allows these values as valid Javascript
* values. Moreover, most JavaScript engines will accept these special values in JSON without
* problem. So, at a practical level, it makes sense to accept these values as valid JSON even
* though JSON specification disallows them.
*
* <p>Gson always accepts these special values during deserialization. However, it outputs
* strictly compliant JSON. Hence, if it encounters a float value {@link Float#NaN},
* {@link Float#POSITIVE_INFINITY}, {@link Float#NEGATIVE_INFINITY}, or a double value
* {@link Double#NaN}, {@link Double#POSITIVE_INFINITY}, {@link Double#NEGATIVE_INFINITY}, it
* will throw an {@link IllegalArgumentException}. This method provides a way to override the
* default behavior when you know that the JSON receiver will be able to handle these special
* values.
*
* @return a reference to this {@code GsonBuilder} object to fulfill the "Builder" pattern
* @since 1.3
*/
public GsonBuilder serializeSpecialFloatingPointValues() {
this.serializeSpecialFloatingPointValues = true;
return this;
}
/**
* Creates a {@link Gson} instance based on the current configuration. This method is free of
* side-effects to this {@code GsonBuilder} instance and hence can be called multiple times.
*
* @return an instance of Gson configured with the options currently set in this builder
*/
public Gson create() {
List<ExclusionStrategy> deserializationStrategies =
new LinkedList<ExclusionStrategy>(deserializeExclusionStrategies);
List<ExclusionStrategy> serializationStrategies =
new LinkedList<ExclusionStrategy>(serializeExclusionStrategies);
deserializationStrategies.add(modifierBasedExclusionStrategy);
serializationStrategies.add(modifierBasedExclusionStrategy);
if (!serializeInnerClasses) {
deserializationStrategies.add(innerClassExclusionStrategy);
serializationStrategies.add(innerClassExclusionStrategy);
}
if (ignoreVersionsAfter != VersionConstants.IGNORE_VERSIONS) {
VersionExclusionStrategy versionExclusionStrategy =
new VersionExclusionStrategy(ignoreVersionsAfter);
deserializationStrategies.add(versionExclusionStrategy);
serializationStrategies.add(versionExclusionStrategy);
}
if (excludeFieldsWithoutExposeAnnotation) {
deserializationStrategies.add(exposeAnnotationDeserializationExclusionStrategy);
serializationStrategies.add(exposeAnnotationSerializationExclusionStrategy);
}
ParameterizedTypeHandlerMap<JsonSerializer<?>> customSerializers =
DefaultTypeAdapters.DEFAULT_HIERARCHY_SERIALIZERS.copyOf();
customSerializers.register(serializers.copyOf());
ParameterizedTypeHandlerMap<JsonDeserializer<?>> customDeserializers =
DefaultTypeAdapters.DEFAULT_HIERARCHY_DESERIALIZERS.copyOf();
customDeserializers.register(deserializers.copyOf());
addTypeAdaptersForDate(datePattern, dateStyle, timeStyle, customSerializers,
customDeserializers);
customSerializers.registerIfAbsent(DefaultTypeAdapters.getDefaultSerializers(
serializeSpecialFloatingPointValues, longSerializationPolicy));
customDeserializers.registerIfAbsent(DefaultTypeAdapters.getDefaultDeserializers());
ParameterizedTypeHandlerMap<InstanceCreator<?>> customInstanceCreators =
instanceCreators.copyOf();
customInstanceCreators.registerIfAbsent(DefaultTypeAdapters.getDefaultInstanceCreators());
customSerializers.makeUnmodifiable();
customDeserializers.makeUnmodifiable();
instanceCreators.makeUnmodifiable();
MappedObjectConstructor objConstructor = new MappedObjectConstructor(customInstanceCreators);
Gson gson = new Gson(new DisjunctionExclusionStrategy(deserializationStrategies),
new DisjunctionExclusionStrategy(serializationStrategies),
fieldNamingPolicy, objConstructor, serializeNulls,
customSerializers, customDeserializers, generateNonExecutableJson, escapeHtmlChars,
prettyPrinting);
return gson;
}
private static void addTypeAdaptersForDate(String datePattern, int dateStyle, int timeStyle,
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers) {
DefaultDateTypeAdapter dateTypeAdapter = null;
if (datePattern != null && !"".equals(datePattern.trim())) {
dateTypeAdapter = new DefaultDateTypeAdapter(datePattern);
} else if (dateStyle != DateFormat.DEFAULT && timeStyle != DateFormat.DEFAULT) {
dateTypeAdapter = new DefaultDateTypeAdapter(dateStyle, timeStyle);
}
if (dateTypeAdapter != null) {
registerIfAbsent(Date.class, serializers, dateTypeAdapter);
registerIfAbsent(Date.class, deserializers, dateTypeAdapter);
registerIfAbsent(Timestamp.class, serializers, dateTypeAdapter);
registerIfAbsent(Timestamp.class, deserializers, dateTypeAdapter);
registerIfAbsent(java.sql.Date.class, serializers, dateTypeAdapter);
registerIfAbsent(java.sql.Date.class, deserializers, dateTypeAdapter);
}
}
private static <T> void registerIfAbsent(Class<?> type,
ParameterizedTypeHandlerMap<T> adapters, T adapter) {
if (!adapters.hasSpecificHandlerFor(type)) {
adapters.register(type, adapter);
}
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Modifier;
/**
* Strategy for excluding inner classes.
*
* @author Joel Leitch
*/
final class InnerClassExclusionStrategy implements ExclusionStrategy {
public boolean shouldSkipField(FieldAttributes f) {
return isInnerClass(f.getDeclaredClass());
}
public boolean shouldSkipClass(Class<?> clazz) {
return isInnerClass(clazz);
}
private boolean isInnerClass(Class<?> clazz) {
return clazz.isMemberClass() && !isStatic(clazz);
}
private boolean isStatic(Class<?> clazz) {
return (clazz.getModifiers() & Modifier.STATIC) != 0;
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Type;
/**
* This interface is implemented to create instances of a class that does not define a no-args
* constructor. If you can modify the class, you should instead add a private, or public
* no-args constructor. However, that is not possible for library classes, such as JDK classes, or
* a third-party library that you do not have source-code of. In such cases, you should define an
* instance creator for the class. Implementations of this interface should be registered with
* {@link GsonBuilder#registerTypeAdapter(Type, Object)} method before Gson will be able to use
* them.
* <p>Let us look at an example where defining an InstanceCreator might be useful. The
* {@code Id} class defined below does not have a default no-args constructor.</p>
*
* <pre>
* public class Id&lt;T&gt; {
* private final Class&lt;T&gt; clazz;
* private final long value;
* public Id(Class&lt;T&gt; clazz, long value) {
* this.clazz = clazz;
* this.value = value;
* }
* }
* </pre>
*
* <p>If Gson encounters an object of type {@code Id} during deserialization, it will throw an
* exception. The easiest way to solve this problem will be to add a (public or private) no-args
* constructor as follows:</p>
*
* <pre>
* private Id() {
* this(Object.class, 0L);
* }
* </pre>
*
* <p>However, let us assume that the developer does not have access to the source-code of the
* {@code Id} class, or does not want to define a no-args constructor for it. The developer
* can solve this problem by defining an {@code InstanceCreator} for {@code Id}:</p>
*
* <pre>
* class IdInstanceCreator implements InstanceCreator&lt;Id&gt; {
* public Id createInstance(Type type) {
* return new Id(Object.class, 0L);
* }
* }
* </pre>
*
* <p>Note that it does not matter what the fields of the created instance contain since Gson will
* overwrite them with the deserialized values specified in Json. You should also ensure that a
* <i>new</i> object is returned, not a common object since its fields will be overwritten.
* The developer will need to register {@code IdInstanceCreator} with Gson as follows:</p>
*
* <pre>
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdInstanceCreator()).create();
* </pre>
*
* @param <T> the type of object that will be created by this implementation.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public interface InstanceCreator<T> {
/**
* Gson invokes this call-back method during deserialization to create an instance of the
* specified type. The fields of the returned instance are overwritten with the data present
* in the Json. Since the prior contents of the object are destroyed and overwritten, do not
* return an instance that is useful elsewhere. In particular, do not return a common instance,
* always use {@code new} to create a new instance.
*
* @param type the parameterized T represented as a {@link Type}.
* @return a default object instance of type T.
*/
public T createInstance(Type type);
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* A simple implementation of the {@link FieldNamingStrategy2} interface such that it does not
* perform any string translation of the incoming field name.
*
* <p>The following is an example:</p>
*
* <pre>
* class IntWrapper {
* public int integerField = 0;
* }
*
* JavaFieldNamingPolicy policy = new JavaFieldNamingPolicy();
* String translatedFieldName =
* policy.translateName(IntWrapper.class.getField("integerField"));
*
* assert("integerField".equals(translatedFieldName));
* </pre>
*
* <p>This is the default {@link FieldNamingStrategy2} used by Gson.</p>
*
* @author Joel Leitch
*/
final class JavaFieldNamingPolicy extends RecursiveFieldNamingPolicy {
@Override
protected String translateName(String target, Type fieldType, Collection<Annotation> annotations) {
return target;
}
}

View File

@ -0,0 +1,322 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
/**
* A class representing an array type in Json. An array is a list of {@link JsonElement}s each of
* which can be of a different type. This is an ordered list, meaning that the order in which
* elements are added is preserved.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonArray extends JsonElement implements Iterable<JsonElement> {
private final List<JsonElement> elements;
/**
* Creates an empty JsonArray.
*/
public JsonArray() {
elements = new ArrayList<JsonElement>();
}
/**
* Adds the specified element to self.
*
* @param element the element that needs to be added to the array.
*/
public void add(JsonElement element) {
if (element == null) {
element = JsonNull.createJsonNull();
}
elements.add(element);
}
/**
* Adds all the elements of the specified array to self.
*
* @param array the array whose elements need to be added to the array.
*/
public void addAll(JsonArray array) {
elements.addAll(array.elements);
}
/**
* Reverses the elements of the array.
*/
void reverse() {
Collections.reverse(elements);
}
/**
* Returns the number of elements in the array.
*
* @return the number of elements in the array.
*/
public int size() {
return elements.size();
}
/**
* Returns an iterator to navigate the elemetns of the array. Since the array is an ordered list,
* the iterator navigates the elements in the order they were inserted.
*
* @return an iterator to navigate the elements of the array.
*/
public Iterator<JsonElement> iterator() {
return elements.iterator();
}
/**
* Returns the ith element of the array.
*
* @param i the index of the element that is being sought.
* @return the element present at the ith index.
* @throws IndexOutOfBoundsException if i is negative or greater than or equal to the
* {@link #size()} of the array.
*/
public JsonElement get(int i) {
return elements.get(i);
}
/**
* convenience method to get this array as a {@link Number} if it contains a single element.
*
* @return get this element as a number if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid Number.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public Number getAsNumber() {
if (elements.size() == 1) {
return elements.get(0).getAsNumber();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a {@link String} if it contains a single element.
*
* @return get this element as a String if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid String.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public String getAsString() {
if (elements.size() == 1) {
return elements.get(0).getAsString();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a double if it contains a single element.
*
* @return get this element as a double if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid double.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public double getAsDouble() {
if (elements.size() == 1) {
return elements.get(0).getAsDouble();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a {@link BigDecimal} if it contains a single element.
*
* @return get this element as a {@link BigDecimal} if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigDecimal}.
* @throws IllegalStateException if the array has more than one element.
* @since 1.2
*/
@Override
public BigDecimal getAsBigDecimal() {
if (elements.size() == 1) {
return elements.get(0).getAsBigDecimal();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a {@link BigInteger} if it contains a single element.
*
* @return get this element as a {@link BigInteger} if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive}.
* @throws NumberFormatException if the element at index 0 is not a valid {@link BigInteger}.
* @throws IllegalStateException if the array has more than one element.
* @since 1.2
*/
@Override
public BigInteger getAsBigInteger() {
if (elements.size() == 1) {
return elements.get(0).getAsBigInteger();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a float if it contains a single element.
*
* @return get this element as a float if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid float.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public float getAsFloat() {
if (elements.size() == 1) {
return elements.get(0).getAsFloat();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a long if it contains a single element.
*
* @return get this element as a long if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid long.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public long getAsLong() {
if (elements.size() == 1) {
return elements.get(0).getAsLong();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as an integer if it contains a single element.
*
* @return get this element as an integer if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid integer.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public int getAsInt() {
if (elements.size() == 1) {
return elements.get(0).getAsInt();
}
throw new IllegalStateException();
}
@Override
public byte getAsByte() {
if (elements.size() == 1) {
return elements.get(0).getAsByte();
}
throw new IllegalStateException();
}
@Override
public char getAsCharacter() {
if (elements.size() == 1) {
return elements.get(0).getAsCharacter();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a primitive short if it contains a single element.
*
* @return get this element as a primitive short if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid short.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public short getAsShort() {
if (elements.size() == 1) {
return elements.get(0).getAsShort();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as a boolean if it contains a single element.
*
* @return get this element as a boolean if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid boolean.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
public boolean getAsBoolean() {
if (elements.size() == 1) {
return elements.get(0).getAsBoolean();
}
throw new IllegalStateException();
}
/**
* convenience method to get this array as an Object if it contains a single element.
*
* @return get this element as an Object if it is single element array.
* @throws ClassCastException if the element in the array is of not a {@link JsonPrimitive} and
* is not a valid Object.
* @throws IllegalStateException if the array has more than one element.
*/
@Override
Object getAsObject() {
if (elements.size() == 1) {
return elements.get(0).getAsObject();
}
throw new IllegalStateException();
}
@Override
public boolean equals(Object o) {
return (o == this) || (o instanceof JsonArray && ((JsonArray) o).elements.equals(elements));
}
@Override
public int hashCode() {
return elements.hashCode();
}
@Override
protected void toString(Appendable sb, Escaper escaper) throws IOException {
sb.append('[');
boolean first = true;
for (JsonElement element : elements) {
if (first) {
first = false;
} else {
sb.append(',');
}
element.toString(sb, escaper);
}
sb.append(']');
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Types;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
/**
* A visitor that populates fields of an object with data from its equivalent
* JSON representation
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class JsonArrayDeserializationVisitor<T> extends JsonDeserializationVisitor<T> {
JsonArrayDeserializationVisitor(JsonArray jsonArray, Type arrayType,
ObjectNavigator objectNavigator, FieldNamingStrategy2 fieldNamingPolicy,
ObjectConstructor objectConstructor,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
JsonDeserializationContext context) {
super(jsonArray, arrayType, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
}
@Override
@SuppressWarnings("unchecked")
protected T constructTarget() {
if (!json.isJsonArray()) {
throw new JsonParseException("Expecting array found: " + json);
}
JsonArray jsonArray = json.getAsJsonArray();
if ($Gson$Types.isArray(targetType)) {
// We know that we are getting back an array of the required type, so
// this typecasting is safe.
return (T) objectConstructor.constructArray($Gson$Types.getArrayComponentType(targetType),
jsonArray.size());
}
// is a collection
return (T) objectConstructor.construct($Gson$Types.getRawType(targetType));
}
public void visitArray(Object array, Type arrayType) {
if (!json.isJsonArray()) {
throw new JsonParseException("Expecting array found: " + json);
}
JsonArray jsonArray = json.getAsJsonArray();
for (int i = 0; i < jsonArray.size(); i++) {
JsonElement jsonChild = jsonArray.get(i);
Object child;
if (jsonChild == null || jsonChild.isJsonNull()) {
child = null;
} else if (jsonChild instanceof JsonObject) {
child = visitChildAsObject($Gson$Types.getArrayComponentType(arrayType), jsonChild);
} else if (jsonChild instanceof JsonArray) {
child = visitChildAsArray($Gson$Types.getArrayComponentType(arrayType),
jsonChild.getAsJsonArray());
} else if (jsonChild instanceof JsonPrimitive) {
child = visitChildAsObject($Gson$Types.getArrayComponentType(arrayType),
jsonChild.getAsJsonPrimitive());
} else {
throw new IllegalStateException();
}
Array.set(array, i, child);
}
}
// We should not implement any other method from Visitor interface since
// all other methods should be invoked on JsonObjectDeserializationVisitor
// instead.
public void startVisitingObject(Object node) {
throw new JsonParseException("Expecting array but found object: " + node);
}
public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
throw new JsonParseException("Expecting array but found array field " + f.getName() + ": "
+ obj);
}
public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
throw new JsonParseException("Expecting array but found object field " + f.getName() + ": "
+ obj);
}
public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type actualTypeOfField, Object parent) {
throw new JsonParseException("Expecting array but found field " + f.getName() + ": "
+ parent);
}
public void visitPrimitive(Object primitive) {
throw new JsonParseException(
"Type information is unavailable, and the target is not a primitive: " + json);
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Type;
/**
* Context for deserialization that is passed to a custom deserializer during invocation of its
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)}
* method.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public interface JsonDeserializationContext {
/**
* Invokes default deserialization on the specified object. It should never be invoked on
* the element received as a parameter of the
* {@link JsonDeserializer#deserialize(JsonElement, Type, JsonDeserializationContext)} method. Doing
* so will result in an infinite loop since Gson will in-turn call the custom deserializer again.
* @param json the parse tree.
* @param typeOfT type of the expected return value.
* @param <T> The type of the deserialized object.
* @return An object of type typeOfT.
* @throws JsonParseException if the parse tree does not contain expected data.
*/
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException;
}

View File

@ -0,0 +1,89 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Type;
/**
* implementation of a deserialization context for Gson
*
* @author Inderjeet Singh
*/
final class JsonDeserializationContextDefault implements JsonDeserializationContext {
private final ObjectNavigator objectNavigator;
private final FieldNamingStrategy2 fieldNamingPolicy;
private final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
private final MappedObjectConstructor objectConstructor;
JsonDeserializationContextDefault(ObjectNavigator objectNavigator,
FieldNamingStrategy2 fieldNamingPolicy,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
MappedObjectConstructor objectConstructor) {
this.objectNavigator = objectNavigator;
this.fieldNamingPolicy = fieldNamingPolicy;
this.deserializers = deserializers;
this.objectConstructor = objectConstructor;
}
ObjectConstructor getObjectConstructor() {
return objectConstructor;
}
@SuppressWarnings("unchecked")
public <T> T deserialize(JsonElement json, Type typeOfT) throws JsonParseException {
if (json == null || json.isJsonNull()) {
return null;
} else if (json.isJsonArray()) {
return (T) fromJsonArray(typeOfT, json.getAsJsonArray(), this);
} else if (json.isJsonObject()) {
return (T) fromJsonObject(typeOfT, json.getAsJsonObject(), this);
} else if (json.isJsonPrimitive()) {
return (T) fromJsonPrimitive(typeOfT, json.getAsJsonPrimitive(), this);
} else {
throw new JsonParseException("Failed parsing JSON source: " + json + " to Json");
}
}
private <T> T fromJsonArray(Type arrayType, JsonArray jsonArray,
JsonDeserializationContext context) throws JsonParseException {
JsonArrayDeserializationVisitor<T> visitor = new JsonArrayDeserializationVisitor<T>(
jsonArray, arrayType, objectNavigator, fieldNamingPolicy,
objectConstructor, deserializers, context);
objectNavigator.accept(new ObjectTypePair(null, arrayType, true), visitor);
return visitor.getTarget();
}
private <T> T fromJsonObject(Type typeOfT, JsonObject jsonObject,
JsonDeserializationContext context) throws JsonParseException {
JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
jsonObject, typeOfT, objectNavigator, fieldNamingPolicy,
objectConstructor, deserializers, context);
objectNavigator.accept(new ObjectTypePair(null, typeOfT, true), visitor);
return visitor.getTarget();
}
@SuppressWarnings("unchecked")
private <T> T fromJsonPrimitive(Type typeOfT, JsonPrimitive json,
JsonDeserializationContext context) throws JsonParseException {
JsonObjectDeserializationVisitor<T> visitor = new JsonObjectDeserializationVisitor<T>(
json, typeOfT, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
objectNavigator.accept(new ObjectTypePair(json.getAsObject(), typeOfT, true), visitor);
Object target = visitor.getTarget();
return (T) target;
}
}

View File

@ -0,0 +1,115 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import java.lang.reflect.Type;
/**
* Abstract data value container for the {@link ObjectNavigator.Visitor}
* implementations. This class exposes the {@link #getTarget()} method
* which returns the class that was visited by this object.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
abstract class JsonDeserializationVisitor<T> implements ObjectNavigator.Visitor {
protected final ObjectNavigator objectNavigator;
protected final FieldNamingStrategy2 fieldNamingPolicy;
protected final ObjectConstructor objectConstructor;
protected final ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers;
protected T target;
protected final JsonElement json;
protected final Type targetType;
protected final JsonDeserializationContext context;
protected boolean constructed;
JsonDeserializationVisitor(JsonElement json, Type targetType,
ObjectNavigator objectNavigator, FieldNamingStrategy2 fieldNamingPolicy,
ObjectConstructor objectConstructor,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
JsonDeserializationContext context) {
this.targetType = targetType;
this.objectNavigator = objectNavigator;
this.fieldNamingPolicy = fieldNamingPolicy;
this.objectConstructor = objectConstructor;
this.deserializers = deserializers;
this.json = $Gson$Preconditions.checkNotNull(json);
this.context = context;
this.constructed = false;
}
public T getTarget() {
if (!constructed) {
target = constructTarget();
constructed = true;
}
return target;
}
protected abstract T constructTarget();
public void start(ObjectTypePair node) {
}
public void end(ObjectTypePair node) {
}
@SuppressWarnings("unchecked")
public final boolean visitUsingCustomHandler(ObjectTypePair objTypePair) {
Pair<JsonDeserializer<?>, ObjectTypePair> pair = objTypePair.getMatchingHandler(deserializers);
if (pair == null) {
return false;
}
Object value = invokeCustomDeserializer(json, pair);
target = (T) value;
constructed = true;
return true;
}
protected Object invokeCustomDeserializer(JsonElement element,
Pair<JsonDeserializer<?>, ObjectTypePair> pair) {
if (element == null || element.isJsonNull()) {
return null;
}
Type objType = pair.second.type;
return (pair.first).deserialize(element, objType, context);
}
final Object visitChildAsObject(Type childType, JsonElement jsonChild) {
JsonDeserializationVisitor<?> childVisitor =
new JsonObjectDeserializationVisitor<Object>(jsonChild, childType,
objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
return visitChild(childType, childVisitor);
}
final Object visitChildAsArray(Type childType, JsonArray jsonChild) {
JsonDeserializationVisitor<?> childVisitor =
new JsonArrayDeserializationVisitor<Object>(jsonChild.getAsJsonArray(), childType,
objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
return visitChild(childType, childVisitor);
}
private Object visitChild(Type type, JsonDeserializationVisitor<?> childVisitor) {
objectNavigator.accept(new ObjectTypePair(null, type, false), childVisitor);
// the underlying object may have changed during the construction phase
// This happens primarily because of custom deserializers
return childVisitor.getTarget();
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Type;
/**
* <p>Interface representing a custom deserializer for Json. You should write a custom
* deserializer, if you are not happy with the default deserialization done by Gson. You will
* also need to register this deserializer through
* {@link GsonBuilder#registerTypeAdapter(Type, Object)}.</p>
*
* <p>Let us look at example where defining a deserializer will be useful. The {@code Id} class
* defined below has two fields: {@code clazz} and {@code value}.</p>
*
* <pre>
* public class Id&lt;T&gt; {
* private final Class&lt;T&gt; clazz;
* private final long value;
* public Id(Class&lt;T&gt; clazz, long value) {
* this.clazz = clazz;
* this.value = value;
* }
* public long getValue() {
* return value;
* }
* }
* </pre>
*
* <p>The default deserialization of {@code Id(com.foo.MyObject.class, 20L)} will require the
* Json string to be <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you already know
* the type of the field that the {@code Id} will be deserialized into, and hence just want to
* deserialize it from a Json string {@code 20}. You can achieve that by writing a custom
* deserializer:</p>
*
* <pre>
* class IdDeserializer implements JsonDeserializer&lt;Id&gt;() {
* public Id fromJson(JsonElement json, Type typeOfT, JsonDeserializationContext context)
* throws JsonParseException {
* return (Id) new Id((Class)typeOfT, id.getValue());
* }
* </pre>
*
* <p>You will also need to register {@code IdDeserializer} with Gson as follows:</p>
*
* <pre>
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdDeserializer()).create();
* </pre>
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @param <T> type for which the deserializer is being registered. It is possible that a
* deserializer may be asked to deserialize a specific generic type of the T.
*/
public interface JsonDeserializer<T> {
/**
* Gson invokes this call-back method during deserialization when it encounters a field of the
* specified type.
* <p>In the implementation of this call-back method, you should consider invoking
* {@link JsonDeserializationContext#deserialize(JsonElement, Type)} method to create objects
* for any non-trivial field of the returned object. However, you should never invoke it on the
* the same type passing {@code json} since that will cause an infinite loop (Gson will call your
* call-back method again).
*
* @param json The Json data being deserialized
* @param typeOfT The type of the Object to deserialize to
* @return a deserialized object of the specified type typeOfT which is a subclass of {@code T}
* @throws JsonParseException if json is not in the expected format of {@code typeofT}
*/
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException;
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import java.lang.reflect.Type;
/**
* Decorators a {@code JsonDeserializer} instance with exception handling. This wrapper class
* ensures that a {@code JsonDeserializer} will not propagate any exception other than a
* {@link JsonParseException}.
*
* @param <T> type of the deserializer being wrapped.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class JsonDeserializerExceptionWrapper<T> implements JsonDeserializer<T> {
private final JsonDeserializer<T> delegate;
/**
* Returns a wrapped {@link JsonDeserializer} object that has been decorated with
* {@link JsonParseException} handling.
*
* @param delegate the {@code JsonDeserializer} instance to be wrapped.
* @throws IllegalArgumentException if {@code delegate} is {@code null}.
*/
JsonDeserializerExceptionWrapper(JsonDeserializer<T> delegate) {
this.delegate = $Gson$Preconditions.checkNotNull(delegate);
}
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
try {
return delegate.deserialize(json, typeOfT, context);
} catch (JsonParseException e) {
// just rethrow the exception
throw e;
} catch (Exception e) {
// rethrow as a JsonParseException
StringBuilder errorMsg = new StringBuilder()
.append("The JsonDeserializer ")
.append(delegate)
.append(" failed to deserialize json object ")
.append(json)
.append(" given the type ")
.append(typeOfT);
throw new JsonParseException(errorMsg.toString(), e);
}
}
@Override
public String toString() {
return delegate.toString();
}
}

View File

@ -0,0 +1,338 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* A class representing an element of Json. It could either be a {@link JsonObject}, a
* {@link JsonArray}, a {@link JsonPrimitive} or a {@link JsonNull}.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public abstract class JsonElement {
private static final Escaper BASIC_ESCAPER = new Escaper(false);
/**
* provides check for verifying if this element is an array or not.
*
* @return true if this element is of type {@link JsonArray}, false otherwise.
*/
public boolean isJsonArray() {
return this instanceof JsonArray;
}
/**
* provides check for verifying if this element is a Json object or not.
*
* @return true if this element is of type {@link JsonObject}, false otherwise.
*/
public boolean isJsonObject() {
return this instanceof JsonObject;
}
/**
* provides check for verifying if this element is a primitive or not.
*
* @return true if this element is of type {@link JsonPrimitive}, false otherwise.
*/
public boolean isJsonPrimitive() {
return this instanceof JsonPrimitive;
}
/**
* provides check for verifying if this element represents a null value or not.
*
* @return true if this element is of type {@link JsonNull}, false otherwise.
* @since 1.2
*/
public boolean isJsonNull() {
return this instanceof JsonNull;
}
/**
* convenience method to get this element as a {@link JsonObject}. If the element is of some
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #isJsonObject()}
* first.
*
* @return get this element as a {@link JsonObject}.
* @throws IllegalStateException if the element is of another type.
*/
public JsonObject getAsJsonObject() {
if (isJsonObject()) {
return (JsonObject) this;
}
throw new IllegalStateException("This is not a JSON Object.");
}
/**
* convenience method to get this element as a {@link JsonArray}. If the element is of some
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #isJsonArray()}
* first.
*
* @return get this element as a {@link JsonArray}.
* @throws IllegalStateException if the element is of another type.
*/
public JsonArray getAsJsonArray() {
if (isJsonArray()) {
return (JsonArray) this;
}
throw new IllegalStateException("This is not a JSON Array.");
}
/**
* convenience method to get this element as a {@link JsonPrimitive}. If the element is of some
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #isJsonPrimitive()}
* first.
*
* @return get this element as a {@link JsonPrimitive}.
* @throws IllegalStateException if the element is of another type.
*/
public JsonPrimitive getAsJsonPrimitive() {
if (isJsonPrimitive()) {
return (JsonPrimitive) this;
}
throw new IllegalStateException("This is not a JSON Primitive.");
}
/**
* convenience method to get this element as a {@link JsonNull}. If the element is of some
* other type, a {@link ClassCastException} will result. Hence it is best to use this method
* after ensuring that this element is of the desired type by calling {@link #isJsonNull()}
* first.
*
* @return get this element as a {@link JsonNull}.
* @throws IllegalStateException if the element is of another type.
* @since 1.2
*/
public JsonNull getAsJsonNull() {
if (isJsonNull()) {
return (JsonNull) this;
}
throw new IllegalStateException("This is not a JSON Null.");
}
/**
* convenience method to get this element as a boolean value.
*
* @return get this element as a primitive boolean value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* boolean value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public boolean getAsBoolean() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a {@link Boolean} value.
*
* @return get this element as a {@link Boolean} value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* boolean value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
Boolean getAsBooleanWrapper() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a {@link Number}.
*
* @return get this element as a {@link Number}.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* number.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public Number getAsNumber() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a string value.
*
* @return get this element as a string value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* string value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public String getAsString() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a primitive double value.
*
* @return get this element as a primitive double value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* double value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public double getAsDouble() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a primitive float value.
*
* @return get this element as a primitive float value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* float value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public float getAsFloat() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a primitive long value.
*
* @return get this element as a primitive long value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* long value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public long getAsLong() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a primitive integer value.
*
* @return get this element as a primitive integer value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* integer value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public int getAsInt() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a primitive byte value.
*
* @return get this element as a primitive byte value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* byte value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
* @since 1.3
*/
public byte getAsByte() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a primitive character value.
*
* @return get this element as a primitive char value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* char value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
* @since 1.3
*/
public char getAsCharacter() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a {@link BigDecimal}.
*
* @return get this element as a {@link BigDecimal}.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
* * @throws NumberFormatException if the element is not a valid {@link BigDecimal}.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
* @since 1.2
*/
public BigDecimal getAsBigDecimal() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a {@link BigInteger}.
*
* @return get this element as a {@link BigInteger}.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive}.
* @throws NumberFormatException if the element is not a valid {@link BigInteger}.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
* @since 1.2
*/
public BigInteger getAsBigInteger() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as a primitive short value.
*
* @return get this element as a primitive short value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* short value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
public short getAsShort() {
throw new UnsupportedOperationException();
}
/**
* convenience method to get this element as an {@link Object} value.
*
* @return get this element as an Object value.
* @throws ClassCastException if the element is of not a {@link JsonPrimitive} and is not a valid
* Object value.
* @throws IllegalStateException if the element is of the type {@link JsonArray} but contains
* more than a single element.
*/
Object getAsObject() {
throw new UnsupportedOperationException();
}
/**
* Returns a String representation of this element.
*
* @return String the string representation of this element.
*/
@Override
public String toString() {
try {
StringBuilder sb = new StringBuilder();
toString(sb, BASIC_ESCAPER);
return sb.toString();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
protected abstract void toString(Appendable sb, Escaper escaper) throws IOException;
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.io.IOException;
/**
* Definition of a visitor for a JsonElement tree.
*
* @author Inderjeet Singh
*/
interface JsonElementVisitor {
void visitPrimitive(JsonPrimitive primitive) throws IOException;
void visitNull() throws IOException;
void startArray(JsonArray array) throws IOException;
void visitArrayMember(JsonArray parent, JsonPrimitive member, boolean isFirst) throws IOException;
void visitArrayMember(JsonArray parent, JsonArray member, boolean isFirst) throws IOException;
void visitArrayMember(JsonArray parent, JsonObject member, boolean isFirst) throws IOException;
void visitNullArrayMember(JsonArray parent, boolean isFirst) throws IOException;
void endArray(JsonArray array) throws IOException;
void startObject(JsonObject object) throws IOException;
void visitObjectMember(JsonObject parent, String memberName, JsonPrimitive member,
boolean isFirst) throws IOException;
void visitObjectMember(JsonObject parent, String memberName, JsonArray member,
boolean isFirst) throws IOException;
void visitObjectMember(JsonObject parent, String memberName, JsonObject member,
boolean isFirst) throws IOException;
void visitNullObjectMember(JsonObject parent, String memberName,
boolean isFirst) throws IOException;
void endObject(JsonObject object) throws IOException;
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* This exception is raised when Gson was unable to read an input stream
* or write to one.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonIOException extends JsonParseException {
private static final long serialVersionUID = 1L;
public JsonIOException(String msg) {
super(msg);
}
public JsonIOException(String msg, Throwable cause) {
super(msg, cause);
}
/**
* Creates exception with the specified cause. Consider using
* {@link #JsonIOException(String, Throwable)} instead if you can describe what happened.
*
* @param cause root exception that caused this exception to be thrown.
*/
public JsonIOException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.io.IOException;
/**
* A class representing a Json {@code null} value.
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.2
*/
public final class JsonNull extends JsonElement {
private static final JsonNull INSTANCE = new JsonNull();
/**
* Creates a new JsonNull object.
*/
public JsonNull() {
// Do nothing
}
@Override
protected void toString(Appendable sb, Escaper escaper) throws IOException {
sb.append("null");
}
/**
* All instances of JsonNull have the same hash code since they are indistinguishable
*/
@Override
public int hashCode() {
return JsonNull.class.hashCode();
}
/**
* All instances of JsonNull are the same
*/
@Override
public boolean equals(Object other) {
return this == other || other instanceof JsonNull;
}
/**
* Creation method used to return an instance of a {@link JsonNull}. To reduce the memory
* footprint, a single object has been created for this class; therefore the same instance is
* being returned for each invocation of this method. This method is kept private since we
* prefer the users to use {@link JsonNull#JsonNull()} which is similar to how other JsonElements
* are created. Note that all instances of JsonNull return true for {@link #equals(Object)}
* when compared to each other.
*
* @return a instance of a {@link JsonNull}
*/
static JsonNull createJsonNull() {
return INSTANCE;
}
}

View File

@ -0,0 +1,220 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
/**
* A class representing an object type in Json. An object consists of name-value pairs where names
* are strings, and values are any other type of {@link JsonElement}. This allows for a creating a
* tree of JsonElements. The member elements of this object are maintained in order they were added.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonObject extends JsonElement {
// We are using a linked hash map because it is important to preserve
// the order in which elements are inserted. This is needed to ensure
// that the fields of an object are inserted in the order they were
// defined in the class.
private final Map<String, JsonElement> members;
/**
* Creates an empty JsonObject.
*/
public JsonObject() {
members = new LinkedHashMap<String, JsonElement>();
}
/**
* Adds a member, which is a name-value pair, to self. The name must be a String, but the value
* can be an arbitrary JsonElement, thereby allowing you to build a full tree of JsonElements
* rooted at this node.
*
* @param property name of the member.
* @param value the member object.
*/
public void add(String property, JsonElement value) {
if (value == null) {
value = JsonNull.createJsonNull();
}
members.put($Gson$Preconditions.checkNotNull(property), value);
}
/**
* Removes the {@code property} from this {@link JsonObject}.
*
* @param property name of the member that should be removed.
* @return the {@link JsonElement} object that is being removed.
* @since 1.3
*/
public JsonElement remove(String property) {
return members.remove(property);
}
/**
* Convenience method to add a primitive member. The specified value is converted to a
* JsonPrimitive of String.
*
* @param property name of the member.
* @param value the string value associated with the member.
*/
public void addProperty(String property, String value) {
add(property, createJsonElement(value));
}
/**
* Convenience method to add a primitive member. The specified value is converted to a
* JsonPrimitive of Number.
*
* @param property name of the member.
* @param value the number value associated with the member.
*/
public void addProperty(String property, Number value) {
add(property, createJsonElement(value));
}
/**
* Convenience method to add a boolean member. The specified value is converted to a
* JsonPrimitive of Boolean.
*
* @param property name of the member.
* @param value the number value associated with the member.
*/
public void addProperty(String property, Boolean value) {
add(property, createJsonElement(value));
}
/**
* Convenience method to add a char member. The specified value is converted to a
* JsonPrimitive of Character.
*
* @param property name of the member.
* @param value the number value associated with the member.
*/
public void addProperty(String property, Character value) {
add(property, createJsonElement(value));
}
/**
* Creates the proper {@link JsonElement} object from the given {@code value} object.
*
* @param value the object to generate the {@link JsonElement} for
* @return a {@link JsonPrimitive} if the {@code value} is not null, otherwise a {@link JsonNull}
*/
private JsonElement createJsonElement(Object value) {
return value == null ? JsonNull.createJsonNull() : new JsonPrimitive(value);
}
/**
* Returns a set of members of this object. The set is ordered, and the order is in which the
* elements were added.
*
* @return a set of members of this object.
*/
public Set<Map.Entry<String, JsonElement>> entrySet() {
return members.entrySet();
}
/**
* Convenience method to check if a member with the specified name is present in this object.
*
* @param memberName name of the member that is being checked for presence.
* @return true if there is a member with the specified name, false otherwise.
*/
public boolean has(String memberName) {
return members.containsKey(memberName);
}
/**
* Returns the member with the specified name.
*
* @param memberName name of the member that is being requested.
* @return the member matching the name. Null if no such member exists.
*/
public JsonElement get(String memberName) {
if (members.containsKey(memberName)) {
JsonElement member = members.get(memberName);
return member == null ? JsonNull.createJsonNull() : member;
}
return null;
}
/**
* Convenience method to get the specified member as a JsonPrimitive element.
*
* @param memberName name of the member being requested.
* @return the JsonPrimitive corresponding to the specified member.
*/
public JsonPrimitive getAsJsonPrimitive(String memberName) {
return (JsonPrimitive) members.get(memberName);
}
/**
* Convenience method to get the specified member as a JsonArray.
*
* @param memberName name of the member being requested.
* @return the JsonArray corresponding to the specified member.
*/
public JsonArray getAsJsonArray(String memberName) {
return (JsonArray) members.get(memberName);
}
/**
* Convenience method to get the specified member as a JsonObject.
*
* @param memberName name of the member being requested.
* @return the JsonObject corresponding to the specified member.
*/
public JsonObject getAsJsonObject(String memberName) {
return (JsonObject) members.get(memberName);
}
@Override
public boolean equals(Object o) {
return (o == this) || (o instanceof JsonObject
&& ((JsonObject) o).members.equals(members));
}
@Override
public int hashCode() {
return members.hashCode();
}
@Override
protected void toString(Appendable sb, Escaper escaper) throws IOException {
sb.append('{');
boolean first = true;
for (Map.Entry<String, JsonElement> entry : members.entrySet()) {
if (first) {
first = false;
} else {
sb.append(',');
}
sb.append('\"');
sb.append(escaper.escapeJsonString(entry.getKey()));
sb.append("\":");
entry.getValue().toString(sb, escaper);
}
sb.append('}');
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Type;
/**
* A visitor that populates fields of an object with data from its equivalent
* JSON representation
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class JsonObjectDeserializationVisitor<T> extends JsonDeserializationVisitor<T> {
JsonObjectDeserializationVisitor(JsonElement json, Type type,
ObjectNavigator objectNavigator, FieldNamingStrategy2 fieldNamingPolicy,
ObjectConstructor objectConstructor,
ParameterizedTypeHandlerMap<JsonDeserializer<?>> deserializers,
JsonDeserializationContext context) {
super(json, type, objectNavigator, fieldNamingPolicy, objectConstructor, deserializers, context);
}
@Override
@SuppressWarnings("unchecked")
protected T constructTarget() {
return (T) objectConstructor.construct(targetType);
}
public void startVisitingObject(Object node) {
// do nothing
}
public void visitArray(Object array, Type componentType) {
// should not be called since this case should invoke JsonArrayDeserializationVisitor
throw new JsonParseException("Expecting object but found array: " + array);
}
public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
try {
if (!json.isJsonObject()) {
throw new JsonParseException("Expecting object found: " + json);
}
JsonObject jsonObject = json.getAsJsonObject();
String fName = getFieldName(f);
JsonElement jsonChild = jsonObject.get(fName);
if (jsonChild != null) {
Object child = visitChildAsObject(typeOfF, jsonChild);
f.set(obj, child);
} else {
f.set(obj, null);
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
try {
if (!json.isJsonObject()) {
throw new JsonParseException("Expecting object found: " + json);
}
JsonObject jsonObject = json.getAsJsonObject();
String fName = getFieldName(f);
JsonArray jsonChild = (JsonArray) jsonObject.get(fName);
if (jsonChild != null) {
Object array = visitChildAsArray(typeOfF, jsonChild);
f.set(obj, array);
} else {
f.set(obj, null);
}
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
private String getFieldName(FieldAttributes f) {
return fieldNamingPolicy.translateName(f);
}
public boolean visitFieldUsingCustomHandler(FieldAttributes f, Type declaredTypeOfField, Object parent) {
try {
String fName = getFieldName(f);
if (!json.isJsonObject()) {
throw new JsonParseException("Expecting object found: " + json);
}
JsonElement child = json.getAsJsonObject().get(fName);
boolean isPrimitive = Primitives.isPrimitive(declaredTypeOfField);
if (child == null) { // Child will be null if the field wasn't present in Json
return true;
} else if (child.isJsonNull()) {
if (!isPrimitive) {
f.set(parent, null);
}
return true;
}
ObjectTypePair objTypePair = new ObjectTypePair(null, declaredTypeOfField, false);
Pair<JsonDeserializer<?>, ObjectTypePair> pair = objTypePair.getMatchingHandler(deserializers);
if (pair == null) {
return false;
}
Object value = invokeCustomDeserializer(child, pair);
if (value != null || !isPrimitive) {
f.set(parent, value);
}
return true;
} catch (IllegalAccessException e) {
throw new RuntimeException();
}
}
@SuppressWarnings("unchecked")
public void visitPrimitive(Object primitive) {
if (!json.isJsonPrimitive()) {
throw new JsonParseException(
"Type information is unavailable, and the target object is not a primitive: " + json);
}
JsonPrimitive prim = json.getAsJsonPrimitive();
target = (T) prim.getAsObject();
}
}

View File

@ -0,0 +1,64 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* This exception is raised if there is a serious issue that occurs during parsing of a Json
* string. One of the main usages for this class is for the Gson infrastructure. If the incoming
* Json is bad/malicious, an instance of this exception is raised.
*
* <p>This exception is a {@link RuntimeException} because it is exposed to the client. Using a
* {@link RuntimeException} avoids bad coding practices on the client side where they catch the
* exception and do nothing. It is often the case that you want to blow up if there is a parsing
* error (i.e. often clients do not know how to recover from a {@link JsonParseException}.</p>
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public class JsonParseException extends RuntimeException {
static final long serialVersionUID = -4086729973971783390L;
/**
* Creates exception with the specified message. If you are wrapping another exception, consider
* using {@link #JsonParseException(String, Throwable)} instead.
*
* @param msg error message describing a possible cause of this exception.
*/
public JsonParseException(String msg) {
super(msg);
}
/**
* Creates exception with the specified message and cause.
*
* @param msg error message describing what happened.
* @param cause root exception that caused this exception to be thrown.
*/
public JsonParseException(String msg, Throwable cause) {
super(msg, cause);
}
/**
* Creates exception with the specified cause. Consider using
* {@link #JsonParseException(String, Throwable)} instead if you can describe what happened.
*
* @param cause root exception that caused this exception to be thrown.
*/
public JsonParseException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.stream.JsonReader;
import com.massivecraft.factions.gson.stream.JsonToken;
import com.massivecraft.factions.gson.stream.MalformedJsonException;
import java.io.EOFException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
/**
* A parser to parse Json into a parse tree of {@link JsonElement}s
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.3
*/
public final class JsonParser {
/**
* Parses the specified JSON string into a parse tree
*
* @param json JSON text
* @return a parse tree of {@link JsonElement}s corresponding to the specified JSON
* @throws JsonParseException if the specified text is not valid JSON
* @since 1.3
*/
public JsonElement parse(String json) throws JsonSyntaxException {
return parse(new StringReader(json));
}
/**
* Parses the specified JSON string into a parse tree
*
* @param json JSON text
* @return a parse tree of {@link JsonElement}s corresponding to the specified JSON
* @throws JsonParseException if the specified text is not valid JSON
* @since 1.3
*/
public JsonElement parse(Reader json) throws JsonIOException, JsonSyntaxException {
try {
JsonReader jsonReader = new JsonReader(json);
JsonElement element = parse(jsonReader);
if (!element.isJsonNull() && jsonReader.peek() != JsonToken.END_DOCUMENT) {
throw new JsonSyntaxException("Did not consume the entire document.");
}
return element;
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
} catch (NumberFormatException e) {
throw new JsonSyntaxException(e);
}
}
/**
* Returns the next value from the JSON stream as a parse tree.
*
* @throws JsonParseException if there is an IOException or if the specified
* text is not valid JSON
* @since 1.6
*/
public JsonElement parse(JsonReader json) throws JsonIOException, JsonSyntaxException {
boolean lenient = json.isLenient();
json.setLenient(true);
try {
return Streams.parse(json);
} catch (StackOverflowError e) {
throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e);
} catch (OutOfMemoryError e) {
throw new JsonParseException("Failed parsing JSON source: " + json + " to Json", e);
} catch (JsonParseException e) {
if (e.getCause() instanceof EOFException) {
return JsonNull.createJsonNull();
}
throw e;
} finally {
json.setLenient(lenient);
}
}
}

View File

@ -0,0 +1,390 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.BigInteger;
/**
* A class representing a Json primitive value. A primitive value
* is either a String, a Java primitive, or a Java primitive
* wrapper type.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonPrimitive extends JsonElement {
private static final Class<?>[] PRIMITIVE_TYPES = { int.class, long.class, short.class,
float.class, double.class, byte.class, boolean.class, char.class, Integer.class, Long.class,
Short.class, Float.class, Double.class, Byte.class, Boolean.class, Character.class };
private static final BigInteger INTEGER_MAX = BigInteger.valueOf(Integer.MAX_VALUE);
private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE);
private Object value;
/**
* Create a primitive containing a boolean value.
*
* @param bool the value to create the primitive with.
*/
public JsonPrimitive(Boolean bool) {
setValue(bool);
}
/**
* Create a primitive containing a {@link Number}.
*
* @param number the value to create the primitive with.
*/
public JsonPrimitive(Number number) {
setValue(number);
}
/**
* Create a primitive containing a String value.
*
* @param string the value to create the primitive with.
*/
public JsonPrimitive(String string) {
setValue(string);
}
/**
* Create a primitive containing a character. The character is turned into a one character String
* since Json only supports String.
*
* @param c the value to create the primitive with.
*/
public JsonPrimitive(Character c) {
setValue(c);
}
/**
* Create a primitive using the specified Object. It must be an instance of {@link Number}, a
* Java primitive type, or a String.
*
* @param primitive the value to create the primitive with.
*/
JsonPrimitive(Object primitive) {
setValue(primitive);
}
void setValue(Object primitive) {
if (primitive instanceof Character) {
// convert characters to strings since in JSON, characters are represented as a single
// character string
char c = ((Character) primitive).charValue();
this.value = String.valueOf(c);
} else {
$Gson$Preconditions.checkArgument(primitive instanceof Number
|| isPrimitiveOrString(primitive));
this.value = primitive;
}
}
/**
* Check whether this primitive contains a boolean value.
*
* @return true if this primitive contains a boolean value, false otherwise.
*/
public boolean isBoolean() {
return value instanceof Boolean;
}
/**
* convenience method to get this element as a {@link Boolean}.
*
* @return get this element as a {@link Boolean}.
*/
@Override
Boolean getAsBooleanWrapper() {
return (Boolean) value;
}
/**
* convenience method to get this element as a boolean value.
*
* @return get this element as a primitive boolean value.
*/
@Override
public boolean getAsBoolean() {
return isBoolean() ? getAsBooleanWrapper().booleanValue() : Boolean.parseBoolean(getAsString());
}
/**
* Check whether this primitive contains a Number.
*
* @return true if this primitive contains a Number, false otherwise.
*/
public boolean isNumber() {
return value instanceof Number;
}
/**
* convenience method to get this element as a Number.
*
* @return get this element as a Number.
* @throws NumberFormatException if the value contained is not a valid Number.
*/
@Override
public Number getAsNumber() {
return value instanceof String ? stringToNumber((String) value) : (Number) value;
}
static Number stringToNumber(String value) {
try {
long longValue = Long.parseLong(value);
if (longValue >= Integer.MIN_VALUE && longValue <= Integer.MAX_VALUE) {
return (int) longValue;
}
return longValue;
} catch (NumberFormatException ignored) {
}
try {
return new BigDecimal(value);
} catch (NumberFormatException ignored) {
return Double.parseDouble(value); // probably NaN, -Infinity or Infinity
}
}
/**
* Check whether this primitive contains a String value.
*
* @return true if this primitive contains a String value, false otherwise.
*/
public boolean isString() {
return value instanceof String;
}
/**
* convenience method to get this element as a String.
*
* @return get this element as a String.
*/
@Override
public String getAsString() {
if (isNumber()) {
return getAsNumber().toString();
} else if (isBoolean()) {
return getAsBooleanWrapper().toString();
} else {
return (String) value;
}
}
/**
* convenience method to get this element as a primitive double.
*
* @return get this element as a primitive double.
* @throws NumberFormatException if the value contained is not a valid double.
*/
@Override
public double getAsDouble() {
return isNumber() ? getAsNumber().doubleValue() : Double.parseDouble(getAsString());
}
/**
* convenience method to get this element as a {@link BigDecimal}.
*
* @return get this element as a {@link BigDecimal}.
* @throws NumberFormatException if the value contained is not a valid {@link BigDecimal}.
*/
@Override
public BigDecimal getAsBigDecimal() {
return value instanceof BigDecimal ? (BigDecimal) value : new BigDecimal(value.toString());
}
/**
* convenience method to get this element as a {@link BigInteger}.
*
* @return get this element as a {@link BigInteger}.
* @throws NumberFormatException if the value contained is not a valid {@link BigInteger}.
*/
@Override
public BigInteger getAsBigInteger() {
return value instanceof BigInteger ? (BigInteger) value : new BigInteger(value.toString());
}
/**
* convenience method to get this element as a float.
*
* @return get this element as a float.
* @throws NumberFormatException if the value contained is not a valid float.
*/
@Override
public float getAsFloat() {
return isNumber() ? getAsNumber().floatValue() : Float.parseFloat(getAsString());
}
/**
* convenience method to get this element as a primitive long.
*
* @return get this element as a primitive long.
* @throws NumberFormatException if the value contained is not a valid long.
*/
@Override
public long getAsLong() {
return isNumber() ? getAsNumber().longValue() : Long.parseLong(getAsString());
}
/**
* convenience method to get this element as a primitive short.
*
* @return get this element as a primitive short.
* @throws NumberFormatException if the value contained is not a valid short value.
*/
@Override
public short getAsShort() {
return isNumber() ? getAsNumber().shortValue() : Short.parseShort(getAsString());
}
/**
* convenience method to get this element as a primitive integer.
*
* @return get this element as a primitive integer.
* @throws NumberFormatException if the value contained is not a valid integer.
*/
@Override
public int getAsInt() {
return isNumber() ? getAsNumber().intValue() : Integer.parseInt(getAsString());
}
@Override
public byte getAsByte() {
return isNumber() ? getAsNumber().byteValue() : Byte.parseByte(getAsString());
}
@Override
public char getAsCharacter() {
return getAsString().charAt(0);
}
/**
* convenience method to get this element as an Object.
*
* @return get this element as an Object that can be converted to a suitable value.
*/
@Override
Object getAsObject() {
if (value instanceof BigInteger) {
BigInteger big = (BigInteger) value;
if (big.compareTo(INTEGER_MAX) < 0) {
return big.intValue();
} else if (big.compareTo(LONG_MAX) < 0) {
return big.longValue();
}
}
// No need to convert to float or double since those lose precision
return value;
}
@Override
protected void toString(Appendable sb, Escaper escaper) throws IOException {
if (isString()) {
sb.append('"');
sb.append(escaper.escapeJsonString(value.toString()));
sb.append('"');
} else {
sb.append(value.toString());
}
}
private static boolean isPrimitiveOrString(Object target) {
if (target instanceof String) {
return true;
}
Class<?> classOfPrimitive = target.getClass();
for (Class<?> standardPrimitive : PRIMITIVE_TYPES) {
if (standardPrimitive.isAssignableFrom(classOfPrimitive)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
if (value == null) {
return 31;
}
// Using recommended hashing algorithm from Effective Java for longs and doubles
if (isIntegral(this)) {
long value = getAsNumber().longValue();
return (int) (value ^ (value >>> 32));
}
if (isFloatingPoint(this)) {
long value = Double.doubleToLongBits(getAsNumber().doubleValue());
return (int) (value ^ (value >>> 32));
}
return value.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null || getClass() != obj.getClass()) {
return false;
}
JsonPrimitive other = (JsonPrimitive)obj;
if (value == null) {
return other.value == null;
}
if (isIntegral(this) && isIntegral(other)) {
return getAsNumber().longValue() == other.getAsNumber().longValue();
}
if (isFloatingPoint(this) && isFloatingPoint(other)) {
double a = getAsNumber().doubleValue();
// Java standard types other than double return true for two NaN. So, need
// special handling for double.
double b = other.getAsNumber().doubleValue();
return a == b || (Double.isNaN(a) && Double.isNaN(b));
}
return value.equals(other.value);
}
/**
* Returns true if the specified number is an integral type
* (Long, Integer, Short, Byte, BigInteger)
*/
private static boolean isIntegral(JsonPrimitive primitive) {
if (primitive.value instanceof Number) {
Number number = (Number) primitive.value;
return number instanceof BigInteger || number instanceof Long || number instanceof Integer
|| number instanceof Short || number instanceof Byte;
}
return false;
}
/**
* Returns true if the specified number is a floating point type (BigDecimal, double, float)
*/
private static boolean isFloatingPoint(JsonPrimitive primitive) {
if (primitive.value instanceof Number) {
Number number = (Number) primitive.value;
return number instanceof BigDecimal || number instanceof Double || number instanceof Float;
}
return false;
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Type;
/**
* Context for serialization that is passed to a custom serializer during invocation of its
* {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public interface JsonSerializationContext {
/**
* Invokes default serialization on the specified object.
*
* @param src the object that needs to be serialized.
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
*/
public JsonElement serialize(Object src);
/**
* Invokes default serialization on the specified object passing the specific type information.
* It should never be invoked on the element received as a parameter of the
* {@link JsonSerializer#serialize(Object, Type, JsonSerializationContext)} method. Doing
* so will result in an infinite loop since Gson will in-turn call the custom serializer again.
*
* @param src the object that needs to be serialized.
* @param typeOfSrc the actual genericized type of src object.
* @return a tree of {@link JsonElement}s corresponding to the serialized form of {@code src}.
*/
public JsonElement serialize(Object src, Type typeOfSrc);
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Type;
/**
* An implementation of serialization context for Gson.
*
* @author Inderjeet Singh
*/
final class JsonSerializationContextDefault implements JsonSerializationContext {
private final ObjectNavigator objectNavigator;
private final FieldNamingStrategy2 fieldNamingPolicy;
private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers;
private final boolean serializeNulls;
private final MemoryRefStack ancestors;
JsonSerializationContextDefault(ObjectNavigator objectNavigator,
FieldNamingStrategy2 fieldNamingPolicy, boolean serializeNulls,
ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers) {
this.objectNavigator = objectNavigator;
this.fieldNamingPolicy = fieldNamingPolicy;
this.serializeNulls = serializeNulls;
this.serializers = serializers;
this.ancestors = new MemoryRefStack();
}
public JsonElement serialize(Object src) {
if (src == null) {
return JsonNull.createJsonNull();
}
return serialize(src, src.getClass(), false);
}
public JsonElement serialize(Object src, Type typeOfSrc) {
return serialize(src, typeOfSrc, true);
}
JsonElement serialize(Object src, Type typeOfSrc, boolean preserveType) {
if (src == null) {
return JsonNull.createJsonNull();
}
JsonSerializationVisitor visitor = new JsonSerializationVisitor(
objectNavigator, fieldNamingPolicy, serializeNulls, serializers, this, ancestors);
objectNavigator.accept(new ObjectTypePair(src, typeOfSrc, preserveType), visitor);
return visitor.getJsonElement();
}
}

View File

@ -0,0 +1,236 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import com.massivecraft.factions.gson.internal.$Gson$Preconditions;
import com.massivecraft.factions.gson.internal.$Gson$Types;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
/**
* A visitor that adds JSON elements corresponding to each field of an object
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class JsonSerializationVisitor implements ObjectNavigator.Visitor {
private final ObjectNavigator objectNavigator;
private final FieldNamingStrategy2 fieldNamingPolicy;
private final ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers;
private final boolean serializeNulls;
private final JsonSerializationContext context;
private final MemoryRefStack ancestors;
private JsonElement root;
JsonSerializationVisitor(ObjectNavigator objectNavigator, FieldNamingStrategy2 fieldNamingPolicy,
boolean serializeNulls, ParameterizedTypeHandlerMap<JsonSerializer<?>> serializers,
JsonSerializationContext context, MemoryRefStack ancestors) {
this.objectNavigator = objectNavigator;
this.fieldNamingPolicy = fieldNamingPolicy;
this.serializeNulls = serializeNulls;
this.serializers = serializers;
this.context = context;
this.ancestors = ancestors;
}
public Object getTarget() {
return null;
}
public void start(ObjectTypePair node) {
if (node == null) {
return;
}
if (ancestors.contains(node)) {
throw new CircularReferenceException(node);
}
ancestors.push(node);
}
public void end(ObjectTypePair node) {
if (node != null) {
ancestors.pop();
}
}
public void startVisitingObject(Object node) {
assignToRoot(new JsonObject());
}
public void visitArray(Object array, Type arrayType) {
assignToRoot(new JsonArray());
int length = Array.getLength(array);
Type componentType = $Gson$Types.getArrayComponentType(arrayType);
for (int i = 0; i < length; ++i) {
Object child = Array.get(array, i);
// we should not get more specific component type yet since it is possible
// that a custom serializer is registered for the componentType
addAsArrayElement(new ObjectTypePair(child, componentType, false));
}
}
public void visitArrayField(FieldAttributes f, Type typeOfF, Object obj) {
try {
if (isFieldNull(f, obj)) {
if (serializeNulls) {
addChildAsElement(f, JsonNull.createJsonNull());
}
} else {
Object array = getFieldValue(f, obj);
addAsChildOfObject(f, new ObjectTypePair(array, typeOfF, false));
}
} catch (CircularReferenceException e) {
throw e.createDetailedException(f);
}
}
public void visitObjectField(FieldAttributes f, Type typeOfF, Object obj) {
try {
if (isFieldNull(f, obj)) {
if (serializeNulls) {
addChildAsElement(f, JsonNull.createJsonNull());
}
} else {
Object fieldValue = getFieldValue(f, obj);
// we should not get more specific component type yet since it is
// possible that a custom
// serializer is registered for the componentType
addAsChildOfObject(f, new ObjectTypePair(fieldValue, typeOfF, false));
}
} catch (CircularReferenceException e) {
throw e.createDetailedException(f);
}
}
public void visitPrimitive(Object obj) {
JsonElement json = obj == null ? JsonNull.createJsonNull() : new JsonPrimitive(obj);
assignToRoot(json);
}
private void addAsChildOfObject(FieldAttributes f, ObjectTypePair fieldValuePair) {
JsonElement childElement = getJsonElementForChild(fieldValuePair);
addChildAsElement(f, childElement);
}
private void addChildAsElement(FieldAttributes f, JsonElement childElement) {
root.getAsJsonObject().add(fieldNamingPolicy.translateName(f), childElement);
}
private void addAsArrayElement(ObjectTypePair elementTypePair) {
if (elementTypePair.getObject() == null) {
root.getAsJsonArray().add(JsonNull.createJsonNull());
} else {
JsonElement childElement = getJsonElementForChild(elementTypePair);
root.getAsJsonArray().add(childElement);
}
}
private JsonElement getJsonElementForChild(ObjectTypePair fieldValueTypePair) {
JsonSerializationVisitor childVisitor = new JsonSerializationVisitor(
objectNavigator, fieldNamingPolicy, serializeNulls, serializers, context, ancestors);
objectNavigator.accept(fieldValueTypePair, childVisitor);
return childVisitor.getJsonElement();
}
public boolean visitUsingCustomHandler(ObjectTypePair objTypePair) {
try {
Object obj = objTypePair.getObject();
if (obj == null) {
if (serializeNulls) {
assignToRoot(JsonNull.createJsonNull());
}
return true;
}
JsonElement element = findAndInvokeCustomSerializer(objTypePair);
if (element != null) {
assignToRoot(element);
return true;
}
return false;
} catch (CircularReferenceException e) {
throw e.createDetailedException(null);
}
}
/**
* objTypePair.getObject() must not be null
*/
@SuppressWarnings("unchecked")
private JsonElement findAndInvokeCustomSerializer(ObjectTypePair objTypePair) {
Pair<JsonSerializer<?>,ObjectTypePair> pair = objTypePair.getMatchingHandler(serializers);
if (pair == null) {
return null;
}
JsonSerializer serializer = pair.first;
objTypePair = pair.second;
start(objTypePair);
try {
JsonElement element =
serializer.serialize(objTypePair.getObject(), objTypePair.getType(), context);
return element == null ? JsonNull.createJsonNull() : element;
} finally {
end(objTypePair);
}
}
public boolean visitFieldUsingCustomHandler(
FieldAttributes f, Type declaredTypeOfField, Object parent) {
try {
$Gson$Preconditions.checkState(root.isJsonObject());
Object obj = f.get(parent);
if (obj == null) {
if (serializeNulls) {
addChildAsElement(f, JsonNull.createJsonNull());
}
return true;
}
ObjectTypePair objTypePair = new ObjectTypePair(obj, declaredTypeOfField, false);
JsonElement child = findAndInvokeCustomSerializer(objTypePair);
if (child != null) {
addChildAsElement(f, child);
return true;
}
return false;
} catch (IllegalAccessException e) {
throw new RuntimeException();
} catch (CircularReferenceException e) {
throw e.createDetailedException(f);
}
}
private void assignToRoot(JsonElement newRoot) {
root = $Gson$Preconditions.checkNotNull(newRoot);
}
private boolean isFieldNull(FieldAttributes f, Object obj) {
return getFieldValue(f, obj) == null;
}
private Object getFieldValue(FieldAttributes f, Object obj) {
try {
return f.get(obj);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
public JsonElement getJsonElement() {
return root;
}
}

View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.reflect.Type;
/**
* Interface representing a custom serializer for Json. You should write a custom serializer, if
* you are not happy with the default serialization done by Gson. You will also need to register
* this serializer through {@link com.massivecraft.factions.gson.GsonBuilder#registerTypeAdapter(Type, Object)}.
*
* <p>Let us look at example where defining a serializer will be useful. The {@code Id} class
* defined below has two fields: {@code clazz} and {@code value}.</p>
*
* <p><pre>
* public class Id&lt;T&gt; {
* private final Class&lt;T&gt; clazz;
* private final long value;
*
* public Id(Class&lt;T&gt; clazz, long value) {
* this.clazz = clazz;
* this.value = value;
* }
*
* public long getValue() {
* return value;
* }
* }
* </pre></p>
*
* <p>The default serialization of {@code Id(com.foo.MyObject.class, 20L)} will be
* <code>{"clazz":com.foo.MyObject,"value":20}</code>. Suppose, you just want the output to be
* the value instead, which is {@code 20} in this case. You can achieve that by writing a custom
* serializer:</p>
*
* <p><pre>
* class IdSerializer implements JsonSerializer&lt;Id&gt;() {
* public JsonElement toJson(Id id, Type typeOfId, JsonSerializationContext context) {
* return new JsonPrimitive(id.getValue());
* }
* }
* </pre></p>
*
* <p>You will also need to register {@code IdSerializer} with Gson as follows:</p>
* <pre>
* Gson gson = new GsonBuilder().registerTypeAdapter(Id.class, new IdSerializer()).create();
* </pre>
*
* @author Inderjeet Singh
* @author Joel Leitch
*
* @param <T> type for which the serializer is being registered. It is possible that a serializer
* may be asked to serialize a specific generic type of the T.
*/
public interface JsonSerializer<T> {
/**
* Gson invokes this call-back method during serialization when it encounters a field of the
* specified type.
*
* <p>In the implementation of this call-back method, you should consider invoking
* {@link JsonSerializationContext#serialize(Object, Type)} method to create JsonElements for any
* non-trivial field of the {@code src} object. However, you should never invoke it on the
* {@code src} object itself since that will cause an infinite loop (Gson will call your
* call-back method again).</p>
*
* @param src the object that needs to be converted to Json.
* @param typeOfSrc the actual type (fully genericized version) of the source object.
* @return a JsonElement corresponding to the specified object.
*/
public JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context);
}

View File

@ -0,0 +1,122 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.io.EOFException;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.util.Iterator;
import java.util.NoSuchElementException;
import com.massivecraft.factions.gson.stream.JsonReader;
import com.massivecraft.factions.gson.stream.JsonToken;
import com.massivecraft.factions.gson.stream.MalformedJsonException;
/**
* A streaming parser that allows reading of multiple {@link JsonElement}s from the specified reader
* asynchronously.
*
* <p>This class is conditionally thread-safe (see Item 70, Effective Java second edition). To
* properly use this class across multiple threads, you will need to add some external
* synchronization. For example:
*
* <pre>
* JsonStreamParser parser = new JsonStreamParser("['first'] {'second':10} 'third'");
* JsonElement element;
* synchronized (parser) { // synchronize on an object shared by threads
* if (parser.hasNext()) {
* element = parser.next();
* }
* }
* </pre>
*
* @author Inderjeet Singh
* @author Joel Leitch
* @since 1.4
*/
public final class JsonStreamParser implements Iterator<JsonElement> {
private final JsonReader parser;
private final Object lock;
/**
* @param json The string containing JSON elements concatenated to each other.
* @since 1.4
*/
public JsonStreamParser(String json) {
this(new StringReader(json));
}
/**
* @param reader The data stream containing JSON elements concatenated to each other.
* @since 1.4
*/
public JsonStreamParser(Reader reader) {
parser = new JsonReader(reader);
parser.setLenient(true);
lock = new Object();
}
/**
* Returns the next available {@link JsonElement} on the reader. Null if none available.
*
* @return the next available {@link JsonElement} on the reader. Null if none available.
* @throws JsonParseException if the incoming stream is malformed JSON.
* @since 1.4
*/
public JsonElement next() throws JsonParseException {
if (!hasNext()) {
throw new NoSuchElementException();
}
try {
return Streams.parse(parser);
} catch (StackOverflowError e) {
throw new JsonParseException("Failed parsing JSON source to Json", e);
} catch (OutOfMemoryError e) {
throw new JsonParseException("Failed parsing JSON source to Json", e);
} catch (JsonParseException e) {
throw e.getCause() instanceof EOFException ? new NoSuchElementException() : e;
}
}
/**
* Returns true if a {@link JsonElement} is available on the input for consumption
* @return true if a {@link JsonElement} is available on the input, false otherwise
* @since 1.4
*/
public boolean hasNext() {
synchronized (lock) {
try {
return parser.peek() != JsonToken.END_DOCUMENT;
} catch (MalformedJsonException e) {
throw new JsonSyntaxException(e);
} catch (IOException e) {
throw new JsonIOException(e);
}
}
}
/**
* This optional {@link Iterator} method is not relevant for stream parsing and hence is not
* implemented.
* @since 1.4
*/
public void remove() {
throw new UnsupportedOperationException();
}
}

View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* This exception is raised when Gson attempts to read (or write) a malformed
* JSON element.
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public final class JsonSyntaxException extends JsonParseException {
private static final long serialVersionUID = 1L;
public JsonSyntaxException(String msg) {
super(msg);
}
public JsonSyntaxException(String msg, Throwable cause) {
super(msg, cause);
}
/**
* Creates exception with the specified cause. Consider using
* {@link #JsonSyntaxException(String, Throwable)} instead if you can
* describe what actually happened.
*
* @param cause root exception that caused this exception to be thrown.
*/
public JsonSyntaxException(Throwable cause) {
super(cause);
}
}

View File

@ -0,0 +1,111 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.io.IOException;
import java.util.Map;
/**
* A navigator to navigate a tree of JsonElement nodes in Depth-first order
*
* @author Inderjeet Singh
*/
final class JsonTreeNavigator {
private final JsonElementVisitor visitor;
private final boolean visitNulls;
JsonTreeNavigator(JsonElementVisitor visitor, boolean visitNulls) {
this.visitor = visitor;
this.visitNulls = visitNulls;
}
public void navigate(JsonElement element) throws IOException {
if (element.isJsonNull()) {
visitor.visitNull();
} else if (element.isJsonArray()) {
JsonArray array = element.getAsJsonArray();
visitor.startArray(array);
boolean isFirst = true;
for (JsonElement child : array) {
visitChild(array, child, isFirst);
if (isFirst) {
isFirst = false;
}
}
visitor.endArray(array);
} else if (element.isJsonObject()) {
JsonObject object = element.getAsJsonObject();
visitor.startObject(object);
boolean isFirst = true;
for (Map.Entry<String, JsonElement> member : object.entrySet()) {
boolean visited = visitChild(object, member.getKey(), member.getValue(), isFirst);
if (visited && isFirst) {
isFirst = false;
}
}
visitor.endObject(object);
} else { // must be JsonPrimitive
visitor.visitPrimitive(element.getAsJsonPrimitive());
}
}
/**
* Returns true if the child was visited, false if it was skipped.
*/
private boolean visitChild(JsonObject parent, String childName, JsonElement child,
boolean isFirst) throws IOException {
if (child.isJsonNull()) {
if (visitNulls) {
visitor.visitNullObjectMember(parent, childName, isFirst);
navigate(child.getAsJsonNull());
} else { // Null value is being skipped.
return false;
}
} else if (child.isJsonArray()) {
JsonArray childAsArray = child.getAsJsonArray();
visitor.visitObjectMember(parent, childName, childAsArray, isFirst);
navigate(childAsArray);
} else if (child.isJsonObject()) {
JsonObject childAsObject = child.getAsJsonObject();
visitor.visitObjectMember(parent, childName, childAsObject, isFirst);
navigate(childAsObject);
} else { // is a JsonPrimitive
visitor.visitObjectMember(parent, childName, child.getAsJsonPrimitive(), isFirst);
}
return true;
}
/**
* Returns true if the child was visited, false if it was skipped.
*/
private void visitChild(JsonArray parent, JsonElement child, boolean isFirst) throws IOException {
if (child.isJsonNull()) {
visitor.visitNullArrayMember(parent, isFirst);
navigate(child);
} else if (child.isJsonArray()) {
JsonArray childAsArray = child.getAsJsonArray();
visitor.visitArrayMember(parent, childAsArray, isFirst);
navigate(childAsArray);
} else if (child.isJsonObject()) {
JsonObject childAsObject = child.getAsJsonObject();
visitor.visitArrayMember(parent, childAsObject, isFirst);
navigate(childAsObject);
} else { // is a JsonPrimitive
visitor.visitArrayMember(parent, child.getAsJsonPrimitive(), isFirst);
}
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (C) 2009 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* Defines the expected format for a {@code long} or {@code Long} type when its serialized.
*
* @since 1.3
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
public enum LongSerializationPolicy {
/**
* This is the "default" serialization policy that will output a {@code long} object as a JSON
* number. For example, assume an object has a long field named "f" then the serialized output
* would be:
* {@code {"f":123}}.
*/
DEFAULT(new DefaultStrategy()),
/**
* Serializes a long value as a quoted string. For example, assume an object has a long field
* named "f" then the serialized output would be:
* {@code {"f":"123"}}.
*/
STRING(new StringStrategy());
private final Strategy strategy;
private LongSerializationPolicy(Strategy strategy) {
this.strategy = strategy;
}
/**
* Serialize this {@code value} using this serialization policy.
*
* @param value the long value to be serialized into a {@link JsonElement}
* @return the serialized version of {@code value}
*/
public JsonElement serialize(Long value) {
return strategy.serialize(value);
}
private interface Strategy {
JsonElement serialize(Long value);
}
private static class DefaultStrategy implements Strategy {
public JsonElement serialize(Long value) {
return new JsonPrimitive(value);
}
}
private static class StringStrategy implements Strategy {
public JsonElement serialize(Long value) {
return new JsonPrimitive(String.valueOf(value));
}
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
/**
* A {@link FieldNamingStrategy2} that ensures the JSON field names consist of only
* lower case letters and are separated by a particular {@code separatorString}.
*
*<p>The following is an example:</p>
* <pre>
* class StringWrapper {
* public String AStringField = "abcd";
* }
*
* LowerCamelCaseSeparatorNamingPolicy policy = new LowerCamelCaseSeparatorNamingPolicy("_");
* String translatedFieldName =
* policy.translateName(StringWrapper.class.getField("AStringField"));
*
* assert("a_string_field".equals(translatedFieldName));
* </pre>
*
* @author Joel Leitch
*/
final class LowerCamelCaseSeparatorNamingPolicy extends CompositionFieldNamingPolicy {
public LowerCamelCaseSeparatorNamingPolicy(String separatorString) {
super(new CamelCaseSeparatorNamingPolicy(separatorString), new LowerCaseNamingPolicy());
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (C) 2008 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.massivecraft.factions.gson;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* A {@link FieldNamingStrategy2} that ensures the JSON field names consist of only
* lower case letters.
*
* <p>The following is an example:</p>
* <pre>
* class IntWrapper {
* public int integerField = 0;
* }
*
* LowerCaseNamingPolicy policy = new LowerCaseNamingPolicy();
* String translatedFieldName =
* policy.translateName(IntWrapper.class.getField("integerField"));
*
* assert("integerfield".equals(translatedFieldName));
* </pre>
*
* @author Inderjeet Singh
* @author Joel Leitch
*/
final class LowerCaseNamingPolicy extends RecursiveFieldNamingPolicy {
@Override
protected String translateName(String target, Type fieldType,
Collection<Annotation> annotations) {
return target.toLowerCase();
}
}

Some files were not shown because too many files have changed in this diff Show More