package comeon.templates;
import com.google.common.base.Charsets;
import com.google.common.eventbus.EventBus;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import comeon.ComeOn;
import comeon.model.Template;
import comeon.model.TemplateKind;
import comeon.templates.velocity.VelocityTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.prefs.BackingStoreException;
import java.util.prefs.Preferences;
import java.util.stream.Collectors;
@Singleton
public final class TemplatesImpl implements Templates {
private static final Logger LOGGER = LoggerFactory.getLogger(TemplatesImpl.class);
private final ArrayList<Template> templates;
private final Preferences prefs;
private final Map<String, TemplateKind> templateKinds;
private final EventBus bus;
@Inject
private TemplatesImpl(final Map<String, TemplateKind> templateKinds, final EventBus bus) {
this.templates = new ArrayList<>(0);
this.prefs = Preferences.userNodeForPackage(ComeOn.class).node("templates");
this.templateKinds = templateKinds;
this.bus = bus;
}
@Override
public void loadPreferences() throws BackingStoreException {
final String[] templateNames = prefs.childrenNames();
this.templates.ensureCapacity(templateNames.length);
for (final String templateName : templateNames) {
readNode(templateName);
}
}
@Override
public List<Template> getTemplates() {
return new ArrayList<>(templates);
}
@Override
public void setTemplates(final List<Template> templates) {
this.templates.clear();
this.templates.ensureCapacity(templates.size());
this.templates.addAll(templates);
this.bus.post(new TemplatesChangedEvent(this.getTemplates()));
}
@Override
public List<TemplateKind> getTemplateKinds() {
return templateKinds.values().stream()
.sorted((o1, o2) -> o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName()))
.collect(Collectors.toList());
}
@Override
public Charset[] getSupportedCharsets() {
return new Charset[]{Charsets.UTF_8, Charsets.ISO_8859_1};
}
@Override
public void save() throws BackingStoreException {
for (final String name : prefs.childrenNames()) {
prefs.node(name).removeNode();
}
for (final Template template : templates) {
final Preferences node = prefs.node(template.getName());
node.put(PreferencesKeys.DESCRIPTION.name(), template.getDescription());
node.put(PreferencesKeys.FILE.name(), template.getFile().toString());
node.put(PreferencesKeys.CHARSET.name(), template.getCharset().name());
node.put(PreferencesKeys.KIND.name(), template.getKind().getClass().getSimpleName());
}
}
private void readNode(final String templateName) throws BackingStoreException {
final Preferences node = prefs.node(templateName);
final String description = node.get(PreferencesKeys.DESCRIPTION.name(), "");
try {
final Charset charset = Charset.forName(node.get(PreferencesKeys.CHARSET.name(), null));
final Path file = Paths.get(node.get(PreferencesKeys.FILE.name(), null));
final TemplateKind kind = templateKinds.get(node.get(PreferencesKeys.KIND.name(), VelocityTemplate.class.getSimpleName()));
final Template template = new Template(templateName, description, file, charset, kind);
templates.add(template);
} catch (final IllegalArgumentException | NullPointerException | IOException e) {
LOGGER.warn("Got exception, removing template {}", templateName, e);
node.removeNode();
}
}
private enum PreferencesKeys {
DESCRIPTION, FILE, KIND, CHARSET
}
}