package me.asofold.bpl.simplyvanish.config.compatlayer;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bukkit.Bukkit;
public class ConfigUtil {
public static final int canaryInt = Integer.MIN_VALUE +7;
public static final long canaryLong = Long.MIN_VALUE + 7L;
public static final double canaryDouble = -Double.MAX_VALUE + 1.125798;
public static String stringPath( String path){
return stringPath(path, '.');
}
public static String stringPath( String path , char sep ){
String useSep = (sep=='.')?"\\.":""+sep;
String[] split = path.split(useSep);
StringBuilder builder = new StringBuilder();
builder.append(stringPart(split[0]));
for (int i = 1; i<split.length; i++){
builder.append(sep+stringPart(split[i]));
}
return builder.toString();
}
/**
* Aimed at numbers in paths.
* @param cfg
* @param path
* @return
*/
public static String bestPath(CompatConfig cfg, String path){
return bestPath(cfg, path, '.');
}
/**
* Aimed at numbers in paths.
* @param cfg
* @param path
* @param sep
* @return
*/
public static String bestPath(CompatConfig cfg, String path, char sep){
String useSep = (sep=='.')?"\\.":""+sep;
String[] split = path.split(useSep);
String res;
if (cfg.hasEntry(split[0]) )res = split[0];
else{
res = stringPart(split[0]);
if ( !cfg.hasEntry(res)) return path;
}
for (int i = 1; i<split.length; i++){
if (cfg.hasEntry(res+sep+split[i]) ) res += sep+split[i];
else{
res += sep+stringPart(split[i]);
if ( !cfg.hasEntry(res)) return path;
}
}
return res;
}
public static String stringPart(String input){
try{
Double.parseDouble(input);
return "'"+input+"'";
} catch (NumberFormatException e){
}
try{
Long.parseLong(input);
return "'"+input+"'";
} catch (NumberFormatException e){
}
try{
Integer.parseInt(input);
return "'"+input+"'";
} catch (NumberFormatException e){
}
return input;
}
public static boolean forceDefaults(CompatConfig defaults, CompatConfig config){
Map<String ,Object> all = defaults.getValuesDeep();
boolean changed = false;
for ( String path : all.keySet()){
if ( !config.hasEntry(path)){
config.setProperty(path, defaults.getProperty(path, null));
changed = true;
}
}
return changed;
}
/**
* Add StringList entries to a set.
* @param cfg
* @param path
* @param set
* @param clear If to clear the set.
* @param trim
* @param lowerCase
*/
public static void readStringSetFromList(CompatConfig cfg, String path, Set<String> set, boolean clear, boolean trim, boolean lowerCase){
if (clear) set.clear();
List<String> tempList = cfg.getStringList(path , null);
if (tempList != null){
for (String entry : tempList){
if (trim) entry = entry.trim();
if (lowerCase) entry = entry.toLowerCase();
set.add(entry);
}
}
}
/**
* Return an ArrayList.
* @param input
* @return
*/
public static final <T> List<T> asList(final T[] input){
final List<T> out = new ArrayList<T>(input.length);
for (int i = 0; i < input.length; i++){
out.add(input[i]);
}
return out;
}
/**
* Return an ArrayList.
* @param input
* @return
*/
public static final List<Integer> asList(final int[] input){
final List<Integer> out = new ArrayList<Integer>(input.length);
for (int i = 0; i < input.length; i++){
out.add(input[i]);
}
return out;
}
/**
* Return an ArrayList.
* @param input
* @return
*/
public static final List<Long> asList(final long[] input){
final List<Long> out = new ArrayList<Long>(input.length);
for (int i = 0; i < input.length; i++){
out.add(input[i]);
}
return out;
}
/**
* Return an ArrayList.
* @param input
* @return
*/
public static final List<Double> asList(final double[] input){
final List<Double> out = new ArrayList<Double>(input.length);
for (int i = 0; i < input.length; i++){
out.add(input[i]);
}
return out;
}
/**
* Return an ArrayList.
* @param input
* @return
*/
public static final List<Float> asList(final float[] input){
final List<Float> out = new ArrayList<Float>(input.length);
for (int i = 0; i < input.length; i++){
out.add(input[i]);
}
return out;
}
/**
* Return an ArrayList.
* @param input
* @return
*/
public static final List<Boolean> asList(final boolean[] input){
final List<Boolean> out = new ArrayList<Boolean>(input.length);
for (int i = 0; i < input.length; i++){
out.add(input[i]);
}
return out;
}
public static final String[] toArray(final Collection<String> collection){
if (collection == null) return null;
final String[] a = new String[collection.size()];
collection.toArray(a);
return a;
}
/**
* Read keys and return map sorted by inheritance, safe for reading.<br>
* Entries without inheritance have their own key set in the map (!).
* <hr>
* Quadratic time algorithm :)
* @param cfg
* @param path
* @param inheritanceKey
* @return
*/
public static LinkedHashMap<String, String> getInheritanceOrder(CompatConfig cfg, String path, String inheritanceKey){
// TODO: detach this to ConfigUtil from compatlayer !
LinkedHashMap<String, String> ordered = new LinkedHashMap<String, String>();
List<String> keys = cfg.getStringKeys(path); // node names
if (keys.isEmpty()) return ordered;
Set<String> done = new HashSet<String>();
Map<String, String> inheritance = new HashMap<String, String>();
// First sorting in:
for (String key : keys){
String parent = cfg.getString(path + "." + key + "." + inheritanceKey, null);
if (parent == null){
done.add(key);
ordered.put(key, key);
}
else inheritance.put(key, parent);
}
// Now attempt to resolve parents:
List<String> rem = new LinkedList<String>();
while (!inheritance.isEmpty()){
rem.clear();
int found = 0;
for (Entry<String, String> entry : inheritance.entrySet()){
String key = entry.getKey();
String parent = entry.getValue();
if (done.contains(parent)){
rem.add(key);
done.add(key);
ordered.put(key, parent);
found ++;
}
}
for (String key : rem){
inheritance.remove(key);
}
if (found == 0) break;
}
if (!inheritance.isEmpty()){
StringBuilder b = new StringBuilder();
b.append("[ConfigUtil] Inheritance entries could not be resolved(" + path + "):");
for (Entry<String, String> entry : inheritance.entrySet()){
b.append(" " + entry.getKey() + "->" + entry.getValue());
}
Bukkit.getLogger().warning(b.toString());
}
return ordered;
}
/**
* Might have a newline at the end.
* @param name
* @param clazz
* @param folderPart
* @return
*/
public static String fetchResource(Class<?> clazz, String path) {
String className = clazz.getSimpleName() + ".class";
String classPath = clazz.getResource(className).toString();
if (!classPath.startsWith("jar")) return null;
String absPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/"+path;
try {
URL url = new URL(absPath);
try {
Object obj = url.getContent();
if (obj instanceof InputStream){
BufferedReader r = new BufferedReader(new InputStreamReader((InputStream) obj));
StringBuilder builder = new StringBuilder();
String last = r.readLine();
while (last != null){
builder.append(last);
builder.append("\n"); // does not hurt if one too many.
last = r.readLine();
}
return builder.toString();
}
else return null;
} catch (IOException e) {
return null;
}
} catch (MalformedURLException e) {
}
return null;
}
public static boolean writeFile(File file, String content) {
if(!file.exists()){
try {
file.createNewFile();
} catch (IOException e) {
return false;
}
}
FileWriter w = null;
try {
w = new FileWriter(file);
BufferedWriter bw = new BufferedWriter(w);
bw.write(content);
bw.flush();
w.flush();
w.close();
return true;
} catch (IOException e) {
if (w!=null){
try {
w.close();
} catch (IOException e2) {
e.printStackTrace();
}
}
return false;
}
}
}