package com.massivecraft.factions; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set; import java.util.TreeSet; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import com.massivecraft.factions.entity.FactionColl; import com.massivecraft.factions.entity.UPlayer; import com.massivecraft.factions.entity.Faction; import com.massivecraft.factions.entity.FactionColls; import com.massivecraft.factions.entity.UPlayerColl; import com.massivecraft.factions.entity.UPlayerColls; public class TerritoryAccess { // -------------------------------------------- // // FIELDS: RAW // -------------------------------------------- // // no default value, can't be null private final String hostFactionId; public String getHostFactionId() { return this.hostFactionId; } // default is true private final boolean hostFactionAllowed; public boolean isHostFactionAllowed() { return this.hostFactionAllowed; } // default is empty private final Set factionIds; public Set getFactionIds() { return this.factionIds; } // default is empty private final Set playerIds; public Set getPlayerIds() { return this.playerIds; } // -------------------------------------------- // // FIELDS: DELTA // -------------------------------------------- // // The simple ones public TerritoryAccess withHostFactionId(String hostFactionId) { return valueOf(hostFactionId, hostFactionAllowed, factionIds, playerIds); } public TerritoryAccess withHostFactionAllowed(Boolean hostFactionAllowed) { return valueOf(hostFactionId, hostFactionAllowed, factionIds, playerIds); } public TerritoryAccess withFactionIds(Collection factionIds) { return valueOf(hostFactionId, hostFactionAllowed, factionIds, playerIds); } public TerritoryAccess withPlayerIds(Collection playerIds) { return valueOf(hostFactionId, hostFactionAllowed, factionIds, playerIds); } // The intermediate ones public TerritoryAccess withFactionId(String factionId, boolean with) { if (this.getHostFactionId().equals(factionId)) { return valueOf(hostFactionId, with, factionIds, playerIds); } Set factionIds = new HashSet(this.getFactionIds()); if (with) { factionIds.add(factionId); } else { factionIds.remove(factionId); } return valueOf(hostFactionId, hostFactionAllowed, factionIds, playerIds); } public TerritoryAccess withPlayerId(String playerId, boolean with) { playerId = playerId.toLowerCase(); Set playerIds = new HashSet(this.getPlayerIds()); if (with) { playerIds.add(playerId); } else { playerIds.remove(playerId); } return valueOf(hostFactionId, hostFactionAllowed, factionIds, playerIds); } // The complex ones public TerritoryAccess toggleFactionId(String factionId) { return this.withFactionId(factionId, !this.isFactionIdGranted(factionId)); } public TerritoryAccess togglePlayerId(String playerId) { return this.withPlayerId(playerId, !this.isPlayerIdGranted(playerId)); } // -------------------------------------------- // // FIELDS: UNIVERSED // -------------------------------------------- // public Faction getHostFaction(Object universe) { return FactionColls.get().get(universe).get(this.getHostFactionId()); } public LinkedHashSet getGrantedUPlayers(Object universe) { LinkedHashSet ret = new LinkedHashSet(); UPlayerColl coll = UPlayerColls.get().get(universe); for (String playerId : this.getPlayerIds()) { ret.add(coll.get(playerId)); } return ret; } public LinkedHashSet getGrantedFactions(Object universe) { LinkedHashSet ret = new LinkedHashSet(); FactionColl coll = FactionColls.get().get(universe); for (String factionId : this.getFactionIds()) { ret.add(coll.get(factionId)); } return ret; } // -------------------------------------------- // // PRIVATE CONSTRUCTOR // -------------------------------------------- // private TerritoryAccess(String hostFactionId, Boolean hostFactionAllowed, Collection factionIds, Collection playerIds) { if (hostFactionId == null) throw new IllegalArgumentException("hostFactionId was null"); this.hostFactionId = hostFactionId; Set factionIdsInner = new TreeSet(); if (factionIds != null) { factionIdsInner.addAll(factionIds); if (factionIdsInner.remove(hostFactionId)) { hostFactionAllowed = true; } } this.factionIds = Collections.unmodifiableSet(factionIdsInner); Set playerIdsInner = new TreeSet(String.CASE_INSENSITIVE_ORDER); if (playerIds != null) { for (String playerId : playerIds) { playerIdsInner.add(playerId.toLowerCase()); } } this.playerIds = Collections.unmodifiableSet(playerIdsInner); this.hostFactionAllowed = (hostFactionAllowed == null || hostFactionAllowed); } // -------------------------------------------- // // FACTORY: VALUE OF // -------------------------------------------- // public static TerritoryAccess valueOf(String hostFactionId, Boolean hostFactionAllowed, Collection factionIds, Collection playerIds) { return new TerritoryAccess(hostFactionId, hostFactionAllowed, factionIds, playerIds); } public static TerritoryAccess valueOf(String hostFactionId) { return valueOf(hostFactionId, null, null, null); } // -------------------------------------------- // // INSTANCE METHODS // -------------------------------------------- // public boolean isFactionIdGranted(String factionId) { if (this.getHostFactionId().equals(factionId)) { return this.isHostFactionAllowed(); } return this.getFactionIds().contains(factionId); } // Note that the player can have access without being specifically granted. // The player could for example be a member of a granted faction. public boolean isPlayerIdGranted(String playerId) { return this.getPlayerIds().contains(playerId); } // A "default" TerritoryAccess could be serialized as a simple string only. // The host faction is still allowed (default) and no faction or player has been granted explicit access (default). public boolean isDefault() { return this.isHostFactionAllowed() && this.getFactionIds().isEmpty() && this.getPlayerIds().isEmpty(); } // TODO: This looks like an extractor in my eyes. // TODO: Perhaps create a factionId extractor? public boolean doesHostFactionMatch(Object testSubject) { String factionId = null; if (testSubject instanceof String) { factionId = (String)testSubject; } else if (testSubject instanceof CommandSender) { factionId = UPlayer.get(testSubject).getFactionId(); } else if (testSubject instanceof UPlayer) { factionId = ((UPlayer)testSubject).getFactionId(); } else if (testSubject instanceof Faction) { factionId = ((Faction)testSubject).getId(); } return this.getHostFactionId().equals(factionId); } // -------------------------------------------- // // DERPINGTON CHECKS // -------------------------------------------- // // these return false if not granted explicit access, or true if granted explicit access (in FPlayer or Faction lists) // they do not take into account hostFactionAllowed, which will need to be checked separately (as to not override FPerms which are denied for faction members and such) public boolean subjectHasAccess(Object testSubject) { if (testSubject instanceof Player) { return fPlayerHasAccess(UPlayer.get(testSubject)); } else if (testSubject instanceof UPlayer) { return fPlayerHasAccess((UPlayer)testSubject); } else if (testSubject instanceof Faction) { return factionHasAccess((Faction)testSubject); } return false; } public boolean fPlayerHasAccess(UPlayer fplayer) { return this.isPlayerIdGranted(fplayer.getId()) || this.isFactionIdGranted(fplayer.getFaction().getId()); } public boolean factionHasAccess(Faction faction) { return this.isFactionIdGranted(faction.getId()); } // this should normally only be checked after running subjectHasAccess() or fPlayerHasAccess() above to see if they have access explicitly granted public boolean subjectAccessIsRestricted(Object testSubject) { Faction hostFaction = FactionColls.get().get(testSubject).get(this.getHostFactionId()); return ( ! this.isHostFactionAllowed() && this.doesHostFactionMatch(testSubject) && ! FPerm.ACCESS.has(testSubject, hostFaction, false)); } }