Current section
Files
Jump to
Current section
Files
src/embryo.erl
%%%-------------------------------------------------------------------
%%% @doc
%%% `embryo' - Library for managing Emergence configuration and embryo objects
%%%
%%% This module provides functions to:
%%% - Create and manipulate embryo objects
%%% - Read Emergence configuration files
%%% - Retrieve URLs from the discovery service
%%% - Merge lists of embryos
%%%
%%% @author Steve Roques
%%% @version 0.1.3
%%% @end
%%%-------------------------------------------------------------------
-module(embryo).
-include("src/embryo.hrl").
%% Public API
-export([new/1, to_map/1, merge_lists_by_url/2, read_emergence_conf/0, get_em_disco_url/0]).
%%====================================================================
%% API Functions
%%====================================================================
-spec new(map()) -> embryo().
new(Properties) ->
#embryo{properties = Properties}.
-spec to_map(embryo()) -> map().
to_map(#embryo{properties = Properties}) ->
#{properties => Properties}.
-spec read_emergence_conf() -> config_map() | undefined.
read_emergence_conf() ->
ConfigPath = get_config_path(),
case ConfigPath of
undefined -> undefined;
Path ->
case filelib:is_file(Path) of
true -> read_file(Path);
false -> undefined
end
end.
-spec get_em_disco_url() -> string().
get_em_disco_url() ->
case os:getenv("server_url") of
false ->
ConfigMap = read_emergence_conf(),
get_url_from_config(ConfigMap);
Url -> Url
end.
-spec merge_lists_by_url([embryo()], [embryo()]) -> [embryo()].
merge_lists_by_url(UriList, OtherList) ->
CombinedList = UriList ++ OtherList,
{Result, _} = lists:foldl(fun merge_embryo/2, {[], sets:new()}, CombinedList),
lists:reverse(Result).
%%====================================================================
%% Internal Functions
%%====================================================================
-spec get_config_path() -> string() | undefined.
get_config_path() ->
case os:getenv("HOME") of
false ->
case os:getenv("APPDATA") of
false -> undefined;
AppData -> filename:join([AppData, "emergence", "emergence.conf"])
end;
Home ->
case os:type() of
{unix, _} -> filename:join([Home, ".config", "emergence", "emergence.conf"]);
{win32, _} -> filename:join([Home, "AppData", "Roaming", "emergence", "emergence.conf"])
end
end.
-spec read_file(string()) -> map().
read_file(Path) ->
case file:read_file(Path) of
{ok, Binary} ->
Lines = binary:split(Binary, <<"\n">>, [global, trim_all]),
parse_config_lines(Lines, #{}, "");
{error, _} ->
#{}
end.
-spec parse_config_lines([binary()], map(), string()) -> map().
parse_config_lines([], Map, _) -> Map;
parse_config_lines([Line|Rest], Map, CurrentSection) ->
case Line of
<<"[", Rest1/binary>> ->
Section = string:trim(binary_to_list(binary:part(Rest1, 0, byte_size(Rest1)-1)), both, "]"),
parse_config_lines(Rest, Map#{Section => #{}}, Section);
<<>> ->
parse_config_lines(Rest, Map, CurrentSection);
_ ->
case binary:split(Line, <<"=">>) of
[Key, Value] ->
TrimmedKey = string:trim(binary_to_list(Key)),
TrimmedValue = string:trim(binary_to_list(Value)),
NewMap = case maps:get(CurrentSection, Map, undefined) of
undefined -> Map;
SectionMap ->
Map#{CurrentSection => SectionMap#{TrimmedKey => TrimmedValue}}
end,
parse_config_lines(Rest, NewMap, CurrentSection);
_ ->
parse_config_lines(Rest, Map, CurrentSection)
end
end.
-spec get_url_from_config(map() | undefined) -> string().
get_url_from_config(undefined) -> "http://localhost:8080";
get_url_from_config(ConfigMap) ->
case maps:get("em_disco", ConfigMap, undefined) of
undefined -> "http://localhost:8080";
EmDisco ->
maps:get("server_url", EmDisco, "http://localhost:8080")
end.
-spec merge_embryo(embryo(), {[embryo()], sets:set()}) -> {[embryo()], sets:set()}.
merge_embryo(Embryo, {Acc, Seen}) ->
Properties = Embryo#embryo.properties,
case maps:get(<<"url">>, Properties, undefined) of
undefined ->
{[Embryo | Acc], Seen};
Url ->
case sets:is_element(Url, Seen) of
true -> {Acc, Seen};
false -> {[Embryo | Acc], sets:add_element(Url, Seen)}
end
end.