diff --git a/apps/schematic/api/.gitignore b/apps/schematic/api/.gitignore index f8a5e334c4..eb3cb89003 100644 --- a/apps/schematic/api/.gitignore +++ b/apps/schematic/api/.gitignore @@ -70,6 +70,8 @@ target/ #secrets *secrets* schematic_service_account_creds.json +private_localhost_certificate.crt +private_localhost.key #config files config.yaml diff --git a/apps/schematic/api/.openapi-generator/FILES b/apps/schematic/api/.openapi-generator/FILES index 2e57b51219..67091db1d9 100644 --- a/apps/schematic/api/.openapi-generator/FILES +++ b/apps/schematic/api/.openapi-generator/FILES @@ -13,6 +13,9 @@ schematic_api/models/__init__.py schematic_api/models/asset_type.py schematic_api/models/base_model_.py schematic_api/models/basic_error.py +schematic_api/models/component_requirement_array.py +schematic_api/models/component_requirement_graph.py +schematic_api/models/component_requirement_subgraph.py schematic_api/models/connected_node_pair.py schematic_api/models/connected_node_pair_array.py schematic_api/models/connected_node_pair_page.py diff --git a/apps/schematic/api/poetry.lock b/apps/schematic/api/poetry.lock index 4d93d460e3..ac915492e0 100644 --- a/apps/schematic/api/poetry.lock +++ b/apps/schematic/api/poetry.lock @@ -1021,20 +1021,20 @@ typing = ["typing-extensions (>=4.8)"] [[package]] name = "flask" -version = "2.1.3" +version = "2.2.5" description = "A simple framework for building complex web applications." optional = false python-versions = ">=3.7" files = [ - {file = "Flask-2.1.3-py3-none-any.whl", hash = "sha256:9013281a7402ad527f8fd56375164f3aa021ecfaff89bfe3825346c24f87e04c"}, - {file = "Flask-2.1.3.tar.gz", hash = "sha256:15972e5017df0575c3d6c090ba168b6db90259e620ac8d7ea813a396bad5b6cb"}, + {file = "Flask-2.2.5-py3-none-any.whl", hash = "sha256:58107ed83443e86067e41eff4631b058178191a355886f8e479e347fa1285fdf"}, + {file = "Flask-2.2.5.tar.gz", hash = "sha256:edee9b0a7ff26621bd5a8c10ff484ae28737a2410d99b0bb9a6850c7fb977aa0"}, ] [package.dependencies] click = ">=8.0" itsdangerous = ">=2.0" Jinja2 = ">=3.0" -Werkzeug = ">=2.0" +Werkzeug = ">=2.2.2" [package.extras] async = ["asgiref (>=3.2)"] @@ -4639,4 +4639,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = "3.10.14" -content-hash = "6d0044f9bd32c57f62dda691e8433145e94429fde021eeabb894d6b1780f13e5" +content-hash = "53601e984e97636dcea9b96c4aa68144604e66ced784f1b3fab7eb1aa6a9c275" diff --git a/apps/schematic/api/pyproject.toml b/apps/schematic/api/pyproject.toml index f8cbe26b8a..b0e1fdfe33 100644 --- a/apps/schematic/api/pyproject.toml +++ b/apps/schematic/api/pyproject.toml @@ -11,7 +11,7 @@ python = "3.10.14" connexion = {version = "2.14.1", extras = ["swagger-ui"]} swagger-ui-bundle = "0.0.9" python-dateutil = "2.8.2" -Flask = "2.1.3" +Flask = "2.2.5" Flask-Cors = "3.0.10" schematicpy = "24.4.1" # jsonschema isn't a direct import, but is used by connexion. diff --git a/apps/schematic/api/schematic_api/controllers/manifest_generation_controller.py b/apps/schematic/api/schematic_api/controllers/manifest_generation_controller.py index 578f94e16a..f6b76007af 100644 --- a/apps/schematic/api/schematic_api/controllers/manifest_generation_controller.py +++ b/apps/schematic/api/schematic_api/controllers/manifest_generation_controller.py @@ -17,8 +17,8 @@ def generate_google_sheet_manifests( manifest_title=None, data_type_array=None, display_label_type=None, - asset_view_id=None, use_strict_validation=None, + asset_view_id=None, generate_all_manifests=None, ): # noqa: E501 """Generates a list of google sheet links @@ -37,10 +37,10 @@ def generate_google_sheet_manifests( :type data_type_array: List[str] :param display_label_type: The type of label to display :type display_label_type: str - :param asset_view_id: ID of view listing all project data assets. E.g. for Synapse this would be the Synapse ID of the fileview listing all data assets for a given project - :type asset_view_id: str :param use_strict_validation: If true, users are blocked from entering incorrect values. If false, users will get a warning when using incorrect values. :type use_strict_validation: bool + :param asset_view_id: ID of view listing all project data assets. E.g. for Synapse this would be the Synapse ID of the fileview listing all data assets for a given project + :type asset_view_id: str :param generate_all_manifests: If true, a manifest for all components will be generated, datasetIds will be ignored. If false, manifests for each id in datasetIds will be generated. :type generate_all_manifests: bool @@ -53,7 +53,7 @@ def generate_google_sheet_manifests( manifest_title, data_type_array, display_label_type, - asset_view_id, use_strict_validation, + asset_view_id, generate_all_manifests, ) diff --git a/apps/schematic/api/schematic_api/controllers/manifest_generation_controller_impl.py b/apps/schematic/api/schematic_api/controllers/manifest_generation_controller_impl.py index 2b93f64fb0..fdd6c7bd02 100644 --- a/apps/schematic/api/schematic_api/controllers/manifest_generation_controller_impl.py +++ b/apps/schematic/api/schematic_api/controllers/manifest_generation_controller_impl.py @@ -11,7 +11,6 @@ handle_exceptions, get_access_token, download_schema_file_as_jsonld, - InvalidValueError, ) @@ -22,10 +21,10 @@ def generate_google_sheet_manifests( dataset_id_array: list[str] | None, manifest_title: str | None, data_type_array: list[str] | None, - display_label_type: DisplayLabelType = "class_label", - asset_view_id: str | None = None, - use_strict_validation: bool = True, - generate_all_manifests: bool = False, + display_label_type: DisplayLabelType, + use_strict_validation: bool, + asset_view_id: str | None, + generate_all_manifests: bool, ) -> tuple[GoogleSheetLinks | BasicError, int]: """Generates a list of links to manifests in google sheet form @@ -57,38 +56,9 @@ def generate_google_sheet_manifests( """ if generate_all_manifests: - if dataset_id_array: - raise InvalidValueError( - "When generate_all_manifests is True dataset_id_array must be None", - {"dataset_id_array": dataset_id_array}, - ) - if data_type_array: - raise InvalidValueError( - "When generate_all_manifests is True data_type_array must be None", - {"data_type_array": data_type_array}, - ) data_type_array = ["all manifests"] - - else: - if not data_type_array: - raise InvalidValueError( - ( - "When generate_all_manifests is False data_type_array must be a list with " - "at least one item" - ), - {"data_type_array": data_type_array}, - ) - if dataset_id_array and len(dataset_id_array) != len(data_type_array): - raise InvalidValueError( - ( - "When generate_all_manifests is False data_type_array and dataset_id_array " - "must both lists with the same length" - ), - { - "data_type_array": data_type_array, - "dataset_id_array": dataset_id_array, - }, - ) + if not data_type_array: + data_type_array = [] access_token = get_access_token() if asset_view_id: diff --git a/apps/schematic/api/schematic_api/controllers/schema_controller.py b/apps/schematic/api/schematic_api/controllers/schema_controller.py index 80fbed68bd..9cc701b0d9 100644 --- a/apps/schematic/api/schematic_api/controllers/schema_controller.py +++ b/apps/schematic/api/schematic_api/controllers/schema_controller.py @@ -5,6 +5,12 @@ from typing import Union from schematic_api.models.basic_error import BasicError # noqa: E501 +from schematic_api.models.component_requirement_array import ( + ComponentRequirementArray, +) # noqa: E501 +from schematic_api.models.component_requirement_graph import ( + ComponentRequirementGraph, +) # noqa: E501 from schematic_api.models.connected_node_pair_array import ( ConnectedNodePairArray, ) # noqa: E501 @@ -42,6 +48,48 @@ def get_component( ) +def get_component_requirements_array( + component_label, schema_url, display_label_type=None +): # noqa: E501 + """Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in array form. + + Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in array form. # noqa: E501 + + :param component_label: The label of a component in a schema + :type component_label: str + :param schema_url: The URL of a schema in jsonld or csv form + :type schema_url: str + :param display_label_type: The type of label to display + :type display_label_type: str + + :rtype: Union[ComponentRequirementArray, Tuple[ComponentRequirementArray, int], Tuple[ComponentRequirementArray, int, Dict[str, str]] + """ + return schema_controller_impl.get_component_requirements_array( + component_label, schema_url, display_label_type + ) + + +def get_component_requirements_graph( + component_label, schema_url, display_label_type=None +): # noqa: E501 + """Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in graph form. + + Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in graph form. # noqa: E501 + + :param component_label: The label of a component in a schema + :type component_label: str + :param schema_url: The URL of a schema in jsonld or csv form + :type schema_url: str + :param display_label_type: The type of label to display + :type display_label_type: str + + :rtype: Union[ComponentRequirementGraph, Tuple[ComponentRequirementGraph, int], Tuple[ComponentRequirementGraph, int, Dict[str, str]] + """ + return schema_controller_impl.get_component_requirements_graph( + component_label, schema_url, display_label_type + ) + + def get_connected_node_pair_array( schema_url, relationship_type, display_label_type=None ): # noqa: E501 diff --git a/apps/schematic/api/schematic_api/controllers/schema_controller_impl.py b/apps/schematic/api/schematic_api/controllers/schema_controller_impl.py index d9573e5360..17e2a0c072 100644 --- a/apps/schematic/api/schematic_api/controllers/schema_controller_impl.py +++ b/apps/schematic/api/schematic_api/controllers/schema_controller_impl.py @@ -11,6 +11,9 @@ from schematic.utils.schema_utils import DisplayLabelType # type: ignore from schematic_api.models.basic_error import BasicError +from schematic_api.models.component_requirement_subgraph import ( + ComponentRequirementSubgraph, +) from schematic_api.models.node_property_array import NodePropertyArray from schematic_api.models.validation_rule import ValidationRule from schematic_api.models.validation_rule_array import ValidationRuleArray @@ -27,6 +30,29 @@ from schematic_api.controllers.paging import Page +def create_data_model_graph_explorer( + schema_url: str, display_label_type: DisplayLabelType +) -> DataModelGraphExplorer: + """Creates a DataModelGraphExplorer for use in variopus endpoints + + Args: + schema_url (str): The URL of the schema in json form + display_label_type (DisplayLabelType): + The type of label to use as display + + Returns: + DataModelGraphExplorer: _description_ + """ + data_model_parser = DataModelParser(path_to_data_model=schema_url) + parsed_data_model = data_model_parser.parse_model() + data_model_grapher = DataModelGraph( + attribute_relationships_dict=parsed_data_model, + data_model_labels=display_label_type, + ) + graph_data_model = data_model_grapher.generate_data_model_graph() + return DataModelGraphExplorer(graph_data_model) + + @handle_exceptions def get_component( component_label: str, @@ -66,6 +92,56 @@ def get_component( return result, status +@handle_exceptions +def get_component_requirements_array( + component_label: str, + schema_url: str, + display_label_type: DisplayLabelType, +) -> tuple[Union[list[str], BasicError], int]: + """Gets the input components required components + + Args: + component_label (str): The label of the component + schema_url (str): The URL of the schema in json form + display_label_type (DisplayLabelType): + The type of label to use as display + Returns: + tuple[Union[ComponentRequirementArray, BasicError], int]: A tuple + item 1 is either the required coponents or an error + item 2 is the status + """ + dmge = create_data_model_graph_explorer(schema_url, display_label_type) + result = dmge.get_component_requirements(source_component=component_label) + status = 200 + return result, status + + +@handle_exceptions +def get_component_requirements_graph( + component_label: str, + schema_url: str, + display_label_type: DisplayLabelType, +) -> tuple[Union[list[ComponentRequirementSubgraph], BasicError], int]: + """Gets the input components required components + + Args: + component_label (str): The label of the component + schema_url (str): The URL of the schema in json form + display_label_type (DisplayLabelType): + The type of label to use as display + Returns: + tuple[Union[ComponentRequirementGrpah, BasicError], int]: A tuple + item 1 is either the required coponents or an error + item 2 is the status + """ + dmge = create_data_model_graph_explorer(schema_url, display_label_type) + graph = dmge.get_component_requirements_graph(source_component=component_label) + edges: list[tuple[str, str]] = graph.edges() + result = [ComponentRequirementSubgraph(edge[0], edge[1]) for edge in edges] + status = 200 + return result, status + + def get_connected_node_pairs_from_schematic( relationship_type: str, schema_url: str, @@ -83,14 +159,7 @@ def get_connected_node_pairs_from_schematic( Returns: list[ConnectedNodePair]: A list of connected node pairs """ - data_model_parser = DataModelParser(path_to_data_model=schema_url) - parsed_data_model = data_model_parser.parse_model() - data_model_grapher = DataModelGraph( - attribute_relationships_dict=parsed_data_model, - data_model_labels=display_label_type, - ) - graph_data_model = data_model_grapher.generate_data_model_graph() - dmge = DataModelGraphExplorer(graph_data_model) + dmge = create_data_model_graph_explorer(schema_url, display_label_type) relationship_subgraph = dmge.get_subgraph_by_edge_type(relationship_type) lst = [list(edge) for edge in relationship_subgraph.edges] @@ -188,14 +257,7 @@ def get_node_is_required_from_schematic( Returns: bool: Whether or no the node is required """ - data_model_parser = DataModelParser(path_to_data_model=schema_url) - parsed_data_model = data_model_parser.parse_model() - data_model_grapher = DataModelGraph( - attribute_relationships_dict=parsed_data_model, - data_model_labels=display_label_type, - ) - graph_data_model = data_model_grapher.generate_data_model_graph() - dmge = DataModelGraphExplorer(graph_data_model) + dmge = create_data_model_graph_explorer(schema_url, display_label_type) return dmge.get_node_required(node_display) @@ -294,14 +356,7 @@ def get_node_properties_from_schematic( Returns: list[str]: A list of properties of the node """ - data_model_parser = DataModelParser(path_to_data_model=schema_url) - parsed_data_model = data_model_parser.parse_model() - data_model_grapher = DataModelGraph( - attribute_relationships_dict=parsed_data_model, - data_model_labels=display_label_type, - ) - graph_data_model = data_model_grapher.generate_data_model_graph() - dmge = DataModelGraphExplorer(graph_data_model) + dmge = create_data_model_graph_explorer(schema_url, display_label_type) properties = dmge.find_class_specific_properties(node_label) return properties @@ -352,14 +407,7 @@ def get_node_validation_rules_from_schematic( Returns: list[ValidationRule]: A list of validation_rules of the node """ - data_model_parser = DataModelParser(path_to_data_model=schema_url) - parsed_data_model = data_model_parser.parse_model() - data_model_grapher = DataModelGraph( - attribute_relationships_dict=parsed_data_model, - data_model_labels=display_label_type, - ) - graph_data_model = data_model_grapher.generate_data_model_graph() - dmge = DataModelGraphExplorer(graph_data_model) + dmge = create_data_model_graph_explorer(schema_url, display_label_type) rules: list[str] = dmge.get_node_validation_rules(node_display) # type: ignore return [ValidationRule(rule) for rule in rules] @@ -418,14 +466,7 @@ def get_node_dependencies_from_schematic( list[Node]: A list of nodes """ - data_model_parser = DataModelParser(path_to_data_model=schema_url) - parsed_data_model = data_model_parser.parse_model() - data_model_grapher = DataModelGraph( - attribute_relationships_dict=parsed_data_model, - data_model_labels=display_label_type, - ) - graph_data_model = data_model_grapher.generate_data_model_graph() - dmge = DataModelGraphExplorer(graph_data_model) + dmge = create_data_model_graph_explorer(schema_url, display_label_type) nodes = dmge.get_node_dependencies( node_label, return_display_names, return_ordered_by_schema ) diff --git a/apps/schematic/api/schematic_api/models/__init__.py b/apps/schematic/api/schematic_api/models/__init__.py index 20d7f19caf..bc2c4edd3d 100644 --- a/apps/schematic/api/schematic_api/models/__init__.py +++ b/apps/schematic/api/schematic_api/models/__init__.py @@ -5,6 +5,9 @@ # import models into model package from schematic_api.models.asset_type import AssetType from schematic_api.models.basic_error import BasicError +from schematic_api.models.component_requirement_array import ComponentRequirementArray +from schematic_api.models.component_requirement_graph import ComponentRequirementGraph +from schematic_api.models.component_requirement_subgraph import ComponentRequirementSubgraph from schematic_api.models.connected_node_pair import ConnectedNodePair from schematic_api.models.connected_node_pair_array import ConnectedNodePairArray from schematic_api.models.connected_node_pair_page import ConnectedNodePairPage diff --git a/apps/schematic/api/schematic_api/models/component_requirement_array.py b/apps/schematic/api/schematic_api/models/component_requirement_array.py new file mode 100644 index 0000000000..d3100f376e --- /dev/null +++ b/apps/schematic/api/schematic_api/models/component_requirement_array.py @@ -0,0 +1,64 @@ +# coding: utf-8 + +from __future__ import absolute_import +from datetime import date, datetime # noqa: F401 + +from typing import List, Dict # noqa: F401 + +from schematic_api.models.base_model_ import Model +from schematic_api import util + + +class ComponentRequirementArray(Model): + """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + + Do not edit the class manually. + """ + + def __init__(self, component_requirements_list=None): # noqa: E501 + """ComponentRequirementArray - a model defined in OpenAPI + + :param component_requirements_list: The component_requirements_list of this ComponentRequirementArray. # noqa: E501 + :type component_requirements_list: List[str] + """ + self.openapi_types = { + 'component_requirements_list': List[str] + } + + self.attribute_map = { + 'component_requirements_list': 'componentRequirementsList' + } + + self._component_requirements_list = component_requirements_list + + @classmethod + def from_dict(cls, dikt) -> 'ComponentRequirementArray': + """Returns the dict as a model + + :param dikt: A dict. + :type: dict + :return: The ComponentRequirementArray of this ComponentRequirementArray. # noqa: E501 + :rtype: ComponentRequirementArray + """ + return util.deserialize_model(dikt, cls) + + @property + def component_requirements_list(self): + """Gets the component_requirements_list of this ComponentRequirementArray. + + + :return: The component_requirements_list of this ComponentRequirementArray. + :rtype: List[str] + """ + return self._component_requirements_list + + @component_requirements_list.setter + def component_requirements_list(self, component_requirements_list): + """Sets the component_requirements_list of this ComponentRequirementArray. + + + :param component_requirements_list: The component_requirements_list of this ComponentRequirementArray. + :type component_requirements_list: List[str] + """ + + self._component_requirements_list = component_requirements_list diff --git a/apps/schematic/api/schematic_api/models/component_requirement_graph.py b/apps/schematic/api/schematic_api/models/component_requirement_graph.py new file mode 100644 index 0000000000..a70a73f2c9 --- /dev/null +++ b/apps/schematic/api/schematic_api/models/component_requirement_graph.py @@ -0,0 +1,66 @@ +# coding: utf-8 + +from __future__ import absolute_import +from datetime import date, datetime # noqa: F401 + +from typing import List, Dict # noqa: F401 + +from schematic_api.models.base_model_ import Model +from schematic_api.models.component_requirement_subgraph import ComponentRequirementSubgraph +from schematic_api import util + +from schematic_api.models.component_requirement_subgraph import ComponentRequirementSubgraph # noqa: E501 + +class ComponentRequirementGraph(Model): + """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + + Do not edit the class manually. + """ + + def __init__(self, component_requirements_graph=None): # noqa: E501 + """ComponentRequirementGraph - a model defined in OpenAPI + + :param component_requirements_graph: The component_requirements_graph of this ComponentRequirementGraph. # noqa: E501 + :type component_requirements_graph: List[ComponentRequirementSubgraph] + """ + self.openapi_types = { + 'component_requirements_graph': List[ComponentRequirementSubgraph] + } + + self.attribute_map = { + 'component_requirements_graph': 'componentRequirementsGraph' + } + + self._component_requirements_graph = component_requirements_graph + + @classmethod + def from_dict(cls, dikt) -> 'ComponentRequirementGraph': + """Returns the dict as a model + + :param dikt: A dict. + :type: dict + :return: The ComponentRequirementGraph of this ComponentRequirementGraph. # noqa: E501 + :rtype: ComponentRequirementGraph + """ + return util.deserialize_model(dikt, cls) + + @property + def component_requirements_graph(self): + """Gets the component_requirements_graph of this ComponentRequirementGraph. + + + :return: The component_requirements_graph of this ComponentRequirementGraph. + :rtype: List[ComponentRequirementSubgraph] + """ + return self._component_requirements_graph + + @component_requirements_graph.setter + def component_requirements_graph(self, component_requirements_graph): + """Sets the component_requirements_graph of this ComponentRequirementGraph. + + + :param component_requirements_graph: The component_requirements_graph of this ComponentRequirementGraph. + :type component_requirements_graph: List[ComponentRequirementSubgraph] + """ + + self._component_requirements_graph = component_requirements_graph diff --git a/apps/schematic/api/schematic_api/models/component_requirement_subgraph.py b/apps/schematic/api/schematic_api/models/component_requirement_subgraph.py new file mode 100644 index 0000000000..9abeee3540 --- /dev/null +++ b/apps/schematic/api/schematic_api/models/component_requirement_subgraph.py @@ -0,0 +1,98 @@ +# coding: utf-8 + +from __future__ import absolute_import +from datetime import date, datetime # noqa: F401 + +from typing import List, Dict # noqa: F401 + +from schematic_api.models.base_model_ import Model +from schematic_api import util + + +class ComponentRequirementSubgraph(Model): + """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + + Do not edit the class manually. + """ + + def __init__(self, component1=None, component2=None): # noqa: E501 + """ComponentRequirementSubgraph - a model defined in OpenAPI + + :param component1: The component1 of this ComponentRequirementSubgraph. # noqa: E501 + :type component1: str + :param component2: The component2 of this ComponentRequirementSubgraph. # noqa: E501 + :type component2: str + """ + self.openapi_types = { + 'component1': str, + 'component2': str + } + + self.attribute_map = { + 'component1': 'component1', + 'component2': 'component2' + } + + self._component1 = component1 + self._component2 = component2 + + @classmethod + def from_dict(cls, dikt) -> 'ComponentRequirementSubgraph': + """Returns the dict as a model + + :param dikt: A dict. + :type: dict + :return: The ComponentRequirementSubgraph of this ComponentRequirementSubgraph. # noqa: E501 + :rtype: ComponentRequirementSubgraph + """ + return util.deserialize_model(dikt, cls) + + @property + def component1(self): + """Gets the component1 of this ComponentRequirementSubgraph. + + The display name of the first component in the graph # noqa: E501 + + :return: The component1 of this ComponentRequirementSubgraph. + :rtype: str + """ + return self._component1 + + @component1.setter + def component1(self, component1): + """Sets the component1 of this ComponentRequirementSubgraph. + + The display name of the first component in the graph # noqa: E501 + + :param component1: The component1 of this ComponentRequirementSubgraph. + :type component1: str + """ + if component1 is None: + raise ValueError("Invalid value for `component1`, must not be `None`") # noqa: E501 + + self._component1 = component1 + + @property + def component2(self): + """Gets the component2 of this ComponentRequirementSubgraph. + + The display name of the second component in the graph # noqa: E501 + + :return: The component2 of this ComponentRequirementSubgraph. + :rtype: str + """ + return self._component2 + + @component2.setter + def component2(self, component2): + """Sets the component2 of this ComponentRequirementSubgraph. + + The display name of the second component in the graph # noqa: E501 + + :param component2: The component2 of this ComponentRequirementSubgraph. + :type component2: str + """ + if component2 is None: + raise ValueError("Invalid value for `component2`, must not be `None`") # noqa: E501 + + self._component2 = component2 diff --git a/apps/schematic/api/schematic_api/openapi/openapi.yaml b/apps/schematic/api/schematic_api/openapi/openapi.yaml index 1b172b056c..81bfeaddd3 100644 --- a/apps/schematic/api/schematic_api/openapi/openapi.yaml +++ b/apps/schematic/api/schematic_api/openapi/openapi.yaml @@ -1202,6 +1202,116 @@ paths: tags: - Schema x-openapi-router-controller: schematic_api.controllers.schema_controller + /components/{componentLabel}/requirementsArray: + get: + description: "Given a source model component (see https://w3id.org/biolink/vocab/category\ + \ for definnition of component), return all components required by it in array\ + \ form." + operationId: get_component_requirements_array + parameters: + - description: The label of a component in a schema + explode: false + in: path + name: componentLabel + required: true + schema: + $ref: '#/components/schemas/ComponentLabel' + style: simple + - description: The URL of a schema in jsonld or csv form + explode: true + in: query + name: schemaUrl + required: true + schema: + $ref: '#/components/schemas/SchemaUrl' + style: form + - description: The type of label to display + explode: true + in: query + name: displayLabelType + required: false + schema: + default: class_label + enum: + - class_label + - display_label + type: string + style: form + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/ComponentRequirementArray' + description: Success + "500": + content: + application/problem+json: + schema: + $ref: '#/components/schemas/BasicError' + description: The request cannot be fulfilled due to an unexpected server + error + summary: "Given a source model component (see https://w3id.org/biolink/vocab/category\ + \ for definnition of component), return all components required by it in array\ + \ form." + tags: + - Schema + x-openapi-router-controller: schematic_api.controllers.schema_controller + /components/{componentLabel}/requirementsGraph: + get: + description: "Given a source model component (see https://w3id.org/biolink/vocab/category\ + \ for definnition of component), return all components required by it in graph\ + \ form." + operationId: get_component_requirements_graph + parameters: + - description: The label of a component in a schema + explode: false + in: path + name: componentLabel + required: true + schema: + $ref: '#/components/schemas/ComponentLabel' + style: simple + - description: The URL of a schema in jsonld or csv form + explode: true + in: query + name: schemaUrl + required: true + schema: + $ref: '#/components/schemas/SchemaUrl' + style: form + - description: The type of label to display + explode: true + in: query + name: displayLabelType + required: false + schema: + default: class_label + enum: + - class_label + - display_label + type: string + style: form + responses: + "200": + content: + application/json: + schema: + $ref: '#/components/schemas/ComponentRequirementGraph' + description: Success + "500": + content: + application/problem+json: + schema: + $ref: '#/components/schemas/BasicError' + description: The request cannot be fulfilled due to an unexpected server + error + summary: "Given a source model component (see https://w3id.org/biolink/vocab/category\ + \ for definnition of component), return all components required by it in graph\ + \ form." + tags: + - Schema + x-openapi-router-controller: schematic_api.controllers.schema_controller /connectedNodePairArray: get: description: Gets a array of connected node pairs @@ -1384,16 +1494,6 @@ paths: - display_label type: string style: form - - description: ID of view listing all project data assets. E.g. for Synapse - this would be the Synapse ID of the fileview listing all data assets for - a given project - explode: true - in: query - name: assetViewId - required: false - schema: - $ref: '#/components/schemas/AssetViewId' - style: form - description: "If true, users are blocked from entering incorrect values. If\ \ false, users will get a warning when using incorrect values." explode: true @@ -1404,6 +1504,16 @@ paths: default: true type: boolean style: form + - description: ID of view listing all project data assets. E.g. for Synapse + this would be the Synapse ID of the fileview listing all data assets for + a given project + explode: true + in: query + name: assetViewId + required: false + schema: + $ref: '#/components/schemas/AssetViewId' + style: form - description: "If true, a manifest for all components will be generated, datasetIds\ \ will be ignored. If false, manifests for each id in datasetIds will be\ \ generated." @@ -2823,6 +2933,17 @@ components: schema: $ref: '#/components/schemas/DataTypeArray' style: form + useStrictValidation: + description: "If true, users are blocked from entering incorrect values. If\ + \ false, users will get a warning when using incorrect values." + explode: true + in: query + name: useStrictValidation + required: false + schema: + default: true + type: boolean + style: form responses: InternalServerError: content: @@ -3300,8 +3421,61 @@ components: type: object ComponentLabel: description: The label of a component in a schema - example: MolecularEntity + example: Patient type: string + ComponentRequirementArray: + description: An array of components + example: + componentRequirementsList: + - componentRequirementsList + - componentRequirementsList + properties: + componentRequirementsList: + items: + type: string + title: componentRequirementsList + type: array + title: ComponentRequirementArray + type: object + ComponentRequirementSubgraph: + description: A pair of components + example: + component1: component1 + component2: component2 + properties: + component1: + description: The display name of the first component in the graph + example: component1 + title: component1 + type: string + component2: + description: The display name of the second component in the graph + example: component2 + title: component2 + type: string + required: + - component1 + - component2 + title: ComponentRequirementSubgraph + type: object + x-java-class-annotations: + - '@lombok.Builder' + ComponentRequirementGraph: + description: A graph of components + example: + componentRequirementsGraph: + - component1: component1 + component2: component2 + - component1: component1 + component2: component2 + properties: + componentRequirementsGraph: + items: + $ref: '#/components/schemas/ComponentRequirementSubgraph' + title: componentRequirementsGraph + type: array + title: ComponentRequirementGraph + type: object RelationshipType: description: A type of schema relationship example: requiresDependency @@ -3397,11 +3571,15 @@ components: items: $ref: '#/components/schemas/DatasetId' type: array + DataType: + description: A data type + example: Patient + title: DataType + type: string DataTypeArray: description: An array of data types items: - example: Patient - type: string + $ref: '#/components/schemas/DataType' type: array GoogleSheetLinks: description: An array of google sheet links diff --git a/apps/schematic/api/schematic_api/test/conftest.py b/apps/schematic/api/schematic_api/test/conftest.py index 90cbfb54dd..ad65c0d856 100644 --- a/apps/schematic/api/schematic_api/test/conftest.py +++ b/apps/schematic/api/schematic_api/test/conftest.py @@ -27,9 +27,6 @@ def csv_to_json_str(path: str) -> str: GET_ACCESS_TOKEN_MOCK = ( "schematic_api.controllers.manifest_generation_controller_impl.get_access_token" ) -CREATE_SINGLE_MANIFEST_MOCK = ( - "schematic.manifest.generator.ManifestGenerator.create_single_manifest" -) CREATE_MANIFESTS_MOCK = ( "schematic.manifest.generator.ManifestGenerator.create_manifests" ) diff --git a/apps/schematic/api/schematic_api/test/test_manifest_generation_controller_impl.py b/apps/schematic/api/schematic_api/test/test_manifest_generation_controller_impl.py index 91f8c5b7ef..1f596c3361 100644 --- a/apps/schematic/api/schematic_api/test/test_manifest_generation_controller_impl.py +++ b/apps/schematic/api/schematic_api/test/test_manifest_generation_controller_impl.py @@ -27,12 +27,13 @@ def test_success(self, test_schema_url: str) -> None: manifest_title="title", use_strict_validation=True, generate_all_manifests=False, + display_label_type="class_label", ) assert status == 200 assert isinstance(result, GoogleSheetLinks) assert result.links == ["link1", "link2"] - def test_error_statuses(self, test_schema_url: str) -> None: + def test_error_statuses(self) -> None: """Test for error statuses""" with patch(GET_ACCESS_TOKEN_MOCK): with patch(CREATE_MANIFESTS_MOCK): @@ -45,92 +46,7 @@ def test_error_statuses(self, test_schema_url: str) -> None: manifest_title="title", use_strict_validation=True, generate_all_manifests=False, + display_label_type="class_label", ) assert status == 404 assert isinstance(result, BasicError) - - result, status = generate_google_sheet_manifests( - schema_url=test_schema_url, - dataset_id_array=["syn2", "syn3"], - asset_view_id="syn1", - data_type_array=["syn4", "syn5"], - add_annotations=False, - manifest_title="title", - use_strict_validation=True, - generate_all_manifests=True, - ) - assert status == 422 - assert isinstance(result, BasicError) - assert result.detail == ( - "When generate_all_manifests is True dataset_id_array must be None: " - "{'dataset_id_array': ['syn2', 'syn3']}" - ) - - result, status = generate_google_sheet_manifests( - schema_url=test_schema_url, - dataset_id_array=None, - asset_view_id="syn1", - data_type_array=["syn4", "syn5"], - add_annotations=False, - manifest_title="title", - use_strict_validation=True, - generate_all_manifests=True, - ) - assert status == 422 - assert isinstance(result, BasicError) - assert result.detail == ( - "When generate_all_manifests is True data_type_array must be None: " - "{'data_type_array': ['syn4', 'syn5']}" - ) - - result, status = generate_google_sheet_manifests( - schema_url=test_schema_url, - dataset_id_array=None, - asset_view_id="syn1", - data_type_array=None, - add_annotations=False, - manifest_title="title", - use_strict_validation=True, - generate_all_manifests=False, - ) - assert status == 422 - assert isinstance(result, BasicError) - assert result.detail == ( - "When generate_all_manifests is False data_type_array must be a list with " - "at least one item: {'data_type_array': None}" - ) - - result, status = generate_google_sheet_manifests( - schema_url=test_schema_url, - dataset_id_array=None, - asset_view_id="syn1", - data_type_array=[], - add_annotations=False, - manifest_title="title", - use_strict_validation=True, - generate_all_manifests=False, - ) - assert status == 422 - assert isinstance(result, BasicError) - assert result.detail == ( - "When generate_all_manifests is False data_type_array must be a list with " - "at least one item: {'data_type_array': []}" - ) - - result, status = generate_google_sheet_manifests( - schema_url=test_schema_url, - dataset_id_array=["syn4"], - asset_view_id="syn1", - data_type_array=["syn2", "syn3"], - add_annotations=False, - manifest_title="title", - use_strict_validation=True, - generate_all_manifests=False, - ) - assert status == 422 - assert isinstance(result, BasicError) - assert result.detail == ( - "When generate_all_manifests is False data_type_array and dataset_id_array " - "must both lists with the same length: " - "{'data_type_array': ['syn2', 'syn3'], 'dataset_id_array': ['syn4']}" - ) diff --git a/apps/schematic/api/schematic_api/test/test_manifest_generation_endpoints.py b/apps/schematic/api/schematic_api/test/test_manifest_generation_endpoints.py index 82853fa35e..dc845a6ad4 100644 --- a/apps/schematic/api/schematic_api/test/test_manifest_generation_endpoints.py +++ b/apps/schematic/api/schematic_api/test/test_manifest_generation_endpoints.py @@ -19,18 +19,6 @@ "Authorization": "Bearer xxx", } -CREATE_MANIFESTS_ARGS = [ - "path_to_data_model", - "output_format", - "data_types", - "title", - "access_token", - "dataset_ids", - "strict", - "use_annotations", - "data_model_labels", -] - class TestGenerateGoogleSheetManifests(BaseTestCase): """Tests google sheet manifest endpoint""" @@ -53,13 +41,13 @@ def test_success(self) -> None: assert list(result.keys()) == ["links"] assert result["links"] == ["l1"] call_args = mock_method.call_args.kwargs - assert list(call_args.keys()) == CREATE_MANIFESTS_ARGS assert call_args["output_format"] == "google_sheet" assert call_args["data_types"] == ["node_label"] assert not call_args["title"] assert call_args["dataset_ids"] == ["syn2"] assert call_args["strict"] assert not call_args["use_annotations"] + assert call_args["data_model_labels"] == "class_label" def test_arguments(self) -> None: """Test for correct arguments""" @@ -73,6 +61,7 @@ def test_arguments(self) -> None: "&manifestTitle=title" "&useStrictValidation=false" "&addAnnotations=true" + "&displayLabelType=display_label" ) response = self.client.open(url, method="GET", headers=HEADERS) self.assert200( @@ -83,15 +72,15 @@ def test_arguments(self) -> None: assert list(result.keys()) == ["links"] assert result["links"] == ["l1"] call_args = mock_method.call_args.kwargs - assert list(call_args.keys()) == CREATE_MANIFESTS_ARGS assert call_args["output_format"] == "google_sheet" assert call_args["data_types"] == ["data_type1", "data_type2"] assert call_args["dataset_ids"] == ["syn2", "syn3"] assert call_args["title"] == "title" assert not call_args["strict"] assert call_args["use_annotations"] + assert call_args["data_model_labels"] == "display_label" - url = f"{GENERATE_GOOGLE_SHEET_MANIFESTS_URL}" "&generateAllManifests=true" + url = f"{GENERATE_GOOGLE_SHEET_MANIFESTS_URL}&generateAllManifests=true" response = self.client.open(url, method="GET", headers=HEADERS) self.assert200( response, f"Response body is : {response.data.decode('utf-8')}" @@ -101,10 +90,10 @@ def test_arguments(self) -> None: assert list(result.keys()) == ["links"] assert result["links"] == ["l1"] call_args = mock_method.call_args.kwargs - assert list(call_args.keys()) == CREATE_MANIFESTS_ARGS assert call_args["output_format"] == "google_sheet" assert call_args["data_types"] == ["all manifests"] assert not call_args["title"] assert not call_args["dataset_ids"] assert call_args["strict"] assert not call_args["use_annotations"] + assert call_args["data_model_labels"] == "class_label" diff --git a/apps/schematic/api/schematic_api/test/test_schema_controller_endpoints.py b/apps/schematic/api/schematic_api/test/test_schema_controller_endpoints.py index 1e517e6340..02fed65857 100644 --- a/apps/schematic/api/schematic_api/test/test_schema_controller_endpoints.py +++ b/apps/schematic/api/schematic_api/test/test_schema_controller_endpoints.py @@ -12,6 +12,12 @@ } COMPONENT_URL = "/api/v1/components/Patient/?schemaUrl=" +COMPONENT_REQUIREMENTS_ARRAY_URL = ( + "/api/v1/components/Biospecimen/requirementsArray?schemaUrl=" +) +COMPONENT_REQUIREMENTS_GRAPH_URL = ( + "/api/v1/components/Biospecimen/requirementsGraph?schemaUrl=" +) CONNECTED_NODE_PAIR_ARRAY_URL = "/api/v1/connectedNodePairArray?schemaUrl=" CONNECTED_NODE_PAIR_PAGE_URL = "/api/v1/connectedNodePairPage?schemaUrl=" NODE_IS_REQUIRED_URL = "/api/v1/nodes/FamilyHistory/isRequired?schemaUrl=" @@ -47,6 +53,40 @@ def test_404(self) -> None: self.assert404(response, f"Response body is : {response.data.decode('utf-8')}") +class TestGetComponentRequirementsArray(BaseTestCase): + """Test case for component requirements array endpoint""" + + def test_success(self) -> None: + """Test for successful result""" + url = f"{COMPONENT_REQUIREMENTS_ARRAY_URL}{TEST_SCHEMA_URL}" + response = self.client.open(url, method="GET", headers=HEADERS) + self.assert200(response, f"Response body is : {response.data.decode('utf-8')}") + assert isinstance(response.json, list) + + def test_500(self) -> None: + """Test for 500 result""" + url = f"{COMPONENT_REQUIREMENTS_ARRAY_URL}not_a_url" + response = self.client.open(url, method="GET", headers=HEADERS) + self.assert500(response, f"Response body is : {response.data.decode('utf-8')}") + + +class TestGetComponentRequirementsGraph(BaseTestCase): + """Test case for component requirements graph endpoint""" + + def test_success(self) -> None: + """Test for successful result""" + url = f"{COMPONENT_REQUIREMENTS_GRAPH_URL}{TEST_SCHEMA_URL}" + response = self.client.open(url, method="GET", headers=HEADERS) + self.assert200(response, f"Response body is : {response.data.decode('utf-8')}") + assert isinstance(response.json, list) + + def test_500(self) -> None: + """Test for 500 result""" + url = f"{COMPONENT_REQUIREMENTS_GRAPH_URL}not_a_url" + response = self.client.open(url, method="GET", headers=HEADERS) + self.assert500(response, f"Response body is : {response.data.decode('utf-8')}") + + class TestGetConnectedNodePairArray(BaseTestCase): """Tests for connected node pair array endpoint""" diff --git a/apps/schematic/api/schematic_api/test/test_schema_controller_impl.py b/apps/schematic/api/schematic_api/test/test_schema_controller_impl.py index 93e4e7cb2d..6d15cfaf8e 100644 --- a/apps/schematic/api/schematic_api/test/test_schema_controller_impl.py +++ b/apps/schematic/api/schematic_api/test/test_schema_controller_impl.py @@ -1,7 +1,11 @@ """Tests for schema endpoint functions""" # pylint: disable=duplicate-code + from schematic_api.models.basic_error import BasicError +from schematic_api.models.component_requirement_subgraph import ( + ComponentRequirementSubgraph, +) from schematic_api.models.node_property_array import NodePropertyArray from schematic_api.models.validation_rule import ValidationRule from schematic_api.models.validation_rule_array import ValidationRuleArray @@ -13,6 +17,8 @@ from schematic_api.models.connected_node_pair import ConnectedNodePair from schematic_api.controllers.schema_controller_impl import ( get_component, + get_component_requirements_array, + get_component_requirements_graph, get_connected_node_pair_page, get_connected_node_pair_array, get_node_is_required, @@ -45,6 +51,60 @@ def test_internal_error(self, test_schema_url: str) -> None: assert isinstance(result, BasicError) +class TestGetComponentRequirementsArray: + """Tests get_component_requirements_array""" + + def test_success(self, test_schema_url: str) -> None: + """Test for successful result""" + result, status = get_component_requirements_array( + component_label="Biospecimen", + schema_url=test_schema_url, + display_label_type="class_label", + ) + assert status == 200 + assert isinstance(result, list) + for req in result: + assert isinstance(req, str) + + def test_internal_error(self, test_schema_url: str) -> None: + """Test for 500 result""" + result, status = get_component_requirements_array( + component_label="not_a_component", + schema_url=test_schema_url, + display_label_type="class_label", + ) + assert status == 500 + assert isinstance(result, BasicError) + + +class TestGetComponentRequirementsGraph: + """Tests get_component_requirements_graph""" + + def test_success(self, test_schema_url: str) -> None: + """Test for successful result""" + result, status = get_component_requirements_graph( + component_label="Biospecimen", + schema_url=test_schema_url, + display_label_type="class_label", + ) + assert status == 200 + assert isinstance(result, list) + for subgraph in result: + assert isinstance(subgraph, ComponentRequirementSubgraph) + assert isinstance(subgraph.component1, str) + assert isinstance(subgraph.component2, str) + + def test_internal_error(self, test_schema_url: str) -> None: + """Test for 500 result""" + result, status = get_component_requirements_graph( + component_label="not_a_component", + schema_url=test_schema_url, + display_label_type="class_label", + ) + assert status == 500 + assert isinstance(result, BasicError) + + class TestGetConnectedNodePairArray: """Tests get_connected_node_pair_array""" diff --git a/libs/schematic/api-description/build/openapi.yaml b/libs/schematic/api-description/build/openapi.yaml index 29c3b502d6..c385780d21 100644 --- a/libs/schematic/api-description/build/openapi.yaml +++ b/libs/schematic/api-description/build/openapi.yaml @@ -623,6 +623,48 @@ paths: type: string '500': $ref: '#/components/responses/InternalServerError' + /components/{componentLabel}/requirementsArray: + parameters: + - $ref: '#/components/parameters/componentLabel' + get: + tags: + - Schema + summary: Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in array form. + description: Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in array form. + operationId: getComponentRequirementsArray + parameters: + - $ref: '#/components/parameters/schemaUrl' + - $ref: '#/components/parameters/displayLabelType' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ComponentRequirementArray' + '500': + $ref: '#/components/responses/InternalServerError' + /components/{componentLabel}/requirementsGraph: + parameters: + - $ref: '#/components/parameters/componentLabel' + get: + tags: + - Schema + summary: Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in graph form. + description: Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in graph form. + operationId: getComponentRequirementsGraph + parameters: + - $ref: '#/components/parameters/schemaUrl' + - $ref: '#/components/parameters/displayLabelType' + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '#/components/schemas/ComponentRequirementGraph' + '500': + $ref: '#/components/responses/InternalServerError' /schemaAttributes: get: tags: @@ -872,19 +914,13 @@ paths: - $ref: '#/components/parameters/manifestTitle' - $ref: '#/components/parameters/dataTypeArray' - $ref: '#/components/parameters/displayLabelType' + - $ref: '#/components/parameters/useStrictValidation' - name: assetViewId in: query description: ID of view listing all project data assets. E.g. for Synapse this would be the Synapse ID of the fileview listing all data assets for a given project required: false schema: $ref: '#/components/schemas/AssetViewId' - - name: useStrictValidation - in: query - description: If true, users are blocked from entering incorrect values. If false, users will get a warning when using incorrect values. - required: false - schema: - type: boolean - default: true - name: generateAllManifests in: query description: If true, a manifest for all components will be generated, datasetIds will be ignored. If false, manifests for each id in datasetIds will be generated. @@ -1283,7 +1319,40 @@ components: ComponentLabel: description: The label of a component in a schema type: string - example: MolecularEntity + example: Patient + ComponentRequirementArray: + type: object + description: An array of components + properties: + componentRequirementsList: + type: array + items: + type: string + ComponentRequirementSubgraph: + type: object + description: A pair of components + properties: + component1: + type: string + description: The display name of the first component in the graph + example: component1 + component2: + type: string + description: The display name of the second component in the graph + example: component2 + required: + - component1 + - component2 + x-java-class-annotations: + - '@lombok.Builder' + ComponentRequirementGraph: + type: object + description: A graph of components + properties: + componentRequirementsGraph: + type: array + items: + $ref: '#/components/schemas/ComponentRequirementSubgraph' RelationshipType: description: A type of schema relationship type: string @@ -1359,12 +1428,15 @@ components: description: An array of dataset ids items: $ref: '#/components/schemas/DatasetId' + DataType: + description: A data type + type: string + example: Patient DataTypeArray: description: An array of data types type: array items: - type: string - example: Patient + $ref: '#/components/schemas/DataType' GoogleSheetLinks: type: object description: An array of google sheet links @@ -1681,3 +1753,11 @@ components: required: false schema: $ref: '#/components/schemas/DataTypeArray' + useStrictValidation: + name: useStrictValidation + in: query + description: If true, users are blocked from entering incorrect values. If false, users will get a warning when using incorrect values. + required: false + schema: + type: boolean + default: true diff --git a/libs/schematic/api-description/src/components/parameters/query/dataType.yaml b/libs/schematic/api-description/src/components/parameters/query/dataType.yaml new file mode 100644 index 0000000000..5bd38b8cc2 --- /dev/null +++ b/libs/schematic/api-description/src/components/parameters/query/dataType.yaml @@ -0,0 +1,6 @@ +name: dataType +in: query +description: A data type +required: false +schema: + $ref: ../../schemas/DataType.yaml diff --git a/libs/schematic/api-description/src/components/parameters/query/useStrictValidation.yaml b/libs/schematic/api-description/src/components/parameters/query/useStrictValidation.yaml new file mode 100644 index 0000000000..b403090dcd --- /dev/null +++ b/libs/schematic/api-description/src/components/parameters/query/useStrictValidation.yaml @@ -0,0 +1,8 @@ +name: useStrictValidation +in: query +description: If true, users are blocked from entering incorrect values. + If false, users will get a warning when using incorrect values. +required: false +schema: + type: boolean + default: true diff --git a/libs/schematic/api-description/src/components/schemas/ComponentDisplay.yaml b/libs/schematic/api-description/src/components/schemas/ComponentDisplay.yaml index 9ac43f40d5..2aad3cb2ac 100644 --- a/libs/schematic/api-description/src/components/schemas/ComponentDisplay.yaml +++ b/libs/schematic/api-description/src/components/schemas/ComponentDisplay.yaml @@ -1,3 +1,3 @@ description: The display name of a component in a schema type: string -example: MolecularEntity +example: Patient diff --git a/libs/schematic/api-description/src/components/schemas/ComponentLabel.yaml b/libs/schematic/api-description/src/components/schemas/ComponentLabel.yaml index 206ef98e55..f64684b560 100644 --- a/libs/schematic/api-description/src/components/schemas/ComponentLabel.yaml +++ b/libs/schematic/api-description/src/components/schemas/ComponentLabel.yaml @@ -1,3 +1,3 @@ description: The label of a component in a schema type: string -example: MolecularEntity +example: Patient diff --git a/libs/schematic/api-description/src/components/schemas/ComponentRequirementArray.yaml b/libs/schematic/api-description/src/components/schemas/ComponentRequirementArray.yaml new file mode 100644 index 0000000000..1a6ff6436a --- /dev/null +++ b/libs/schematic/api-description/src/components/schemas/ComponentRequirementArray.yaml @@ -0,0 +1,7 @@ +type: object +description: An array of components +properties: + componentRequirementsList: + type: array + items: + type: string diff --git a/libs/schematic/api-description/src/components/schemas/ComponentRequirementGraph.yaml b/libs/schematic/api-description/src/components/schemas/ComponentRequirementGraph.yaml new file mode 100644 index 0000000000..a528c2d8e4 --- /dev/null +++ b/libs/schematic/api-description/src/components/schemas/ComponentRequirementGraph.yaml @@ -0,0 +1,7 @@ +type: object +description: A graph of components +properties: + componentRequirementsGraph: + type: array + items: + $ref: ComponentRequirementSubgraph.yaml diff --git a/libs/schematic/api-description/src/components/schemas/ComponentRequirementSubgraph.yaml b/libs/schematic/api-description/src/components/schemas/ComponentRequirementSubgraph.yaml new file mode 100644 index 0000000000..6a22a9c1bb --- /dev/null +++ b/libs/schematic/api-description/src/components/schemas/ComponentRequirementSubgraph.yaml @@ -0,0 +1,16 @@ +type: object +description: A pair of components +properties: + component1: + type: string + description: The display name of the first component in the graph + example: component1 + component2: + type: string + description: The display name of the second component in the graph + example: component2 +required: + - component1 + - component2 +x-java-class-annotations: + - '@lombok.Builder' diff --git a/libs/schematic/api-description/src/components/schemas/DataType.yaml b/libs/schematic/api-description/src/components/schemas/DataType.yaml new file mode 100644 index 0000000000..746e651257 --- /dev/null +++ b/libs/schematic/api-description/src/components/schemas/DataType.yaml @@ -0,0 +1,3 @@ +description: A data type +type: string +example: Patient diff --git a/libs/schematic/api-description/src/components/schemas/DataTypeArray.yaml b/libs/schematic/api-description/src/components/schemas/DataTypeArray.yaml index a73a0cbca2..8500bbedfd 100644 --- a/libs/schematic/api-description/src/components/schemas/DataTypeArray.yaml +++ b/libs/schematic/api-description/src/components/schemas/DataTypeArray.yaml @@ -1,5 +1,4 @@ description: An array of data types type: array items: - type: string - example: Patient + $ref: DataType.yaml diff --git a/libs/schematic/api-description/src/openapi.yaml b/libs/schematic/api-description/src/openapi.yaml index 944ffdf4b2..ebd57d8ec9 100644 --- a/libs/schematic/api-description/src/openapi.yaml +++ b/libs/schematic/api-description/src/openapi.yaml @@ -89,6 +89,12 @@ paths: /components/{componentLabel}/: $ref: paths/components/@{componentLabel}/component.yaml + /components/{componentLabel}/requirementsArray: + $ref: paths/components/@{componentLabel}/requirementsArray.yaml + + /components/{componentLabel}/requirementsGraph: + $ref: paths/components/@{componentLabel}/requirementsGraph.yaml + /schemaAttributes: $ref: paths/schemaAttributes.yaml diff --git a/libs/schematic/api-description/src/paths/components/@{componentLabel}/requirementsArray.yaml b/libs/schematic/api-description/src/paths/components/@{componentLabel}/requirementsArray.yaml new file mode 100644 index 0000000000..2605d91337 --- /dev/null +++ b/libs/schematic/api-description/src/paths/components/@{componentLabel}/requirementsArray.yaml @@ -0,0 +1,20 @@ +parameters: + - $ref: ../../../components/parameters/path/componentLabel.yaml +get: + tags: + - Schema + summary: Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in array form. + description: Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in array form. + operationId: getComponentRequirementsArray + parameters: + - $ref: ../../../components/parameters/query/schemaUrl.yaml + - $ref: ../../../components/parameters/query/displayLabelType.yaml + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: ../../../components/schemas/ComponentRequirementArray.yaml + '500': + $ref: ../../../components/responses/InternalServerError.yaml diff --git a/libs/schematic/api-description/src/paths/components/@{componentLabel}/requirementsGraph.yaml b/libs/schematic/api-description/src/paths/components/@{componentLabel}/requirementsGraph.yaml new file mode 100644 index 0000000000..50fb974060 --- /dev/null +++ b/libs/schematic/api-description/src/paths/components/@{componentLabel}/requirementsGraph.yaml @@ -0,0 +1,20 @@ +parameters: + - $ref: ../../../components/parameters/path/componentLabel.yaml +get: + tags: + - Schema + summary: Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in graph form. + description: Given a source model component (see https://w3id.org/biolink/vocab/category for definnition of component), return all components required by it in graph form. + operationId: getComponentRequirementsGraph + parameters: + - $ref: ../../../components/parameters/query/schemaUrl.yaml + - $ref: ../../../components/parameters/query/displayLabelType.yaml + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: ../../../components/schemas/ComponentRequirementGraph.yaml + '500': + $ref: ../../../components/responses/InternalServerError.yaml diff --git a/libs/schematic/api-description/src/paths/generateGoogleSheetManifests.yaml b/libs/schematic/api-description/src/paths/generateGoogleSheetManifests.yaml index 251622d549..40ab67dd60 100644 --- a/libs/schematic/api-description/src/paths/generateGoogleSheetManifests.yaml +++ b/libs/schematic/api-description/src/paths/generateGoogleSheetManifests.yaml @@ -11,20 +11,13 @@ get: - $ref: ../components/parameters/query/manifestTitle.yaml - $ref: ../components/parameters/query/dataTypeArray.yaml - $ref: ../components/parameters/query/displayLabelType.yaml + - $ref: ../components/parameters/query/useStrictValidation.yaml - name: assetViewId in: query description: ID of view listing all project data assets. E.g. for Synapse this would be the Synapse ID of the fileview listing all data assets for a given project required: false schema: $ref: ../components/schemas/AssetViewId.yaml - - name: useStrictValidation - in: query - description: If true, users are blocked from entering incorrect values. - If false, users will get a warning when using incorrect values. - required: false - schema: - type: boolean - default: true - name: generateAllManifests in: query description: