create new io strategies
This commit is contained in:
parent
e730dee6f5
commit
dd783a0b2e
@ -5,6 +5,8 @@ import com.intellij.openapi.project.Project;
|
||||
import de.marhali.easyi18n.io.IOStrategy;
|
||||
import de.marhali.easyi18n.io.json.JsonIOStrategy;
|
||||
import de.marhali.easyi18n.io.json.ModularizedJsonIOStrategy;
|
||||
import de.marhali.easyi18n.io.properties.PropertiesIOStrategy;
|
||||
import de.marhali.easyi18n.io.yaml.YamlIOStrategy;
|
||||
import de.marhali.easyi18n.model.SettingsState;
|
||||
import de.marhali.easyi18n.model.TranslationData;
|
||||
import de.marhali.easyi18n.service.SettingsService;
|
||||
@ -24,7 +26,9 @@ import java.util.function.Consumer;
|
||||
public class DataStore {
|
||||
|
||||
private static final Set<IOStrategy> STRATEGIES = new LinkedHashSet<>(Arrays.asList(
|
||||
new JsonIOStrategy(), new ModularizedJsonIOStrategy()
|
||||
new JsonIOStrategy(), new ModularizedJsonIOStrategy(),
|
||||
new YamlIOStrategy("yaml"), new YamlIOStrategy("yml"),
|
||||
new PropertiesIOStrategy()
|
||||
));
|
||||
|
||||
private final Project project;
|
||||
|
@ -66,7 +66,7 @@ public class JsonIOStrategy implements IOStrategy {
|
||||
|
||||
try {
|
||||
for(VirtualFile file : directory.getChildren()) {
|
||||
if(!isFileRelevant(state, file)) {
|
||||
if(file.isDirectory() || !isFileRelevant(state, file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -84,7 +84,7 @@ public class ModularizedJsonIOStrategy implements IOStrategy {
|
||||
|
||||
// Read all underlying module files
|
||||
for(VirtualFile module : localeDir.getChildren()) {
|
||||
if(module.isDirectory() || isFileRelevant(state, module)) {
|
||||
if(module.isDirectory() || !isFileRelevant(state, module)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,116 @@
|
||||
package de.marhali.easyi18n.io.properties;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
import de.marhali.easyi18n.io.IOStrategy;
|
||||
import de.marhali.easyi18n.model.SettingsState;
|
||||
import de.marhali.easyi18n.model.TranslationData;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Strategy for simple 'properties' locale files. Each locale has its own file.
|
||||
* For example localesPath/en.properties, localesPath/de.properties.
|
||||
* @author marhali
|
||||
*/
|
||||
public class PropertiesIOStrategy implements IOStrategy {
|
||||
|
||||
private static final String FILE_EXTENSION = "properties";
|
||||
|
||||
@Override
|
||||
public boolean canUse(@NotNull Project project, @NotNull String localesPath, @NotNull SettingsState state) {
|
||||
VirtualFile directory = LocalFileSystem.getInstance().findFileByIoFile(new File(localesPath));
|
||||
|
||||
if(directory == null || directory.getChildren() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(VirtualFile children : directory.getChildren()) {
|
||||
if(!children.isDirectory() && isFileRelevant(state, children)) {
|
||||
if(children.getFileType().getDefaultExtension().equalsIgnoreCase(FILE_EXTENSION)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(@NotNull Project project, @NotNull String localesPath,
|
||||
@NotNull SettingsState state, @NotNull Consumer<@Nullable TranslationData> result) {
|
||||
ApplicationManager.getApplication().saveAll(); // Save opened files (required if new locales were added)
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(() -> {
|
||||
VirtualFile directory = LocalFileSystem.getInstance().findFileByIoFile(new File(localesPath));
|
||||
|
||||
if(directory == null || directory.getChildren() == null) {
|
||||
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
||||
}
|
||||
|
||||
TranslationData data = new TranslationData(state.isSortKeys(), state.isNestedKeys());
|
||||
|
||||
try {
|
||||
for(VirtualFile file : directory.getChildren()) {
|
||||
if(file.isDirectory() || !isFileRelevant(state, file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String locale = file.getNameWithoutExtension();
|
||||
data.addLocale(locale);
|
||||
|
||||
SortableProperties properties = new SortableProperties(state.isSortKeys());
|
||||
properties.load(new InputStreamReader(file.getInputStream()));
|
||||
PropertiesMapper.read(locale, properties, data);
|
||||
}
|
||||
|
||||
result.accept(data);
|
||||
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
result.accept(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull Project project, @NotNull String localesPath,
|
||||
@NotNull SettingsState state, @NotNull TranslationData data, @NotNull Consumer<Boolean> result) {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
try {
|
||||
for(String locale : data.getLocales()) {
|
||||
SortableProperties properties = new SortableProperties(state.isSortKeys());
|
||||
PropertiesMapper.write(locale, properties, data);
|
||||
|
||||
File file = new File(localesPath + "/" + locale + "." + FILE_EXTENSION);
|
||||
boolean exists = file.createNewFile();
|
||||
|
||||
VirtualFile vf = exists
|
||||
? LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)
|
||||
: LocalFileSystem.getInstance().findFileByIoFile(file);
|
||||
|
||||
StringWriter writer = new StringWriter();
|
||||
properties.store(writer, null);
|
||||
|
||||
vf.setBinaryContent(writer.toString().getBytes(vf.getCharset()));
|
||||
}
|
||||
|
||||
result.accept(true);
|
||||
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
result.accept(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package de.marhali.easyi18n.io.properties;
|
||||
|
||||
import de.marhali.easyi18n.model.Translation;
|
||||
import de.marhali.easyi18n.model.TranslationData;
|
||||
import de.marhali.easyi18n.util.StringUtil;
|
||||
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Mapper for mapping properties files into translation nodes and backwards.
|
||||
* @author marhali
|
||||
*/
|
||||
public class PropertiesMapper {
|
||||
|
||||
// TODO: support array values
|
||||
|
||||
public static void read(String locale, SortableProperties properties, TranslationData data) {
|
||||
for(Map.Entry<Object, Object> entry : properties.entrySet()) {
|
||||
String key = String.valueOf(entry.getKey());
|
||||
String content = StringUtil.escapeControls(String.valueOf(entry.getValue()), true);
|
||||
|
||||
Translation translation = data.getTranslation(key);
|
||||
|
||||
if(translation == null) {
|
||||
translation = new Translation();
|
||||
}
|
||||
|
||||
translation.put(locale, content);
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(String locale, SortableProperties properties, TranslationData data) {
|
||||
for(String key : data.getFullKeys()) {
|
||||
Translation translation = data.getTranslation(key);
|
||||
|
||||
if(translation != null && translation.containsKey(locale)) {
|
||||
String content = StringEscapeUtils.unescapeJava(translation.get(locale));
|
||||
properties.put(key, content);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package de.marhali.easyi18n.io.properties;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Extends {@link Properties} class to support sorted or non-sorted keys.
|
||||
* @author marhali
|
||||
*/
|
||||
public class SortableProperties extends Properties {
|
||||
|
||||
private final transient Map<Object, Object> properties;
|
||||
|
||||
public SortableProperties(boolean sort) {
|
||||
this.properties = sort ? new TreeMap<>() : new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public Map<Object, Object> getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Object> keySet() {
|
||||
return Collections.unmodifiableSet(new TreeSet<>(super.keySet()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Map.Entry<Object, Object>> entrySet() {
|
||||
return this.properties.entrySet();
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized Object put(Object key, Object value) {
|
||||
return this.properties.put(key, value);
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package de.marhali.easyi18n.io.yaml;
|
||||
|
||||
import de.marhali.easyi18n.io.ArrayMapper;
|
||||
|
||||
import thito.nodeflow.config.ListSection;
|
||||
|
||||
/**
|
||||
* Map for yaml array values.
|
||||
* @author marhali
|
||||
*/
|
||||
public class YamlArrayMapper extends ArrayMapper {
|
||||
public static String read(ListSection list) {
|
||||
return read(list.iterator(), Object::toString);
|
||||
}
|
||||
|
||||
public static ListSection write(String concat) {
|
||||
ListSection list = new ListSection();
|
||||
write(concat, list::add);
|
||||
return list;
|
||||
}
|
||||
}
|
121
src/main/java/de/marhali/easyi18n/io/yaml/YamlIOStrategy.java
Normal file
121
src/main/java/de/marhali/easyi18n/io/yaml/YamlIOStrategy.java
Normal file
@ -0,0 +1,121 @@
|
||||
package de.marhali.easyi18n.io.yaml;
|
||||
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
|
||||
import de.marhali.easyi18n.io.IOStrategy;
|
||||
import de.marhali.easyi18n.model.SettingsState;
|
||||
import de.marhali.easyi18n.model.TranslationData;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import thito.nodeflow.config.MapSection;
|
||||
import thito.nodeflow.config.Section;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Strategy for simple yaml locale files. Each locale has its own file.
|
||||
* For example localesPath/en.y(a)ml, localesPath/de.y(a)ml
|
||||
* @author marhali
|
||||
*/
|
||||
public class YamlIOStrategy implements IOStrategy {
|
||||
|
||||
private final String FILE_EXTENSION;
|
||||
|
||||
public YamlIOStrategy(@NotNull String fileExtension) {
|
||||
this.FILE_EXTENSION = fileExtension;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(@NotNull Project project, @NotNull String localesPath, @NotNull SettingsState state) {
|
||||
VirtualFile directory = LocalFileSystem.getInstance().findFileByIoFile(new File(localesPath));
|
||||
|
||||
if(directory == null || directory.getChildren() == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for(VirtualFile children : directory.getChildren()) {
|
||||
if(!children.isDirectory() && isFileRelevant(state, children)) {
|
||||
if(children.getFileType().getDefaultExtension().equalsIgnoreCase(FILE_EXTENSION)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(@NotNull Project project, @NotNull String localesPath,
|
||||
@NotNull SettingsState state, @NotNull Consumer<@Nullable TranslationData> result) {
|
||||
ApplicationManager.getApplication().saveAll(); // Save opened files (required if new locales were added)
|
||||
|
||||
ApplicationManager.getApplication().runReadAction(() -> {
|
||||
VirtualFile directory = LocalFileSystem.getInstance().findFileByIoFile(new File(localesPath));
|
||||
|
||||
if(directory == null || directory.getChildren() == null) {
|
||||
throw new IllegalArgumentException("Specified folder is invalid (" + localesPath + ")");
|
||||
}
|
||||
|
||||
TranslationData data = new TranslationData(state.isSortKeys(), state.isNestedKeys());
|
||||
|
||||
try {
|
||||
for(VirtualFile file : directory.getChildren()) {
|
||||
if(file.isDirectory() || !isFileRelevant(state, file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String locale = file.getNameWithoutExtension();
|
||||
data.addLocale(locale);
|
||||
|
||||
try(Reader reader = new InputStreamReader(file.getInputStream())) {
|
||||
Section section = Section.parseToMap(reader);
|
||||
YamlMapper.read(locale, section, data.getRootNode());
|
||||
}
|
||||
}
|
||||
|
||||
result.accept(data);
|
||||
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
result.accept(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(@NotNull Project project, @NotNull String localesPath,
|
||||
@NotNull SettingsState state, @NotNull TranslationData data, @NotNull Consumer<Boolean> result) {
|
||||
ApplicationManager.getApplication().runWriteAction(() -> {
|
||||
try {
|
||||
for(String locale : data.getLocales()) {
|
||||
Section section = new MapSection();
|
||||
YamlMapper.write(locale, section, data.getRootNode());
|
||||
|
||||
File file = new File(localesPath + "/" + locale + "." + FILE_EXTENSION);
|
||||
boolean exists = file.createNewFile();
|
||||
|
||||
VirtualFile vf = exists
|
||||
? LocalFileSystem.getInstance().refreshAndFindFileByIoFile(file)
|
||||
: LocalFileSystem.getInstance().findFileByIoFile(file);
|
||||
|
||||
vf.setBinaryContent(Section.toString(section).getBytes(vf.getCharset()));
|
||||
}
|
||||
|
||||
result.accept(true);
|
||||
|
||||
} catch(IOException e) {
|
||||
e.printStackTrace();
|
||||
result.accept(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
71
src/main/java/de/marhali/easyi18n/io/yaml/YamlMapper.java
Normal file
71
src/main/java/de/marhali/easyi18n/io/yaml/YamlMapper.java
Normal file
@ -0,0 +1,71 @@
|
||||
package de.marhali.easyi18n.io.yaml;
|
||||
|
||||
import de.marhali.easyi18n.model.Translation;
|
||||
import de.marhali.easyi18n.model.TranslationNode;
|
||||
import de.marhali.easyi18n.util.StringUtil;
|
||||
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
|
||||
import thito.nodeflow.config.MapSection;
|
||||
import thito.nodeflow.config.Section;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Mapper for mapping yaml files into translation nodes and backwards.
|
||||
* @author marhali
|
||||
*/
|
||||
public class YamlMapper {
|
||||
|
||||
public static void read(String locale, Section section, TranslationNode node) {
|
||||
for(String key : section.getKeys()) {
|
||||
TranslationNode childNode = node.getOrCreateChildren(key);
|
||||
|
||||
if(section.getMap(key).isPresent()) {
|
||||
// Nested element - run recursively
|
||||
read(locale, section.getMap(key).get(), childNode);
|
||||
} else {
|
||||
Translation translation = childNode.getValue();
|
||||
|
||||
if(section.getList(key).isPresent() || section.getString(key).isPresent()) {
|
||||
String content = section.isList(key) && section.getList(key).isPresent()
|
||||
? YamlArrayMapper.read(section.getList(key).get())
|
||||
: StringUtil.escapeControls(section.getString(key).get(), true);
|
||||
|
||||
translation.put(locale, content);
|
||||
childNode.setValue(translation);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void write(String locale, Section section, TranslationNode node) {
|
||||
for(Map.Entry<String, TranslationNode> entry : node.getChildren().entrySet()) {
|
||||
String key = entry.getKey();
|
||||
TranslationNode childNode = entry.getValue();
|
||||
|
||||
if(!childNode.isLeaf()) {
|
||||
// Nested node - run recursively
|
||||
MapSection childSection = new MapSection();
|
||||
write(locale, childSection, childNode);
|
||||
if(childSection.size() > 0) {
|
||||
section.set(key, childSection);
|
||||
}
|
||||
} else {
|
||||
Translation translation = childNode.getValue();
|
||||
String content = translation.get(locale);
|
||||
|
||||
if(content != null) {
|
||||
if(YamlArrayMapper.isArray(content)) {
|
||||
section.set(key, YamlArrayMapper.write(content));
|
||||
} else if(NumberUtils.isNumber(content)) {
|
||||
section.set(key, NumberUtils.createNumber(content));
|
||||
} else {
|
||||
section.set(key, StringEscapeUtils.unescapeJava(content));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import thito.nodeflow.config.ListSection;
|
||||
* Utility methods to read and write yaml lists.
|
||||
* @author marhali
|
||||
*/
|
||||
@Deprecated
|
||||
public class YamlArrayUtil extends ArrayUtil {
|
||||
|
||||
public static String read(ListSection list) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user