79 lines
2.4 KiB
Python
79 lines
2.4 KiB
Python
|
def is_node(value):
|
||
|
return value in ("node", "element")
|
||
|
|
||
|
|
||
|
def is_shape(value):
|
||
|
return value in ("shape", "exact")
|
||
|
|
||
|
|
||
|
def collect_array(a_value, base, nodes):
|
||
|
a_type = a_value["name"]
|
||
|
if is_node(a_type):
|
||
|
nodes.append(base)
|
||
|
elif a_type in ("shape", "exact"):
|
||
|
nodes = collect_nodes(a_value["value"], base + "[]", nodes)
|
||
|
elif a_type == "union":
|
||
|
nodes = collect_union(a_value["value"], base + "[]", nodes)
|
||
|
elif a_type == "objectOf":
|
||
|
nodes = collect_object(a_value["value"], base + "[]", nodes)
|
||
|
return nodes
|
||
|
|
||
|
|
||
|
def collect_union(type_list, base, nodes):
|
||
|
for t in type_list:
|
||
|
if is_node(t["name"]):
|
||
|
nodes.append(base)
|
||
|
elif is_shape(t["name"]):
|
||
|
nodes = collect_nodes(t["value"], base, nodes)
|
||
|
elif t["name"] == "arrayOf":
|
||
|
nodes = collect_array(t["value"], base, nodes)
|
||
|
elif t["name"] == "objectOf":
|
||
|
nodes = collect_object(t["value"], base, nodes)
|
||
|
return nodes
|
||
|
|
||
|
|
||
|
def collect_object(o_value, base, nodes):
|
||
|
o_name = o_value.get("name")
|
||
|
o_key = base + "{}"
|
||
|
if is_node(o_name):
|
||
|
nodes.append(o_key)
|
||
|
elif is_shape(o_name):
|
||
|
nodes = collect_nodes(o_value.get("value", {}), o_key, nodes)
|
||
|
elif o_name == "union":
|
||
|
nodes = collect_union(o_value.get("value"), o_key, nodes)
|
||
|
elif o_name == "arrayOf":
|
||
|
nodes = collect_array(o_value, o_key, nodes)
|
||
|
return nodes
|
||
|
|
||
|
|
||
|
def collect_nodes(metadata, base="", nodes=None):
|
||
|
nodes = nodes or []
|
||
|
|
||
|
for prop_name, value in metadata.items():
|
||
|
# Support for recursive shapes, the type is directly in the field.
|
||
|
t_value = value.get("type", value)
|
||
|
p_type = t_value.get("name")
|
||
|
|
||
|
if base:
|
||
|
key = f"{base}.{prop_name}"
|
||
|
else:
|
||
|
key = prop_name
|
||
|
if is_node(p_type):
|
||
|
nodes.append(key)
|
||
|
elif p_type == "arrayOf":
|
||
|
a_value = t_value.get("value", t_value)
|
||
|
nodes = collect_array(a_value, key, nodes)
|
||
|
elif is_shape(p_type):
|
||
|
nodes = collect_nodes(t_value["value"], key, nodes)
|
||
|
elif p_type == "union":
|
||
|
nodes = collect_union(t_value["value"], key, nodes)
|
||
|
elif p_type == "objectOf":
|
||
|
o_value = t_value.get("value", {})
|
||
|
nodes = collect_object(o_value, key, nodes)
|
||
|
|
||
|
return nodes
|
||
|
|
||
|
|
||
|
def filter_base_nodes(nodes):
|
||
|
return [n for n in nodes if not any(e in n for e in ("[]", ".", "{}"))]
|