mirror of
https://github.com/LuckPerms/LuckPerms.git
synced 2024-11-24 11:38:40 +01:00
Implement nicer json format for Sponge local data
This commit is contained in:
parent
85c7a7db8d
commit
073b775566
@ -25,6 +25,7 @@ package me.lucko.luckperms.api.context;
|
|||||||
import com.google.common.collect.HashMultimap;
|
import com.google.common.collect.HashMultimap;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.ImmutableSetMultimap;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.collect.Multimaps;
|
import com.google.common.collect.Multimaps;
|
||||||
import com.google.common.collect.SetMultimap;
|
import com.google.common.collect.SetMultimap;
|
||||||
@ -179,7 +180,7 @@ public final class MutableContextSet implements ContextSet {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Multimap<String, String> toMultimap() {
|
public Multimap<String, String> toMultimap() {
|
||||||
return map;
|
return ImmutableSetMultimap.copyOf(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -30,6 +30,7 @@ import com.google.gson.GsonBuilder;
|
|||||||
import com.google.gson.JsonArray;
|
import com.google.gson.JsonArray;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
|
||||||
import me.lucko.luckperms.api.HeldPermission;
|
import me.lucko.luckperms.api.HeldPermission;
|
||||||
import me.lucko.luckperms.api.Node;
|
import me.lucko.luckperms.api.Node;
|
||||||
@ -547,11 +548,11 @@ public class JSONBacking extends FlatfileBacking {
|
|||||||
int size = vals.size();
|
int size = vals.size();
|
||||||
|
|
||||||
if (size == 1) {
|
if (size == 1) {
|
||||||
context.addProperty(e.getKey(), vals.get(0));;
|
context.addProperty(e.getKey(), vals.get(0));
|
||||||
} else if (size > 1) {
|
} else if (size > 1) {
|
||||||
JsonArray arr = new JsonArray();
|
JsonArray arr = new JsonArray();
|
||||||
for (String s : vals) {
|
for (String s : vals) {
|
||||||
arr.add(s);
|
arr.add(new JsonPrimitive(s));
|
||||||
}
|
}
|
||||||
context.add(e.getKey(), arr);
|
context.add(e.getKey(), arr);
|
||||||
}
|
}
|
||||||
|
@ -57,12 +57,13 @@ import me.lucko.luckperms.sponge.model.SpongeGroup;
|
|||||||
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
||||||
import me.lucko.luckperms.sponge.service.calculated.OptionLookup;
|
import me.lucko.luckperms.sponge.service.calculated.OptionLookup;
|
||||||
import me.lucko.luckperms.sponge.service.calculated.PermissionLookup;
|
import me.lucko.luckperms.sponge.service.calculated.PermissionLookup;
|
||||||
|
import me.lucko.luckperms.sponge.service.legacystorage.LegacyDataMigrator;
|
||||||
import me.lucko.luckperms.sponge.service.persisted.PersistedCollection;
|
import me.lucko.luckperms.sponge.service.persisted.PersistedCollection;
|
||||||
import me.lucko.luckperms.sponge.service.persisted.SubjectStorage;
|
|
||||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
import me.lucko.luckperms.sponge.service.proxy.LPSubjectData;
|
||||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||||
|
import me.lucko.luckperms.sponge.service.storage.SubjectStorage;
|
||||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||||
|
|
||||||
import org.spongepowered.api.plugin.PluginContainer;
|
import org.spongepowered.api.plugin.PluginContainer;
|
||||||
@ -129,7 +130,8 @@ public class LuckPermsService implements PermissionService {
|
|||||||
localOptionCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
localOptionCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
||||||
localDataCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
localDataCaches = Collections.newSetFromMap(new MapMaker().weakKeys().makeMap());
|
||||||
|
|
||||||
storage = new SubjectStorage(new File(plugin.getDataDirectory(), "local"));
|
storage = new SubjectStorage(new File(plugin.getDataDirectory(), "sponge-data"));
|
||||||
|
new LegacyDataMigrator(plugin, new File(plugin.getDataDirectory(), "local"), storage).run();
|
||||||
|
|
||||||
userSubjects = plugin.getUserManager();
|
userSubjects = plugin.getUserManager();
|
||||||
fallbackUserSubjects = new PersistedCollection(this, "fallback-users", true);
|
fallbackUserSubjects = new PersistedCollection(this, "fallback-users", true);
|
||||||
|
@ -47,6 +47,7 @@ import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
|||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -133,29 +134,29 @@ public class CalculatedSubjectData implements LPSubjectData {
|
|||||||
return permissionCache.getUnchecked(contexts).getCalculator().getPermissionValue(permission);
|
return permissionCache.getUnchecked(contexts).getCalculator().getPermissionValue(permission);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replacePermissions(Map<ContextSet, Map<String, Boolean>> map) {
|
public void replacePermissions(Map<ImmutableContextSet, Map<String, Boolean>> map) {
|
||||||
permissions.clear();
|
permissions.clear();
|
||||||
for (Map.Entry<ContextSet, Map<String, Boolean>> e : map.entrySet()) {
|
for (Map.Entry<ImmutableContextSet, Map<String, Boolean>> e : map.entrySet()) {
|
||||||
permissions.put(e.getKey().makeImmutable(), new ConcurrentHashMap<>(e.getValue()));
|
permissions.put(e.getKey(), new ConcurrentHashMap<>(e.getValue()));
|
||||||
}
|
}
|
||||||
permissionCache.invalidateAll();
|
permissionCache.invalidateAll();
|
||||||
service.invalidatePermissionCaches();
|
service.invalidatePermissionCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceParents(Map<ContextSet, Set<SubjectReference>> map) {
|
public void replaceParents(Map<ImmutableContextSet, List<SubjectReference>> map) {
|
||||||
parents.clear();
|
parents.clear();
|
||||||
for (Map.Entry<ContextSet, Set<SubjectReference>> e : map.entrySet()) {
|
for (Map.Entry<ImmutableContextSet, List<SubjectReference>> e : map.entrySet()) {
|
||||||
Set<SubjectReference> set = ConcurrentHashMap.newKeySet();
|
Set<SubjectReference> set = ConcurrentHashMap.newKeySet();
|
||||||
set.addAll(e.getValue());
|
set.addAll(e.getValue());
|
||||||
parents.put(e.getKey().makeImmutable(), set);
|
parents.put(e.getKey(), set);
|
||||||
}
|
}
|
||||||
service.invalidateParentCaches();
|
service.invalidateParentCaches();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void replaceOptions(Map<ContextSet, Map<String, String>> map) {
|
public void replaceOptions(Map<ImmutableContextSet, Map<String, String>> map) {
|
||||||
options.clear();
|
options.clear();
|
||||||
for (Map.Entry<ContextSet, Map<String, String>> e : map.entrySet()) {
|
for (Map.Entry<ImmutableContextSet, Map<String, String>> e : map.entrySet()) {
|
||||||
options.put(e.getKey().makeImmutable(), new ConcurrentHashMap<>(e.getValue()));
|
options.put(e.getKey(), new ConcurrentHashMap<>(e.getValue()));
|
||||||
}
|
}
|
||||||
service.invalidateOptionCaches();
|
service.invalidateOptionCaches();
|
||||||
}
|
}
|
||||||
@ -228,6 +229,14 @@ public class CalculatedSubjectData implements LPSubjectData {
|
|||||||
return map.build();
|
return map.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Map<ImmutableContextSet, List<SubjectReference>> getParentsAsList() {
|
||||||
|
ImmutableMap.Builder<ImmutableContextSet, List<SubjectReference>> map = ImmutableMap.builder();
|
||||||
|
for (Map.Entry<ContextSet, Set<SubjectReference>> e : parents.entrySet()) {
|
||||||
|
map.put(e.getKey().makeImmutable(), ImmutableList.copyOf(e.getValue()));
|
||||||
|
}
|
||||||
|
return map.build();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<SubjectReference> getParents(ContextSet contexts) {
|
public Set<SubjectReference> getParents(ContextSet contexts) {
|
||||||
return ImmutableSet.copyOf(parents.getOrDefault(contexts, ImmutableSet.of()));
|
return ImmutableSet.copyOf(parents.getOrDefault(contexts, ImmutableSet.of()));
|
||||||
|
@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.sponge.service.legacystorage;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.common.plugin.LuckPermsPlugin;
|
||||||
|
import me.lucko.luckperms.sponge.service.storage.SubjectStorage;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LegacyDataMigrator implements Runnable {
|
||||||
|
private final LuckPermsPlugin plugin;
|
||||||
|
|
||||||
|
private final File oldDirectory;
|
||||||
|
private final SubjectStorage storage;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
if (!oldDirectory.exists() || !oldDirectory.isDirectory()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.getLog().warn("Migrating old sponge data... Please wait.");
|
||||||
|
|
||||||
|
File[] collections = oldDirectory.listFiles(File::isDirectory);
|
||||||
|
if (collections == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File collectionDir : collections) {
|
||||||
|
|
||||||
|
File[] subjects = collectionDir.listFiles((dir, name) -> name.endsWith(".json"));
|
||||||
|
if (subjects == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File subjectFile : subjects) {
|
||||||
|
String subjectName = subjectFile.getName().substring(0, subjectFile.getName().length() - ".json".length());
|
||||||
|
|
||||||
|
try (BufferedReader reader = Files.newBufferedReader(subjectFile.toPath(), StandardCharsets.UTF_8)) {
|
||||||
|
SubjectDataHolder holder = storage.getGson().fromJson(reader, SubjectDataHolder.class);
|
||||||
|
storage.saveToFile(holder.asSubjectModel(), storage.resolveFile(collectionDir.getName(), subjectName));
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
subjectFile.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
collectionDir.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
oldDirectory.delete();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.sponge.service.legacystorage;
|
||||||
|
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.context.ContextSet;
|
||||||
|
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||||
|
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Because this format is no longer being used to store data.
|
||||||
|
* @see SubjectStorageModel
|
||||||
|
*/
|
||||||
|
@ToString
|
||||||
|
@Deprecated
|
||||||
|
public class SubjectDataHolder {
|
||||||
|
private Map<Map<String, String>, Map<String, Boolean>> permissions;
|
||||||
|
private Map<Map<String, String>, Map<String, String>> options;
|
||||||
|
private Map<Map<String, String>, List<String>> parents;
|
||||||
|
|
||||||
|
public SubjectDataHolder() {
|
||||||
|
// For gson
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubjectStorageModel asSubjectModel() {
|
||||||
|
return new SubjectStorageModel(
|
||||||
|
permissions.entrySet().stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
k -> ContextSet.fromMap(k.getKey()),
|
||||||
|
Map.Entry::getValue
|
||||||
|
)),
|
||||||
|
options.entrySet().stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
k -> ContextSet.fromMap(k.getKey()),
|
||||||
|
Map.Entry::getValue
|
||||||
|
)),
|
||||||
|
parents.entrySet().stream()
|
||||||
|
.collect(Collectors.toMap(
|
||||||
|
k -> ContextSet.fromMap(k.getKey()),
|
||||||
|
v -> v.getValue().stream().map(SubjectReference::deserialize).collect(Collectors.toList())
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -39,6 +39,7 @@ import me.lucko.luckperms.sponge.service.LuckPermsService;
|
|||||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||||
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
import me.lucko.luckperms.sponge.service.proxy.LPSubjectCollection;
|
||||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||||
|
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -63,8 +64,8 @@ public class PersistedCollection implements LPSubjectCollection {
|
|||||||
});
|
});
|
||||||
|
|
||||||
public void loadAll() {
|
public void loadAll() {
|
||||||
Map<String, SubjectDataHolder> holders = service.getStorage().loadAllFromFile(identifier);
|
Map<String, SubjectStorageModel> holders = service.getStorage().loadAllFromFile(identifier);
|
||||||
for (Map.Entry<String, SubjectDataHolder> e : holders.entrySet()) {
|
for (Map.Entry<String, SubjectStorageModel> e : holders.entrySet()) {
|
||||||
PersistedSubject subject = get(e.getKey());
|
PersistedSubject subject = get(e.getKey());
|
||||||
subject.loadData(e.getValue());
|
subject.loadData(e.getValue());
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,7 @@ import me.lucko.luckperms.sponge.service.calculated.PermissionLookup;
|
|||||||
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
import me.lucko.luckperms.sponge.service.proxy.LPSubject;
|
||||||
import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference;
|
import me.lucko.luckperms.sponge.service.references.SubjectCollectionReference;
|
||||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||||
|
import me.lucko.luckperms.sponge.service.storage.SubjectStorageModel;
|
||||||
import me.lucko.luckperms.sponge.timings.LPTiming;
|
import me.lucko.luckperms.sponge.timings.LPTiming;
|
||||||
|
|
||||||
import org.spongepowered.api.command.CommandSource;
|
import org.spongepowered.api.command.CommandSource;
|
||||||
@ -130,9 +131,9 @@ public class PersistedSubject implements LPSubject {
|
|||||||
this.optionLookupCache.cleanUp();
|
this.optionLookupCache.cleanUp();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadData(SubjectDataHolder dataHolder) {
|
public void loadData(SubjectStorageModel dataHolder) {
|
||||||
subjectData.setSave(false);
|
subjectData.setSave(false);
|
||||||
dataHolder.copyTo(subjectData);
|
dataHolder.applyToData(subjectData);
|
||||||
subjectData.setSave(true);
|
subjectData.setSave(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package me.lucko.luckperms.sponge.service.persisted;
|
|
||||||
|
|
||||||
import lombok.ToString;
|
|
||||||
|
|
||||||
import me.lucko.luckperms.api.context.ContextSet;
|
|
||||||
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
|
||||||
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
|
||||||
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds SubjectData in a "gson friendly" format for serialization
|
|
||||||
*/
|
|
||||||
@ToString
|
|
||||||
public class SubjectDataHolder {
|
|
||||||
private final Map<Map<String, String>, Map<String, Boolean>> permissions;
|
|
||||||
private final Map<Map<String, String>, Map<String, String>> options;
|
|
||||||
private final Map<Map<String, String>, List<String>> parents;
|
|
||||||
|
|
||||||
public SubjectDataHolder(Map<ImmutableContextSet, Map<String, String>> options, Map<ImmutableContextSet, Map<String, Boolean>> permissions, Map<ImmutableContextSet, Set<SubjectReference>> parents) {
|
|
||||||
this.options = new HashMap<>();
|
|
||||||
for (Map.Entry<ImmutableContextSet, Map<String, String>> e : options.entrySet()) {
|
|
||||||
if (!e.getValue().isEmpty()) {
|
|
||||||
this.options.put(e.getKey().toMap(), new HashMap<>(e.getValue()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.permissions = new HashMap<>();
|
|
||||||
for (Map.Entry<ImmutableContextSet, Map<String, Boolean>> e : permissions.entrySet()) {
|
|
||||||
if (!e.getValue().isEmpty()) {
|
|
||||||
this.permissions.put(e.getKey().toMap(), new HashMap<>(e.getValue()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.parents = new HashMap<>();
|
|
||||||
for (Map.Entry<ImmutableContextSet, Set<SubjectReference>> e : parents.entrySet()) {
|
|
||||||
if (!e.getValue().isEmpty()) {
|
|
||||||
this.parents.put(e.getKey().toMap(), e.getValue().stream().map(SubjectReference::serialize).collect(Collectors.toList()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public SubjectDataHolder(CalculatedSubjectData data) {
|
|
||||||
this(data.getOptions(), data.getPermissions(), data.getParents());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void copyTo(CalculatedSubjectData subjectData) {
|
|
||||||
subjectData.replacePermissions(permissions.entrySet().stream()
|
|
||||||
.collect(Collectors.toMap(
|
|
||||||
k -> ContextSet.fromMap(k.getKey()),
|
|
||||||
Map.Entry::getValue
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
subjectData.replaceOptions(options.entrySet().stream()
|
|
||||||
.collect(Collectors.toMap(
|
|
||||||
k -> ContextSet.fromMap(k.getKey()),
|
|
||||||
Map.Entry::getValue
|
|
||||||
))
|
|
||||||
);
|
|
||||||
|
|
||||||
subjectData.replaceParents(parents.entrySet().stream()
|
|
||||||
.collect(Collectors.toMap(
|
|
||||||
k -> ContextSet.fromMap(k.getKey()),
|
|
||||||
v -> v.getValue().stream().map(SubjectReference::deserialize).collect(Collectors.toSet())
|
|
||||||
))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,17 +20,24 @@
|
|||||||
* SOFTWARE.
|
* SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package me.lucko.luckperms.sponge.service.persisted;
|
package me.lucko.luckperms.sponge.service.storage;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.sponge.service.persisted.PersistedSubject;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.AbstractMap;
|
import java.nio.file.Files;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -41,11 +48,14 @@ import java.util.stream.Collectors;
|
|||||||
* Handles persisted Subject I/O and (de)serialization
|
* Handles persisted Subject I/O and (de)serialization
|
||||||
*/
|
*/
|
||||||
public class SubjectStorage {
|
public class SubjectStorage {
|
||||||
|
|
||||||
|
@Getter
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
|
|
||||||
private final File container;
|
private final File container;
|
||||||
|
|
||||||
public SubjectStorage(File container) {
|
public SubjectStorage(File container) {
|
||||||
this.gson = new GsonBuilder().setPrettyPrinting().enableComplexMapKeySerialization().create();
|
this.gson = new GsonBuilder().setPrettyPrinting().create();
|
||||||
this.container = container;
|
this.container = container;
|
||||||
checkContainer();
|
checkContainer();
|
||||||
}
|
}
|
||||||
@ -65,32 +75,35 @@ public class SubjectStorage {
|
|||||||
return ImmutableSet.copyOf(dirs).stream().map(File::getName).collect(Collectors.toSet());
|
return ImmutableSet.copyOf(dirs).stream().map(File::getName).collect(Collectors.toSet());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveToFile(PersistedSubject subject) throws IOException {
|
public File resolveFile(String collectionName, String subjectName) {
|
||||||
checkContainer();
|
checkContainer();
|
||||||
File collection = new File(container, subject.getContainingCollection().getIdentifier());
|
File collection = new File(container, collectionName);
|
||||||
if (!collection.exists()) {
|
if (!collection.exists()) {
|
||||||
collection.mkdirs();
|
collection.mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
File subjectFile = new File(collection, subject.getIdentifier() + ".json");
|
return new File(collection, subjectName + ".json");
|
||||||
saveToFile(subject, subjectFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void saveToFile(PersistedSubject subject, File file) throws IOException {
|
public void saveToFile(PersistedSubject subject) throws IOException {
|
||||||
|
File subjectFile = resolveFile(subject.getContainingCollection().getIdentifier(), subject.getIdentifier());
|
||||||
|
saveToFile(new SubjectStorageModel(subject.getSubjectData()), subjectFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void saveToFile(SubjectStorageModel model, File file) throws IOException {
|
||||||
file.getParentFile().mkdirs();
|
file.getParentFile().mkdirs();
|
||||||
if (file.exists()) {
|
if (file.exists()) {
|
||||||
file.delete();
|
file.delete();
|
||||||
}
|
}
|
||||||
file.createNewFile();
|
file.createNewFile();
|
||||||
|
|
||||||
Files.write(saveToString(new SubjectDataHolder(subject.getSubjectData())), file, Charset.defaultCharset());
|
try (BufferedWriter writer = Files.newBufferedWriter(file.toPath(), StandardCharsets.UTF_8)) {
|
||||||
|
gson.toJson(model.toJson(), writer);
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String saveToString(SubjectDataHolder subject) {
|
public Map<String, SubjectStorageModel> loadAllFromFile(String collectionName) {
|
||||||
return gson.toJson(subject);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Map<String, SubjectDataHolder> loadAllFromFile(String collectionName) {
|
|
||||||
checkContainer();
|
checkContainer();
|
||||||
File collection = new File(container, collectionName);
|
File collection = new File(container, collectionName);
|
||||||
if (!collection.exists()) {
|
if (!collection.exists()) {
|
||||||
@ -100,12 +113,12 @@ public class SubjectStorage {
|
|||||||
String[] fileNames = collection.list((dir, name) -> name.endsWith(".json"));
|
String[] fileNames = collection.list((dir, name) -> name.endsWith(".json"));
|
||||||
if (fileNames == null) return Collections.emptyMap();
|
if (fileNames == null) return Collections.emptyMap();
|
||||||
|
|
||||||
Map<String, SubjectDataHolder> holders = new HashMap<>();
|
Map<String, SubjectStorageModel> holders = new HashMap<>();
|
||||||
for (String name : fileNames) {
|
for (String name : fileNames) {
|
||||||
File subject = new File(collection, name);
|
File subject = new File(collection, name);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map.Entry<String, SubjectDataHolder> s = loadFromFile(subject);
|
Map.Entry<String, SubjectStorageModel> s = loadFromFile(subject);
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
holders.put(s.getKey(), s.getValue());
|
holders.put(s.getKey(), s.getValue());
|
||||||
}
|
}
|
||||||
@ -117,7 +130,7 @@ public class SubjectStorage {
|
|||||||
return holders;
|
return holders;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map.Entry<String, SubjectDataHolder> loadFromFile(String collectionName, String subjectName) throws IOException {
|
public Map.Entry<String, SubjectStorageModel> loadFromFile(String collectionName, String subjectName) throws IOException {
|
||||||
checkContainer();
|
checkContainer();
|
||||||
File collection = new File(container, collectionName);
|
File collection = new File(container, collectionName);
|
||||||
if (!collection.exists()) {
|
if (!collection.exists()) {
|
||||||
@ -125,20 +138,21 @@ public class SubjectStorage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
File subject = new File(collection, subjectName + ".json");
|
File subject = new File(collection, subjectName + ".json");
|
||||||
return new AbstractMap.SimpleEntry<>(subjectName, loadFromFile(subject).getValue());
|
return Maps.immutableEntry(subjectName, loadFromFile(subject).getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map.Entry<String, SubjectDataHolder> loadFromFile(File file) throws IOException {
|
public Map.Entry<String, SubjectStorageModel> loadFromFile(File file) throws IOException {
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String s = Files.toString(file, Charset.defaultCharset());
|
String subjectName = file.getName().substring(0, file.getName().length() - ".json".length());
|
||||||
return new AbstractMap.SimpleEntry<>(file.getName().substring(0, file.getName().length() - 5), loadFromString(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
public SubjectDataHolder loadFromString(String s) {
|
try (BufferedReader reader = Files.newBufferedReader(file.toPath(), StandardCharsets.UTF_8)) {
|
||||||
return gson.fromJson(s, SubjectDataHolder.class);
|
JsonObject data = gson.fromJson(reader, JsonObject.class);
|
||||||
|
SubjectStorageModel model = new SubjectStorageModel(data);
|
||||||
|
return Maps.immutableEntry(subjectName, model);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -0,0 +1,274 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016 Lucko (Luck) <luck@lucko.me>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package me.lucko.luckperms.sponge.service.storage;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import com.google.common.base.Preconditions;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.google.gson.JsonPrimitive;
|
||||||
|
|
||||||
|
import me.lucko.luckperms.api.context.ContextSet;
|
||||||
|
import me.lucko.luckperms.api.context.ImmutableContextSet;
|
||||||
|
import me.lucko.luckperms.api.context.MutableContextSet;
|
||||||
|
import me.lucko.luckperms.sponge.service.calculated.CalculatedSubjectData;
|
||||||
|
import me.lucko.luckperms.sponge.service.references.SubjectReference;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used for converting a SubjectData instance to and from JSON
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
public class SubjectStorageModel {
|
||||||
|
private final Map<ImmutableContextSet, Map<String, Boolean>> permissions;
|
||||||
|
private final Map<ImmutableContextSet, Map<String, String>> options;
|
||||||
|
private final Map<ImmutableContextSet, List<SubjectReference>> parents;
|
||||||
|
|
||||||
|
public SubjectStorageModel(Map<ImmutableContextSet, Map<String, Boolean>> permissions, Map<ImmutableContextSet, Map<String, String>> options, Map<ImmutableContextSet, List<SubjectReference>> parents) {
|
||||||
|
ImmutableMap.Builder<ImmutableContextSet, Map<String, Boolean>> permissionsBuilder = ImmutableMap.builder();
|
||||||
|
for (Map.Entry<ImmutableContextSet, Map<String, Boolean>> e : permissions.entrySet()) {
|
||||||
|
permissionsBuilder.put(e.getKey(), ImmutableMap.copyOf(e.getValue()));
|
||||||
|
}
|
||||||
|
this.permissions = permissionsBuilder.build();
|
||||||
|
|
||||||
|
ImmutableMap.Builder<ImmutableContextSet, Map<String, String>> optionsBuilder = ImmutableMap.builder();
|
||||||
|
for (Map.Entry<ImmutableContextSet, Map<String, String>> e : options.entrySet()) {
|
||||||
|
optionsBuilder.put(e.getKey(), ImmutableMap.copyOf(e.getValue()));
|
||||||
|
}
|
||||||
|
this.options = optionsBuilder.build();
|
||||||
|
|
||||||
|
ImmutableMap.Builder<ImmutableContextSet, List<SubjectReference>> parentsBuilder = ImmutableMap.builder();
|
||||||
|
for (Map.Entry<ImmutableContextSet, List<SubjectReference>> e : parents.entrySet()) {
|
||||||
|
parentsBuilder.put(e.getKey(), ImmutableList.copyOf(e.getValue()));
|
||||||
|
}
|
||||||
|
this.parents = parentsBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubjectStorageModel(CalculatedSubjectData data) {
|
||||||
|
this(data.getPermissions(), data.getOptions(), data.getParentsAsList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubjectStorageModel(JsonObject root) {
|
||||||
|
Preconditions.checkArgument(root.get("permissions").isJsonArray());
|
||||||
|
Preconditions.checkArgument(root.get("options").isJsonArray());
|
||||||
|
Preconditions.checkArgument(root.get("parents").isJsonArray());
|
||||||
|
|
||||||
|
JsonArray permissions = root.get("permissions").getAsJsonArray();
|
||||||
|
JsonArray options = root.get("options").getAsJsonArray();
|
||||||
|
JsonArray parents = root.get("parents").getAsJsonArray();
|
||||||
|
|
||||||
|
ImmutableMap.Builder<ImmutableContextSet, Map<String, Boolean>> permissionsBuilder = ImmutableMap.builder();
|
||||||
|
for (JsonElement e : permissions) {
|
||||||
|
if (!e.isJsonObject()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject section = e.getAsJsonObject();
|
||||||
|
if (!section.get("context").isJsonObject()) continue;
|
||||||
|
if (!section.get("data").isJsonObject()) continue;
|
||||||
|
|
||||||
|
JsonObject context = section.get("context").getAsJsonObject();
|
||||||
|
JsonObject data = section.get("data").getAsJsonObject();
|
||||||
|
|
||||||
|
ImmutableContextSet contextSet = contextsFromJson(context);
|
||||||
|
ImmutableMap.Builder<String, Boolean> perms = ImmutableMap.builder();
|
||||||
|
for (Map.Entry<String, JsonElement> perm : data.entrySet()) {
|
||||||
|
perms.put(perm.getKey(), perm.getValue().getAsBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
permissionsBuilder.put(contextSet, perms.build());
|
||||||
|
}
|
||||||
|
this.permissions = permissionsBuilder.build();
|
||||||
|
|
||||||
|
ImmutableMap.Builder<ImmutableContextSet, Map<String, String>> optionsBuilder = ImmutableMap.builder();
|
||||||
|
for (JsonElement e : options) {
|
||||||
|
if (!e.isJsonObject()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject section = e.getAsJsonObject();
|
||||||
|
if (!section.get("context").isJsonObject()) continue;
|
||||||
|
if (!section.get("data").isJsonObject()) continue;
|
||||||
|
|
||||||
|
JsonObject context = section.get("context").getAsJsonObject();
|
||||||
|
JsonObject data = section.get("data").getAsJsonObject();
|
||||||
|
|
||||||
|
ImmutableContextSet contextSet = contextsFromJson(context);
|
||||||
|
ImmutableMap.Builder<String, String> opts = ImmutableMap.builder();
|
||||||
|
for (Map.Entry<String, JsonElement> opt : data.entrySet()) {
|
||||||
|
opts.put(opt.getKey(), opt.getValue().getAsString());
|
||||||
|
}
|
||||||
|
|
||||||
|
optionsBuilder.put(contextSet, opts.build());
|
||||||
|
}
|
||||||
|
this.options = optionsBuilder.build();
|
||||||
|
|
||||||
|
ImmutableMap.Builder<ImmutableContextSet, List<SubjectReference>> parentsBuilder = ImmutableMap.builder();
|
||||||
|
for (JsonElement e : parents) {
|
||||||
|
if (!e.isJsonObject()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject section = e.getAsJsonObject();
|
||||||
|
if (!section.get("context").isJsonObject()) continue;
|
||||||
|
if (!section.get("data").isJsonArray()) continue;
|
||||||
|
|
||||||
|
JsonObject context = section.get("context").getAsJsonObject();
|
||||||
|
JsonArray data = section.get("data").getAsJsonArray();
|
||||||
|
|
||||||
|
ImmutableContextSet contextSet = contextsFromJson(context);
|
||||||
|
ImmutableList.Builder<SubjectReference> pars = ImmutableList.builder();
|
||||||
|
for (JsonElement p : data) {
|
||||||
|
if (!p.isJsonObject()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject parent = p.getAsJsonObject();
|
||||||
|
|
||||||
|
String collection = parent.get("collection").getAsString();
|
||||||
|
String subject = parent.get("subject").getAsString();
|
||||||
|
|
||||||
|
pars.add(SubjectReference.of(collection, subject));
|
||||||
|
}
|
||||||
|
|
||||||
|
parentsBuilder.put(contextSet, pars.build());
|
||||||
|
}
|
||||||
|
this.parents = parentsBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JsonObject toJson() {
|
||||||
|
JsonObject root = new JsonObject();
|
||||||
|
|
||||||
|
JsonArray permissions = new JsonArray();
|
||||||
|
for (Map.Entry<ImmutableContextSet, Map<String, Boolean>> e : this.permissions.entrySet()) {
|
||||||
|
if (e.getValue().isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject section = new JsonObject();
|
||||||
|
section.add("context", contextsToJson(e.getKey()));
|
||||||
|
|
||||||
|
JsonObject data = new JsonObject();
|
||||||
|
for (Map.Entry<String, Boolean> ent : e.getValue().entrySet()) {
|
||||||
|
data.addProperty(ent.getKey(), ent.getValue());
|
||||||
|
}
|
||||||
|
section.add("data", data);
|
||||||
|
|
||||||
|
permissions.add(section);
|
||||||
|
}
|
||||||
|
root.add("permissions", permissions);
|
||||||
|
|
||||||
|
JsonArray options = new JsonArray();
|
||||||
|
for (Map.Entry<ImmutableContextSet, Map<String, String>> e : this.options.entrySet()) {
|
||||||
|
if (e.getValue().isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject section = new JsonObject();
|
||||||
|
section.add("context", contextsToJson(e.getKey()));
|
||||||
|
|
||||||
|
JsonObject data = new JsonObject();
|
||||||
|
for (Map.Entry<String, String> ent : e.getValue().entrySet()) {
|
||||||
|
data.addProperty(ent.getKey(), ent.getValue());
|
||||||
|
}
|
||||||
|
section.add("data", data);
|
||||||
|
|
||||||
|
options.add(section);
|
||||||
|
}
|
||||||
|
root.add("options", options);
|
||||||
|
|
||||||
|
JsonArray parents = new JsonArray();
|
||||||
|
for (Map.Entry<ImmutableContextSet, List<SubjectReference>> e : this.parents.entrySet()) {
|
||||||
|
if (e.getValue().isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
JsonObject section = new JsonObject();
|
||||||
|
section.add("context", contextsToJson(e.getKey()));
|
||||||
|
|
||||||
|
JsonArray data = new JsonArray();
|
||||||
|
for (SubjectReference ref : e.getValue()) {
|
||||||
|
JsonObject parent = new JsonObject();
|
||||||
|
parent.addProperty("collection", ref.getCollection());
|
||||||
|
parent.addProperty("subject", ref.getCollection());
|
||||||
|
data.add(parent);
|
||||||
|
}
|
||||||
|
section.add("data", data);
|
||||||
|
|
||||||
|
options.add(section);
|
||||||
|
}
|
||||||
|
root.add("parents", parents);
|
||||||
|
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void applyToData(CalculatedSubjectData subjectData) {
|
||||||
|
subjectData.replacePermissions(permissions);
|
||||||
|
subjectData.replaceOptions(options);
|
||||||
|
subjectData.replaceParents(parents);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ImmutableContextSet contextsFromJson(JsonObject contexts) {
|
||||||
|
MutableContextSet ret = MutableContextSet.create();
|
||||||
|
for (Map.Entry<String, JsonElement> e : contexts.entrySet()) {
|
||||||
|
String key = e.getKey();
|
||||||
|
|
||||||
|
if (e.getValue().isJsonArray()) {
|
||||||
|
JsonArray values = e.getValue().getAsJsonArray();
|
||||||
|
for (JsonElement value : values) {
|
||||||
|
ret.add(key, value.getAsString());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ret.add(key, e.getValue().getAsString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret.makeImmutable();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JsonObject contextsToJson(ContextSet contexts) {
|
||||||
|
JsonObject ret = new JsonObject();
|
||||||
|
for (Map.Entry<String, Collection<String>> e : contexts.toMultimap().asMap().entrySet()) {
|
||||||
|
String key = e.getKey();
|
||||||
|
List<String> values = new ArrayList<>(e.getValue());
|
||||||
|
|
||||||
|
if (values.size() == 1) {
|
||||||
|
ret.addProperty(key, values.get(0));
|
||||||
|
} else if (values.size() > 1) {
|
||||||
|
JsonArray arr = new JsonArray();
|
||||||
|
for (String s : values) {
|
||||||
|
arr.add(new JsonPrimitive(s));
|
||||||
|
}
|
||||||
|
ret.add(key, arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user