diff --git a/src/main/java/run/halo/app/handler/theme/ThemeConfigResolvers.java b/src/main/java/run/halo/app/handler/theme/ThemeConfigResolvers.java new file mode 100644 index 000000000..cb6406e44 --- /dev/null +++ b/src/main/java/run/halo/app/handler/theme/ThemeConfigResolvers.java @@ -0,0 +1,71 @@ +package run.halo.app.handler.theme; + +import org.springframework.lang.NonNull; +import org.springframework.lang.Nullable; +import org.springframework.stereotype.Component; +import run.halo.app.handler.theme.impl.YamlThemeConfigResolverImpl; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Theme configuration resolver manager. + * + * @author johnniang + * @date 4/10/19 + */ +@Component +public class ThemeConfigResolvers { + + private final Map resolverMap = new ConcurrentHashMap<>(2); + + public ThemeConfigResolvers() { + resolverMap.put(ConfigType.YAML, new YamlThemeConfigResolverImpl()); + // TODO Add another theme config resolver + } + + /** + * Config type enum. + */ + public enum ConfigType { + + YAML, + + PROPERTY + } + + /** + * Resolves the content. + * + * @param content content must not be blank + * @param type config type + * @return a list of group + * @throws IOException throws when content conversion fails + */ + public List resolve(@NonNull String content, @Nullable ConfigType type) throws IOException { + ThemeConfigResolver resolver = getResolver(type); + + if (resolver == null) { + throw new UnsupportedOperationException("Unsupported theme config type: " + type); + } + + return resolver.resolve(content); + } + + /** + * Resolves the content. + * + * @param content content must not be blank + * @return a list of group + * @throws IOException throws when content conversion fails + */ + public List resolve(String content) throws IOException { + return resolve(content, ConfigType.YAML); + } + + private ThemeConfigResolver getResolver(@Nullable ConfigType type) { + return type == null ? null : resolverMap.get(type); + } +} diff --git a/src/main/java/run/halo/app/handler/theme/impl/YamlThemeConfigResolverImpl.java b/src/main/java/run/halo/app/handler/theme/impl/YamlThemeConfigResolverImpl.java index 87e4f5ea9..718f9802b 100644 --- a/src/main/java/run/halo/app/handler/theme/impl/YamlThemeConfigResolverImpl.java +++ b/src/main/java/run/halo/app/handler/theme/impl/YamlThemeConfigResolverImpl.java @@ -3,7 +3,6 @@ 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.Group; import run.halo.app.handler.theme.Item; import run.halo.app.handler.theme.Option; @@ -23,7 +22,6 @@ import java.util.Map; * @author johnniang * @date 4/10/19 */ -@Component public class YamlThemeConfigResolverImpl implements ThemeConfigResolver { private final ObjectMapper yamlMapper = new ObjectMapper(new YAMLFactory()); diff --git a/src/main/java/run/halo/app/service/ThemeService.java b/src/main/java/run/halo/app/service/ThemeService.java index 4c225c2f2..0bd5699ac 100644 --- a/src/main/java/run/halo/app/service/ThemeService.java +++ b/src/main/java/run/halo/app/service/ThemeService.java @@ -2,6 +2,7 @@ package run.halo.app.service; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; +import run.halo.app.handler.theme.Group; import run.halo.app.model.support.ThemeFile; import run.halo.app.model.support.ThemeProperty; @@ -164,10 +165,10 @@ public interface ThemeService { * Fetches theme configuration. * * @param themeId must not be blank - * @return theme configuration or null if not found + * @return theme configuration */ - @Nullable - Object fetchConfig(@NonNull String themeId); + @NonNull + List fetchConfig(@NonNull String themeId); /** * Renders a theme page. diff --git a/src/main/java/run/halo/app/service/impl/ThemeServiceImpl.java b/src/main/java/run/halo/app/service/impl/ThemeServiceImpl.java index cf0867a41..7b69dccc2 100644 --- a/src/main/java/run/halo/app/service/impl/ThemeServiceImpl.java +++ b/src/main/java/run/halo/app/service/impl/ThemeServiceImpl.java @@ -21,6 +21,8 @@ import run.halo.app.exception.BadRequestException; import run.halo.app.exception.ForbiddenException; import run.halo.app.exception.NotFoundException; import run.halo.app.exception.ServiceException; +import run.halo.app.handler.theme.Group; +import run.halo.app.handler.theme.ThemeConfigResolvers; import run.halo.app.model.properties.PrimaryProperties; import run.halo.app.model.support.HaloConst; import run.halo.app.model.support.ThemeFile; @@ -60,22 +62,23 @@ public class ThemeServiceImpl implements ThemeService { */ private String activatedThemeId; - private final ObjectMapper yamlMapper; - private final OptionService optionService; private final StringCacheStore cacheStore; private final Configuration configuration; + private final ThemeConfigResolvers resolvers; + public ThemeServiceImpl(HaloProperties haloProperties, OptionService optionService, StringCacheStore cacheStore, - Configuration configuration) { + Configuration configuration, + ThemeConfigResolvers resolvers) { this.optionService = optionService; this.cacheStore = cacheStore; this.configuration = configuration; - yamlMapper = new ObjectMapper(new YAMLFactory()); + this.resolvers = resolvers; workDir = Paths.get(haloProperties.getWorkDir(), THEME_FOLDER); } @@ -224,15 +227,15 @@ public class ThemeServiceImpl implements ThemeService { } @Override - public Object fetchConfig(String themeId) { + public List fetchConfig(String themeId) { Assert.hasText(themeId, "Theme name must not be blank"); // Get theme property ThemeProperty themeProperty = getThemeOfNonNullBy(themeId); if (!themeProperty.isHasOptions()) { - // If this theme dose not has an option, then return null - return null; + // If this theme dose not has an option, then return empty list + return Collections.emptyList(); } try { @@ -247,14 +250,15 @@ public class ThemeServiceImpl implements ThemeService { continue; } - // Read the yaml file and return the object value - return yamlMapper.readValue(optionsPath.toFile(), Object.class); + // Read the yaml file + String optionContent = new String(Files.readAllBytes(optionsPath)); + // Resolve it + return resolvers.resolve(optionContent); } - return null; + return Collections.emptyList(); } catch (IOException e) { - log.error("Failed to read options.yaml", e); - return null; + throw new ServiceException("Failed to read options file", e); } } diff --git a/src/main/java/run/halo/app/web/controller/admin/api/ThemeController.java b/src/main/java/run/halo/app/web/controller/admin/api/ThemeController.java index 40401e0fc..e03931c2b 100644 --- a/src/main/java/run/halo/app/web/controller/admin/api/ThemeController.java +++ b/src/main/java/run/halo/app/web/controller/admin/api/ThemeController.java @@ -2,6 +2,7 @@ package run.halo.app.web.controller.admin.api; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.*; +import run.halo.app.handler.theme.Group; import run.halo.app.model.support.BaseResponse; import run.halo.app.model.support.ThemeFile; import run.halo.app.model.support.ThemeProperty; @@ -97,8 +98,8 @@ public class ThemeController { @GetMapping("{themeId}/configurations") @ApiOperation("Fetches theme configuration by theme id") - public BaseResponse fetchConfig(@PathVariable("themeId") String themeId) { - return BaseResponse.ok(themeService.fetchConfig(themeId)); + public List fetchConfig(@PathVariable("themeId") String themeId) { + return themeService.fetchConfig(themeId); } @PostMapping("{themeId}/settings")