Implement persisting subjects (+ defaults)

This commit is contained in:
Luck 2016-10-10 18:58:43 +01:00
parent 069e535f1a
commit 5b4975f34c
No known key found for this signature in database
GPG Key ID: EFA9B3EC5FD90F8B
10 changed files with 633 additions and 26 deletions

View File

@ -29,6 +29,8 @@ import me.lucko.luckperms.LPSpongePlugin;
import me.lucko.luckperms.api.sponge.collections.GroupCollection;
import me.lucko.luckperms.api.sponge.collections.UserCollection;
import me.lucko.luckperms.api.sponge.simple.SimpleCollection;
import me.lucko.luckperms.api.sponge.simple.persisted.SimplePersistedCollection;
import me.lucko.luckperms.api.sponge.simple.persisted.SubjectStorage;
import me.lucko.luckperms.contexts.SpongeCalculatorLink;
import org.spongepowered.api.plugin.PluginContainer;
import org.spongepowered.api.service.context.ContextCalculator;
@ -36,21 +38,31 @@ import org.spongepowered.api.service.permission.*;
import org.spongepowered.api.text.Text;
import org.spongepowered.api.util.Tristate;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
/**
* The LuckPerms implementation of the Sponge Permission Service
*/
public class LuckPermsService implements PermissionService {
public static final String SERVER_CONTEXT = "server";
@Getter
private final LPSpongePlugin plugin;
@Getter
private final SubjectStorage storage;
@Getter
private final UserCollection userSubjects;
@Getter
private final GroupCollection groupSubjects;
@Getter
private final SimplePersistedCollection defaultSubjects;
@Getter
private final Set<PermissionDescription> descriptionSet;
@ -59,12 +71,17 @@ public class LuckPermsService implements PermissionService {
public LuckPermsService(LPSpongePlugin plugin) {
this.plugin = plugin;
storage = new SubjectStorage(new File(plugin.getDataFolder(), "local"));
userSubjects = new UserCollection(this, plugin.getUserManager());
groupSubjects = new GroupCollection(this, plugin.getGroupManager());
defaultSubjects = new SimplePersistedCollection(this, "defaults");
defaultSubjects.loadAll();
subjects = new ConcurrentHashMap<>();
subjects.put(PermissionService.SUBJECTS_USER, userSubjects);
subjects.put(PermissionService.SUBJECTS_GROUP, groupSubjects);
subjects.put("defaults", defaultSubjects);
descriptionSet = ConcurrentHashMap.newKeySet();
}
@ -75,7 +92,7 @@ public class LuckPermsService implements PermissionService {
@Override
public Subject getDefaults() {
return getSubjects("defaults").get("default");
return getDefaultSubjects().get("default");
}
@Override

View File

@ -89,6 +89,6 @@ public class GroupCollection implements SubjectCollection {
@Override
public Subject getDefaults() {
return service.getDefaults();
return service.getDefaultSubjects().get(getIdentifier());
}
}

View File

@ -161,6 +161,6 @@ public class UserCollection implements SubjectCollection {
@Override
public Subject getDefaults() {
return service.getDefaults();
return service.getDefaultSubjects().get(getIdentifier());
}
}

View File

@ -25,8 +25,8 @@ package me.lucko.luckperms.api.sponge.simple;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.sponge.LuckPermsService;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectCollection;
import org.spongepowered.api.util.Tristate;
@ -37,9 +37,12 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* Super simple SubjectCollection implementation
*/
@RequiredArgsConstructor
public class SimpleCollection implements SubjectCollection {
private final PermissionService service;
private final LuckPermsService service;
@Getter
private final String identifier;
@ -85,6 +88,6 @@ public class SimpleCollection implements SubjectCollection {
@Override
public Subject getDefaults() {
return new SimpleSubject("default", service, this);
return service.getDefaultSubjects().get(identifier);
}
}

View File

@ -66,11 +66,6 @@ public class SimpleSubject implements Subject {
return getPermissionValue(contexts, node).asBoolean();
}
@Override
public boolean hasPermission(@NonNull String permission) {
return hasPermission(getActiveContexts(), permission);
}
@Override
public Tristate getPermissionValue(@NonNull Set<Context> contexts, @NonNull String node) {
Tristate res = subjectData.getNodeTree(contexts).get(node);
@ -86,21 +81,11 @@ public class SimpleSubject implements Subject {
return res;
}
@Override
public boolean isChildOf(@NonNull Subject parent) {
return isChildOf(getActiveContexts(), parent);
}
@Override
public boolean isChildOf(@NonNull Set<Context> contexts, @NonNull Subject subject) {
return subjectData.getParents(contexts).contains(subject);
}
@Override
public List<Subject> getParents() {
return getParents(getActiveContexts());
}
@Override
public List<Subject> getParents(@NonNull Set<Context> contexts) {
return subjectData.getParents(contexts);
@ -121,11 +106,6 @@ public class SimpleSubject implements Subject {
return res;
}
@Override
public Optional<String> getOption(String key) {
return getOption(getActiveContexts(), key);
}
@Override
public Set<Context> getActiveContexts() {
return SubjectData.GLOBAL_CONTEXT;

View File

@ -0,0 +1,103 @@
/*
* 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.api.sponge.simple.persisted;
import lombok.Getter;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import me.lucko.luckperms.api.sponge.LuckPermsService;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectCollection;
import org.spongepowered.api.util.Tristate;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* A simple persistable subject collection
*/
@RequiredArgsConstructor
public class SimplePersistedCollection implements SubjectCollection {
private final LuckPermsService service;
@Getter
private final String identifier;
private final Map<String, SimplePersistedSubject> subjects = new ConcurrentHashMap<>();
public void loadAll() {
Map<String, SimpleSubjectDataHolder> holders = service.getStorage().loadAllFromFile(identifier);
for (Map.Entry<String, SimpleSubjectDataHolder> e : holders.entrySet()) {
SimplePersistedSubject subject = new SimplePersistedSubject(e.getKey(), service, this);
subject.loadData(e.getValue());
subjects.put(e.getKey(), subject);
}
}
@Override
public synchronized Subject get(@NonNull String id) {
if (!subjects.containsKey(id)) {
subjects.put(id, new SimplePersistedSubject(id, service, this));
}
return subjects.get(id);
}
@Override
public boolean hasRegistered(@NonNull String id) {
return subjects.containsKey(id);
}
@Override
public Iterable<Subject> getAllSubjects() {
return subjects.values().stream().map(s -> (Subject) s).collect(Collectors.toList());
}
@Override
public Map<Subject, Boolean> getAllWithPermission(@NonNull String id) {
return getAllWithPermission(Collections.emptySet(), id);
}
@Override
public Map<Subject, Boolean> getAllWithPermission(@NonNull Set<Context> contexts, @NonNull String node) {
Map<Subject, Boolean> m = new HashMap<>();
for (Subject subject : subjects.values()) {
Tristate ts = subject.getPermissionValue(contexts, node);
if (ts != Tristate.UNDEFINED) {
m.put(subject, ts.asBoolean());
}
}
return m;
}
@Override
public Subject getDefaults() {
return service.getDefaultSubjects().get(identifier);
}
}

View File

@ -0,0 +1,141 @@
/*
* 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.api.sponge.simple.persisted;
import lombok.Getter;
import lombok.NonNull;
import me.lucko.luckperms.api.sponge.LuckPermsService;
import org.spongepowered.api.command.CommandSource;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.MemorySubjectData;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.service.permission.SubjectCollection;
import org.spongepowered.api.service.permission.SubjectData;
import org.spongepowered.api.util.Tristate;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Set;
/**
* A simple persistable Subject implementation
*/
@Getter
public class SimplePersistedSubject implements Subject {
private final String identifier;
private final LuckPermsService service;
private final SubjectCollection containingCollection;
private final SimplePersistedSubjectData subjectData;
private final MemorySubjectData transientSubjectData;
public SimplePersistedSubject(String identifier, LuckPermsService service, SubjectCollection containingCollection) {
this.identifier = identifier;
this.service = service;
this.containingCollection = containingCollection;
this.subjectData = new SimplePersistedSubjectData(service, this);
this.transientSubjectData = new MemorySubjectData(service);
}
public void loadData(SimpleSubjectDataHolder dataHolder) {
subjectData.setSave(false);
dataHolder.copyTo(subjectData, service);
subjectData.setSave(true);
}
public void save() {
service.getPlugin().doAsync(() -> {
try {
service.getStorage().saveToFile(this);
} catch (IOException e) {
e.printStackTrace();
}
});
}
@Override
public Optional<CommandSource> getCommandSource() {
return Optional.empty();
}
@Override
public boolean hasPermission(@NonNull Set<Context> contexts, @NonNull String node) {
return getPermissionValue(contexts, node).asBoolean();
}
@Override
public Tristate getPermissionValue(@NonNull Set<Context> contexts, @NonNull String node) {
Tristate res = subjectData.getNodeTree(contexts).get(node);
if (res == Tristate.UNDEFINED) {
transientSubjectData.getNodeTree(contexts).get(node);
}
if (res == Tristate.UNDEFINED) {
for (Subject parent : getParents(contexts)) {
Tristate tempRes = parent.getPermissionValue(contexts, node);
if (tempRes != Tristate.UNDEFINED) {
res = tempRes;
break;
}
}
}
return res;
}
@Override
public boolean isChildOf(@NonNull Set<Context> contexts, @NonNull Subject subject) {
return subjectData.getParents(contexts).contains(subject) || transientSubjectData.getParents(contexts).contains(subject);
}
@Override
public List<Subject> getParents(@NonNull Set<Context> contexts) {
List<Subject> s = new ArrayList<>();
s.addAll(subjectData.getParents(contexts));
s.addAll(transientSubjectData.getParents(contexts));
return s;
}
@Override
public Optional<String> getOption(Set<Context> set, String key) {
Optional<String> res = Optional.ofNullable(subjectData.getOptions(getActiveContexts()).get(key));
if (!res.isPresent()) {
res = Optional.ofNullable(transientSubjectData.getOptions(getActiveContexts()).get(key));
}
if (!res.isPresent()) {
for (Subject parent : getParents(getActiveContexts())) {
Optional<String> tempRes = parent.getOption(getActiveContexts(), key);
if (tempRes.isPresent()) {
res = tempRes;
break;
}
}
}
return res;
}
@Override
public Set<Context> getActiveContexts() {
return SubjectData.GLOBAL_CONTEXT;
}
}

View File

@ -0,0 +1,130 @@
/*
* 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.api.sponge.simple.persisted;
import lombok.Getter;
import lombok.Setter;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.MemorySubjectData;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.service.permission.Subject;
import org.spongepowered.api.util.Tristate;
import javax.annotation.Nullable;
import java.util.Set;
/**
* Extension of MemorySubjectData which persists data when modified
*/
public class SimplePersistedSubjectData extends MemorySubjectData {
private final SimplePersistedSubject subject;
@Getter
@Setter
private boolean save = true;
public SimplePersistedSubjectData(PermissionService service, SimplePersistedSubject subject) {
super(service);
this.subject = subject;
}
private void save() {
if (!save) {
return;
}
if (subject != null) {
subject.save();
}
}
@Override
public boolean setPermission(Set<Context> contexts, String permission, Tristate value) {
boolean r = super.setPermission(contexts, permission, value);
save();
return r;
}
@Override
public boolean clearPermissions() {
boolean r = super.clearPermissions();
save();
return r;
}
@Override
public boolean clearPermissions(Set<Context> context) {
boolean r = super.clearPermissions(context);
save();
return r;
}
@Override
public boolean addParent(Set<Context> contexts, Subject parent) {
boolean r = super.addParent(contexts, parent);
save();
return r;
}
@Override
public boolean removeParent(Set<Context> contexts, Subject parent) {
boolean r = super.removeParent(contexts, parent);
save();
return r;
}
@Override
public boolean clearParents() {
boolean r = super.clearParents();
save();
return r;
}
@Override
public boolean clearParents(Set<Context> contexts) {
boolean r = super.clearParents(contexts);
save();
return r;
}
@Override
public boolean setOption(Set<Context> contexts, String key, @Nullable String value) {
boolean r = super.setOption(contexts, key, value);
save();
return r;
}
@Override
public boolean clearOptions(Set<Context> contexts) {
boolean r = super.clearOptions(contexts);
save();
return r;
}
@Override
public boolean clearOptions() {
boolean r = super.clearOptions();
save();
return r;
}
}

View File

@ -0,0 +1,103 @@
/*
* 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.api.sponge.simple.persisted;
import org.spongepowered.api.service.context.Context;
import org.spongepowered.api.service.permission.MemorySubjectData;
import org.spongepowered.api.service.permission.PermissionService;
import org.spongepowered.api.util.Tristate;
import java.util.*;
import java.util.stream.Collectors;
/**
* Holds SubjectData in a "gson friendly" format for serialization
*/
public class SimpleSubjectDataHolder {
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<Map.Entry<String, String>>> parents;
public SimpleSubjectDataHolder(Map<Set<Context>, Map<String, String>> options, Map<Set<Context>, Map<String, Boolean>> permissions, Map<Set<Context>, List<Map.Entry<String, String>>> parents) {
this.options = new HashMap<>();
for (Map.Entry<Set<Context>, Map<String, String>> e : options.entrySet()) {
this.options.put(convertContexts(e.getKey()), new HashMap<>(e.getValue()));
}
this.permissions = new HashMap<>();
for (Map.Entry<Set<Context>, Map<String, Boolean>> e : permissions.entrySet()) {
this.permissions.put(convertContexts(e.getKey()), new HashMap<>(e.getValue()));
}
this.parents = new HashMap<>();
for (Map.Entry<Set<Context>, List<Map.Entry<String, String>>> e : parents.entrySet()) {
this.parents.put(convertContexts(e.getKey()), e.getValue().stream().map(p -> new AbstractMap.SimpleEntry<>(p.getKey(), p.getValue())).collect(Collectors.toList()));
}
}
public SimpleSubjectDataHolder(MemorySubjectData data) {
this(
data.getAllOptions(),
data.getAllPermissions(),
data.getAllParents().entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
e -> e.getValue().stream()
.map(s -> new AbstractMap.SimpleEntry<>(
s.getContainingCollection().getIdentifier(),
s.getIdentifier())
)
.collect(Collectors.toList())
)
)
);
}
public void copyTo(MemorySubjectData subjectData, PermissionService service) {
for (Map.Entry<Map<String, String>, Map<String, Boolean>> e : permissions.entrySet()) {
for (Map.Entry<String, Boolean> perm : e.getValue().entrySet()) {
subjectData.setPermission(convertContexts(e.getKey()), perm.getKey(), Tristate.fromBoolean(perm.getValue()));
}
}
for (Map.Entry<Map<String, String>, Map<String, String>> e : options.entrySet()) {
for (Map.Entry<String, String> option : e.getValue().entrySet()) {
subjectData.setOption(convertContexts(e.getKey()), option.getKey(), option.getValue());
}
}
for (Map.Entry<Map<String, String>, List<Map.Entry<String, String>>> e : parents.entrySet()) {
for (Map.Entry<String, String> parent : e.getValue()) {
subjectData.addParent(convertContexts(e.getKey()), service.getSubjects(parent.getKey()).get(parent.getValue()));
}
}
}
public static Map<String, String> convertContexts(Set<Context> contexts) {
return contexts.stream().collect(Collectors.toMap(Context::getKey, Context::getValue));
}
public static Set<Context> convertContexts(Map<String, String> contexts) {
return contexts.entrySet().stream().map(e -> new Context(e.getKey(), e.getValue())).collect(Collectors.toSet());
}
}

View File

@ -0,0 +1,130 @@
/*
* 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.api.sponge.simple.persisted;
import com.google.common.io.Files;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.AbstractMap;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Handles persisted Subject I/O and (de)serialization
*/
public class SubjectStorage {
private final Gson gson;
private final File container;
public SubjectStorage(File container) {
this.gson = new GsonBuilder().setPrettyPrinting().enableComplexMapKeySerialization().create();
this.container = container;
checkContainer();
}
private void checkContainer() {
this.container.getParentFile().mkdirs();
}
public void saveToFile(SimplePersistedSubject subject) throws IOException {
checkContainer();
File collection = new File(container, subject.getContainingCollection().getIdentifier());
if (!collection.exists()) {
collection.mkdirs();
}
File subjectFile = new File(collection, subject.getIdentifier().toLowerCase() + ".json");
saveToFile(subject, subjectFile);
}
public void saveToFile(SimplePersistedSubject subject, File file) throws IOException {
file.getParentFile().mkdirs();
if (file.exists()) {
file.delete();
}
file.createNewFile();
Files.write(saveToString(new SimpleSubjectDataHolder(subject.getSubjectData())), file, Charset.defaultCharset());
}
public String saveToString(SimpleSubjectDataHolder subject) {
return gson.toJson(subject);
}
public Map<String, SimpleSubjectDataHolder> loadAllFromFile(String collectionName) {
checkContainer();
File collection = new File(container, collectionName);
if (!collection.exists()) {
return Collections.emptyMap();
}
String[] fileNames = collection.list((dir, name) -> name.endsWith(".json"));
if (fileNames == null) return Collections.emptyMap();
Map<String, SimpleSubjectDataHolder> holders = new HashMap<>();
for (String name : fileNames) {
File subject = new File(collection, name);
try {
Map.Entry<String, SimpleSubjectDataHolder> s = loadFromFile(subject);
if (s != null) {
holders.put(s.getKey(), s.getValue());
}
} catch (IOException e) {
e.printStackTrace();
}
}
return holders;
}
public Map.Entry<String, SimpleSubjectDataHolder> loadFromFile(String collectionName, String subjectName) throws IOException {
checkContainer();
File collection = new File(container, collectionName);
if (!collection.exists()) {
return null;
}
File subject = new File(collection, subjectName.toLowerCase() + ".json");
return new AbstractMap.SimpleEntry<>(subjectName.toLowerCase(), loadFromFile(subject).getValue());
}
public Map.Entry<String, SimpleSubjectDataHolder> loadFromFile(File file) throws IOException {
if (!file.exists()) {
return null;
}
String s = Files.toString(file, Charset.defaultCharset());
return new AbstractMap.SimpleEntry<>(file.getName().substring(file.getName().length() - 5).toLowerCase(), loadFromString(s));
}
public SimpleSubjectDataHolder loadFromString(String s) {
return gson.fromJson(s, SimpleSubjectDataHolder.class);
}
}