You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
336 lines
13 KiB
336 lines
13 KiB
package ru.simsonic.rscPermissions.Engine; |
|
|
|
import java.util.ArrayList; |
|
import java.util.Arrays; |
|
import java.util.Collections; |
|
import java.util.HashMap; |
|
import java.util.HashSet; |
|
import java.util.LinkedHashSet; |
|
import java.util.List; |
|
import java.util.Map.Entry; |
|
import java.util.Set; |
|
import ru.simsonic.rscPermissions.API.EntityType; |
|
import ru.simsonic.rscPermissions.API.PlayerType; |
|
import ru.simsonic.rscPermissions.API.RowEntity; |
|
import ru.simsonic.rscPermissions.API.RowInheritance; |
|
import ru.simsonic.rscPermissions.API.RowPermission; |
|
import ru.simsonic.rscPermissions.API.Settings; |
|
import ru.simsonic.rscPermissions.Engine.Backends.DatabaseContents; |
|
import ru.simsonic.rscUtilityLibrary.TextProcessing.GenericChatCodes; |
|
|
|
public class InternalCache |
|
{ |
|
private final HashMap<String, RowEntity> entities_g = new HashMap<>(); |
|
private final HashMap<String, RowEntity> entities_u = new HashMap<>(); |
|
private final RowInheritance defaultInheritance = new RowInheritance(); |
|
private boolean alwaysInheritDefaultGroup = false; |
|
private RowEntity implicit_g; |
|
private RowEntity implicit_u; |
|
public void setDefaultGroup(String defaultGroup, boolean alwaysInheritDefaultGroup) |
|
{ |
|
defaultInheritance.parent = defaultGroup; |
|
defaultInheritance.deriveInstance(); |
|
this.alwaysInheritDefaultGroup = alwaysInheritDefaultGroup; |
|
} |
|
public synchronized void fill(DatabaseContents contents) |
|
{ |
|
clear(); |
|
importEntities(contents); |
|
importPermissions(contents.permissions); |
|
importInheritance(contents.inheritance); |
|
implicit_g = entities_g.get(""); |
|
implicit_u = entities_u.get(""); |
|
} |
|
private void importEntities(DatabaseContents contents) |
|
{ |
|
final HashSet<String> names_u = new HashSet<>(); |
|
final HashSet<String> names_g = new HashSet<>(); |
|
for(RowEntity row : contents.entities) |
|
if(row.entityType == EntityType.GROUP) |
|
{ |
|
names_g.add(row.entity); |
|
entities_g.put(row.entity.toLowerCase(), row); |
|
} else { |
|
names_u.add(row.entity); |
|
entities_u.put(row.entity, row); |
|
} |
|
for(RowPermission row : contents.permissions) |
|
if(row.entityType == EntityType.GROUP) |
|
names_g.add(row.entity); |
|
else |
|
names_u.add(row.entity); |
|
for(RowInheritance row : contents.inheritance) |
|
{ |
|
names_g.add(row.parent); |
|
if(row.childType == EntityType.GROUP) |
|
names_g.add(row.entity); |
|
else |
|
names_u.add(row.entity); |
|
} |
|
names_g.add(defaultInheritance.parent); |
|
for(String name : names_g) |
|
{ |
|
final String groupInternalName = name.toLowerCase(); |
|
if(!entities_g.containsKey(groupInternalName)) |
|
{ |
|
final RowEntity dummy = new RowEntity(); |
|
dummy.entity = name; |
|
dummy.entityType = EntityType.GROUP; |
|
entities_g.put(groupInternalName, dummy); |
|
} |
|
} |
|
for(String name : names_u) |
|
if(!entities_u.containsKey(name)) |
|
{ |
|
final RowEntity dummy = new RowEntity(); |
|
dummy.entity = name; |
|
dummy.entityType = EntityType.PLAYER; |
|
entities_u.put(name, dummy); |
|
} |
|
for(RowEntity row : entities_u.values()) |
|
row.playerType = PlayerType.scanPlayerEntity(row.entity); |
|
} |
|
private void importPermissions(RowPermission[] rows) |
|
{ |
|
final ArrayList<RowPermission> permissions_p2g = new ArrayList<>(); |
|
final ArrayList<RowPermission> permissions_p2u = new ArrayList<>(); |
|
for(RowPermission row : rows) |
|
if(row.entityType == EntityType.GROUP) |
|
{ |
|
row.entityObject = entities_g.get(row.entity.toLowerCase()); |
|
permissions_p2g.add(row); |
|
} else { |
|
row.entityObject = entities_u.get(row.entity); |
|
permissions_p2u.add(row); |
|
} |
|
for(String entry : entities_g.keySet()) |
|
{ |
|
final ArrayList<RowPermission> permissions = new ArrayList<>(); |
|
for(RowPermission row : permissions_p2g) |
|
if(row.entity.toLowerCase().equals(entry)) |
|
permissions.add(row); |
|
entities_g.get(entry).permissions = permissions.toArray(new RowPermission[permissions.size()]); |
|
} |
|
for(String entry : entities_u.keySet()) |
|
{ |
|
final ArrayList<RowPermission> permissions = new ArrayList<>(); |
|
for(RowPermission row : permissions_p2u) |
|
if(row.entity.equals(entry)) |
|
permissions.add(row); |
|
entities_u.get(entry).permissions = permissions.toArray(new RowPermission[permissions.size()]); |
|
} |
|
} |
|
private void importInheritance(RowInheritance[] rows) |
|
{ |
|
final ArrayList<RowInheritance> inheritance_g2g = new ArrayList<>(); |
|
final ArrayList<RowInheritance> inheritance_g2u = new ArrayList<>(); |
|
for(RowInheritance row : rows) |
|
if(row.childType == EntityType.GROUP) |
|
{ |
|
row.entityChild = entities_g.get(row.entity.toLowerCase()); |
|
row.entityParent = entities_g.get(row.parent.toLowerCase()); |
|
inheritance_g2g.add(row); |
|
} else { |
|
row.entityChild = entities_u.get(row.entity); |
|
row.entityParent = entities_g.get(row.parent.toLowerCase()); |
|
inheritance_g2u.add(row); |
|
} |
|
for(Entry<String, RowEntity> entry : entities_g.entrySet()) |
|
{ |
|
final ArrayList<RowInheritance> inheritances = new ArrayList<>(); |
|
final String name = entry.getKey(); |
|
for(RowInheritance row : inheritance_g2g) |
|
if(row.entity.toLowerCase().equals(name)) |
|
inheritances.add(row); |
|
Collections.sort(inheritances); |
|
entry.getValue().inheritance = inheritances.toArray(new RowInheritance[inheritances.size()]); |
|
} |
|
for(Entry<String, RowEntity> entry : entities_u.entrySet()) |
|
{ |
|
final ArrayList<RowInheritance> inheritances = new ArrayList<>(); |
|
final String name = entry.getKey(); |
|
for(RowInheritance row : inheritance_g2u) |
|
if(row.entity.equals(name)) |
|
inheritances.add(row); |
|
Collections.sort(inheritances); |
|
entry.getValue().inheritance = inheritances.toArray(new RowInheritance[inheritances.size()]); |
|
} |
|
defaultInheritance.childType = EntityType.PLAYER; |
|
defaultInheritance.entityParent = entities_g.get(defaultInheritance.parent.toLowerCase()); |
|
} |
|
public synchronized ResolutionResult resolvePlayer(String player) |
|
{ |
|
return resolvePlayer(new String[] { player }); |
|
} |
|
public synchronized ResolutionResult resolvePlayer(String[] player) |
|
{ |
|
final ResolutionParams params = new ResolutionParams(); |
|
params.applicableIdentifiers = player; |
|
params.destRegions = new String[] {}; |
|
return resolvePlayer(params); |
|
} |
|
public synchronized ResolutionResult resolvePlayer(ResolutionParams params) |
|
{ |
|
final ArrayList<RowEntity> applicableEntities = new ArrayList<>(); |
|
final ArrayList<RowPermission> applicablePermissions = new ArrayList<>(); |
|
final ArrayList<RowInheritance> applicableInheritance = new ArrayList<>(); |
|
if(implicit_u != null && implicit_u.permissions != null) |
|
processPermissions(params, Arrays.asList(implicit_u.permissions)); |
|
params.groupList = new LinkedHashSet<>(); |
|
params.finalPerms = new HashMap<>(); |
|
params.instantiator = ""; |
|
params.depth = 0; |
|
for(RowEntity row : entities_u.values()) |
|
for(String identifier : params.applicableIdentifiers) |
|
if(row.playerType.isEntityApplicable(row.entity, identifier)) |
|
{ |
|
// Apply direct inheritance |
|
if(row.inheritance != null && row.inheritance.length > 0) |
|
for(RowInheritance inheritance : row.inheritance) |
|
if(isInheritanceApplicable(params, inheritance)) |
|
applicableInheritance.add(inheritance); |
|
// Apply direct permissions |
|
applicablePermissions.addAll(Arrays.asList(row.permissions)); |
|
// Apply direct prefixes and suffixes |
|
applicableEntities.add(row); |
|
} |
|
Collections.sort(applicableEntities); |
|
final ArrayList<ResolutionResult> intermediateResults = new ArrayList<>(); |
|
Collections.sort(applicableInheritance); |
|
// Mix into default inheritance |
|
if(applicableInheritance.isEmpty() || alwaysInheritDefaultGroup) |
|
applicableInheritance.add(0, defaultInheritance); |
|
for(RowInheritance row : applicableInheritance) |
|
{ |
|
params.instantiator = ""; |
|
params.parentEntity = row.entityParent; |
|
intermediateResults.add(resolveParent(params)); |
|
} |
|
// Process all applicable prefixes using only entity id order |
|
ResolutionResult result = processPrefixesAndSuffixes(params, intermediateResults); |
|
for(RowEntity row : applicableEntities) |
|
{ |
|
params.instantiator = ""; |
|
params.parentEntity = row; |
|
result = processPrefixesAndSuffixes(params, Arrays.asList(new ResolutionResult[] { result })); |
|
} |
|
result.prefix = GenericChatCodes.processStringStatic(result.prefix); |
|
result.suffix = GenericChatCodes.processStringStatic(result.suffix); |
|
processPermissions(params, applicablePermissions); |
|
result.permissions = params.finalPerms; |
|
result.groups = params.groupList; |
|
return result; |
|
} |
|
private ResolutionResult resolveParent(ResolutionParams params) |
|
{ |
|
if(implicit_g != null && implicit_g.permissions != null) |
|
processPermissions(params, Arrays.asList(implicit_g.permissions)); |
|
final RowEntity currentParent = params.parentEntity; |
|
final String instantiator = params.instantiator; |
|
final ArrayList<ResolutionResult> intermediateResults = new ArrayList<>(); |
|
params.depth += 1; |
|
for(RowInheritance row : params.parentEntity.inheritance) |
|
if(isInheritanceApplicable(params, row)) |
|
{ |
|
params.parentEntity = row.entityParent; |
|
params.instantiator = (row.instance != null && !"".equals(row.instance)) |
|
? row.instance |
|
: instantiator; |
|
intermediateResults.add(resolveParent(params)); |
|
} |
|
params.depth -= 1; |
|
params.groupList.add(depthPrefix(params.depth) + currentParent.entity |
|
+ ("".equals(instantiator) ? "" : Settings.separator + instantiator)); |
|
// Prefixes and suffixes |
|
params.parentEntity = currentParent; |
|
params.instantiator = instantiator; |
|
final ResolutionResult result = processPrefixesAndSuffixes(params, intermediateResults); |
|
intermediateResults.clear(); |
|
// Permissions |
|
if(currentParent.permissions != null) |
|
processPermissions(params, Arrays.asList(currentParent.permissions)); |
|
return result; |
|
} |
|
private String depthPrefix(int depth) |
|
{ |
|
if(depth > 0) |
|
{ |
|
final char[] levelParent = new char[depth]; |
|
levelParent[depth - 1] = Settings.groupLevelTab; |
|
return new String(levelParent).replace('\0', ' '); |
|
} |
|
return ""; |
|
} |
|
private ResolutionResult processPrefixesAndSuffixes(ResolutionParams params, List<ResolutionResult> intermediate) |
|
{ |
|
final ResolutionResult result = new ResolutionResult(); |
|
result.prefix = params.parentEntity.prefix; |
|
result.suffix = params.parentEntity.suffix; |
|
if(result.prefix == null || "".equals(result.prefix)) |
|
result.prefix = "%"; |
|
if(result.suffix == null || "".equals(result.suffix)) |
|
result.suffix = "%"; |
|
final StringBuilder sbp = new StringBuilder(); |
|
final StringBuilder sbs = new StringBuilder(); |
|
for(ResolutionResult inherited : intermediate) |
|
{ |
|
if(inherited.prefix != null) |
|
sbp.append(inherited.prefix); |
|
if(inherited.suffix != null) |
|
sbs.append(inherited.suffix); |
|
} |
|
result.prefix = result.prefix.replace(Settings.textInheriter, sbp.toString()); |
|
result.suffix = result.suffix.replace(Settings.textInheriter, sbs.toString()); |
|
result.prefix = result.prefix.replace(Settings.instantiator, params.instantiator); |
|
result.suffix = result.suffix.replace(Settings.instantiator, params.instantiator); |
|
return result; |
|
} |
|
private void processPermissions(ResolutionParams params, List<RowPermission> permissions) |
|
{ |
|
for(RowPermission row : permissions) |
|
if(isPermissionApplicable(params, row)) |
|
params.finalPerms.put( |
|
row.permission.replace(Settings.instantiator, params.instantiator), |
|
row.value); |
|
} |
|
private boolean isPermissionApplicable(ResolutionParams params, RowPermission row) |
|
{ |
|
if(params.expirience < row.expirience) |
|
return false; |
|
return row.destination.isWorldApplicable(params.destWorld, params.instantiator) |
|
? row.destination.isRegionApplicable(params.destRegions, params.instantiator) |
|
: false; |
|
} |
|
private boolean isInheritanceApplicable(ResolutionParams params, RowInheritance row) |
|
{ |
|
if(params.expirience < row.expirience) |
|
return false; |
|
return row.destination.isWorldApplicable(params.destWorld, params.instantiator) |
|
? row.destination.isRegionApplicable(params.destRegions, params.instantiator) |
|
: false; |
|
} |
|
public synchronized RowEntity getGroup(String group) |
|
{ |
|
if(group != null && !"".equals(group)) |
|
{ |
|
final RowEntity row = entities_g.get(group.toLowerCase()); |
|
if(row != null) |
|
return row; |
|
} |
|
return new RowEntity(); |
|
} |
|
public synchronized Set<String> getGroups() |
|
{ |
|
final HashSet<String> result = new HashSet<>(entities_g.size()); |
|
for(RowEntity row : entities_g.values()) |
|
result.add(row.entity); |
|
return result; |
|
} |
|
public synchronized void clear() |
|
{ |
|
entities_g.clear(); |
|
entities_u.clear(); |
|
implicit_g = null; |
|
implicit_u = null; |
|
} |
|
}
|
|
|