package com.xenoage.zong.io.symbols;
import static com.xenoage.utils.PlatformUtils.platformUtils;
import static com.xenoage.utils.collections.CollectionUtils.alist;
import static com.xenoage.utils.collections.CollectionUtils.map;
import static com.xenoage.utils.error.Err.handle;
import static com.xenoage.utils.log.Level.Warning;
import static com.xenoage.utils.log.Report.createReport;
import java.util.List;
import java.util.Map;
import com.xenoage.utils.PlatformUtils;
import com.xenoage.utils.async.AsyncResult;
import com.xenoage.utils.async.AsyncProducer;
import com.xenoage.utils.io.FileFilters;
import com.xenoage.utils.io.FileNotFoundException;
import com.xenoage.zong.Voc;
import com.xenoage.zong.symbols.PathSymbol;
import com.xenoage.zong.symbols.Symbol;
import com.xenoage.zong.symbols.SymbolPool;
/**
* This class reads a {@link SymbolPool}
* from the filesystem of {@link PlatformUtils}.
*
* @author Andreas Wenger
*/
public final class SymbolPoolReader
implements AsyncProducer<SymbolPool> {
/** Directory, where the symbol pool subdirectories can be found. */
public static final String symbolPoolPath = "data/symbols/";
//parameters
private final String id;
private final String dir;
//state
private AsyncResult<SymbolPool> result;
private int symbolsCount;
private Map<String, Symbol> symbols = map();
private List<String> symbolsWithErrors = alist();
/**
* Creates a loader for the {@link SymbolPool} with the given ID from
* {@value #symbolPoolPath}.
*/
public SymbolPoolReader(String id) {
this.id = id;
this.dir = symbolPoolPath + id;
}
@Override public void produce(AsyncResult<SymbolPool> result) {
this.result = result;
step1_checkDir();
}
private void step1_checkDir() {
platformUtils().getFilesystemInput().existsDirectoryAsync(dir, new AsyncResult<Boolean>() {
@Override public void onSuccess(Boolean data) {
if (data) {
step2_listFiles();
}
else {
result.onFailure(new FileNotFoundException(dir));
}
}
@Override public void onFailure(Exception ex) {
result.onFailure(ex);
}
});
}
private void step2_listFiles() {
platformUtils().getFilesystemInput().listFilesAsync(dir, FileFilters.svgFilter,
new AsyncResult<List<String>>() {
@Override public void onSuccess(List<String> files) {
symbolsCount = files.size();
//load files in parallel, when possible
for (String file : files) {
String symbolPath = "data/symbols/" + id + "/" + file;
step3_loadSymbol(symbolPath);
}
}
@Override public void onFailure(Exception ex) {
result.onFailure(ex);
}
});
}
private void step3_loadSymbol(final String symbolPath) {
SvgSymbolReader loader = new SvgSymbolReader(symbolPath);
loader.produce(new AsyncResult<PathSymbol>() {
@Override public void onSuccess(PathSymbol symbol) {
symbols.put(symbol.getId(), symbol);
checkFinished();
}
@Override public void onFailure(Exception ex) {
symbolsWithErrors.add(symbolPath);
checkFinished();
}
});
}
private void checkFinished() {
if (symbols.size() + symbolsWithErrors.size() == symbolsCount) {
if (symbolsWithErrors.size() > 0) {
handle(createReport(Warning, true, Voc.CouldNotLoadSymbolPool, null, null,
symbolsWithErrors));
}
result.onSuccess(new SymbolPool(id, symbols));
}
}
}