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

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;
}
}