Skip to content

Commit

Permalink
Support @deprecated, source, and references in enum items (#117)
Browse files Browse the repository at this point in the history
* Schema issue #1227: add support for @deprecated and references in enum items

* Support source in enum values

* Add validation support for deprecated enum values in the v2 validate APIs
  • Loading branch information
rmouritzen-splunk authored Nov 1, 2024
1 parent 45ccdb4 commit 0b24bc7
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 46 deletions.
110 changes: 102 additions & 8 deletions lib/schema/validator2.ex
Original file line number Diff line number Diff line change
Expand Up @@ -686,10 +686,10 @@ defmodule Schema.Validator2 do
value_atom = String.to_atom(value_str)

if Map.has_key?(attribute_details[:enum], value_atom) do
# The enum array value is good - check sibling
# The enum array value is good - check sibling and deprecation
response =
validate_enum_array_sibling(
response,
response
|> validate_enum_array_sibling(
event_item,
parent_attribute_path,
index,
Expand All @@ -698,6 +698,14 @@ defmodule Schema.Validator2 do
attribute_name,
attribute_details
)
|> validate_enum_array_value_deprecated(
parent_attribute_path,
index,
value,
value_atom,
attribute_name,
attribute_details
)

{response, index + 1}
else
Expand All @@ -709,7 +717,7 @@ defmodule Schema.Validator2 do
add_error(
response,
"attribute_enum_array_value_unknown",
"Unknown enum array value at \"#{attribute_path}\"; array value" <>
"Unknown enum array value at \"#{attribute_path}\"; value" <>
" #{inspect(value)} is not defined for enum \"#{attribute_name}\".",
%{
attribute_path: attribute_path,
Expand All @@ -732,16 +740,23 @@ defmodule Schema.Validator2 do
value_atom = String.to_atom(value_str)

if Map.has_key?(attribute_details[:enum], value_atom) do
# The enum value is good - check sibling
validate_enum_sibling(
response,
# The enum value is good - check sibling and deprecation
response
|> validate_enum_sibling(
event_item,
parent_attribute_path,
value,
value_atom,
attribute_name,
attribute_details
)
|> validate_enum_value_deprecated(
parent_attribute_path,
value,
value_atom,
attribute_name,
attribute_details
)
else
attribute_path = make_attribute_path(parent_attribute_path, attribute_name)

Expand Down Expand Up @@ -912,6 +927,85 @@ defmodule Schema.Validator2 do
end
end

@spec validate_enum_value_deprecated(
map(),
nil | String.t(),
any(),
atom(),
String.t(),
map()
) :: map()
defp validate_enum_value_deprecated(
response,
parent_attribute_path,
event_enum_value,
event_enum_value_atom,
attribute_name,
attribute_details
) do
if Map.has_key?(attribute_details[:enum][event_enum_value_atom], :"@deprecated") do
attribute_path = make_attribute_path(parent_attribute_path, attribute_name)
deprecated = attribute_details[:enum][event_enum_value_atom][:"@deprecated"]

add_warning(
response,
"attribute_enum_value_deprecated",
"Deprecated enum value at \"#{attribute_path}\";" <>
" value #{inspect(event_enum_value)} is deprecated. #{deprecated[:message]}",
%{
attribute_path: attribute_path,
attribute: attribute_name,
value: event_enum_value,
since: deprecated[:since]
}
)
else
response
end
end

@spec validate_enum_array_value_deprecated(
map(),
nil | String.t(),
integer(),
any(),
atom(),
String.t(),
map()
) :: map()
defp validate_enum_array_value_deprecated(
response,
parent_attribute_path,
index,
event_enum_value,
event_enum_value_atom,
attribute_name,
attribute_details
) do
if Map.has_key?(attribute_details[:enum][event_enum_value_atom], :"@deprecated") do
attribute_path =
make_attribute_path(parent_attribute_path, attribute_name)
|> make_attribute_path_array_element(index)

deprecated = attribute_details[:enum][event_enum_value_atom][:"@deprecated"]

add_warning(
response,
"attribute_enum_array_value_deprecated",
"Deprecated enum array value at \"#{attribute_path}\";" <>
" value #{inspect(event_enum_value)} is deprecated. #{deprecated[:message]}",
%{
attribute_path: attribute_path,
attribute: attribute_name,
value: event_enum_value,
since: deprecated[:since]
}
)
else
response
end
end

@spec validate_attribute(
map(),
any(),
Expand Down Expand Up @@ -1800,7 +1894,7 @@ defmodule Schema.Validator2 do
add_warning(
response,
"class_deprecated",
"Class \"#{class[:name]}\" uid #{class[:uid]}, is deprecated. #{deprecated[:message]}",
"Class \"#{class[:name]}\" uid #{class[:uid]} is deprecated. #{deprecated[:message]}",
%{class_uid: class[:uid], class_name: class[:name], since: deprecated[:since]}
)
end
Expand Down
69 changes: 39 additions & 30 deletions lib/schema_web/views/page_view.ex
Original file line number Diff line number Diff line change
Expand Up @@ -470,32 +470,7 @@ defmodule SchemaWeb.PageView do

@spec format_desc(String.t() | atom(), map()) :: any
def format_desc(key, obj) do
source = obj[:source]
references = obj[:references]

source_html =
if source != nil do
# source can have embedded markup
["<dt>Source<dd class=\"ml-3\">", source]
else
""
end

refs_html =
if references != nil and !Enum.empty?(references) do
[
"<dt>References",
Enum.map(references, fn ref -> ["<dd class=\"ml-3\">", reference_anchor(ref)] end)
]
else
""
end

if source_html != "" or refs_html != "" do
[base_format_desc(key, obj), "<p><hr><dd>", source_html, refs_html, "</dd>"]
else
base_format_desc(key, obj)
end
append_source_references(base_format_desc(key, obj), "<p><hr>", obj)
end

@spec base_format_desc(String.t() | atom(), map()) :: any
Expand Down Expand Up @@ -529,7 +504,6 @@ defmodule SchemaWeb.PageView do
[],
fn {id, item}, acc ->
id = to_string(id)
desc = Map.get(item, :description) || ""

[
"<tr class='bg-transparent'><td style='width: 25px' class='text-right' id='",
Expand All @@ -541,7 +515,7 @@ defmodule SchemaWeb.PageView do
"</code></td><td class='textnowrap'>",
Map.get(item, :caption, id),
"<div class='text-secondary'>",
desc,
append_source_references(description(item), item),
"</div></td><tr>" | acc
]
end
Expand All @@ -551,6 +525,41 @@ defmodule SchemaWeb.PageView do
end
end

@spec append_source_references(any(), map()) :: any()
defp append_source_references(html, obj) do
append_source_references(html, "", obj)
end

@spec append_source_references(any(), any(), map()) :: any()
defp append_source_references(html, prefix_html, obj) do
source = obj[:source]
references = obj[:references]

source_html =
if source != nil do
# source can have embedded markup
["<dt>Source<dd class=\"ml-3\">", source]
else
""
end

refs_html =
if references != nil and !Enum.empty?(references) do
[
"<dt>References",
Enum.map(references, fn ref -> ["<dd class=\"ml-3\">", reference_anchor(ref)] end)
]
else
""
end

if source_html != "" or refs_html != "" do
[html, prefix_html, "<dd>", source_html, refs_html, "</dd>"]
else
html
end
end

def constraints(rules) do
Enum.reduce(rules, [], fn {name, list}, acc ->
constraints(name, list, acc)
Expand Down Expand Up @@ -1180,12 +1189,12 @@ defmodule SchemaWeb.PageView do
end

defp deprecated(map, nil) do
Map.get(map, :description)
Map.get(map, :description) || ""
end

defp deprecated(map, deprecated) do
[
Map.get(map, :description),
Map.get(map, :description) || "",
"<div class='text-dark mt-2'><span class='bg-warning'>DEPRECATED since v",
Map.get(deprecated, :since),
"</span></div>",
Expand Down
2 changes: 1 addition & 1 deletion mix.exs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
defmodule Schema.MixProject do
use Mix.Project

@version "2.75.0"
@version "2.76.0"

def project do
build = System.get_env("GITHUB_RUN_NUMBER") || "SNAPSHOT"
Expand Down
49 changes: 45 additions & 4 deletions test/test_ocsf_schema/dictionary.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@
"0": {
"caption": "Unknown",
"description": "The event activity is unknown."
},
"-1": {
"@deprecated": {
"message": "Use 0 (Unknown) instead.",
"since": "0.1.0-test"
},
"caption": "Negative Unknown",
"description": "The event activity is not not unknown.",
"references": [
{
"url": "https://en.wikipedia.org/wiki/Double_negative",
"description": "Double negative on Wikipedia"
},
{
"url": "https://en.wikipedia.org/wiki/Deprecation",
"description": "Deprecation on Wikipedia"
}
]
}
},
"sibling": "activity_name",
Expand Down Expand Up @@ -51,6 +69,11 @@
"type": "string_t",
"source": "Beta is from atomic decay (dictionary attribute)"
},
"car_number": {
"caption": "Car Number",
"description": "The car's number.",
"type": "integer_t"
},
"category_name": {
"caption": "Category",
"description": "The event category name, as defined by category_uid value.",
Expand Down Expand Up @@ -116,10 +139,28 @@
"description": "An entity's thingy. (From base dictionary attribute.)",
"type": "entity_thing_t"
},
"gamma": {
"caption": "Gammas",
"description": "A gamma is a gamma, which is a gamma, and so on.",
"type": "integer_t"
"flag_ids": {
"caption": "Flag IDs",
"description": "The list of normalized flag IDs. See specific usage.",
"sibling": "flags",
"type": "integer_t",
"enum": {
"0": {
"caption": "Unknown",
"description": "The flag is unknown."
},
"99": {
"caption": "Other",
"description": "The flag is not mapped. See the <code>flags</code> attribute, which contains a data source specific value."
}
},
"is_array": true
},
"flags": {
"caption": "Flags",
"description": "The list of flags, normalized to the captions of the flag_ids values. In the case of 'Other', they are defined by the event source.",
"type": "string_t",
"is_array": true
},
"gammas": {
"caption": "Gammas",
Expand Down
Loading

0 comments on commit 0b24bc7

Please sign in to comment.