/*
* Copyright 2015 Demigods RPG
* Copyright 2015 Alexander Chauncey
* Copyright 2015 Alex Bennett
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.demigodsrpg.util.datasection;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@SuppressWarnings("unchecked")
public abstract class AbstractDataRegistry<T extends AbstractPersistentModel<String>> {
protected final ConcurrentMap<String, T> REGISTERED_DATA = new ConcurrentHashMap<>();
protected final String SAVE_PATH;
protected final boolean SAVE_PRETTY;
protected final boolean PSQL_PERSISTENCE;
protected final String PSQL_CONNECTION;
public AbstractDataRegistry(String savePath, boolean savePretty, boolean psqlPersistence, String psqlConnection) {
SAVE_PATH = savePath;
SAVE_PRETTY = savePretty;
PSQL_PERSISTENCE = psqlPersistence;
PSQL_CONNECTION = psqlConnection;
}
public T fromId(String id) {
if (REGISTERED_DATA.get(id) == null) {
DataSection currentDb = getDatabase();
if (currentDb != null) {
synchronized (currentDb) {
if (currentDb.isSection(id)) {
registerFromDatabase();
}
}
}
}
return REGISTERED_DATA.get(id);
}
public void register(T data) {
REGISTERED_DATA.put(data.getPersistentId(), data);
synchronized (data) {
addToDatabase(data.getPersistentId(), data);
}
}
public final void register(T[] data) {
register(Arrays.asList(data));
}
final void register(Collection<T> data) {
data.forEach(this::register);
}
public final synchronized void registerFromDatabase() {
DataSection currentDb = getDatabase();
if (currentDb != null) {
synchronized (currentDb) {
for (String key : currentDb.getKeys()) {
REGISTERED_DATA.put(key, valueFromData(key, currentDb.getSectionNullable(key)));
}
}
}
}
public void unregister(T data) {
REGISTERED_DATA.remove(data.getPersistentId());
synchronized (data) {
deleteFromDatabase(data.getPersistentId());
}
}
public Collection<T> getRegistered() {
if (REGISTERED_DATA.isEmpty()) {
registerFromDatabase();
}
return REGISTERED_DATA.values();
}
synchronized boolean deleteFromDatabase(String key) {
// Grab the current db, and its data as a usable map.
DataSection currentDb = getDatabase();
if (currentDb != null) {
// Remove data.
currentDb.remove(key);
if (!PSQL_PERSISTENCE) {
// Save the file!
if (isPretty() || SAVE_PRETTY) {
return DataSectionUtil.saveFilePretty(SAVE_PATH + getName() + getExtention(), currentDb);
}
return DataSectionUtil.saveFile(SAVE_PATH + getName() + getExtention(), currentDb);
} else {
return DataSectionUtil.savePSQL(getName(), PSQL_CONNECTION, currentDb);
}
}
return false;
}
synchronized boolean addToDatabase(String key, T data) {
// Grab the current file, and its data as a usable map.
DataSection currentDb = getDatabase();
if (currentDb != null) {
// Create/overwrite a configuration section.
currentDb.createSection(key, data.serialize());
if (!PSQL_PERSISTENCE) {
// Save the file!
if (isPretty() || SAVE_PRETTY) {
return DataSectionUtil.saveFilePretty(SAVE_PATH + getName() + getExtention(), currentDb);
}
return DataSectionUtil.saveFile(SAVE_PATH + getName() + getExtention(), currentDb);
} else {
return DataSectionUtil.savePSQL(getName(), PSQL_CONNECTION, currentDb);
}
}
return false;
}
final DataSection getDatabase() {
if (PSQL_PERSISTENCE) {
try {
return DataSectionUtil.loadSectionFromPSQL(getName(), PSQL_CONNECTION).get();
} catch (Exception ignored) {
}
} else {
try {
return DataSectionUtil.loadSectionFromFile(SAVE_PATH + getName() + getExtention()).get();
} catch (Exception ignored) {
}
}
if (PSQL_PERSISTENCE) {
return new PJsonSection(new ConcurrentHashMap<>());
}
return new FJsonSection(new ConcurrentHashMap<>());
}
public synchronized final void clearCache() {
REGISTERED_DATA.clear();
}
/**
* Convert to a get from a number of objects representing the data.
*
* @param stringKey The string key for the data.
* @param data The provided data object.
* @return The converted get.
*/
protected abstract T valueFromData(String stringKey, DataSection data);
protected abstract String getName();
protected String getExtention() {
return ".extdat";
}
protected boolean isPretty() {
return false;
}
}