Requirements - outdated!
- New app must be created:
quality
- New models must be created
Rule
name
- CharField
field_name
- CharField (with choices)
property
- CharField (with choices)
operator
- CharField (with choices)
threshold
- IntegerField
RuleSet
name
- CharField
rules
- M2MField (on Rule
)
ConformityCheckConfiguration
name
- CharField
ConformityCheckConfigurationExternal
inherits from ConformityCheckConfiguration
external_url
- URLField
parameter_map
- TextField (contains json)
response_map
- TextField (contains json)
ConformityCheckConfigurationInternal
inherits from ConformityCheckConfiguration
mandatoryrulesets
- M2MField (on RuleSet
)
optionalrulesets
- M2MField (on RuleSet
)
ConformityCheckRun
metadata
- ForeignKey (on Metadata
)
confirmity_check_configuration
- ForeignKey (on ConformityCheckConfiguration
)
time_start
- DateTimeField
time_stop
- DateTimeField
errors
- TextField (contains json)
additional_info
- TextField (contains json)
- All models must be configurable in the django admin interface
Requirements reduced 2020-10-15
-
New app must be created: quality
-
New models must be created
ConformityCheckConfiguration
name
- CharField
metadata_types
- TextField (contains json) - metadata.metadata_type, view format
ConformityCheckConfigurationExternal
inherits from ConformityCheckConfiguration
external_url
- URLField - API
api_configuration
- TextField (contains json) - defines test classes, result parsing, ...
ConformityCheckRun
- async - see pending tasks - type validate
metadata
- ForeignKey (on Metadata
)
conformity_check_configuration
- ForeignKey (on ConformityCheckConfiguration
)
time_start
- DateTimeField
time_stop
- DateTimeField
errors
- TextField (contains json)
passed
- Boolean
result
- TextField (contains json, xml, html)
Conformity checks
We need to separate between internal and external confirmity checks. Please regard the attached diagram to get an idea of the structure.
ConformityCheckConfiguration
Base model for ConformityCheckConfigurationExternal
and ...Internal
.
name
The name of the configuration
ConformityCheckConfigurationInternal
Holds the configuration for an internal conformity check.
mandatory_rule_sets
A set of ruleSet records, which are mandatory to pass successfully.
optional_rule_sets
A set of ruleSet records, which are nice if passed successfully.
ConformityCheckConfigurationExternal
Holds the configuration for an external conformity check.
external_url
A link pointing to an external test API.
parameter_map
Holds json as text. Further details below.
response_map
Holds json as text. Further details below.
ConformityCheckRun
Holds the relation of a metadata record to the results of a check
metadata
A ForeignKey to the related metadata
conformity_check_configuration
A ForeignKey to a ConformityCheckConfiguration record.
time_start
DateTime when the test started
time_stop
DateTime when the test ended
errors
Holds json as text.
additional_info
Holds json as text.
ConformityCheckInternal
Internal checks are based on Rule
s and RuleSet
s.
RuleSet
Groups rules and holds the results of a rule check run. RuleSets iterate over their rules and perform the rule checks.
name
The name of a ruleSet.
rules
A set of rules.
Rule
name
The name of a rule.
field_name
field_name
defines an attribute of the Metadata model, such as abstract
or keywords
. A list of valid choices must be provided, so the rules can be easily created.
Valid choices are
title
abstract
access_constraints
keywords
formats
reference_system
property
A property describes what can be measured on the field_name
. E.g. abstract
can have the property len
, since it's a string. keywords
is a queryset of records and can have the property count
, which is semantically equal to len
but reduces the query time.
For now there are only these two properties which can be checked. The list of choices can be extended in the future.
operator
Defines a mathematical operator, which is used to describe the expected field_name
property.
Valid choices are:
>
>=
<
<=
==
!=
How a rule could be used
A rule could be checked like this
def check_rule(metadata: Metadata, rule: Rule):
prop = rule.property
if prop == 'len':
attribute = metadata.__getattribute__(role.field_name)
real_value = len(attribute)
elif prop == 'count':
# count wird fรผr M2M relations verwendet
manager = metadata.__getattribute__(field)
elements = manager.all()
real_value = elements.count()
else:
raise Exception("No valid property")
condition = str(real_value) + rule.operator + str(rule.threshold)
return eval(condition, {'__builtins__': None})
rules = Rule.objects.all()
failed = []
for rule in rules:
success = check_condition(metadata, rule)
if not success:
failed.append(rule)
ConformityCheckExternal
Mandatory attributes for this class are:
- external_url
- parameter_map
- response_map
external_url
Points to an online API
parameter_map
Maps the metadata records field names on the required parameters for the API.
Example:
We have a metadata object with a field named get_capabilities_uri
, which has to be used as the parameter inputURI
of the API:
{
"inputURI": "get_capabilities_uri",
}
Example implementation for usage
json_obj = json.loads("...") # the json from above
params = {}
for key, val in json_obj.items():
params[key] = metadata.__getattribute__(val)
request.post(api_uri, params) # perform test request
response_map
Maps the known response elements to a given structure. This way, we are aware of how, e.g. the differen error elements of the response are named, so we can parse the response in a generic way.
Example:
{
"error_identifier": [],
"additional_info_identifier": [],
"success_identifier": "ResultOfTest",
}
error_identifier
Every API must have at least one error element, which contains the found errors during the test. It may be, that there is not just one error element, but rather multiple error elements for different types of error (TypeError, OutOfRangeError, ...). All these error element identifiers have to be collected in a list, which we call error_identifier
additional_info_identifier
Some APIs might provide warnings or hints as well, which are not really errors but some kind of additional information. We proceed here the same as we did for error_identifiers
: Put all these hints or warning element identifier in a list, which is called additional_info_identifier
.
success_identifier
Every test API should have one element in response, which states whether the test run was successful or failed for the input. This element has to be named by using success_identifier
Example implementation for usage
json_obj = json.loads("...") # the response_map from above
result = {
"errors": [],
"additional_information": [],
"success": None,
}
error_identifiers = json_obj["error_identifier"]
additional_info_identifier = json_obj["additional_info_identifier"]
success_identifier = json_obj["success_identifier"]
for error_identifier in error_identifiers:
result["errors"] = response.get_val_for_identifier(error_identifier)
# analogous for additional_information and success
Please note: The function get_val_for_identifier(id: str)
does not exist yet and I didn't give any example of how to implement it. This function would be more complex, since it has to handle json, as well as xml responses, in case we deal with a test API, that uses xml.