defmodule RedisGraph.Util do
@moduledoc "Provides utility functions for RedisGraph modules."
@doc """
Generate a random string of characters `a-z` of length `n`.
This is used to create a random alias for a node or relationship if one is not already set.
"""
@spec random_string(pos_integer()) :: String.t()
def random_string(n \\ 10) do
1..n
|> Enum.reduce("", fn _, acc -> acc <> to_string(Enum.take_random(?a..?z, 1)) end)
end
@doc """
Converts properties map into string representation. Otherwise returns empty string.
This is used to serialize edisGraph.Node or RedisGraph.Relationship properties
into strings when preparing redisgraph queries.
## Example
```
alias RedisGraph.{Node, Util}
bob = Node.new(%{
alias: :n,
labels: ["person"],
properties: %{
name: "Bob Thomsen",
age: 22
}
})
bob_properties = Util.properties_to_string(bob.properties)
```
"""
@spec properties_to_string(map() | any()) :: String.t()
def properties_to_string(properties) do
props =
if is_map(properties) and map_size(properties) > 0 do
Stream.map(properties, fn {k, x} -> "#{k}: #{value_to_string(x)}" end)
|> Enum.join(", ")
else
""
end
case String.length(props) do
0 -> ""
_ -> " {#{props}}"
end
end
@doc """
Converts labels list into string representation. Otherwise returns empty string.
This is used to serialize RedisGraph.Node labels into strings when preparing redisgraph queries.
## Example
```
alias RedisGraph.{Node, Util}
bob = Node.new(%{
alias: :n,
labels: ["person", "student"],
properties: %{
name: "Bob Thomsen",
age: 22
}
})
bob_labels = Util.labels_to_string(bob.labels)
```
"""
@spec labels_to_string(list(String.t()) | any()) :: String.t()
def labels_to_string(labels) do
if is_list(labels) and length(labels) > 0 do
":" <> Enum.join(labels, ":")
else
""
end
end
@doc """
Converts labels list into string representation. Otherwise returns empty string.
This is used to serialize RedisGraph.Node labels into strings when preparing redisgraph queries.
## Example
```
alias RedisGraph.{Relationship, Util}
relationship = Relationship.new(%{
src_node: 1,
dest_node: 2,
type: "friend",
properties: %{
best_friend: true
}
})
relationship_type = Util.type_to_string(relationship.type)
```
"""
@spec type_to_string(list(String.t()) | any()) :: String.t()
def type_to_string(type) do
if is_binary(type) and String.length(type) > 0 do
":" <> type
else
""
end
end
@doc """
Converts received value into string representation.
This is used to serialize value into strings when preparing redisgraph queries.
## Example
```
alias RedisGraph.{Node, Util}
list_to_string = Util.value_to_string(["test", 11, 12.12, false, nil, ["hi", "bye"], %{me: "you"}])
```
"""
@spec value_to_string(any()) :: String.t()
def value_to_string(val) do
cond do
# check if string contains function
is_binary(val) and String.contains?(val, "(") and String.contains?(val, ")") ->
val
is_binary(val) and String.length(val) > 0 ->
"'" <> val <> "'"
is_number(val) ->
"#{val}"
is_boolean(val) ->
"#{val}"
is_nil(val) ->
"null"
is_atom(val) ->
Atom.to_string(val)
is_list(val) ->
"[#{Stream.map(val, fn individual_value -> value_to_string(individual_value) end) |> Enum.join(", ")}]"
is_map(val) ->
"{#{Stream.map(val, fn {k, x} -> "#{k}: #{value_to_string(x)}" end) |> Enum.join(", ")}}"
true ->
"#{val}"
end
end
end