/*
Tango - Personal Media Center
Copyright (C) 2021 Ulrich Hilger
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
published by the Free Software Foundation, either version 3 of the
License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
package de.uhilger.tango.store;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import de.uhilger.tango.Server;
import de.uhilger.tango.entity.Ablageort;
import de.uhilger.tango.entity.Abspieler;
import de.uhilger.tango.entity.Abspielliste;
import de.uhilger.tango.entity.Einstellung;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.logging.Logger;
import de.uhilger.tango.entity.Entity;
import de.uhilger.tango.entity.Geraet;
import de.uhilger.tango.entity.Livestream;
import de.uhilger.tango.entity.Titel;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
/**
* Ablage fuer Dateien der Mediazentrale
*
* [Basispfad]/[Typ]/[Name]
*
* Typ ist eine der Klassen der Package entity
* Name muss identisch mit dem Element laut Entity.getName() sein
*
* @author ulrich
* @version 1, 5.4.2021
*/
public class FileStorage implements Storage {
private static final Logger logger = Logger.getLogger(FileStorage.class.getName());
/** StorageType Ablageort */
public static final String ST_ABLAGEORT = "Ablageort";
public static final String ST_EINSTELLUNG = "Einstellung";
public static final String ST_ABSPIELER = "Abspieler";
public static final String ST_ABSPIELLISTE = "Abspielliste";
public static final String ST_LIVESTREAM = "Livestream";
public static final String ST_GERAET = "Geraet";
private final String fileBase;
private final Map types;
public FileStorage(String base) {
this.fileBase = base;
// Beispiel: TypeToken> list = new TypeToken>() {};
TypeToken ttAblageort = new TypeToken() {};
TypeToken ttEinstellung = new TypeToken() {};
TypeToken ttAbspieler = new TypeToken() {};
TypeToken ttAbspielliste = new TypeToken() {};
TypeToken ttLivestream = new TypeToken() {};
TypeToken ttGeraet = new TypeToken() {};
TypeToken ttTitel = new TypeToken() {};
types = new HashMap();
types.put(Ablageort.class.getSimpleName(), ttAblageort);
types.put(Einstellung.class.getSimpleName(), ttEinstellung);
types.put(Abspieler.class.getSimpleName(), ttAbspieler);
types.put(Abspielliste.class.getSimpleName(), ttAbspielliste);
types.put(Titel.class.getSimpleName(), ttTitel);
types.put(Livestream.class.getSimpleName(), ttLivestream);
types.put(Geraet.class.getSimpleName(), ttGeraet);
}
/**
* Ein Objekt als JSON in eine Datei schreiben
*
* Es wird in den Ordner geschrieben, der von conf angegeben ist
*
* Wenn es z.B.ein Ablage-Objekt ist, wird das Objekt in die Datei
[conf]/Ablage/[name der Ablage].json geschrieben
Der Name der Ablage muss eindeutig sein
*
*
* @param entity das Objekt, das geschrieben werden soll
* @param overwrite true, wenn Aenderung, false fuer neue Elemente
* @return die Datei oder null, wenn die Datei existiert und ein
* neues Element (overwrite=false) uebergeben wurde
* @throws java.io.IOException
*/
public File writeToFile(Entity entity, boolean overwrite) throws IOException {
String className = entity.getClass().getSimpleName();
logger.finer(className);
File dir = new File(fileBase, className);
dir.mkdirs();
File file = new File(dir, entity.getName());
if(file.exists() && !overwrite) {
return null;
} else {
FileWriter fw = new FileWriter(file);
Gson gson = new Gson();
fw.write(gson.toJson(entity));
fw.flush();
fw.close();
return file;
}
}
public String readFromFile(File file) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader r = new BufferedReader(new FileReader(file));
String line = r.readLine();
while(line != null) {
sb.append(line);
line = r.readLine();
}
r.close();
return sb.toString();
}
public Entity entityFromFile(File file) throws ClassNotFoundException, FileNotFoundException, IOException {
String json = readFromFile(file);
logger.finer("json: " + json);
Gson gson = new Gson();
return gson.fromJson(json, typeFromName(typeNameFromPath(file)).getType());
}
private String typeNameFromPath(File file) {
String[] parts = file.getPath().split(Server.SLASH);
return parts[parts.length-2];
}
@Override
public Object write(Entity e, boolean overwrite) {
try {
return writeToFile(e, overwrite);
} catch (IOException ex) {
logger.log(Level.SEVERE, null, ex);
return null;
}
}
@Override
public Entity read(String typ, String name) {
try {
return entityFromFile(getFile(typ, name));
} catch (ClassNotFoundException | IOException ex) {
logger.log(Level.SEVERE, null, ex);
return null;
}
}
@Override
public List list(String typ) {
File base = new File(fileBase);
File dir = new File(base, typ);
List list = new ArrayList();
File[] files = dir.listFiles();
if(files != null) {
for(File file : files) {
//NamedItem n = new NamedItem();
//n.setLabel(file.getName());
list.add(file.getName());
}
}
return list;
}
@Override
public TypeToken typeFromName(String name) {
return types.get(name);
}
@Override
public String readJson(String typ, String name) {
try {
return readFromFile(getFile(typ, name));
} catch (IOException ex) {
logger.log(Level.SEVERE, null, ex);
return null;
}
}
private File getFile(String typ, String name) {
File base = new File(fileBase);
File dir = new File(base, typ);
return new File(dir, name);
}
@Override
public boolean delete(String typ, String name) {
File file = getFile(typ, name);
if(file.exists()) {
return file.delete();
} else {
return false;
}
}
@Override
public List listObjects(String typ) {
File base = new File(fileBase);
File dir = new File(base, typ);
List list = new ArrayList();
File[] files = dir.listFiles();
if(files != null) {
for(File file : files) {
try {
list.add(entityFromFile(file));
} catch (ClassNotFoundException | IOException ex) {
logger.log(Level.SEVERE, null, ex);
}
}
}
return list;
}
public boolean exists(String typ, String name) {
return getFile(typ, name).exists();
}
}