Skip to content

Commit

Permalink
Merge pull request #341 from meaningfy-ws/feature/MWB-820
Browse files Browse the repository at this point in the history
  • Loading branch information
kaleanych authored Nov 5, 2024
2 parents 5b7eeec + eef4c2a commit 20710d3
Show file tree
Hide file tree
Showing 8 changed files with 1,957 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import io
import re
from typing import List, Any, Union
from typing import Any, Union
from xml.etree import ElementTree

from pydantic import validate_call
Expand All @@ -9,29 +9,30 @@

from mapping_workbench.backend.logger.services import mwb_logger
from mapping_workbench.backend.package_validator.adapters.data_validator import TestDataValidator
from mapping_workbench.backend.package_validator.models.xpath_validation import XPathAssertionEntry
from mapping_workbench.backend.package_validator.models.xpath_validation import XPathAssertionEntry, \
XPATHMatchingElements


class XPATHValidator(TestDataValidator):
"""
"""

xp: Any = None # saxon_processor
xpp: Any = None # xpath_processor
xqp: Any = None # xquery_processor
xp: Any = None # saxon_processor
xpp: Any = None # xpath_processor
xqp: Any = None # xquery_processor
namespaces: Any = None
prefixes: Any = None
DEFAULT_XML_NS_PREFIX: str = ''

@validate_call
def __init__(self, xml_content, **data: Any):
def __init__(self, xml_content, namespaces=None, **data: Any):
super().__init__(**data)
self.namespaces = self.extract_namespaces(xml_content)
self.namespaces = namespaces or self.extract_namespaces(xml_content)
self.prefixes = {v: k for k, v in self.namespaces.items()}
self.xp = PySaxonProcessor(license=False)
self.init_xp_processors(xml_content)

def validate(self, xpath_expression) -> List[XPathAssertionEntry]:
def validate(self, xpath_expression) -> XPATHMatchingElements:
return self.get_unique_xpaths(xpath_expression)

def check_xpath_condition(self, xquery_expression) -> bool:
Expand Down Expand Up @@ -114,7 +115,7 @@ def check_xpath_expression(self, xpath_expression: str) -> Union[PyXdmValue, Non
mwb_logger.log_all_error(str(e), str(e))
return None

def get_unique_xpaths(self, xpath_expression) -> List[XPathAssertionEntry]:
def get_unique_xpaths(self, xpath_expression) -> XPATHMatchingElements:
"""Get unique XPaths that cover elements matching e XPath expression."""
xpath_assertions = []
matching_elements = self.check_xpath_expression(xpath_expression)
Expand All @@ -129,4 +130,7 @@ def get_unique_xpaths(self, xpath_expression) -> List[XPathAssertionEntry]:
value=self.get_node_text_value(xpath_node)
))

return xpath_assertions
return XPATHMatchingElements(
xpath_assertions=xpath_assertions,
elements=matching_elements or []
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from typing import Optional, List

from pydantic import BaseModel
from pydantic import BaseModel, ConfigDict
from saxonche import PyXdmItem

from mapping_workbench.backend.package_validator.models.test_data_validation import TestDataValidationResult, \
ValidationTestDataEntry, CMRuleSDKElement
Expand Down Expand Up @@ -31,3 +32,9 @@ class Settings:

class XPATHTestDataValidationResult(TestDataValidationResult):
results: Optional[List[XPathAssertion]] = []


class XPATHMatchingElements(BaseModel):
model_config = ConfigDict(arbitrary_types_allowed=True)
xpath_assertions: List[XPathAssertionEntry] = [],
elements: List[PyXdmItem] = []
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
from mapping_workbench.backend.mapping_package.models.entity import MappingPackageState
from mapping_workbench.backend.package_validator.adapters.xpath_validator import XPATHValidator
from mapping_workbench.backend.package_validator.models.xpath_validation import XPathAssertion, \
XPATHTestDataValidationResult, XPathAssertionTestDataEntry, XPathAssertionEntry, XPathAssertionCondition
XPATHTestDataValidationResult, XPathAssertionTestDataEntry, XPathAssertionEntry, XPathAssertionCondition, \
XPATHMatchingElements
from mapping_workbench.backend.test_data_suite.models.entity import TestDataSuiteState, TestDataValidation, \
TestDataState

TRY_TO_MEET_XPATH_CONDITION = True # try to meet xpath condition on matched elements and if not, try it on whole test data


def update_xpath_assertion(
state: TestDataValidation,
Expand Down Expand Up @@ -95,12 +98,16 @@ def update_xpath_assertion_test_data_entry(
if idx < 0:
test_data_xpath_assertion.xpath_conditions.append(xpath_condition)
else:
test_data_xpath_assertion.xpath_conditions[idx].meets_xpath_condition &= xpath_condition.meets_xpath_condition
if test_data_xpath_assertion.xpath_conditions[idx]:
test_data_xpath_assertion.xpath_conditions[idx].meets_xpath_condition \
|= xpath_condition.meets_xpath_condition
else:
test_data_xpath_assertion.xpath_conditions[idx].meets_xpath_condition \
&= xpath_condition.meets_xpath_condition

test_data_xpath_assertion.is_covered = (len(test_data_xpath_assertion.test_data_xpaths) > 0)



def update_xpath_assertion_test_data_entry_xpaths(
test_data_entry: XPathAssertionTestDataEntry,
xpaths: List[XPathAssertionEntry]
Expand Down Expand Up @@ -136,15 +143,27 @@ def compute_xpath_assertions_for_mapping_package(mapping_package_state: MappingP

validation_message = None
xpaths: List[XPathAssertionEntry] = []
matching_elements: XPATHMatchingElements = xpath_validator.validate(cm_xpath)
try:
xpaths = xpath_validator.validate(cm_xpath)
xpaths = matching_elements.xpath_assertions
except Exception as e:
validation_message = str(e)

cm_xpath_condition = conceptual_mapping_rule_state.xpath_condition
meets_xpath_condition: bool = True
if cm_xpath_condition:
meets_xpath_condition = xpath_validator.check_xpath_condition(cm_xpath_condition)
meets_xpath_condition = False
if TRY_TO_MEET_XPATH_CONDITION:
for matching_element in matching_elements.elements:
element_xpath_validator: XPATHValidator = XPATHValidator(
xml_content=str(matching_element),
namespaces=xpath_validator.namespaces
)
meets_xpath_condition = element_xpath_validator.check_xpath_condition(cm_xpath_condition)
if meets_xpath_condition:
break
if not meets_xpath_condition:
meets_xpath_condition = xpath_validator.check_xpath_condition(cm_xpath_condition)

xpath_condition = XPathAssertionCondition(
xpath_condition=cm_xpath_condition or '',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ const Page = () => {
disabled={formik.isSubmitting || !formik.values.absolute_xpath}
error={formik.touched['parent_node'] && formik.errors['parent_node']}
isOptionEqualToValue={(option, value) => option.absolute_xpath === value}
// getOptionLabel={option => option.absolute_xpath ?? ''}
// getOptionLabel={option => option?.absolute_xpath ?? ''}
onBlur={formik.handleBlur}
defaultValue={''}
onChange={(e, value) => formik.setFieldValue('parent_node', value)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export const TaskLine = ({item}) => {
>
{stepsCount && stepsCount.map((stepIdx) => {
const step = getProgressElement(steps, stepIdx);
let stepStatus = step != null ? step.status : taskProgressStatus.QUEUED
let stepStatus = step?.status ?? taskProgressStatus.QUEUED
return (<span
key={'task_action_step_' + actionIdx + '_' + stepIdx}
style={{
Expand Down Expand Up @@ -130,8 +130,8 @@ export const TaskActions = ({item}) => {
<Stack>
{stepsCount?.map((stepIdx) => {
const step = getProgressElement(steps, stepIdx);
const stepStatus = step.status ?? taskProgressStatus.QUEUED
const stepName = step.name ?? ""
const stepStatus = step?.status ?? taskProgressStatus.QUEUED
const stepName = step?.name ?? ""
return (
<Typography
key={'step' + stepIdx}
Expand Down
Loading

0 comments on commit 20710d3

Please sign in to comment.