Complete yaml theme configuration resolver

pull/146/head
johnniang 2019-04-10 11:53:22 +08:00
parent f72be35337
commit e84025e9e3
3 changed files with 236 additions and 199 deletions

View File

@ -1,12 +1,25 @@
package run.halo.app.handler.theme; package run.halo.app.handler.theme;
import org.springframework.lang.NonNull;
import java.io.IOException;
import java.util.List;
/** /**
* Theme configuration resolver. * Theme config resolver interface.
* *
* @author johnniang * @author johnniang
* @date 4/10/19 * @date 4/10/19
*/ */
public class ThemeConfigResolver { public interface ThemeConfigResolver {
/**
* Resolves content as tab.
*
* @param content content must not be blank
* @return a list of tab
* @throws IOException throws when content conversion fails
*/
@NonNull
List<Tab> resolve(@NonNull String content) throws IOException;
} }

View File

@ -0,0 +1,201 @@
package run.halo.app.handler.theme.impl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;
import run.halo.app.handler.theme.Item;
import run.halo.app.handler.theme.Option;
import run.halo.app.handler.theme.Tab;
import run.halo.app.handler.theme.ThemeConfigResolver;
import run.halo.app.model.enums.DataType;
import run.halo.app.model.enums.InputType;
import java.io.IOException;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
/**
* Theme configuration resolver.
*
* @author johnniang
* @date 4/10/19
*/
@Component
public class YamlThemeConfigResolverImpl implements ThemeConfigResolver {
private final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory());
@Override
public List<Tab> resolve(String content) throws IOException {
return handleTabs(yamlMapper.readValue(content, Object.class));
}
@SuppressWarnings("unchecked")
private List<Tab> handleTabs(@Nullable Object config) {
List<Tab> tabs = new LinkedList<>();
if (config instanceof List) {
List configList = (List) config;
// Resolve tab
configList.forEach(tabYaml -> {
// tabYaml should be map
if (!(tabYaml instanceof Map)) {
return;
}
Map tabMap = ((Map) tabYaml);
Tab tab = new Tab();
tab.setName(tabMap.get("name").toString());
tab.setLabel(tabMap.get("label").toString());
// Handle items
tab.setItems(handleItems(tabMap.get("items")));
tabs.add(tab);
});
} else if (config instanceof Map) {
Map configMap = (Map) config;
configMap.forEach((key, value) -> {
// key: tab name
// value: tab property, should be a map
if (!(value instanceof Map)) {
return;
}
Map tabMap = (Map) value;
Tab tab = new Tab();
tab.setName(key.toString());
tab.setLabel(tabMap.get("label").toString());
// Handle items
tab.setItems(handleItems(tabMap.get("items")));
tabs.add(tab);
});
}
return tabs;
}
@SuppressWarnings("unchecked")
private List<Item> handleItems(@Nullable Object items) {
if (items == null) {
return Collections.emptyList();
}
List<Item> result = new LinkedList<>();
if (items instanceof List) {
((List) items).forEach(itemYaml -> {
if (!(itemYaml instanceof Map)) {
return;
}
// Should be Map
Map itemMap = (Map) itemYaml;
// Build item
Item item = new Item();
item.setName(itemMap.get("name").toString());
item.setLabel(itemMap.getOrDefault("label", item.getName()).toString());
item.setDataType(DataType.typeOf(itemMap.get("data_type")));
item.setType(InputType.typeOf(itemMap.get("type")));
item.setDefaultValue(itemMap.get("default"));
// Handle options
item.setOptions(handleOptions(itemMap.get("options")));
// Add item
result.add(item);
});
} else if (items instanceof Map) {
Map itemsMap = (Map) items;
itemsMap.forEach((key, value) -> {
if (!(value instanceof Map)) {
return;
}
Map itemMap = (Map) value;
// key: item name
Item item = new Item();
item.setName(key.toString());
item.setLabel(itemMap.getOrDefault("label", item.getName()).toString());
item.setDataType(DataType.typeOf(itemMap.get("data_type")));
item.setType(InputType.typeOf(itemMap.get("type")));
item.setDefaultValue(itemMap.get("default"));
// Handle options
item.setOptions(handleOptions(itemMap.get("options")));
// Add item
result.add(item);
});
}
return result;
}
@SuppressWarnings("unchecked")
private List<Option> handleOptions(@Nullable Object options) {
if (options == null) {
return Collections.emptyList();
}
List<Option> result = new LinkedList<>();
if (options instanceof List) {
((List) options).forEach(optionYaml -> {
// optionYaml should be Map
if (!(optionYaml instanceof Map)) {
return;
}
Map optionMap = (Map) optionYaml;
// Build option
Option option = new Option();
// TODO Convert the value type
option.setValue(optionMap.get("value"));
option.setLabel(optionMap.get("label").toString());
result.add(option);
});
} else if (options instanceof Map) {
Map optionsMap = (Map) options;
optionsMap.forEach((key, value) -> {
// key: option value
// value: Map that contains option label
if (!(value instanceof Map)) {
return;
}
Map optionMap = (Map) value;
Option option = new Option();
// TODO Convert the value type
option.setValue(key);
option.setLabel(optionMap.get("label").toString());
result.add(option);
});
}
return result;
}
}

View File

@ -1,17 +1,14 @@
package run.halo.app.utils; package run.halo.app.utils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.junit.Test; import org.junit.Test;
import org.springframework.lang.Nullable;
import run.halo.app.handler.theme.Item;
import run.halo.app.handler.theme.Option;
import run.halo.app.handler.theme.Tab; import run.halo.app.handler.theme.Tab;
import run.halo.app.model.enums.DataType; import run.halo.app.handler.theme.impl.YamlThemeConfigResolverImpl;
import run.halo.app.model.enums.InputType;
import java.io.IOException; import java.io.IOException;
import java.util.*; import java.util.List;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertThat;
/** /**
* Yaml test. * Yaml test.
@ -21,9 +18,7 @@ import java.util.*;
*/ */
public class YamlTest { public class YamlTest {
private final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); private final YamlThemeConfigResolverImpl resolver = new YamlThemeConfigResolverImpl();
private final ObjectMapper jsonMapper = new ObjectMapper();
@Test @Test
public void readYamlTest() throws IOException { public void readYamlTest() throws IOException {
@ -67,11 +62,11 @@ public class YamlTest {
" - value: false\n" + " - value: false\n" +
" label: 关闭"; " label: 关闭";
LinkedHashMap config = yamlMapper.readValue(yaml, LinkedHashMap.class); List<Tab> tabs = resolver.resolve(yaml);
System.out.println(config.getClass()); assertThat(tabs.size(), equalTo(2));
assertThat(tabs.get(0).getItems().size(), equalTo(3));
System.out.println(jsonMapper.writeValueAsString(config)); assertThat(tabs.get(1).getItems().size(), equalTo(2));
} }
@Test @Test
@ -123,15 +118,12 @@ public class YamlTest {
" - value: false\n" + " - value: false\n" +
" label: 关闭\n"; " label: 关闭\n";
Object config = yamlMapper.readValue(yaml, Object.class);
List<Tab> tabs = handleTabs(config); List<Tab> tabs = resolver.resolve(yaml);
System.out.println(config.getClass()); assertThat(tabs.size(), equalTo(2));
assertThat(tabs.get(0).getItems().size(), equalTo(4));
System.out.println(tabs); assertThat(tabs.get(1).getItems().size(), equalTo(3));
System.out.println(jsonMapper.writeValueAsString(config));
} }
@Test @Test
@ -182,181 +174,12 @@ public class YamlTest {
" - value: false\n" + " - value: false\n" +
" label: 关闭"; " label: 关闭";
List<Tab> tabs = resolver.resolve(yaml);
Object config = yamlMapper.readValue(yaml, Object.class); assertThat(tabs.size(), equalTo(2));
assertThat(tabs.get(0).getItems().size(), equalTo(4));
List<Tab> tabs = handleTabs(config); assertThat(tabs.get(1).getItems().size(), equalTo(3));
assertThat(tabs.get(0).getItems().get(0).getOptions().size(), equalTo(2));
System.out.println(config.getClass());
System.out.print(tabs);
}
@SuppressWarnings("unchecked")
private List<Tab> handleTabs(@Nullable Object config) {
List<Tab> tabs = new LinkedList<>();
if (config instanceof List) {
List configList = (List) config;
// Resolve tab
configList.forEach(tabYaml -> {
// tabYaml should be map
if (!(tabYaml instanceof Map)) {
return;
}
Map tabMap = ((Map) tabYaml);
Tab tab = new Tab();
tab.setName(tabMap.get("name").toString());
tab.setLabel(tabMap.get("label").toString());
// Handle items
tab.setItems(handleItems(tabMap.get("items")));
tabs.add(tab);
});
} else if (config instanceof Map) {
Map configMap = (Map) config;
configMap.forEach((key, value) -> {
// key: tab name
// value: tab property, should be a map
if (!(value instanceof Map)) {
return;
}
Map tabMap = (Map) value;
Tab tab = new Tab();
tab.setName(key.toString());
tab.setLabel(tabMap.get("label").toString());
// Handle items
tab.setItems(handleItems(tabMap.get("items")));
tabs.add(tab);
});
}
return tabs;
}
@SuppressWarnings("unchecked")
private List<Item> handleItems(@Nullable Object items) {
if (items == null) {
return Collections.emptyList();
}
List<Item> result = new LinkedList<>();
if (items instanceof List) {
((List) items).forEach(itemYaml -> {
if (!(itemYaml instanceof Map)) {
return;
}
// Should be Map
Map itemMap = (Map) itemYaml;
// Build item
Item item = new Item();
item.setName(itemMap.get("name").toString());
item.setLabel(itemMap.getOrDefault("label", item.getName()).toString());
item.setDataType(DataType.typeOf(itemMap.get("data_type")));
item.setType(InputType.typeOf(itemMap.get("type")));
item.setDefaultValue(itemMap.get("default"));
// Handle options
item.setOptions(handleOptions(itemMap.get("options")));
// Add item
result.add(item);
});
} else if (items instanceof Map) {
Map itemsMap = (Map) items;
itemsMap.forEach((key, value) -> {
if (!(value instanceof Map)) {
return;
}
Map itemMap = (Map) value;
// key: item name
Item item = new Item();
item.setName(key.toString());
item.setLabel(itemMap.getOrDefault("label", item.getName()).toString());
item.setDataType(DataType.typeOf(itemMap.get("data_type")));
item.setType(InputType.typeOf(itemMap.get("type")));
item.setDefaultValue(itemMap.get("default"));
// Handle options
item.setOptions(handleOptions(itemMap.get("options")));
// Add item
result.add(item);
});
}
return result;
}
@SuppressWarnings("unchecked")
private List<Option> handleOptions(@Nullable Object options) {
if (options == null) {
return Collections.emptyList();
}
List<Option> result = new LinkedList<>();
if (options instanceof List) {
((List) options).forEach(optionYaml -> {
// optionYaml should be Map
if (!(optionYaml instanceof Map)) {
return;
}
Map optionMap = (Map) optionYaml;
// Build option
Option option = new Option();
// TODO Convert the value type
option.setValue(optionMap.get("value"));
option.setLabel(optionMap.get("label").toString());
result.add(option);
});
} else if (options instanceof Map) {
Map optionsMap = (Map) options;
optionsMap.forEach((key, value) -> {
// key: option value
// value: Map that contains option label
if (!(value instanceof Map)) {
return;
}
Map optionMap = (Map) value;
Option option = new Option();
// TODO Convert the value type
option.setValue(key);
option.setLabel(optionMap.get("label").toString());
result.add(option);
});
}
return result;
} }
} }