diff --git a/python-restclient/.openapi-generator/FILES b/python-restclient/.openapi-generator/FILES index bd03d3b283..54329b8441 100644 --- a/python-restclient/.openapi-generator/FILES +++ b/python-restclient/.openapi-generator/FILES @@ -19,8 +19,11 @@ docs/Curve.md docs/CurveSelectionInfo.md docs/DataIdentifier.md docs/DetailedState.md +docs/DifferentParameterValues.md docs/Domain.md docs/ExportEvent.md +docs/ExportFormat.md +docs/ExportHistory.md docs/ExportProgressType.md docs/ExportResourceApi.md docs/ExportableDataType.md @@ -135,8 +138,11 @@ vcell_client/models/curve.py vcell_client/models/curve_selection_info.py vcell_client/models/data_identifier.py vcell_client/models/detailed_state.py +vcell_client/models/different_parameter_values.py vcell_client/models/domain.py vcell_client/models/export_event.py +vcell_client/models/export_format.py +vcell_client/models/export_history.py vcell_client/models/export_progress_type.py vcell_client/models/exportable_data_type.py vcell_client/models/extent.py diff --git a/python-restclient/README.md b/python-restclient/README.md index 9f03577c84..c91772ead2 100644 --- a/python-restclient/README.md +++ b/python-restclient/README.md @@ -98,6 +98,7 @@ Class | Method | HTTP request | Description *BioModelResourceApi* | [**save_bio_model**](docs/BioModelResourceApi.md#save_bio_model) | **POST** /api/v1/bioModel | Save's the given BioModel. Optional parameters of name and simulations to update due to math changes. Returns saved BioModel as VCML. *ExportResourceApi* | [**export_n5**](docs/ExportResourceApi.md#export_n5) | **POST** /api/v1/export/N5 | *ExportResourceApi* | [**export_status**](docs/ExportResourceApi.md#export_status) | **GET** /api/v1/export/status | +*ExportResourceApi* | [**get_export_history**](docs/ExportResourceApi.md#get_export_history) | **GET** /api/v1/export/history | *FieldDataResourceApi* | [**advanced_create**](docs/FieldDataResourceApi.md#advanced_create) | **POST** /api/v1/fieldData/advancedCreate | Create Field Data with granular detail in one request.The following files are accepted: .tif and .zip. *FieldDataResourceApi* | [**analyze_file**](docs/FieldDataResourceApi.md#analyze_file) | **POST** /api/v1/fieldData/analyzeFile | Analyze uploaded image file (Tiff, Zip, and Non-GPL BioFormats) and return field data. Color mapped images not supported (the colors in those images will be interpreted as separate channels). Filenames must be lowercase alphanumeric, and can contain underscores. *FieldDataResourceApi* | [**copy_models_field_data**](docs/FieldDataResourceApi.md#copy_models_field_data) | **POST** /api/v1/fieldData/copyModelsFieldData | Copy all existing field data from a BioModel/MathModel that you have access to, but don't own. @@ -163,8 +164,11 @@ Class | Method | HTTP request | Description - [CurveSelectionInfo](docs/CurveSelectionInfo.md) - [DataIdentifier](docs/DataIdentifier.md) - [DetailedState](docs/DetailedState.md) + - [DifferentParameterValues](docs/DifferentParameterValues.md) - [Domain](docs/Domain.md) - [ExportEvent](docs/ExportEvent.md) + - [ExportFormat](docs/ExportFormat.md) + - [ExportHistory](docs/ExportHistory.md) - [ExportProgressType](docs/ExportProgressType.md) - [ExportableDataType](docs/ExportableDataType.md) - [Extent](docs/Extent.md) diff --git a/python-restclient/docs/DifferentParameterValues.md b/python-restclient/docs/DifferentParameterValues.md new file mode 100644 index 0000000000..1451490b86 --- /dev/null +++ b/python-restclient/docs/DifferentParameterValues.md @@ -0,0 +1,30 @@ +# DifferentParameterValues + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**parameter_name** | **str** | | [optional] +**original_value** | **str** | | [optional] +**changed_value** | **str** | | [optional] + +## Example + +```python +from vcell_client.models.different_parameter_values import DifferentParameterValues + +# TODO update the JSON string below +json = "{}" +# create an instance of DifferentParameterValues from a JSON string +different_parameter_values_instance = DifferentParameterValues.from_json(json) +# print the JSON string representation of the object +print DifferentParameterValues.to_json() + +# convert the object into a dict +different_parameter_values_dict = different_parameter_values_instance.to_dict() +# create an instance of DifferentParameterValues from a dict +different_parameter_values_form_dict = different_parameter_values.from_dict(different_parameter_values_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/ExportFormat.md b/python-restclient/docs/ExportFormat.md new file mode 100644 index 0000000000..70aaec6b71 --- /dev/null +++ b/python-restclient/docs/ExportFormat.md @@ -0,0 +1,10 @@ +# ExportFormat + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- + +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/ExportHistory.md b/python-restclient/docs/ExportHistory.md new file mode 100644 index 0000000000..4e0a56a60f --- /dev/null +++ b/python-restclient/docs/ExportHistory.md @@ -0,0 +1,41 @@ +# ExportHistory + + +## Properties +Name | Type | Description | Notes +------------ | ------------- | ------------- | ------------- +**export_job_id** | **int** | | [optional] +**simulation_ref** | **str** | | [optional] +**bio_model_ref** | **str** | | [optional] +**math_model_ref** | **str** | | [optional] +**math_ref** | **str** | | [optional] +**export_format** | [**ExportFormat**](ExportFormat.md) | | [optional] +**export_date** | **datetime** | | [optional] +**uri** | **str** | | [optional] +**sim_name** | **str** | | [optional] +**model_name** | **str** | | [optional] +**variables** | **List[str]** | | [optional] +**start_time_value** | **float** | | [optional] +**end_time_value** | **float** | | [optional] +**event_status** | [**ExportProgressType**](ExportProgressType.md) | | [optional] + +## Example + +```python +from vcell_client.models.export_history import ExportHistory + +# TODO update the JSON string below +json = "{}" +# create an instance of ExportHistory from a JSON string +export_history_instance = ExportHistory.from_json(json) +# print the JSON string representation of the object +print ExportHistory.to_json() + +# convert the object into a dict +export_history_dict = export_history_instance.to_dict() +# create an instance of ExportHistory from a dict +export_history_form_dict = export_history.from_dict(export_history_dict) +``` +[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) + + diff --git a/python-restclient/docs/ExportResourceApi.md b/python-restclient/docs/ExportResourceApi.md index 0f8f17bfa0..243034843d 100644 --- a/python-restclient/docs/ExportResourceApi.md +++ b/python-restclient/docs/ExportResourceApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**export_n5**](ExportResourceApi.md#export_n5) | **POST** /api/v1/export/N5 | [**export_status**](ExportResourceApi.md#export_status) | **GET** /api/v1/export/status | +[**get_export_history**](ExportResourceApi.md#get_export_history) | **GET** /api/v1/export/history | # **export_n5** @@ -156,3 +157,74 @@ Name | Type | Description | Notes [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +# **get_export_history** +> List[ExportHistory] get_export_history(page_number=page_number) + + + +### Example + +```python +import time +import os +import vcell_client +from vcell_client.models.export_history import ExportHistory +from vcell_client.rest import ApiException +from pprint import pprint + +# Defining the host is optional and defaults to https://vcell.cam.uchc.edu +# See configuration.py for a list of all supported configuration parameters. +configuration = vcell_client.Configuration( + host = "https://vcell.cam.uchc.edu" +) + +# The client must configure the authentication and authorization parameters +# in accordance with the API server security policy. +# Examples for each auth method are provided below, use the example that +# satisfies your auth use case. + +# Enter a context with an instance of the API client +with vcell_client.ApiClient(configuration) as api_client: + # Create an instance of the API class + api_instance = vcell_client.ExportResourceApi(api_client) + page_number = 56 # int | (optional) + + try: + api_response = api_instance.get_export_history(page_number=page_number) + print("The response of ExportResourceApi->get_export_history:\n") + pprint(api_response) + except Exception as e: + print("Exception when calling ExportResourceApi->get_export_history: %s\n" % e) +``` + + + +### Parameters + +Name | Type | Description | Notes +------------- | ------------- | ------------- | ------------- + **page_number** | **int**| | [optional] + +### Return type + +[**List[ExportHistory]**](ExportHistory.md) + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +**200** | OK | - | +**401** | Not Authenticated | - | +**403** | Not Allowed | - | +**500** | Data Access Exception | - | + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + diff --git a/python-restclient/docs/HumanReadableExportData.md b/python-restclient/docs/HumanReadableExportData.md index bbe8bee352..c04ba6e6b4 100644 --- a/python-restclient/docs/HumanReadableExportData.md +++ b/python-restclient/docs/HumanReadableExportData.md @@ -7,7 +7,7 @@ Name | Type | Description | Notes **simulation_name** | **str** | | [optional] **biomodel_name** | **str** | | [optional] **application_name** | **str** | | [optional] -**different_parameter_values** | **List[str]** | | [optional] +**different_parameter_values** | [**List[DifferentParameterValues]**](DifferentParameterValues.md) | | [optional] **application_type** | **str** | | [optional] **server_saved_file_name** | **str** | | [optional] **non_spatial** | **bool** | | [optional] diff --git a/python-restclient/docs/StandardExportInfo.md b/python-restclient/docs/StandardExportInfo.md index da7a8f6e8e..bfac077b60 100644 --- a/python-restclient/docs/StandardExportInfo.md +++ b/python-restclient/docs/StandardExportInfo.md @@ -12,6 +12,9 @@ Name | Type | Description | Notes **geometry_specs** | [**GeometrySpecDTO**](GeometrySpecDTO.md) | | [optional] **time_specs** | [**TimeSpecs**](TimeSpecs.md) | | [optional] **variable_specs** | [**VariableSpecs**](VariableSpecs.md) | | [optional] +**bio_model_key** | **str** | | [optional] +**math_model_key** | **str** | | [optional] +**math_description_key** | **str** | | [optional] ## Example diff --git a/python-restclient/test/test_different_parameter_values.py b/python-restclient/test/test_different_parameter_values.py new file mode 100644 index 0000000000..03f9abf69b --- /dev/null +++ b/python-restclient/test/test_different_parameter_values.py @@ -0,0 +1,55 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.different_parameter_values import DifferentParameterValues + +class TestDifferentParameterValues(unittest.TestCase): + """DifferentParameterValues unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> DifferentParameterValues: + """Test DifferentParameterValues + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `DifferentParameterValues` + """ + model = DifferentParameterValues() + if include_optional: + return DifferentParameterValues( + parameter_name = '', + original_value = '', + changed_value = '' + ) + else: + return DifferentParameterValues( + ) + """ + + def testDifferentParameterValues(self): + """Test DifferentParameterValues""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_export_format.py b/python-restclient/test/test_export_format.py new file mode 100644 index 0000000000..473e94d801 --- /dev/null +++ b/python-restclient/test/test_export_format.py @@ -0,0 +1,35 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.export_format import ExportFormat + +class TestExportFormat(unittest.TestCase): + """ExportFormat unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def testExportFormat(self): + """Test ExportFormat""" + # inst = ExportFormat() + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/test/test_export_history.py b/python-restclient/test/test_export_history.py new file mode 100644 index 0000000000..fb979122d6 --- /dev/null +++ b/python-restclient/test/test_export_history.py @@ -0,0 +1,78 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +import unittest +import datetime + +from vcell_client.models.export_history import ExportHistory + +class TestExportHistory(unittest.TestCase): + """ExportHistory unit test stubs""" + + def setUp(self): + pass + + def tearDown(self): + pass + + def make_instance(self, include_optional) -> ExportHistory: + """Test ExportHistory + include_option is a boolean, when False only required + params are included, when True both required and + optional params are included """ + # uncomment below to create an instance of `ExportHistory` + """ + model = ExportHistory() + if include_optional: + return ExportHistory( + job_id = 56, + simulation_ref = '', + export_format = 'CSV', + export_date = '', + uri = '', + data_id_value = '', + sim_name = '', + app_name = '', + bio_name = '', + variables = [ + '' + ], + parameter_values = [ + vcell_client.models.different_parameter_values.DifferentParameterValues( + parameter_name = '', + original_value = '', + changed_value = '', ) + ], + start_time_value = 1.337, + end_time_value = 1.337, + saved_file_name_value = '', + application_type_value = '', + non_spatial_value = True, + z_slices_value = 56, + t_slices_value = 56, + num_variables_value = 56 + ) + else: + return ExportHistory( + ) + """ + + def testExportHistory(self): + """Test ExportHistory""" + # inst_req_only = self.make_instance(include_optional=False) + # inst_req_and_optional = self.make_instance(include_optional=True) + +if __name__ == '__main__': + unittest.main() diff --git a/python-restclient/vcell_client/__init__.py b/python-restclient/vcell_client/__init__.py index 8ad5416366..7ccbfe809f 100644 --- a/python-restclient/vcell_client/__init__.py +++ b/python-restclient/vcell_client/__init__.py @@ -59,8 +59,11 @@ from vcell_client.models.curve_selection_info import CurveSelectionInfo from vcell_client.models.data_identifier import DataIdentifier from vcell_client.models.detailed_state import DetailedState +from vcell_client.models.different_parameter_values import DifferentParameterValues from vcell_client.models.domain import Domain from vcell_client.models.export_event import ExportEvent +from vcell_client.models.export_format import ExportFormat +from vcell_client.models.export_history import ExportHistory from vcell_client.models.export_progress_type import ExportProgressType from vcell_client.models.exportable_data_type import ExportableDataType from vcell_client.models.extent import Extent diff --git a/python-restclient/vcell_client/api/export_resource_api.py b/python-restclient/vcell_client/api/export_resource_api.py index 51b2e44c4f..1a495797be 100644 --- a/python-restclient/vcell_client/api/export_resource_api.py +++ b/python-restclient/vcell_client/api/export_resource_api.py @@ -29,6 +29,7 @@ from typing import List, Optional from vcell_client.models.export_event import ExportEvent +from vcell_client.models.export_history import ExportHistory from vcell_client.models.n5_export_request import N5ExportRequest from vcell_client.api_client import ApiClient @@ -610,3 +611,273 @@ def _export_status_serialize( ) + + + @validate_call + def get_export_history( + self, + page_number: Optional[StrictInt] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> List[ExportHistory]: + """get_export_history + + + :param page_number: + :type page_number: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_export_history_serialize( + page_number=page_number, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[ExportHistory]", + '401': "VCellHTTPError", + '403': None, + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ).data + + + @validate_call + def get_export_history_with_http_info( + self, + page_number: Optional[StrictInt] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> ApiResponse[List[ExportHistory]]: + """get_export_history + + + :param page_number: + :type page_number: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_export_history_serialize( + page_number=page_number, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[ExportHistory]", + '401': "VCellHTTPError", + '403': None, + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + response_data.read() + return self.api_client.response_deserialize( + response_data=response_data, + response_types_map=_response_types_map, + ) + + + @validate_call + def get_export_history_without_preload_content( + self, + page_number: Optional[StrictInt] = None, + _request_timeout: Union[ + None, + Annotated[StrictFloat, Field(gt=0)], + Tuple[ + Annotated[StrictFloat, Field(gt=0)], + Annotated[StrictFloat, Field(gt=0)] + ] + ] = None, + _request_auth: Optional[Dict[StrictStr, Any]] = None, + _content_type: Optional[StrictStr] = None, + _headers: Optional[Dict[StrictStr, Any]] = None, + _host_index: Annotated[StrictInt, Field(ge=0, le=0)] = 0, + ) -> RESTResponseType: + """get_export_history + + + :param page_number: + :type page_number: int + :param _request_timeout: timeout setting for this request. If one + number provided, it will be total request + timeout. It can also be a pair (tuple) of + (connection, read) timeouts. + :type _request_timeout: int, tuple(int, int), optional + :param _request_auth: set to override the auth_settings for an a single + request; this effectively ignores the + authentication in the spec for a single request. + :type _request_auth: dict, optional + :param _content_type: force content-type for the request. + :type _content_type: str, Optional + :param _headers: set to override the headers for a single + request; this effectively ignores the headers + in the spec for a single request. + :type _headers: dict, optional + :param _host_index: set to override the host_index for a single + request; this effectively ignores the host_index + in the spec for a single request. + :type _host_index: int, optional + :return: Returns the result object. + """ # noqa: E501 + + _param = self._get_export_history_serialize( + page_number=page_number, + _request_auth=_request_auth, + _content_type=_content_type, + _headers=_headers, + _host_index=_host_index + ) + + _response_types_map: Dict[str, Optional[str]] = { + '200': "List[ExportHistory]", + '401': "VCellHTTPError", + '403': None, + '500': "VCellHTTPError" + + } + response_data = self.api_client.call_api( + *_param, + _request_timeout=_request_timeout + ) + return response_data.response + + + def _get_export_history_serialize( + self, + page_number, + _request_auth, + _content_type, + _headers, + _host_index, + ) -> Tuple: + + _host = None + + _collection_formats: Dict[str, str] = { + + } + + _path_params: Dict[str, str] = {} + _query_params: List[Tuple[str, str]] = [] + _header_params: Dict[str, Optional[str]] = _headers or {} + _form_params: List[Tuple[str, str]] = [] + _files: Dict[str, str] = {} + _body_params: Optional[bytes] = None + + # process the path parameters + # process the query parameters + if page_number is not None: + + _query_params.append(('pageNumber', page_number)) + + # process the header parameters + # process the form parameters + # process the body parameter + + + # set the HTTP header `Accept` + _header_params['Accept'] = self.api_client.select_header_accept( + [ + 'application/json' + ] + ) + + + # authentication setting + _auth_settings: List[str] = [ + 'openId' + ] + + return self.api_client.param_serialize( + method='GET', + resource_path='/api/v1/export/history', + path_params=_path_params, + query_params=_query_params, + header_params=_header_params, + body=_body_params, + post_params=_form_params, + files=_files, + auth_settings=_auth_settings, + collection_formats=_collection_formats, + _host=_host, + _request_auth=_request_auth + ) + + diff --git a/python-restclient/vcell_client/models/__init__.py b/python-restclient/vcell_client/models/__init__.py index 5690747f2e..f529412d99 100644 --- a/python-restclient/vcell_client/models/__init__.py +++ b/python-restclient/vcell_client/models/__init__.py @@ -28,8 +28,11 @@ from vcell_client.models.curve_selection_info import CurveSelectionInfo from vcell_client.models.data_identifier import DataIdentifier from vcell_client.models.detailed_state import DetailedState +from vcell_client.models.different_parameter_values import DifferentParameterValues from vcell_client.models.domain import Domain from vcell_client.models.export_event import ExportEvent +from vcell_client.models.export_format import ExportFormat +from vcell_client.models.export_history import ExportHistory from vcell_client.models.export_progress_type import ExportProgressType from vcell_client.models.exportable_data_type import ExportableDataType from vcell_client.models.extent import Extent diff --git a/python-restclient/vcell_client/models/different_parameter_values.py b/python-restclient/vcell_client/models/different_parameter_values.py new file mode 100644 index 0000000000..8851f45eb2 --- /dev/null +++ b/python-restclient/vcell_client/models/different_parameter_values.py @@ -0,0 +1,98 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + + +from typing import Any, ClassVar, Dict, List, Optional +from pydantic import BaseModel, StrictStr +from pydantic import Field +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class DifferentParameterValues(BaseModel): + """ + DifferentParameterValues + """ # noqa: E501 + parameter_name: Optional[StrictStr] = Field(default=None, alias="parameterName") + original_value: Optional[StrictStr] = Field(default=None, alias="originalValue") + changed_value: Optional[StrictStr] = Field(default=None, alias="changedValue") + __properties: ClassVar[List[str]] = ["parameterName", "originalValue", "changedValue"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of DifferentParameterValues from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of DifferentParameterValues from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in DifferentParameterValues) in the input: " + _key) + + _obj = cls.model_validate({ + "parameterName": obj.get("parameterName"), + "originalValue": obj.get("originalValue"), + "changedValue": obj.get("changedValue") + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/export_format.py b/python-restclient/vcell_client/models/export_format.py new file mode 100644 index 0000000000..dc6f9728bb --- /dev/null +++ b/python-restclient/vcell_client/models/export_format.py @@ -0,0 +1,56 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import json +import pprint +import re # noqa: F401 +from enum import Enum + + + +try: + from typing import Self +except ImportError: + from typing_extensions import Self + + +class ExportFormat(str, Enum): + """ + ExportFormat + """ + + """ + allowed enum values + """ + CSV = 'CSV' + HDF5 = 'HDF5' + QUICKTIME = 'QUICKTIME' + GIF = 'GIF' + ANIMATED_GIF = 'ANIMATED_GIF' + FORMAT_JPEG = 'FORMAT_JPEG' + NRRD = 'NRRD' + UCD = 'UCD' + VTK_UNSTRUCT = 'VTK_UNSTRUCT' + VTK_IMAGE = 'VTK_IMAGE' + PLY = 'PLY' + N5 = 'N5' + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of ExportFormat from a JSON string""" + return cls(json.loads(json_str)) + + diff --git a/python-restclient/vcell_client/models/export_history.py b/python-restclient/vcell_client/models/export_history.py new file mode 100644 index 0000000000..cd2d206fb8 --- /dev/null +++ b/python-restclient/vcell_client/models/export_history.py @@ -0,0 +1,122 @@ +# coding: utf-8 + +""" + VCell API + + VCell API + + The version of the OpenAPI document: 1.0.1 + Contact: vcell_support@uchc.com + Generated by OpenAPI Generator (https://openapi-generator.tech) + + Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations +import pprint +import re # noqa: F401 +import json + +from datetime import datetime +from typing import Any, ClassVar, Dict, List, Optional, Union +from pydantic import BaseModel, StrictFloat, StrictInt, StrictStr +from pydantic import Field +from vcell_client.models.export_format import ExportFormat +from vcell_client.models.export_progress_type import ExportProgressType +try: + from typing import Self +except ImportError: + from typing_extensions import Self + +class ExportHistory(BaseModel): + """ + ExportHistory + """ # noqa: E501 + export_job_id: Optional[StrictInt] = Field(default=None, alias="exportJobID") + simulation_ref: Optional[StrictStr] = Field(default=None, alias="simulationRef") + bio_model_ref: Optional[StrictStr] = Field(default=None, alias="bioModelRef") + math_model_ref: Optional[StrictStr] = Field(default=None, alias="mathModelRef") + math_ref: Optional[StrictStr] = Field(default=None, alias="mathRef") + export_format: Optional[ExportFormat] = Field(default=None, alias="exportFormat") + export_date: Optional[datetime] = Field(default=None, alias="exportDate") + uri: Optional[StrictStr] = None + sim_name: Optional[StrictStr] = Field(default=None, alias="simName") + model_name: Optional[StrictStr] = Field(default=None, alias="modelName") + variables: Optional[List[StrictStr]] = None + start_time_value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, alias="startTimeValue") + end_time_value: Optional[Union[StrictFloat, StrictInt]] = Field(default=None, alias="endTimeValue") + event_status: Optional[ExportProgressType] = Field(default=None, alias="eventStatus") + __properties: ClassVar[List[str]] = ["exportJobID", "simulationRef", "bioModelRef", "mathModelRef", "mathRef", "exportFormat", "exportDate", "uri", "simName", "modelName", "variables", "startTimeValue", "endTimeValue", "eventStatus"] + + model_config = { + "populate_by_name": True, + "validate_assignment": True + } + + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Self: + """Create an instance of ExportHistory from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + _dict = self.model_dump( + by_alias=True, + exclude={ + }, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Dict) -> Self: + """Create an instance of ExportHistory from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + # raise errors for additional fields in the input + for _key in obj.keys(): + if _key not in cls.__properties: + raise ValueError("Error due to additional fields (not defined in ExportHistory) in the input: " + _key) + + _obj = cls.model_validate({ + "exportJobID": obj.get("exportJobID"), + "simulationRef": obj.get("simulationRef"), + "bioModelRef": obj.get("bioModelRef"), + "mathModelRef": obj.get("mathModelRef"), + "mathRef": obj.get("mathRef"), + "exportFormat": obj.get("exportFormat"), + "exportDate": obj.get("exportDate"), + "uri": obj.get("uri"), + "simName": obj.get("simName"), + "modelName": obj.get("modelName"), + "variables": obj.get("variables"), + "startTimeValue": obj.get("startTimeValue"), + "endTimeValue": obj.get("endTimeValue"), + "eventStatus": obj.get("eventStatus") + }) + return _obj + + diff --git a/python-restclient/vcell_client/models/human_readable_export_data.py b/python-restclient/vcell_client/models/human_readable_export_data.py index d8b3b80707..eac6da9c33 100644 --- a/python-restclient/vcell_client/models/human_readable_export_data.py +++ b/python-restclient/vcell_client/models/human_readable_export_data.py @@ -22,6 +22,7 @@ from typing import Any, ClassVar, Dict, List, Optional from pydantic import BaseModel, StrictBool, StrictInt, StrictStr from pydantic import Field +from vcell_client.models.different_parameter_values import DifferentParameterValues try: from typing import Self except ImportError: @@ -34,7 +35,7 @@ class HumanReadableExportData(BaseModel): simulation_name: Optional[StrictStr] = Field(default=None, alias="simulationName") biomodel_name: Optional[StrictStr] = Field(default=None, alias="biomodelName") application_name: Optional[StrictStr] = Field(default=None, alias="applicationName") - different_parameter_values: Optional[List[StrictStr]] = Field(default=None, alias="differentParameterValues") + different_parameter_values: Optional[List[DifferentParameterValues]] = Field(default=None, alias="differentParameterValues") application_type: Optional[StrictStr] = Field(default=None, alias="applicationType") server_saved_file_name: Optional[StrictStr] = Field(default=None, alias="serverSavedFileName") non_spatial: Optional[StrictBool] = Field(default=None, alias="nonSpatial") @@ -80,6 +81,13 @@ def to_dict(self) -> Dict[str, Any]: }, exclude_none=True, ) + # override the default output from pydantic by calling `to_dict()` of each item in different_parameter_values (list) + _items = [] + if self.different_parameter_values: + for _item in self.different_parameter_values: + if _item: + _items.append(_item.to_dict()) + _dict['differentParameterValues'] = _items return _dict @classmethod @@ -100,7 +108,7 @@ def from_dict(cls, obj: Dict) -> Self: "simulationName": obj.get("simulationName"), "biomodelName": obj.get("biomodelName"), "applicationName": obj.get("applicationName"), - "differentParameterValues": obj.get("differentParameterValues"), + "differentParameterValues": [DifferentParameterValues.from_dict(_item) for _item in obj.get("differentParameterValues")] if obj.get("differentParameterValues") is not None else None, "applicationType": obj.get("applicationType"), "serverSavedFileName": obj.get("serverSavedFileName"), "nonSpatial": obj.get("nonSpatial"), diff --git a/python-restclient/vcell_client/models/standard_export_info.py b/python-restclient/vcell_client/models/standard_export_info.py index 3244390068..bd0db9c0b8 100644 --- a/python-restclient/vcell_client/models/standard_export_info.py +++ b/python-restclient/vcell_client/models/standard_export_info.py @@ -43,7 +43,10 @@ class StandardExportInfo(BaseModel): geometry_specs: Optional[GeometrySpecDTO] = Field(default=None, alias="geometrySpecs") time_specs: Optional[TimeSpecs] = Field(default=None, alias="timeSpecs") variable_specs: Optional[VariableSpecs] = Field(default=None, alias="variableSpecs") - __properties: ClassVar[List[str]] = ["outputContext", "contextName", "simulationName", "simulationKey", "simulationJob", "geometrySpecs", "timeSpecs", "variableSpecs"] + bio_model_key: Optional[StrictStr] = Field(default=None, alias="bioModelKey") + math_model_key: Optional[StrictStr] = Field(default=None, alias="mathModelKey") + math_description_key: Optional[StrictStr] = Field(default=None, alias="mathDescriptionKey") + __properties: ClassVar[List[str]] = ["outputContext", "contextName", "simulationName", "simulationKey", "simulationJob", "geometrySpecs", "timeSpecs", "variableSpecs", "bioModelKey", "mathModelKey", "mathDescriptionKey"] model_config = { "populate_by_name": True, @@ -121,7 +124,10 @@ def from_dict(cls, obj: Dict) -> Self: "simulationJob": obj.get("simulationJob"), "geometrySpecs": GeometrySpecDTO.from_dict(obj.get("geometrySpecs")) if obj.get("geometrySpecs") is not None else None, "timeSpecs": TimeSpecs.from_dict(obj.get("timeSpecs")) if obj.get("timeSpecs") is not None else None, - "variableSpecs": VariableSpecs.from_dict(obj.get("variableSpecs")) if obj.get("variableSpecs") is not None else None + "variableSpecs": VariableSpecs.from_dict(obj.get("variableSpecs")) if obj.get("variableSpecs") is not None else None, + "bioModelKey": obj.get("bioModelKey"), + "mathModelKey": obj.get("mathModelKey"), + "mathDescriptionKey": obj.get("mathDescriptionKey") }) return _obj diff --git a/tools/openapi.yaml b/tools/openapi.yaml index 0c7df40f21..3315d9370b 100644 --- a/tools/openapi.yaml +++ b/tools/openapi.yaml @@ -461,6 +461,45 @@ paths: security: - openId: - user + /api/v1/export/history: + get: + tags: + - Export Resource + operationId: getExportHistory + parameters: + - name: pageNumber + in: query + required: false + schema: + format: int32 + default: "0" + type: integer + responses: + "200": + description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/ExportHistory' + "401": + description: Not Authenticated + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + "403": + description: Not Allowed + "500": + description: Data Access Exception + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + security: + - openId: + - user /api/v1/export/status: get: tags: @@ -2491,6 +2530,15 @@ components: - WORKEREVENT_FAILURE - JOB_FAILED type: string + DifferentParameterValues: + type: object + properties: + parameterName: + type: string + originalValue: + type: string + changedValue: + type: string Domain: type: object properties: @@ -2519,6 +2567,57 @@ components: type: string humanReadableData: $ref: '#/components/schemas/HumanReadableExportData' + ExportFormat: + enum: + - CSV + - HDF5 + - QUICKTIME + - GIF + - ANIMATED_GIF + - FORMAT_JPEG + - NRRD + - UCD + - VTK_UNSTRUCT + - VTK_IMAGE + - PLY + - N5 + type: string + ExportHistory: + type: object + properties: + exportJobID: + format: int64 + type: integer + simulationRef: + $ref: '#/components/schemas/KeyValue' + bioModelRef: + $ref: '#/components/schemas/KeyValue' + mathModelRef: + $ref: '#/components/schemas/KeyValue' + mathRef: + $ref: '#/components/schemas/KeyValue' + exportFormat: + $ref: '#/components/schemas/ExportFormat' + exportDate: + $ref: '#/components/schemas/Instant' + uri: + type: string + simName: + type: string + modelName: + type: string + variables: + type: array + items: + type: string + startTimeValue: + format: double + type: number + endTimeValue: + format: double + type: number + eventStatus: + $ref: '#/components/schemas/ExportProgressType' ExportProgressType: enum: - EXPORT_START @@ -2794,7 +2893,7 @@ components: differentParameterValues: type: array items: - type: string + $ref: '#/components/schemas/DifferentParameterValues' applicationType: type: string serverSavedFileName: @@ -3262,6 +3361,12 @@ components: $ref: '#/components/schemas/TimeSpecs' variableSpecs: $ref: '#/components/schemas/VariableSpecs' + bioModelKey: + $ref: '#/components/schemas/KeyValue' + mathModelKey: + $ref: '#/components/schemas/KeyValue' + mathDescriptionKey: + $ref: '#/components/schemas/KeyValue' Status: enum: - UNKNOWN diff --git a/vcell-api-types/src/main/java/org/vcell/api/types/events/ExportHumanReadableDataSpec.java b/vcell-api-types/src/main/java/org/vcell/api/types/events/ExportHumanReadableDataSpec.java index 4fbea677d1..fff26d5511 100644 --- a/vcell-api-types/src/main/java/org/vcell/api/types/events/ExportHumanReadableDataSpec.java +++ b/vcell-api-types/src/main/java/org/vcell/api/types/events/ExportHumanReadableDataSpec.java @@ -1,14 +1,17 @@ package org.vcell.api.types.events; +import cbit.vcell.export.server.HumanReadableExportData; + import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; public class ExportHumanReadableDataSpec { public final String bioModelName; public String applicationName; public String simulationName; - public ArrayList differentParameterValues; + public List differentParameterValues; public String serverSavedFileName; public String applicationType; public boolean nonSpatial; @@ -18,7 +21,7 @@ public class ExportHumanReadableDataSpec { public int numChannels; public ExportHumanReadableDataSpec(String bioModelName, String applicationName, String simulationName, - ArrayList differentParameterValues, + List differentParameterValues, String serverSavedFileName, String applicationType, boolean nonSpatial, Map subVolume, int zSlices, int tSlices, int numChannels){ this.bioModelName = bioModelName; diff --git a/vcell-cli/src/main/java/org/vcell/cli/run/RunUtils.java b/vcell-cli/src/main/java/org/vcell/cli/run/RunUtils.java index 8e4ed71896..f5cf4efbce 100644 --- a/vcell-cli/src/main/java/org/vcell/cli/run/RunUtils.java +++ b/vcell-cli/src/main/java/org/vcell/cli/run/RunUtils.java @@ -455,7 +455,8 @@ private static ExportSpecs getExportSpecs(OutputContext outputContext, User user ExportFormat.CSV, ASCIISpecs.CsvRoiLayout.var_time_val, true, false); return new ExportSpecs(vcId, ExportFormat.HDF5, variableSpecs, timeSpecs, geometrySpecs, - formatSpecificSpecs, vcellSim.getName(), simContext.getBioModel().getName() + ":" + simContext.getName()); + formatSpecificSpecs, vcellSim.getName(), simContext.getBioModel().getName() + ":" + simContext.getName(), simContext.getBioModel().getVersion().getVersionKey(), + null, simContext.getMathDescription().getKey()); } } diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/ExportDataRepresentation.java b/vcell-client/src/main/java/cbit/vcell/client/data/ExportDataRepresentation.java index 4035a665c2..6916075bee 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/ExportDataRepresentation.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/ExportDataRepresentation.java @@ -1,7 +1,10 @@ package cbit.vcell.client.data; +import cbit.vcell.export.server.HumanReadableExportData; + import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Stack; public class ExportDataRepresentation { @@ -34,7 +37,7 @@ public static class SimulationExportDataRepresentation { public String variables; public String startAndEndTime; - public ArrayList differentParameterValues; + public List differentParameterValues; public String savedFileName; public String applicationType; public boolean nonSpatial; @@ -44,7 +47,7 @@ public static class SimulationExportDataRepresentation { public SimulationExportDataRepresentation(String exportDate, String uri, String jobID, String dataID, String simulationName, String applicationName, String biomodelName, String variables, String startAndEndTime, - ArrayList differentParameterValues, + List differentParameterValues, String savedFileName, String applicationType, boolean nonSpatial, int zSlices, int tSlices, int numVariables){ this.exportDate = exportDate; diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/ExportedDataTableModel.java b/vcell-client/src/main/java/cbit/vcell/client/data/ExportedDataTableModel.java index 22a450d0e1..14d4766222 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/ExportedDataTableModel.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/ExportedDataTableModel.java @@ -1,6 +1,7 @@ package cbit.vcell.client.data; import cbit.vcell.client.desktop.biomodel.VCellSortTableModel; +import cbit.vcell.export.server.HumanReadableExportData; import cbit.vcell.model.ModelProcess; import org.vcell.util.gui.ScrollTable; @@ -184,13 +185,13 @@ public static class TableData { public String appName = null; public String simName = null; public String variables = null; - public ArrayList differentParameterValues; + public List differentParameterValues; public boolean nonSpatial; public String applicationType = null; public TableData(String jobID, String simID, String dateExported, String format, String link, String name, String bioModelName, String timeSlice, String appName, String simName, String variables, - ArrayList differentParameterValues, boolean nonSpatial, String applicationType){ + List differentParameterValues, boolean nonSpatial, String applicationType){ this.jobID = jobID; this.simID = simID; this.dateExported = dateExported; diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/ExportedDataViewer.java b/vcell-client/src/main/java/cbit/vcell/client/data/ExportedDataViewer.java index b51bdacb85..41c1533dd5 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/ExportedDataViewer.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/ExportedDataViewer.java @@ -3,6 +3,7 @@ import cbit.vcell.client.ClientRequestManager; import cbit.vcell.client.desktop.biomodel.DocumentEditorSubPanel; import cbit.vcell.export.server.ExportFormat; +import cbit.vcell.export.server.HumanReadableExportData; import cbit.vcell.graph.GraphConstants; import cbit.vcell.mapping.SimulationContext; import cbit.vcell.resource.ResourceUtil; @@ -33,6 +34,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.*; +import java.util.List; public class ExportedDataViewer extends DocumentEditorSubPanel implements ActionListener, PropertyChangeListener, ListSelectionListener, KeyListener { @@ -509,7 +511,7 @@ public void valueChanged(ListSelectionEvent e) { exportVariableText.setText(""); return; } - ArrayList differentParameterValues = rowData.differentParameterValues; + List differentParameterValues = rowData.differentParameterValues; StyleContext styleContext = new StyleContext(); // AttributeSet attributeSet = styleContext.addAttribute(SimpleAttributeSet.EMPTY, StyleConstants.) StyledDocument doc = new DefaultStyledDocument(); @@ -528,10 +530,9 @@ public void valueChanged(ListSelectionEvent e) { } parameterScrollTableModel.resetData(); - for(int i =0; i < differentParameterValues.size(); i++){ - String[] parameterTokens = differentParameterValues.get(i).split(":"); + for (HumanReadableExportData.DifferentParameterValues differentParameterValue : differentParameterValues) { ParameterTableModelExport.ParameterTableData data = new ParameterTableModelExport.ParameterTableData( - parameterTokens[0], parameterTokens[1], parameterTokens[2] + differentParameterValue.parameterName(), differentParameterValue.originalValue(), differentParameterValue.changedValue() ); parameterScrollTableModel.addRow(data); } diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java b/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java index 5d4b366891..b5a97d16ef 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/PDEDataViewer.java @@ -1970,6 +1970,7 @@ private PDEExportDataPanel getPDEExportPanel1() { try { ivjPDEExportPanel1 = new PDEExportDataPanel(); ivjPDEExportPanel1.setName("PDEExportPanel1"); + ivjPDEExportPanel1.setSimulation(getSimulation()); // user code begin {1} // user code end } catch (java.lang.Throwable ivjExc) { diff --git a/vcell-client/src/main/java/cbit/vcell/client/data/PDEExportDataPanel.java b/vcell-client/src/main/java/cbit/vcell/client/data/PDEExportDataPanel.java index 5b2a2dd4c3..92c7fb06fb 100644 --- a/vcell-client/src/main/java/cbit/vcell/client/data/PDEExportDataPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/client/data/PDEExportDataPanel.java @@ -32,10 +32,7 @@ import cbit.vcell.solver.*; import cbit.vcell.solvers.CartesianMesh; import org.vcell.util.UserCancelException; -import org.vcell.util.document.LocalVCDataIdentifier; -import org.vcell.util.document.User; -import org.vcell.util.document.VCDataIdentifier; -import org.vcell.util.document.VCDocument; +import org.vcell.util.document.*; import org.vcell.util.gui.*; import javax.swing.*; @@ -48,6 +45,8 @@ import java.net.URL; import java.nio.channels.FileChannel; import java.util.*; +import java.util.List; + /** * This type was created in VisualAge. */ @@ -650,7 +649,7 @@ private ExportSpecs getExportSpecs() { MathOverrides mathOverrides = getSimulation().getMathOverrides(); String[] filteredConstants = mathOverrides.getFilteredConstantNames(); - ArrayList differentParameterValues = new ArrayList<>(); + List differentParameterValues = new ArrayList<>(); VCDataIdentifier vcDataIdentifier = getPdeDataContext().getVCDataIdentifier(); if (vcDataIdentifier instanceof VCSimulationDataIdentifier){ for (String filteredConstant : filteredConstants) { @@ -659,7 +658,9 @@ private ExportSpecs getExportSpecs() { MathOverrides.ScanIndex scanIndex = simulation.getScanIndex(jobIndex); String setValue = mathOverrides.getActualExpression(filteredConstant, scanIndex).infix(); if(!defaultValue.equals(setValue)){ - differentParameterValues.add(filteredConstant + ":" +defaultValue + ":" + setValue); + differentParameterValues.add(new HumanReadableExportData.DifferentParameterValues( + filteredConstant, defaultValue, setValue + )); } } } @@ -690,7 +691,15 @@ private ExportSpecs getExportSpecs() { throw new IllegalArgumentException("Expected " + SimulationContext.class.getName() + " or " + MathModel.class.getName()); } - ExportSpecs exportSpecs = new ExportSpecs( + VCDocument thisDocument = (getDataViewerManager() instanceof DocumentWindowManager?((DocumentWindowManager)getDataViewerManager()).getVCDocument():null); + KeyValue bioModelKey = null; + KeyValue mathModelKey = null; + if (thisDocument != null){ + bioModelKey = thisDocument.getDocumentType() == VCDocument.VCDocumentType.BIOMODEL_DOC ? thisDocument.getVersion().getVersionKey() : null; + mathModelKey = thisDocument.getDocumentType() == VCDocument.VCDocumentType.MATHMODEL_DOC ? thisDocument.getVersion().getVersionKey() : null; + } + + return new ExportSpecs( vcDataIdentifier, getExportSettings1().getSelectedFormat(), variableSpecs, @@ -698,10 +707,11 @@ private ExportSpecs getExportSpecs() { geometrySpecs, getExportSettings1().getFormatSpecificSpecs(), dataInfoProvider.getSimulationModelInfo().getSimulationName(), - dataInfoProvider.getSimulationModelInfo().getContextName() + dataInfoProvider.getSimulationModelInfo().getContextName(), + bioModelKey, + mathModelKey, + getSimulation().getMathDescription().getKey() ); - exportSpecs.setExportMetaData(humanReadableExportData); - return exportSpecs; } private ExportSpecs.SimulationSelector createSimulationSelector(){ diff --git a/vcell-client/src/main/java/cbit/vcell/export/gui/N5SettingsPanel.java b/vcell-client/src/main/java/cbit/vcell/export/gui/N5SettingsPanel.java index 793db5fe8a..332ae06aa7 100644 --- a/vcell-client/src/main/java/cbit/vcell/export/gui/N5SettingsPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/export/gui/N5SettingsPanel.java @@ -264,7 +264,7 @@ public N5Specs getN5Specs(){ int[] paramScanIndexes = simulationSelector == null ? null : simulationSelector.getselectedParamScanIndexes(); String dataSetName = getJTextFieldDataSetName().getText(); - return new N5Specs(ExportEnums.ExportableDataType.PDE_VARIABLE_DATA, ExportFormat.N5, N5Specs.CompressionLevel.GZIP, dataSetName); + return new N5Specs(ExportEnums.ExportableDataType.PDE_VARIABLE_DATA, ExportFormat.N5, dataSetName, null); } private JLabel lblSeeVcellHelp; diff --git a/vcell-client/src/main/java/cbit/vcell/microscopy/gui/FRAPStudyPanel.java b/vcell-client/src/main/java/cbit/vcell/microscopy/gui/FRAPStudyPanel.java index 5184191cb0..490abb226c 100644 --- a/vcell-client/src/main/java/cbit/vcell/microscopy/gui/FRAPStudyPanel.java +++ b/vcell-client/src/main/java/cbit/vcell/microscopy/gui/FRAPStudyPanel.java @@ -1393,7 +1393,9 @@ public void run(Hashtable hashTable) throws Exception false, FormatSpecificSpecs.PARTICLE_NONE); // mSpec.setViewZoom(1); - ExportSpecs exSpecs = new ExportSpecs(vcDataId, format, variableSpecs, timeSpecs, geometrySpecs, mSpec,fStudy.getName(),null); + BioModel bioModel = getFrapWorkspace().getWorkingFrapStudy().getBioModel(); + ExportSpecs exSpecs = new ExportSpecs(vcDataId, format, variableSpecs, timeSpecs, geometrySpecs, mSpec,fStudy.getName(),null, + bioModel.getVersion().getVersionKey(), null, sim.getMathDescription().getKey()); // pass the request ExportEvent exportEvt = ((VirtualFrapWindowManager)getFlourDataViewer().getDataViewerManager()).startExportMovie(exSpecs, outputContext, this.getClientTaskStatusSupport()); hashTable.put("ExportEvt", exportEvt); diff --git a/vcell-core/pom.xml b/vcell-core/pom.xml index 78a83a6373..204d48a916 100644 --- a/vcell-core/pom.xml +++ b/vcell-core/pom.xml @@ -694,7 +694,7 @@ - + diff --git a/vcell-core/src/main/java/cbit/vcell/export/server/ClientExportEventController.java b/vcell-core/src/main/java/cbit/vcell/export/server/ClientExportEventController.java index 5464079c68..7772efa011 100644 --- a/vcell-core/src/main/java/cbit/vcell/export/server/ClientExportEventController.java +++ b/vcell-core/src/main/java/cbit/vcell/export/server/ClientExportEventController.java @@ -45,7 +45,6 @@ public ExportEvent fireExportCompleted(long jobID, VCDataIdentifier vcdID, Strin ExportEvent event = new ExportEvent( this, jobID, user, vcdID.getID(), dataKey, ExportEnums.ExportProgressType.EXPORT_COMPLETE, format, location, null); - event.setHumanReadableExportData(exportSpecs != null ? exportSpecs.getHumanReadableExportData() : null); fireExportEvent(event); return event; } diff --git a/vcell-core/src/main/java/cbit/vcell/export/server/ExportServiceImpl.java b/vcell-core/src/main/java/cbit/vcell/export/server/ExportServiceImpl.java index b9c0957871..51d5a91f14 100644 --- a/vcell-core/src/main/java/cbit/vcell/export/server/ExportServiceImpl.java +++ b/vcell-core/src/main/java/cbit/vcell/export/server/ExportServiceImpl.java @@ -9,20 +9,15 @@ */ package cbit.vcell.export.server; -import java.io.BufferedOutputStream; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.ObjectOutputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.Collection; -import java.util.zip.DataFormatException; -import java.util.zip.ZipEntry; -import java.util.zip.ZipOutputStream; +import cbit.rmi.event.ExportEvent; import cbit.rmi.event.ExportEventController; +import cbit.vcell.export.nrrd.NrrdInfo; +import cbit.vcell.resource.PropertyLoader; +import cbit.vcell.simdata.DataServerImpl; +import cbit.vcell.simdata.OutputContext; +import cbit.vcell.solver.VCSimulationDataIdentifier; +import com.google.common.io.Files; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.vcell.util.ClientTaskStatusSupport; @@ -30,14 +25,15 @@ import org.vcell.util.UserCancelException; import org.vcell.util.document.User; -import com.google.common.io.Files; +import java.io.*; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Collection; +import java.util.zip.DataFormatException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + -import cbit.rmi.event.ExportEvent; -import cbit.vcell.export.nrrd.NrrdInfo; -import cbit.vcell.resource.PropertyLoader; -import cbit.vcell.simdata.DataServerImpl; -import cbit.vcell.simdata.OutputContext; -import cbit.vcell.solver.VCSimulationDataIdentifier; /** * This type was created in VisualAge. @@ -204,7 +200,7 @@ private static ExportEvent makeRemoteFile(String fileFormat, String exportBaseDi if (nrrdInfos[i].isHasData()) { // nrrdInfo 'header' file contains either just the header or both the header and data together ZipEntry zipEntry = new ZipEntry(nrrdInfos[i].getCanonicalFilename((nrrdInfos[i].isSeparateHeader()?true:false))); - zipOut.putNextEntry(zipEntry); + zipOut.putNextEntry(zipEntry); fileDataContainerManager.writeAndFlush(nrrdInfos[i].getHeaderFileID(), zipOut); if (nrrdInfos[i].isSeparateHeader()) { // The data was not saved with the 'header' file so save it separately @@ -222,7 +218,7 @@ private static ExportEvent makeRemoteFile(String fileFormat, String exportBaseDi } finally { zipOut.close(); } - + if (exportValid) { if (lg.isTraceEnabled()) lg.trace("ExportServiceImpl.makeRemoteFile(): Successfully exported to file: " + zipFile.getName()); URL url = new URL(exportBaseURL + zipFile.getName()); @@ -267,7 +263,7 @@ private static ExportEvent saveResultsToRemoteFile(String fileFormat, String exp } } zipOut.close(); - + if (exportValid) { if (lg.isTraceEnabled()) lg.trace("ExportServiceImpl.makeRemoteFile(): Successfully exported to file: " + zipFile.getName()); URL url = new URL(exportBaseURL + zipFile.getName()); @@ -303,7 +299,7 @@ private static ExportEvent makeRemoteFile_Unzipped(String fileFormat, String exp //if there are more export outputs, loops through the second till the last. for (int i=1;i fromJSON(String json) throws JsonProcessingException { + ObjectMapper objectMapper = new ObjectMapper(); + return objectMapper.readValue(json, new TypeReference>() {}); + } + } + public final String simulationName; public final String biomodelName; public final String applicationName; - public ArrayList differentParameterValues; + public List differentParameterValues; public String applicationType; // File name that is saved by the user or server. In N5 case it'll be the dataset name. This way individual datasets can be automatically opened public String serverSavedFileName; @@ -24,7 +39,7 @@ public class HumanReadableExportData implements Serializable { @JsonCreator public HumanReadableExportData(@JsonProperty("simulationName") String simulationName, @JsonProperty("applicationName") String applicationName, - @JsonProperty("biomodelName") String biomodelName, @JsonProperty("differentParameterValues") ArrayList differentParameterValues, + @JsonProperty("biomodelName") String biomodelName, @JsonProperty("differentParameterValues") List differentParameterValues, @JsonProperty("serverSavedFileName") String serverSavedFileName, @JsonProperty("applicationType") String applicationType, @JsonProperty("nonSpatial") boolean nonSpatial, @JsonProperty("subVolume") Map subVolume){ this.simulationName = simulationName; diff --git a/vcell-core/src/main/java/cbit/vcell/export/server/IMGExporter.java b/vcell-core/src/main/java/cbit/vcell/export/server/IMGExporter.java index cc5b17e6f7..918e24196b 100644 --- a/vcell-core/src/main/java/cbit/vcell/export/server/IMGExporter.java +++ b/vcell-core/src/main/java/cbit/vcell/export/server/IMGExporter.java @@ -95,7 +95,9 @@ public static void main(String [] args) throws Exception{ MovieSpecs movieSpecs = new MovieSpecs( 1000.0, false, new DisplayPreferences[] {displayPreferences}, ExportFormat.FORMAT_JPEG, ExportEnums.MirroringMethod.NO_MIRRORING, 1, 1, 1,/// ImagePaneModel.MESH_MODE, FormatSpecificSpecs.CODEC_JPEG, 1.0f, false,FormatSpecificSpecs.PARTICLE_SELECT); - ExportSpecs exportSpecs = new ExportSpecs(vcdID, ExportFormat.QUICKTIME, variableSpecs, timeSpecs, geometrySpecs, movieSpecs,"IMGExporterTest",null); + ExportSpecs exportSpecs = new ExportSpecs(vcdID, ExportFormat.QUICKTIME, variableSpecs, timeSpecs, + geometrySpecs, movieSpecs,"IMGExporterTest",null, + null, null, null); exportServiceImpl.makeRemoteFile(null, user, dataServerImpl, exportSpecs); } diff --git a/vcell-core/src/main/java/cbit/vcell/export/server/N5Exporter.java b/vcell-core/src/main/java/cbit/vcell/export/server/N5Exporter.java index 1fcfd79a47..4578c2f7e4 100644 --- a/vcell-core/src/main/java/cbit/vcell/export/server/N5Exporter.java +++ b/vcell-core/src/main/java/cbit/vcell/export/server/N5Exporter.java @@ -138,7 +138,7 @@ private ExportOutput exportToN5(OutputContext outputContext, long jobID, N5Specs N5Specs.writeImageJMetaData(jobID, dimensions, blockSize, n5Specs.getCompression(), n5FSWriter, n5Specs.dataSetName, numVariables, sizeZ, allTimes.length, - exportSpecs.getHumanReadableExportData().subVolume, + n5Specs.getSubVolumeMapping(), lengthPerPixelY, lengthPerPixelX, lengthPerPixelZ, lengthUnit.getSymbol(), channelInfo); int timeLoops = 1; @@ -181,9 +181,6 @@ private ExportOutput exportToN5(OutputContext outputContext, long jobID, N5Specs timeLoops += 1; } n5FSWriter.close(); - exportSpecs.getHumanReadableExportData().numChannels = (int) dimensions[2]; - exportSpecs.getHumanReadableExportData().zSlices = (int) dimensions[3]; - exportSpecs.getHumanReadableExportData().tSlices = (int) dimensions[4]; ExportOutput exportOutput = new ExportOutput(true, "." + N5Specs.n5Suffix, vcDataID.getID(), getN5FileNameHash(), fileDataContainerManager); return exportOutput; } diff --git a/vcell-core/src/main/java/cbit/vcell/export/server/N5Specs.java b/vcell-core/src/main/java/cbit/vcell/export/server/N5Specs.java index 084963df0b..26c2657ad5 100644 --- a/vcell-core/src/main/java/cbit/vcell/export/server/N5Specs.java +++ b/vcell-core/src/main/java/cbit/vcell/export/server/N5Specs.java @@ -49,19 +49,6 @@ public static enum CompressionLevel{ GZIP } -/** - * TextSpecs constructor comment. - */ - public N5Specs(ExportEnums.ExportableDataType dataType, ExportFormat format, - CompressionLevel compressionLevel, String dataSetName) { - super("N5"); - this.formatType = format; - this.dataType = dataType; - this.compression = compressionLevel; - this.dataSetName = dataSetName; - this.subVolumeMapping = null; // it gets set within the HumanReadableExportData - } - @JsonCreator public N5Specs(@JsonProperty("dataType") ExportEnums.ExportableDataType dataType, @JsonProperty("format") ExportFormat format, @JsonProperty("dataSetName") String dataSetName, @JsonProperty("subVolumeMapping") Map subVolumeMapping) { diff --git a/vcell-core/src/test/java/cbit/vcell/export/N5ExporterTest.java b/vcell-core/src/test/java/cbit/vcell/export/N5ExporterTest.java index fbf7848a89..74a8e21c45 100644 --- a/vcell-core/src/test/java/cbit/vcell/export/N5ExporterTest.java +++ b/vcell-core/src/test/java/cbit/vcell/export/N5ExporterTest.java @@ -173,19 +173,20 @@ public void restore() throws IOException { } - public void makeN5FileWithSpecificSimulationResults(N5Specs.CompressionLevel compressionLevel, int startTimeIndex, int endTimeIndex, String modelID) throws Exception { + public void makeN5FileWithSpecificSimulationResults(int startTimeIndex, int endTimeIndex, String modelID) throws Exception { OutputContext outputContext = new OutputContext(new AnnotatedFunction[0]); VariableSpecs variableSpecs = new VariableSpecs(variables.stream().map(di -> di.getName()).toList(), ExportEnums.VariableMode.VARIABLE_MULTI); GeometrySpecs geometrySpecs = new GeometrySpecs(new SpatialSelection[0], 0, 0, ExportEnums.GeometryMode.GEOMETRY_SELECTIONS); - N5Specs n5Specs = new N5Specs(ExportEnums.ExportableDataType.PDE_VARIABLE_DATA, ExportFormat.N5, compressionLevel, modelID); + Map dummyMaskInfo = new HashMap<>(){{put(0, "Dummy"); put(1, "Test");}}; + N5Specs n5Specs = new N5Specs(ExportEnums.ExportableDataType.PDE_VARIABLE_DATA, ExportFormat.N5, modelID, dummyMaskInfo); double[] allTimes = dataServer.getDataSetTimes(testUser,n5Exporter.getVcDataID()); TimeSpecs timeSpecs = new TimeSpecs(startTimeIndex, endTimeIndex, allTimes, ExportEnums.TimeMode.TIME_RANGE); - ExportSpecs exportSpecs = new ExportSpecs(n5Exporter.getVcDataID(), ExportFormat.N5, variableSpecs, timeSpecs, geometrySpecs, n5Specs, "", ""); - HashMap dummyMaskInfo = new HashMap<>(){{put(0, "Dummy"); put(1, "Test");}}; - exportSpecs.setExportMetaData(new HumanReadableExportData("", "", "", new ArrayList<>(), "", "", false, dummyMaskInfo)); + ExportSpecs exportSpecs = new ExportSpecs(n5Exporter.getVcDataID(), ExportFormat.N5, variableSpecs, timeSpecs, + geometrySpecs, n5Specs, "", "", + null, null, null); FileDataContainerManager fileDataContainerManager = new FileDataContainerManager(); ExportOutput exportOutput = n5Exporter.makeN5Data(outputContext, Integer.parseInt(modelID), exportSpecs, fileDataContainerManager); @@ -223,7 +224,7 @@ public void testMetaData() throws Exception { for(TestModels model: TestModels.values()){ this.setExportTestState(model); - this.makeN5FileWithSpecificSimulationResults(N5Specs.CompressionLevel.RAW, 0, times.length - 1, model.simID); + this.makeN5FileWithSpecificSimulationResults(0, times.length - 1, model.simID); int sizeX = modelMesh.getSizeX(), sizeY = modelMesh.getSizeY(), @@ -290,7 +291,7 @@ private void compareData(N5Specs.CompressionLevel compressionLevel, TestModels m this.setExportTestState(model); OutputContext outputContext = new OutputContext(new AnnotatedFunction[0]); int endTimeIndex = times.length - 1; - makeN5FileWithSpecificSimulationResults(compressionLevel, 0, endTimeIndex, model.simID); + makeN5FileWithSpecificSimulationResults(0, endTimeIndex, model.simID); int sizeZ = postProcessVariable ? modelMesh.getSizeZ() : MeshToImage.newNumElements(modelMesh.getSizeZ()); int sizeX = postProcessVariable ? modelMesh.getSizeX() : MeshToImage.newNumElements(modelMesh.getSizeX()); diff --git a/vcell-rest/src/main/java/org/vcell/restq/activemq/ExportRequestListenerMQ.java b/vcell-rest/src/main/java/org/vcell/restq/activemq/ExportRequestListenerMQ.java index f8f2456367..7e3772c297 100644 --- a/vcell-rest/src/main/java/org/vcell/restq/activemq/ExportRequestListenerMQ.java +++ b/vcell-rest/src/main/java/org/vcell/restq/activemq/ExportRequestListenerMQ.java @@ -25,6 +25,7 @@ import org.vcell.restq.handlers.ExportResource; import org.vcell.restq.services.Exports.ServerExportEventController; import org.vcell.util.DataAccessException; +import org.vcell.util.document.KeyValue; import org.vcell.util.document.User; import java.io.File; @@ -140,12 +141,9 @@ private ExportSpecs getExportSpecs(ExportJob exportJob) throws SQLException, Dat exportJob.geometrySpecs().sliceNumber(), exportJob.geometrySpecs().geometryMode()); } - Map subVolume = exportJob.formatSpecificSpecs() instanceof N5Specs n5ExportRequest ? - n5ExportRequest.getSubVolumeMapping() : null; - HumanReadableExportData humanReadableExportData = new HumanReadableExportData(null, - null, null, null, null, null, false, subVolume); return new ExportSpecs(new VCSimulationDataIdentifier(exportJob.simulationIdentifier(), exportJob.simulationJob()), exportJob.format(), exportJob.variableSpecs(), exportJob.timeSpecs(), - geometrySpecs, exportJob.formatSpecificSpecs(), exportJob.simulationName(), exportJob.contextName(), humanReadableExportData); + geometrySpecs, exportJob.formatSpecificSpecs(), exportJob.simulationName(), exportJob.contextName(), + exportJob.bioModelKey(), exportJob.mathModelKey(), exportJob.mathDescriptionKey()); } public void setThreadWaitTimeUnit(TimeUnit timeUnit) { @@ -161,6 +159,7 @@ public record ExportJob( ExportFormat format, VariableSpecs variableSpecs, TimeSpecs timeSpecs, ExportResource.GeometrySpecDTO geometrySpecs, FormatSpecificSpecs formatSpecificSpecs, - String simulationName, String contextName + String simulationName, String contextName, + KeyValue bioModelKey, KeyValue mathModelKey, KeyValue mathDescriptionKey ){ } } diff --git a/vcell-rest/src/main/java/org/vcell/restq/handlers/ExportResource.java b/vcell-rest/src/main/java/org/vcell/restq/handlers/ExportResource.java index 47488a8f95..5a9e75f72d 100644 --- a/vcell-rest/src/main/java/org/vcell/restq/handlers/ExportResource.java +++ b/vcell-rest/src/main/java/org/vcell/restq/handlers/ExportResource.java @@ -2,8 +2,10 @@ import cbit.rmi.event.ExportEvent; import cbit.vcell.export.server.*; +import cbit.vcell.exports.ExportHistory; import cbit.vcell.math.Variable; import cbit.vcell.math.VariableType; +import cbit.vcell.exports.ExportHistoryDBRep; import cbit.vcell.simdata.SpatialSelection; import cbit.vcell.solver.AnnotatedFunction; import com.fasterxml.jackson.core.JsonProcessingException; @@ -24,14 +26,14 @@ import org.vcell.restq.services.UserRestService; import org.vcell.util.DataAccessException; import org.vcell.util.ObjectNotFoundException; +import org.vcell.util.document.KeyValue; import org.vcell.util.document.User; import java.sql.SQLException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; +import java.util.Optional; @Path("/api/v1/export") public class ExportResource { @@ -50,11 +52,11 @@ public class ExportResource { @Path("/history") @GET @RolesAllowed("user") - @Operation(operationId = "getExportHistory", hidden = true) - public ExportHistory getExportHistory() throws DataAccessWebException, NotAuthenticatedWebException { + @Operation(operationId = "getExportHistory") + public List getExportHistory(@QueryParam("pageNumber") @DefaultValue("0") Optional pageNumber) throws DataAccessWebException, NotAuthenticatedWebException { User user = userRestService.getUserFromIdentity(securityIdentity); try { - return exportService.getExportHistory(user); + return exportService.getExportHistory(user, pageNumber.orElseGet(() -> 0)); } catch (DataAccessException e) { throw new DataAccessWebException(e.getMessage(), e); } @@ -64,13 +66,9 @@ public ExportHistory getExportHistory() throws DataAccessWebException, NotAuthen @DELETE @RolesAllowed("user") @Operation(operationId = "deleteExportHistory", hidden = true) - public ExportHistory deleteExportHistoryEntry() throws DataAccessWebException, NotAuthenticatedWebException { + public void deleteExportHistoryEntry() throws DataAccessWebException, NotAuthenticatedWebException { User user = userRestService.getUserFromIdentity(securityIdentity); - try { - return exportService.getExportHistory(user); - } catch (DataAccessException e) { - throw new DataAccessWebException(e.getMessage(), e); - } + return; } @Path("/status") @@ -132,7 +130,8 @@ public record StandardExportInfo( ArrayList outputContext, String contextName, String simulationName, String simulationKey, int simulationJob, GeometrySpecDTO geometrySpecs, - TimeSpecs timeSpecs, VariableSpecs variableSpecs + TimeSpecs timeSpecs, VariableSpecs variableSpecs, + KeyValue bioModelKey, KeyValue mathModelKey, KeyValue mathDescriptionKey ){ } public record AnnotatedFunctionDTO( @@ -144,10 +143,6 @@ public record AnnotatedFunctionDTO( AnnotatedFunction.FunctionCategory category ) { } - public record ExportHistory( - String exportHistory - ){ } - public record GeometrySpecDTO( SpatialSelection[] selections, int axis, int sliceNumber, ExportEnums.GeometryMode geometryMode ){ } diff --git a/vcell-rest/src/main/java/org/vcell/restq/services/ExportService.java b/vcell-rest/src/main/java/org/vcell/restq/services/ExportService.java new file mode 100644 index 0000000000..429afc2d93 --- /dev/null +++ b/vcell-rest/src/main/java/org/vcell/restq/services/ExportService.java @@ -0,0 +1,30 @@ +package org.vcell.restq.services; + +import cbit.vcell.modeldb.DatabaseServerImpl; +import cbit.vcell.exports.ExportHistoryDBRep; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.inject.Inject; +import org.vcell.restq.db.AgroalConnectionFactory; +import org.vcell.util.DataAccessException; +import org.vcell.util.document.User; + +@ApplicationScoped +public class ExportService { + private final DatabaseServerImpl databaseServer; + + @Inject + public ExportService(AgroalConnectionFactory connectionFactory) throws DataAccessException { + this.databaseServer = new DatabaseServerImpl(connectionFactory, connectionFactory.getKeyFactory()); + } + + + public ExportHistoryDBRep getExportHistory(User user) throws DataAccessException { + // TODO: Pipe down to DB layer + return null; + } + + public void addExportHistory(User user, ExportHistoryDBRep history) throws DataAccessException { + databaseServer.addExportHistory(user, history); + } + +} diff --git a/vcell-rest/src/main/java/org/vcell/restq/services/Exports/ExportService.java b/vcell-rest/src/main/java/org/vcell/restq/services/Exports/ExportService.java index d680d095e1..b5213acb75 100644 --- a/vcell-rest/src/main/java/org/vcell/restq/services/Exports/ExportService.java +++ b/vcell-rest/src/main/java/org/vcell/restq/services/Exports/ExportService.java @@ -5,17 +5,20 @@ import cbit.vcell.export.server.ExportFormat; import cbit.vcell.export.server.FormatSpecificSpecs; import cbit.vcell.export.server.JobRequest; +import cbit.vcell.exports.ExportHistory; +import cbit.vcell.modeldb.DatabaseServerImpl; +import cbit.vcell.exports.ExportHistoryDBRep; import cbit.vcell.modeldb.SimulationRep; import cbit.vcell.parser.Expression; import cbit.vcell.parser.ExpressionException; import cbit.vcell.solver.AnnotatedFunction; import cbit.vcell.solver.VCSimulationIdentifier; -import com.fasterxml.jackson.databind.ObjectMapper; import io.smallrye.mutiny.Multi; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.inject.Instance; import jakarta.inject.Inject; import org.vcell.restq.activemq.ExportRequestListenerMQ; +import org.vcell.restq.db.AgroalConnectionFactory; import org.vcell.restq.errors.exceptions.RuntimeWebException; import org.vcell.restq.handlers.ExportResource; import org.vcell.restq.services.SimulationRestService; @@ -24,11 +27,9 @@ import org.vcell.util.document.KeyValue; import org.vcell.util.document.User; -import java.io.FileNotFoundException; import java.sql.SQLException; import java.time.Instant; import java.util.List; -import java.util.Set; @ApplicationScoped public class ExportService { @@ -40,8 +41,14 @@ public class ExportService { @Inject SimulationRestService simulationRestService; - public ExportResource.ExportHistory getExportHistory(User user) throws DataAccessException { - return new ExportResource.ExportHistory("Hello"); + DatabaseServerImpl databaseServer; + @Inject + public ExportService(AgroalConnectionFactory connectionFactory) throws DataAccessException { + databaseServer = new DatabaseServerImpl(connectionFactory, connectionFactory.getKeyFactory()); + } + + public List getExportHistory(User user, int pageNumber) throws DataAccessException { + return databaseServer.getUsersExportHistory(user, pageNumber); } public Multi getExportStatuses(User user, long jobID) throws ObjectNotFoundException { @@ -71,7 +78,8 @@ public ExportRequestListenerMQ.ExportJob createExportJobFromRequest(User user, E ).toArray(AnnotatedFunction[]::new); } return new ExportRequestListenerMQ.ExportJob(exportID, user, annotatedFunctions, simulationIdentifier, request.simulationJob(), format, - request.variableSpecs(), request.timeSpecs(), request.geometrySpecs(), formatSpecificSpecs, request.simulationName(), request.contextName()); + request.variableSpecs(), request.timeSpecs(), request.geometrySpecs(), formatSpecificSpecs, request.simulationName(), request.contextName(), + request.bioModelKey(), request.mathModelKey(), request.mathDescriptionKey()); } } diff --git a/vcell-rest/src/main/java/org/vcell/restq/services/Exports/ServerExportEventController.java b/vcell-rest/src/main/java/org/vcell/restq/services/Exports/ServerExportEventController.java index 1a1c8b8712..8cc4faae22 100644 --- a/vcell-rest/src/main/java/org/vcell/restq/services/Exports/ServerExportEventController.java +++ b/vcell-rest/src/main/java/org/vcell/restq/services/Exports/ServerExportEventController.java @@ -5,6 +5,8 @@ import cbit.rmi.event.ExportListener; import cbit.vcell.export.server.ExportEnums; import cbit.vcell.export.server.ExportSpecs; +import cbit.vcell.modeldb.DatabaseServerImpl; +import cbit.vcell.exports.ExportHistoryDBRep; import cbit.vcell.solver.VCSimulationDataIdentifier; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -18,6 +20,8 @@ import org.eclipse.microprofile.reactive.messaging.Channel; import org.eclipse.microprofile.reactive.messaging.Emitter; import org.vcell.restq.activemq.ExportRequestListenerMQ; +import org.vcell.restq.db.AgroalConnectionFactory; +import org.vcell.util.DataAccessException; import org.vcell.util.ObjectNotFoundException; import org.vcell.util.document.ExternalDataIdentifier; import org.vcell.util.document.KeyValue; @@ -62,6 +66,7 @@ public class ServerExportEventController implements cbit.rmi.event.ExportEventCo private final ConcurrentHashMap> listeners = new ConcurrentHashMap<>(); private final static Logger logger = LogManager.getLogger(ServerExportEventController.class); + private final DatabaseServerImpl databaseServerImpl; @Inject @Channel("publisher-client-status") @@ -70,6 +75,12 @@ public class ServerExportEventController implements cbit.rmi.event.ExportEventCo @Inject ObjectMapper objectMapper; + @Inject + public ServerExportEventController(AgroalConnectionFactory agroalConnectionFactory) throws DataAccessException { + databaseServerImpl = new DatabaseServerImpl(agroalConnectionFactory, agroalConnectionFactory.getKeyFactory()); + + } + public synchronized Multi getSSEUsersExportStatus(User user, long exportJobID) throws ObjectNotFoundException { String key = sseEventListenerKey(user, exportJobID); @@ -140,7 +151,19 @@ public synchronized ExportEvent fireExportCompleted(long jobID, VCDataIdentifier ExportEvent event = new ExportEvent( this, jobID, user, vcdID.getID(), dataKey, ExportEnums.ExportProgressType.EXPORT_COMPLETE, format, location, null); - event.setHumanReadableExportData(exportSpecs != null ? exportSpecs.getHumanReadableExportData() : null); + + if (exportSpecs != null && exportSpecs.getVCDataIdentifier() instanceof VCSimulationDataIdentifier vcSimulationDataIdentifier){ + try{ + databaseServerImpl.addExportHistory(user, ExportHistoryDBRep.fromExportSpec(exportSpecs, location, jobID, vcSimulationDataIdentifier, ExportEnums.ExportProgressType.EXPORT_COMPLETE)); + } catch (DataAccessException e) { + logger.error("Couldn't add export history to database for user " + user.getName() + ", job id " + jobID + + ", and export spec " + exportSpecs, e); + } + } else { + logger.warn("ExportSpecs was null or did not contain a VCSimulationDataIdentifier, " + + "so export history was not added to the database for user {}, job id {}, and export spec {}", user.getName(), jobID, exportSpecs); + } + fireExportEvent(event); return event; diff --git a/vcell-rest/src/main/resources/scripts/init.sql b/vcell-rest/src/main/resources/scripts/init.sql index f338f9d49a..64e9fcd0e3 100644 --- a/vcell-rest/src/main/resources/scripts/init.sql +++ b/vcell-rest/src/main/resources/scripts/init.sql @@ -76,6 +76,7 @@ CREATE TABLE vc_userlogininfo(id bigint PRIMARY KEY,userRef bigint NOT NULL REFE CREATE TABLE vc_metadata(id bigint PRIMARY KEY,bioModelRef bigint NOT NULL REFERENCES vc_biomodel(id) ON DELETE CASCADE,vcMetaDataLarge text ,vcMetaDataSmall varchar(4000) ); CREATE TABLE vc_simdelfromdisk(deldate varchar(20) ,userid varchar(255) NOT NULL,userkey bigint ,simid bigint ,simpref bigint ,simdate varchar(20) ,simname varchar(255) NOT NULL,status varchar(10) ,numfiles bigint ,totalsize bigint ); CREATE TABLE vc_useridentity(id bigint PRIMARY KEY,userRef bigint NOT NULL REFERENCES vc_userinfo(id),authSubject varchar(128) NOT NULL,authIssuer varchar(128) NOT NULL,insertDate timestamp NOT NULL); +CREATE TABLE vc_simulation_export_job(id bigint PRIMARY KEY,job_id bigint NOT NULL,user_ref bigint NOT NULL REFERENCES vc_userinfo(id),biomodel_ref bigint REFERENCES vc_biomodel(id),mathmodel_ref bigint REFERENCES vc_mathmodel(id),simulation_ref bigint NOT NULL REFERENCES vc_simulation(id),math_ref bigint NOT NULL REFERENCES vc_math(id),export_format varchar(50) NOT NULL,export_date timestamp NOT NULL,uri varchar(1024) NOT NULL,variables varchar(4000) [] NOT NULL,start_time numeric NOT NULL,end_time numeric NOT NULL,event_status varchar(50) NOT NULL); CREATE VIEW public.dual AS SELECT CAST('X' as varchar) AS dummy; @@ -87,6 +88,8 @@ CREATE INDEX geom_extentref ON vc_geometry(extentRef); CREATE INDEX geom_imageref ON vc_geometry(imageRef); CREATE INDEX mathdesc_geomref ON vc_math(geometryRef); CREATE INDEX simcstat_simcref ON vc_simcontextstat(simContextRef); +CREATE INDEX idx_export_history_simulation_ref ON vc_simulation_export_job(simulation_ref); + INSERT INTO vc_userinfo VALUES ( 0,'void','1700596370242','void@example.com','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty',CURRENT_TIMESTAMP,'B9BDD75BC5382CA83D5AB82172A98D869555899C' ); INSERT INTO vc_userinfo VALUES ( 2,'Administrator','1700596370260','Administrator@example.com','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty','empty',CURRENT_TIMESTAMP,'CD181552B879A2F29D10434D8ACF692B6C8126F9' ); diff --git a/vcell-rest/src/test/java/org/vcell/restq/TestEndpointUtils.java b/vcell-rest/src/test/java/org/vcell/restq/TestEndpointUtils.java index 8d008d8664..79e1eb5f4c 100644 --- a/vcell-rest/src/test/java/org/vcell/restq/TestEndpointUtils.java +++ b/vcell-rest/src/test/java/org/vcell/restq/TestEndpointUtils.java @@ -7,10 +7,12 @@ import cbit.vcell.model.Kinetics; import cbit.vcell.model.SimpleReaction; import cbit.vcell.model.SpeciesContext; -import cbit.vcell.modeldb.AdminDBTopLevel; import cbit.vcell.modeldb.DatabaseServerImpl; import cbit.vcell.parser.Expression; import cbit.vcell.resource.PropertyLoader; +import cbit.vcell.simdata.Cachetable; +import cbit.vcell.simdata.DataServerImpl; +import cbit.vcell.simdata.DataSetControllerImpl; import cbit.vcell.solver.Simulation; import cbit.vcell.solver.TimeBounds; import cbit.vcell.xml.XMLSource; @@ -27,13 +29,14 @@ import org.vcell.restclient.model.Publication; import org.vcell.restclient.model.UserLoginInfoForMapping; import org.vcell.restq.db.AgroalConnectionFactory; +import org.vcell.restq.exports.ExportRequestTest; import org.vcell.util.BigString; import org.vcell.util.DataAccessException; -import org.vcell.util.document.KeyValue; -import org.vcell.util.document.User; +import org.vcell.util.document.*; import java.beans.PropertyVetoException; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.sql.Connection; @@ -111,6 +114,16 @@ public static MathModel getTestMathModel() throws XmlParseException, PropertyVet return mathModel; } + public static Simulation getTestSimulation() throws IOException, XmlParseException, PropertyVetoException { + String vcmlString = IOUtils.toString(TestEndpointUtils.class.getResourceAsStream("/TestVCML.vcml")); + cbit.vcell.biomodel.BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(vcmlString)); + bioModel.setName("TestBioModel"); + bioModel.clearVersion(); + Simulation simulation = bioModel.getSimulation(0); + simulation.setName("TestSimulation"); + return simulation; + } + public static Publication defaultPublication(){ Publication publication = new Publication(); publication.setAuthors(Arrays.asList("author1", "author2")); @@ -159,12 +172,21 @@ public static String getResourceString(String relativeResourcePath) throws IOExc return IOUtils.toString(inputStream); } + public static DataServerImpl createDataServerImpl() throws FileNotFoundException { + File testSimData = new File(ExportRequestTest.class.getResource("/simdata").getPath()); + TestEndpointUtils.setSystemProperties(testSimData.getAbsolutePath(), System.getProperty("java.io.tmpdir")); + Cachetable cachetable = new Cachetable(10 * Cachetable.minute, 10000); + DataSetControllerImpl dataSetController = new DataSetControllerImpl(cachetable, testSimData, testSimData); + return new DataServerImpl(dataSetController, null); + } + /** * Empties out all BioModel, Geometry, math, and simulation related tables */ public static void clearAllBioModelEntries(AgroalConnectionFactory agroalConnectionFactory) throws DataAccessException, SQLException { Object object = new Object(); Connection connection = agroalConnectionFactory.getConnection(object); + connection.prepareStatement("DELETE FROM VC_SIMULATION_EXPORT_JOB").execute(); connection.prepareStatement("DELETE FROM VC_BIOMODEL").execute(); connection.prepareStatement("DELETE FROM VC_BIOMODELXML").execute(); connection.prepareStatement("DELETE FROM VC_BIOMODELSIM").execute(); @@ -192,17 +214,46 @@ public static void clearAllBioModelEntries(AgroalConnectionFactory agroalConnect connection.close(); } - public static void insertAdminsSimulation(DatabaseServerImpl databaseServer, AgroalConnectionFactory connectionFactory) throws IOException, DataAccessException, SQLException { - InputStream xmlFile = TestEndpointUtils.class.getResourceAsStream("/simdata/Administrator/SimID_597714292_0__0.simtask.xml"); + public static BioModel insertFrapModel(AgroalConnectionFactory connectionFactory) throws IOException, DataAccessException, SQLException, PropertyVetoException, XmlParseException { + DatabaseServerImpl databaseServer = new DatabaseServerImpl(connectionFactory, connectionFactory.getKeyFactory()); + InputStream xmlFile = TestEndpointUtils.class.getResourceAsStream("/simdata/Administrator/Tutorial_FRAP.vcml"); assert xmlFile != null; - String readXML = new String(xmlFile.readAllBytes()); - xmlFile.close(); - databaseServer.saveSimulation(administratorUser, new BigString(readXML), false); + BigString bioModelString = new BigString(new String(xmlFile.readAllBytes())); + bioModelString = databaseServer.saveBioModel(administratorUser, bioModelString, new String[]{}); + BioModel bioModel = XmlHelper.XMLToBioModel(new XMLSource(bioModelString.toString())); + String simulationKey = bioModel.getSimulation(0).getKey().toString(); + + // Have the key be set, that way the simulation files match the key. Object object = new Object(); Connection connection = connectionFactory.getConnection(object); - connection.prepareStatement("UPDATE vc_simulation SET id = 597714292 WHERE name = 'FRAP'").executeUpdate(); + connection.prepareStatement( + "ALTER TABLE vc_biomodelsim DISABLE TRIGGER ALL; ALTER TABLE vc_simulation DISABLE TRIGGER ALL;" + + "UPDATE vc_biomodelsim SET simref = 597714292 WHERE simref = " + simulationKey + ";" + + "UPDATE vc_simulation SET id = 597714292 WHERE id = " + simulationKey + ";" + + "ALTER TABLE vc_biomodelsim ENABLE TRIGGER ALL; ALTER TABLE vc_simulation ENABLE TRIGGER ALL" + ).executeUpdate(); connection.commit(); connection.close(); + Simulation originalSim = bioModel.getSimulation(0); + Simulation updatedSim = new Simulation( + new SimulationVersion( + new KeyValue("597714292"), + originalSim.getVersion().getName(), + originalSim.getVersion().getOwner(), + new GroupAccessAll(), + originalSim.getVersion().getBranchPointRefKey(), + originalSim.getVersion().getBranchID(), + originalSim.getVersion().getDate(), + originalSim.getVersion().getFlag(), + originalSim.getVersion().getAnnot(), + null + ), + originalSim.getMathDescription(), + originalSim.getSimulationOwner() + ); + bioModel.removeSimulation(originalSim); + bioModel.addSimulation(updatedSim); + return bioModel; } diff --git a/vcell-rest/src/test/java/org/vcell/restq/exports/ExportHelper.java b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportHelper.java new file mode 100644 index 0000000000..10aa3b1d8e --- /dev/null +++ b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportHelper.java @@ -0,0 +1,113 @@ +package org.vcell.restq.exports; + +import cbit.vcell.biomodel.BioModel; +import cbit.vcell.export.server.ExportEnums; +import cbit.vcell.exports.ExportHistory; +import cbit.vcell.exports.ExportHistoryDBRep; +import cbit.vcell.math.VariableType; +import cbit.vcell.simdata.*; +import cbit.vcell.simdata.DataIdentifier; +import cbit.vcell.solver.AnnotatedFunction; +import cbit.vcell.solver.Simulation; +import cbit.vcell.solver.VCSimulationDataIdentifier; +import cbit.vcell.solver.VCSimulationIdentifier; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.junit.jupiter.api.Assertions; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.api.ExportResourceApi; +import org.vcell.restclient.model.*; +import org.vcell.restq.TestEndpointUtils; +import org.vcell.util.document.KeyValue; + +import java.io.File; +import java.io.FileNotFoundException; +import java.time.Instant; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; + +public class ExportHelper { + private static final Logger lg = LogManager.getLogger(ExportRequestTest.class); + + public static ExportEvent exportAndWait(ExportResourceApi exportResourceApi, N5ExportRequest n5ExportRequest) throws ApiException { + final long time = Instant.now().getEpochSecond(); // Before export even starts, so that all events are grabbed from the queue + long jobId = exportResourceApi.exportN5(n5ExportRequest); + CompletableFuture future = CompletableFuture.supplyAsync(() -> { + try{ + List allEvents = new ArrayList<>(); + while (allEvents.isEmpty()){ + Thread.sleep(100); + allEvents = exportResourceApi.exportStatus(time); + lg.debug("The number of events found for time {} is 0. Retrying...", time); + } + ExportEvent eventUnderInspection = getLastEventForJob(allEvents, jobId); +// Assertions.assertEquals(ExportEnums.ExportProgressType.EXPORT_ASSEMBLING, ExportEnums.ExportProgressType.valueOf(eventUnderInspection.getEventType().getValue())); + while (ExportEnums.ExportProgressType.valueOf(eventUnderInspection.getEventType().getValue()) != ExportEnums.ExportProgressType.EXPORT_COMPLETE){ + allEvents = exportResourceApi.exportStatus(time); + lg.debug("The events retrieved are: {}", allEvents); + eventUnderInspection = getLastEventForJob(allEvents, jobId); + lg.debug("The event under inspection is: {}", eventUnderInspection); + Thread.sleep(500); + } + Assertions.assertEquals(ExportProgressType.COMPLETE, eventUnderInspection.getEventType()); + return eventUnderInspection; + } catch (Exception e){ + Assertions.fail(); + } + throw new RuntimeException("This should never be reached"); + }).orTimeout(20, TimeUnit.SECONDS); + return future.join(); + } + + private static ExportEvent getLastEventForJob(List events, long jobId){ + for (int i = events.size() - 1; i >= 0; i--){ + ExportEvent event = events.get(i); + if(event.getJobID() == jobId){ + return event; + } + } + throw new RuntimeException("Cannot find event for job id " + jobId); + } + + public static N5ExportRequest getValidExportRequestDTO(int startTimeIndex, int endTimeIndex, + DataServerImpl dataServer, Simulation simulationID, BioModel bioModel) throws Exception { + VCSimulationIdentifier vcSimulationIdentifier = new VCSimulationIdentifier(simulationID.getKey(), TestEndpointUtils.administratorUser); + VCSimulationDataIdentifier simulationDataIdentifier = new VCSimulationDataIdentifier(vcSimulationIdentifier, 0); + DataIdentifier[] dataIdentifier = dataServer.getDataIdentifiers(new OutputContext(new AnnotatedFunction[0]), TestEndpointUtils.administratorUser, simulationDataIdentifier); + DataIdentifier volumetricDataID = getOneDIWithSpecificType(VariableType.VOLUME, dataIdentifier); + double[] allTimes = dataServer.getDataSetTimes(TestEndpointUtils.administratorUser, simulationDataIdentifier); + StandardExportInfo exportRequest = new StandardExportInfo() + .simulationKey(simulationID.getVersion().getVersionKey().toString()) + .simulationJob(0) + .geometrySpecs(new GeometrySpecDTO().geometryMode(GeometryMode.FULL)) + .timeSpecs( + new org.vcell.restclient.model.TimeSpecs().beginTimeIndex(startTimeIndex).endTimeIndex(endTimeIndex).allTimes(Arrays.stream(allTimes).boxed().toList()).mode(TimeMode.RANGE) + ) + .variableSpecs( + new org.vcell.restclient.model.VariableSpecs().variableNames(new ArrayList<>(){{add(volumetricDataID.getName());}}).mode(VariableMode.ONE) + ) + .contextName("") + .simulationName(vcSimulationIdentifier.getID()) + .bioModelKey(bioModel.getVersion().getVersionKey().toString()) + .mathModelKey(null) + .mathDescriptionKey(bioModel.getSimulationContext(0).getMathDescription().getVersion().getVersionKey().toString()) + .outputContext(new ArrayList<>()); + + return new N5ExportRequest().standardExportInformation(exportRequest) + .exportableDataType(ExportableDataType.PDE_VARIABLE_DATA) + .datasetName("testExport") + .subVolume(new java.util.HashMap<>()); + } + + private static DataIdentifier getOneDIWithSpecificType(VariableType variableType, DataIdentifier[] dataIdentifiers){ + for(DataIdentifier dataIdentifier: dataIdentifiers){ + if(dataIdentifier.getVariableType().equals(variableType)){ + return dataIdentifier; + } + } + throw new RuntimeException("Cannot find variable type " + variableType); + } +} diff --git a/vcell-rest/src/test/java/org/vcell/restq/exports/ExportHistoryClientTest.java b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportHistoryClientTest.java new file mode 100644 index 0000000000..dfe3130b9f --- /dev/null +++ b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportHistoryClientTest.java @@ -0,0 +1,126 @@ +package org.vcell.restq.exports; + +import cbit.vcell.biomodel.BioModel; +import cbit.vcell.resource.PropertyLoader; +import cbit.vcell.simdata.DataServerImpl; +import cbit.vcell.xml.XmlParseException; +import io.quarkus.test.junit.QuarkusTest; +import io.quarkus.test.keycloak.client.KeycloakTestClient; +import jakarta.inject.Inject; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.eclipse.microprofile.config.inject.ConfigProperty; +import org.junit.jupiter.api.*; +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.api.ExportResourceApi; +import org.vcell.restclient.model.*; +import org.vcell.restq.TestEndpointUtils; +import org.vcell.restq.config.CDIVCellConfigProvider; +import org.vcell.restq.db.AgroalConnectionFactory; +import org.vcell.util.DataAccessException; + +import java.beans.PropertyVetoException; +import java.io.IOException; +import java.sql.SQLException; +import java.util.List; + +@QuarkusTest +public class ExportHistoryClientTest { + @ConfigProperty(name = "quarkus.http.test-port") + Integer testPort; + @Inject + AgroalConnectionFactory agroalConnectionFactory; + + private static final Logger lg = LogManager.getLogger(ExportHistoryClientTest.class); + + KeycloakTestClient keycloakClient = new KeycloakTestClient(); + + private DataServerImpl dataServer; + private final String simulationID = "597714292"; + private BioModel frapModel; + private ApiClient aliceAPIClient; + + @BeforeAll + public static void setupConfig(){ + PropertyLoader.setConfigProvider(new CDIVCellConfigProvider()); + } + + @BeforeEach + public void setUp() throws IOException, DataAccessException, ApiException, SQLException, PropertyVetoException, XmlParseException { + aliceAPIClient = TestEndpointUtils.createAuthenticatedAPIClient(keycloakClient, testPort, TestEndpointUtils.TestOIDCUsers.alice); + TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); + + dataServer = TestEndpointUtils.createDataServerImpl(); + frapModel = TestEndpointUtils.insertFrapModel(agroalConnectionFactory); + } + + @AfterEach + public void removeOIDCMappings() throws SQLException, DataAccessException { + TestEndpointUtils.clearAllBioModelEntries(agroalConnectionFactory); + TestEndpointUtils.restoreSystemProperties(); + } + +// Tests the clients capability to submit exports, our queue for accepting and distributing messages, retrieval of export status, and the export job itself + @Test + public void testExportRequestClient() throws Exception { + ExportResourceApi exportResourceApi = new ExportResourceApi(aliceAPIClient); + N5ExportRequest exportRequest = ExportHelper.getValidExportRequestDTO(0, 1, dataServer, + frapModel.getSimulation(0), frapModel); + ExportEvent completedExport = ExportHelper.exportAndWait(exportResourceApi, exportRequest); + List exportHistories = exportResourceApi.getExportHistory(0); + Assertions.assertFalse(exportHistories.isEmpty()); + Assertions.assertEquals(exportHistories.size(), 1); + Assertions.assertEquals(exportHistories.get(0).getExportJobID(), completedExport.getJobID()); + Assertions.assertEquals(exportHistories.get(0).getSimName(), frapModel.getSimulation(0).getName()); + Assertions.assertEquals(exportHistories.get(0).getModelName(), frapModel.getName()); + Assertions.assertTrue(requestEqualHistory(exportRequest, exportHistories.get(0))); + } + + @Test + public void testExportHistorySequence() throws Exception { + ExportResourceApi exportResourceApi = new ExportResourceApi(aliceAPIClient); + N5ExportRequest exportRequest = ExportHelper.getValidExportRequestDTO(0, 1, dataServer, + frapModel.getSimulation(0), frapModel); + N5ExportRequest exportRequest2 = ExportHelper.getValidExportRequestDTO(2, 4, dataServer, + frapModel.getSimulation(0), frapModel); + ExportEvent completedExport1 = ExportHelper.exportAndWait(exportResourceApi, exportRequest); + ExportEvent completedExport2 = ExportHelper.exportAndWait(exportResourceApi, exportRequest2); + List exportHistories = exportResourceApi.getExportHistory(0); + + Assertions.assertFalse(exportHistories.isEmpty()); + Assertions.assertEquals(exportHistories.size(), 2); + Assertions.assertTrue(requestEqualHistory(exportRequest, exportHistories.get(1))); + Assertions.assertTrue(requestEqualHistory(exportRequest2, exportHistories.get(0))); + + Assertions.assertTrue(exportHistories.get(0).getExportDate().isAfter(exportHistories.get(1).getExportDate())); + } + + @Test + public void testExportPaging() throws Exception { + ExportResourceApi exportResourceApi = new ExportResourceApi(aliceAPIClient); + N5ExportRequest exportRequest = ExportHelper.getValidExportRequestDTO(0, 1, dataServer, + frapModel.getSimulation(0), frapModel); + N5ExportRequest exportRequest2 = ExportHelper.getValidExportRequestDTO(2, 4, dataServer, + frapModel.getSimulation(0), frapModel); + ExportEvent completedExport1 = ExportHelper.exportAndWait(exportResourceApi, exportRequest); + ExportEvent completedExport2 = ExportHelper.exportAndWait(exportResourceApi, exportRequest2); + List exportHistories = exportResourceApi.getExportHistory(0); + + Assertions.assertEquals(exportHistories.size(), 2); + exportHistories = exportResourceApi.getExportHistory(1); + Assertions.assertTrue(exportHistories.isEmpty()); + } + + private boolean requestEqualHistory(N5ExportRequest request, ExportHistory history){ + List allTimes = request.getStandardExportInformation().getTimeSpecs().getAllTimes(); + boolean modelEqual = request.getStandardExportInformation().getBioModelKey().equals(history.getBioModelRef()); + boolean simEqual = request.getStandardExportInformation().getSimulationKey().equals(history.getSimulationRef()); + boolean startTimeEqual = allTimes.get(request.getStandardExportInformation().getTimeSpecs().getBeginTimeIndex()).equals(history.getStartTimeValue()); + boolean endTimeEqual = allTimes.get(request.getStandardExportInformation().getTimeSpecs().getEndTimeIndex()).equals(history.getEndTimeValue()); + boolean exportComplete = history.getEventStatus().equals(ExportProgressType.COMPLETE); + boolean correctFormat = history.getExportFormat().equals(ExportFormat.N5); + boolean variablesEqual = List.of(request.getStandardExportInformation().getVariableSpecs().getVariableNames()).equals(List.of(history.getVariables())); + return modelEqual && simEqual && startTimeEqual && endTimeEqual && exportComplete && correctFormat && variablesEqual; + } +} diff --git a/vcell-rest/src/test/java/org/vcell/restq/exports/ExportHistoryDBTest.java b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportHistoryDBTest.java new file mode 100644 index 0000000000..3cf011aab9 --- /dev/null +++ b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportHistoryDBTest.java @@ -0,0 +1,194 @@ +package org.vcell.restq.exports; + +import cbit.vcell.biomodel.BioModel; +import cbit.vcell.export.server.*; +import cbit.vcell.exports.ExportHistory; +import cbit.vcell.exports.ExportHistoryDBDriver; +import cbit.vcell.exports.ExportHistoryDBRep; +import cbit.vcell.parser.ExpressionException; +import cbit.vcell.resource.PropertyLoader; +import cbit.vcell.solver.Simulation; +import cbit.vcell.solver.VCSimulationDataIdentifier; +import cbit.vcell.solver.VCSimulationIdentifier; +import cbit.vcell.xml.XmlParseException; +import com.fasterxml.jackson.core.JsonProcessingException; +import io.quarkus.test.junit.QuarkusTest; +import jakarta.inject.Inject; +import org.junit.jupiter.api.*; +import org.vcell.restq.TestEndpointUtils; +import org.vcell.restq.config.CDIVCellConfigProvider; +import org.vcell.restq.db.AgroalConnectionFactory; +import org.vcell.util.DataAccessException; +import org.vcell.util.document.KeyValue; +import org.vcell.util.document.User; +import org.vcell.util.document.VCDataIdentifier; +import cbit.vcell.export.server.ExportFormat; + +import java.beans.PropertyVetoException; +import java.io.IOException; +import java.sql.*; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; + +import static org.bouncycastle.math.raw.Nat.equalTo; +import static org.hamcrest.Matchers.notNullValue; +import static org.junit.Assert.assertEquals; +import static org.vcell.util.VCAssert.assertTrue; + +// TODO: Use GenericVCMLTests class for the principle tests for VCDocuments +@QuarkusTest +public class ExportHistoryDBTest { + + @Inject + AgroalConnectionFactory agroalConnectionFactory; + + private BioModel savedBioModel; + private Simulation savedSimulation; + private KeyValue simulationKey; + + @BeforeAll + public static void setupConfig() { + PropertyLoader.setConfigProvider(new CDIVCellConfigProvider()); + } + + @BeforeEach + public void initializeDB() throws DataAccessException, PropertyVetoException, XmlParseException, IOException, ExpressionException, SQLException { + savedBioModel = TestEndpointUtils.insertFrapModel(agroalConnectionFactory); + savedSimulation = savedBioModel.getSimulation(0); + simulationKey = savedSimulation.getVersion().getVersionKey(); + } + + private ExportHistoryDBRep getExportHistoryRep(int jobID, String uri, Timestamp timestamp) { + VCSimulationIdentifier vcSimId = new VCSimulationIdentifier(simulationKey, TestEndpointUtils.administratorUser); + VCDataIdentifier vcdId = new VCSimulationDataIdentifier(vcSimId, jobID); + GeometrySpecs geometrySpecs = new GeometrySpecs(null, 1, 1, ExportEnums.GeometryMode.GEOMETRY_FULL); + + TimeSpecs timeSpecs = new TimeSpecs(0, 1, new double[]{0.0, 1.0}, ExportEnums.TimeMode.TIME_RANGE); + VariableSpecs variableSpecs = new VariableSpecs(new String[]{"X"}, ExportEnums.VariableMode.VARIABLE_ONE); + + + List parameterValues = new ArrayList<>() {{ + add(new HumanReadableExportData.DifferentParameterValues("parameter_name", "original_0", "changed_1")); + add(new HumanReadableExportData.DifferentParameterValues("parameter_name2", "original_0", "changed_1")); + }}; + + return new ExportHistoryDBRep( + jobID, savedBioModel.getVersion().getVersionKey(), + null, savedSimulation.getKey(), savedSimulation.getMathDescription().getKey(), ExportFormat.N5, + timestamp, uri, variableSpecs.getVariableNames(), + 1.2, 3.4, ExportEnums.ExportProgressType.EXPORT_COMPLETE + ); + } + + + @AfterEach + public void cleanUp() throws SQLException, DataAccessException { + String sql = "DELETE FROM VC_SIMULATION_EXPORT_JOB"; + Connection connection = agroalConnectionFactory.getConnection(null); + connection.prepareStatement(sql).execute(); + connection.commit(); + TestEndpointUtils.clearAllBioModelEntries(agroalConnectionFactory); + } + + + @Test + public void testAddExportHistory() { + User user = TestEndpointUtils.administratorUser; + Timestamp now = Timestamp.from(Instant.now()); + + try (Connection conn = agroalConnectionFactory.getConnection(null)) { + ExportHistoryDBDriver driver = new ExportHistoryDBDriver(null, null); + ExportHistoryDBRep rep = getExportHistoryRep( + 42, + "https://vcell.cam.uchc.edu/n5Data/paulricky/5456fb59b530a19.n5?dataSetName=3681309072", + now + ); + + driver.addExportHistory(conn, user, rep, agroalConnectionFactory.getKeyFactory()); + try { + List exportHistoryRecord = driver.getExportHistoryForUser(conn, user, 0); + Assertions.assertEquals(1, exportHistoryRecord.size(), "expected one record"); + Assertions.assertTrue(historyDBEqualHistory(rep, exportHistoryRecord.get(0))); + Assertions.assertEquals(savedBioModel.getName(), exportHistoryRecord.get(0).modelName()); + Assertions.assertEquals(savedSimulation.getName(), exportHistoryRecord.get(0).simName()); + } catch (SQLException | JsonProcessingException e) { + throw new RuntimeException(e); + } + } catch (SQLException | DataAccessException e) { + throw new RuntimeException(e); + } + } + + @Test + public void testDeleteExportHistory() throws SQLException { + User user = TestEndpointUtils.administratorUser; + Timestamp now = new Timestamp(System.currentTimeMillis()); + + try (Connection conn = agroalConnectionFactory.getConnection(null)) { + ExportHistoryDBDriver driver = new ExportHistoryDBDriver(null, null); + ExportHistoryDBRep exportHistoryDBRep = getExportHistoryRep(7, "to-delete", now); + ExportHistoryDBRep notDeletedRep = getExportHistoryRep(8, "to-keep", now); + + + driver.addExportHistory(conn, user, + exportHistoryDBRep, + agroalConnectionFactory.getKeyFactory() + ); + driver.addExportHistory(conn, user, + notDeletedRep, + agroalConnectionFactory.getKeyFactory() + ); + + + List retrievedExportHistory = driver.getExportHistoryForUser(conn, user, 0); + Assertions.assertEquals(2, retrievedExportHistory.size(), "expected two records"); + Assertions.assertTrue(historyDBEqualHistory(exportHistoryDBRep, retrievedExportHistory.get(0))); + Assertions.assertTrue(historyDBEqualHistory(notDeletedRep, retrievedExportHistory.get(1))); + + driver.deleteExportHistory(conn, exportHistoryDBRep.uri()); + retrievedExportHistory = driver.getExportHistoryForUser(conn, user, 0); + Assertions.assertEquals(1, retrievedExportHistory.size(), "expected one record after deletion"); + Assertions.assertTrue(historyDBEqualHistory(notDeletedRep, retrievedExportHistory.get(0))); + } catch (DataAccessException | JsonProcessingException e) { + throw new RuntimeException(e); + } + } + + @Test + public void testGetExportHistory() throws SQLException, DataAccessException, JsonProcessingException { + User user = TestEndpointUtils.administratorUser; + Timestamp now = new Timestamp(System.currentTimeMillis()); + + try (Connection conn = agroalConnectionFactory.getConnection(null)) { + ExportHistoryDBDriver driver = new ExportHistoryDBDriver(null, null); + ExportHistoryDBRep exportHistoryDBRep = getExportHistoryRep(100, "uri100", now); + ExportHistoryDBRep exportHistoryDBRep1 = getExportHistoryRep(101, "uri101", now); + + driver.addExportHistory(conn, user, + exportHistoryDBRep, + agroalConnectionFactory.getKeyFactory() + ); + driver.addExportHistory(conn, user, + exportHistoryDBRep1, + agroalConnectionFactory.getKeyFactory() + ); + + List retrievedExportHistory = driver.getExportHistoryForUser(conn, user, 0); + Assertions.assertEquals(2, retrievedExportHistory.size(), "expected two records"); + Assertions.assertTrue(historyDBEqualHistory(exportHistoryDBRep, retrievedExportHistory.get(0))); + Assertions.assertTrue(historyDBEqualHistory(exportHistoryDBRep1, retrievedExportHistory.get(1))); + } + } + + private boolean historyDBEqualHistory(ExportHistoryDBRep dbRep, ExportHistory history) { + return dbRep.simulationRef().equals(history.simulationRef()) && + dbRep.exportFormat().equals(history.exportFormat()) && + Math.abs(history.exportDate().toEpochMilli() - dbRep.exportDate().getTime()) <= 1000 && + dbRep.uri().equals(history.uri()) && + List.of(dbRep.variables()).equals(List.of(history.variables())) && + Double.compare(dbRep.startTimeValue(), history.startTimeValue()) == 0 && + Double.compare(dbRep.endTimeValue(), history.endTimeValue()) == 0 && + dbRep.eventStatus().toString().equals(history.eventStatus().toString()); + } +} diff --git a/vcell-rest/src/test/java/org/vcell/restq/exports/ExportRequestTest.java b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportRequestTest.java index 6b170510a6..60cc67a0aa 100644 --- a/vcell-rest/src/test/java/org/vcell/restq/exports/ExportRequestTest.java +++ b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportRequestTest.java @@ -1,19 +1,13 @@ package org.vcell.restq.exports; -import cbit.vcell.export.server.ExportEnums; -import cbit.vcell.math.VariableType; +import cbit.vcell.biomodel.BioModel; import cbit.vcell.modeldb.DatabaseServerImpl; import cbit.vcell.resource.PropertyLoader; -import cbit.vcell.simdata.DataIdentifier; import cbit.vcell.simdata.*; -import cbit.vcell.solver.AnnotatedFunction; -import cbit.vcell.solver.VCSimulationDataIdentifier; -import cbit.vcell.solver.VCSimulationIdentifier; +import cbit.vcell.xml.XmlParseException; import io.quarkus.test.junit.QuarkusTest; import io.quarkus.test.keycloak.client.KeycloakTestClient; import jakarta.inject.Inject; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; import org.eclipse.microprofile.config.inject.ConfigProperty; import org.junit.jupiter.api.*; import org.vcell.restclient.ApiClient; @@ -23,21 +17,13 @@ import org.vcell.restq.TestEndpointUtils; import org.vcell.restq.config.CDIVCellConfigProvider; import org.vcell.restq.db.AgroalConnectionFactory; -import org.vcell.restq.handlers.AdminResource; import org.vcell.util.DataAccessException; -import org.vcell.util.document.KeyValue; -import java.io.File; +import java.beans.PropertyVetoException; import java.io.IOException; import java.sql.SQLException; -import java.time.Instant; -import java.time.OffsetDateTime; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; + +import static org.vcell.restq.exports.ExportHelper.getValidExportRequestDTO; @QuarkusTest public class ExportRequestTest { @@ -46,13 +32,11 @@ public class ExportRequestTest { @Inject AgroalConnectionFactory agroalConnectionFactory; - private static final Logger lg = LogManager.getLogger(ExportRequestTest.class); - KeycloakTestClient keycloakClient = new KeycloakTestClient(); private DataServerImpl dataServer; - private final String simulationID = "597714292"; private ApiClient aliceAPIClient; + private BioModel frapModel; @BeforeAll public static void setupConfig(){ @@ -60,17 +44,11 @@ public static void setupConfig(){ } @BeforeEach - public void setUp() throws IOException, DataAccessException, ApiException, SQLException { + public void setUp() throws IOException, DataAccessException, ApiException, SQLException, PropertyVetoException, XmlParseException { aliceAPIClient = TestEndpointUtils.createAuthenticatedAPIClient(keycloakClient, testPort, TestEndpointUtils.TestOIDCUsers.alice); TestEndpointUtils.mapApiClientToAdmin(aliceAPIClient); - DatabaseServerImpl databaseServer = new DatabaseServerImpl(agroalConnectionFactory, agroalConnectionFactory.getKeyFactory()); - - File testSimData = new File(ExportRequestTest.class.getResource("/simdata").getPath()); - TestEndpointUtils.setSystemProperties(testSimData.getAbsolutePath(), System.getProperty("java.io.tmpdir")); - Cachetable cachetable = new Cachetable(10 * Cachetable.minute, 10000); - DataSetControllerImpl dataSetController = new DataSetControllerImpl(cachetable, testSimData, testSimData); - dataServer = new DataServerImpl(dataSetController, null); - TestEndpointUtils.insertAdminsSimulation(databaseServer, agroalConnectionFactory); + dataServer = TestEndpointUtils.createDataServerImpl(); + frapModel = TestEndpointUtils.insertFrapModel(agroalConnectionFactory); } @AfterEach @@ -82,69 +60,10 @@ public void removeOIDCMappings() throws SQLException, DataAccessException { // Tests the clients capability to submit exports, our queue for accepting and distributing messages, retrieval of export status, and the export job itself @Test public void testExportRequestClient() throws Exception { - final long time = Instant.now().getEpochSecond(); // Before export even starts, so that all events are grabbed from the queue ExportResourceApi exportResourceApi = new ExportResourceApi(aliceAPIClient); - N5ExportRequest exportRequest = getValidExportRequestDTO(0, 1); - exportResourceApi.exportN5(exportRequest); - - CompletableFuture future = CompletableFuture.runAsync(() -> { - try{ - List allEvents = new ArrayList<>(); - while (allEvents.isEmpty()){ - Thread.sleep(100); - allEvents = exportResourceApi.exportStatus(time); - lg.debug("The number of events found for time {} is 0. Retrying...", time); - } - ExportEvent eventUnderInspection = allEvents.stream().toList().get(0); - Assertions.assertEquals(ExportEnums.ExportProgressType.EXPORT_ASSEMBLING, ExportEnums.ExportProgressType.valueOf(eventUnderInspection.getEventType().getValue())); - while (ExportEnums.ExportProgressType.valueOf(eventUnderInspection.getEventType().getValue()) != ExportEnums.ExportProgressType.EXPORT_COMPLETE){ - allEvents = exportResourceApi.exportStatus(time); - lg.debug("The events retrieved are: {}", allEvents); - eventUnderInspection = allEvents.stream().toList().get(allEvents.size() - 1); - lg.debug("The event under inspection is: {}", eventUnderInspection); - Thread.sleep(500); - } - Assertions.assertEquals(ExportProgressType.COMPLETE, eventUnderInspection.getEventType()); - } catch (Exception e){ - Assertions.fail(); - } - }).orTimeout(20, TimeUnit.SECONDS); - future.join(); - } - - private N5ExportRequest getValidExportRequestDTO(int startTimeIndex, int endTimeIndex) throws Exception { - VCSimulationIdentifier vcSimulationIdentifier = new VCSimulationIdentifier(new KeyValue(simulationID), TestEndpointUtils.administratorUser); - VCSimulationDataIdentifier simulationDataIdentifier = new VCSimulationDataIdentifier(vcSimulationIdentifier, 0); - DataIdentifier[] dataIdentifier = dataServer.getDataIdentifiers(new OutputContext(new AnnotatedFunction[0]), TestEndpointUtils.administratorUser, simulationDataIdentifier); - DataIdentifier volumetricDataID = getOneDIWithSpecificType(VariableType.VOLUME, dataIdentifier); - double[] allTimes = dataServer.getDataSetTimes(TestEndpointUtils.administratorUser, simulationDataIdentifier); - StandardExportInfo exportRequest = new StandardExportInfo() - .simulationKey(simulationID) - .simulationJob(0) - .geometrySpecs(new GeometrySpecDTO().geometryMode(GeometryMode.SELECTIONS).selections(new ArrayList<>())) - .timeSpecs( - new org.vcell.restclient.model.TimeSpecs().beginTimeIndex(startTimeIndex).endTimeIndex(endTimeIndex).allTimes(Arrays.stream(allTimes).boxed().toList()).mode(TimeMode.RANGE) - ) - .variableSpecs( - new org.vcell.restclient.model.VariableSpecs().variableNames(new ArrayList<>(){{add(volumetricDataID.getName());}}).mode(VariableMode.ONE) - ) - .contextName("") - .simulationName(vcSimulationIdentifier.getID()) - .outputContext(new ArrayList<>()); - - return new N5ExportRequest().standardExportInformation(exportRequest) - .exportableDataType(ExportableDataType.PDE_VARIABLE_DATA) - .datasetName("testExport") - .subVolume(new java.util.HashMap<>()); - } - - private DataIdentifier getOneDIWithSpecificType(VariableType variableType, DataIdentifier[] dataIdentifiers){ - for(DataIdentifier dataIdentifier: dataIdentifiers){ - if(dataIdentifier.getVariableType().equals(variableType)){ - return dataIdentifier; - } - } - throw new RuntimeException("Cannot find variable type " + variableType); + N5ExportRequest exportRequest = getValidExportRequestDTO(0, 1, dataServer, + frapModel.getSimulation(0), frapModel); + ExportHelper.exportAndWait(exportResourceApi, exportRequest); } } diff --git a/vcell-rest/src/test/java/org/vcell/restq/exports/ExportServerTest.java b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportServerTest.java index bb7f3d9378..fc46c24246 100644 --- a/vcell-rest/src/test/java/org/vcell/restq/exports/ExportServerTest.java +++ b/vcell-rest/src/test/java/org/vcell/restq/exports/ExportServerTest.java @@ -1,14 +1,17 @@ package org.vcell.restq.exports; import cbit.rmi.event.ExportEvent; +import cbit.vcell.biomodel.BioModel; import cbit.vcell.export.server.*; import cbit.vcell.math.VariableType; import cbit.vcell.modeldb.DatabaseServerImpl; +import cbit.vcell.parser.ExpressionException; import cbit.vcell.resource.PropertyLoader; import cbit.vcell.simdata.*; import cbit.vcell.solver.AnnotatedFunction; import cbit.vcell.solver.VCSimulationDataIdentifier; import cbit.vcell.solver.VCSimulationIdentifier; +import cbit.vcell.xml.XmlParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.quarkus.test.junit.QuarkusTest; @@ -30,6 +33,7 @@ import org.vcell.util.DataAccessException; import org.vcell.util.document.KeyValue; +import java.beans.PropertyVetoException; import java.io.File; import java.io.IOException; import java.sql.SQLException; @@ -54,6 +58,7 @@ public class ExportServerTest { @Inject ObjectMapper mapper; + private BioModel bioModel; private DataServerImpl dataServer; private final String simulationID = "597714292"; private final HashMap dummyMaskInfo = new HashMap<>(){{put(0, "Dummy"); put(1, "Test");}}; @@ -64,14 +69,14 @@ public static void setupConfig() throws JMSException { } @BeforeEach - public void setUp() throws IOException, DataAccessException, SQLException { + public void setUp() throws IOException, DataAccessException, SQLException, PropertyVetoException, XmlParseException, ExpressionException { File testSimData = new File(ExportServerTest.class.getResource("/simdata").getPath()); TestEndpointUtils.setSystemProperties(testSimData.getAbsolutePath(), System.getProperty("java.io.tmpdir")); Cachetable cachetable = new Cachetable(10 * Cachetable.minute, 10000); DataSetControllerImpl dataSetController = new DataSetControllerImpl(cachetable, testSimData, testSimData); dataServer = new DataServerImpl(dataSetController, null); - DatabaseServerImpl databaseServer = new DatabaseServerImpl(agroalConnectionFactory, agroalConnectionFactory.getKeyFactory()); - TestEndpointUtils.insertAdminsSimulation(databaseServer, agroalConnectionFactory); + + bioModel = TestEndpointUtils.insertFrapModel(agroalConnectionFactory); } @AfterEach @@ -139,13 +144,16 @@ public void testInvalidInputException() throws Exception { ExportSpecs exportSpecs = getValidExportSpec(0, 1); long badJobID = 2; ExportSpecs badExportSpecs = new ExportSpecs(exportSpecs.getVCDataIdentifier(), ExportFormat.N5, null, null, - new GeometrySpecs(new SpatialSelection[]{}, -1, 5000, ExportEnums.GeometryMode.GEOMETRY_SLICE), null, "TestSim", null); + new GeometrySpecs(new SpatialSelection[]{}, -1, 5000, ExportEnums.GeometryMode.GEOMETRY_SLICE), + null, "TestSim", null, null, null, null); Multi status = createExportListener(badExportSpecs, badJobID); // Start job, while having it be blocking on the main thread to check status CompletableFuture future = CompletableFuture.runAsync(() -> { VCSimulationDataIdentifier vcSimulationDataIdentifier = (VCSimulationDataIdentifier) exportSpecs.getVCDataIdentifier(); - ExportRequestListenerMQ.ExportJob exportJob = new ExportRequestListenerMQ.ExportJob(badJobID, TestEndpointUtils.administratorUser, new AnnotatedFunction[]{}, vcSimulationDataIdentifier.getVcSimID(), vcSimulationDataIdentifier.getJobIndex(), null, null, null, null, null,"TestSim", null); + ExportRequestListenerMQ.ExportJob exportJob = new ExportRequestListenerMQ.ExportJob(badJobID, TestEndpointUtils.administratorUser, new AnnotatedFunction[]{}, vcSimulationDataIdentifier.getVcSimID(), vcSimulationDataIdentifier.getJobIndex(), + null, null, null, null, null,"TestSim", null, + bioModel.getVersion().getVersionKey(), null, bioModel.getSimulationContext(0).getMathDescription().getKey()); CompletableFuture job = null; try { job = requestListenerMQ.get().startJob(Message.of(mapper.writeValueAsString(exportJob))); @@ -206,7 +214,8 @@ private ExportResource.N5ExportRequest getValidExportRequest(int startTimeIndex, HashMap dummyMaskInfo = new HashMap<>(){{put(0, "Dummy"); put(1, "Test");}}; ExportResource.StandardExportInfo request = new ExportResource.StandardExportInfo(new ArrayList<>(){},"", "TestSim", simulationID, 0, - geometrySpecs, timeSpecs, variableSpecs); + geometrySpecs, timeSpecs, variableSpecs, + bioModel.getVersion().getVersionKey(), null, bioModel.getSimulationContext(0).getMathDescription().getKey()); return new ExportResource.N5ExportRequest(request, dummyMaskInfo, ExportEnums.ExportableDataType.PDE_VARIABLE_DATA, "TestDataset"); } @@ -220,10 +229,8 @@ private ExportSpecs getValidExportSpec(int startTimeIndex, int endTimeIndex) thr return new ExportSpecs(simulationDataIdentifier, ExportFormat.N5, request.standardExportInformation().variableSpecs(), request.standardExportInformation().timeSpecs(), new GeometrySpecs(geometrySpecs.selections(), geometrySpecs.axis(), geometrySpecs.sliceNumber(), geometrySpecs.geometryMode()), n5Specs, request.standardExportInformation().simulationName(), - request.standardExportInformation().contextName(), new HumanReadableExportData( - request.standardExportInformation().simulationName(), "fds", - "tretre", new ArrayList<>(), "fsdfds", - "fdsfsd", false, request.subVolume())); + request.standardExportInformation().contextName(), + bioModel.getVersion().getVersionKey(), null, bioModel.getSimulationContext(0).getMathDescription().getKey()); } private DataIdentifier getOneDIWithSpecificType(VariableType variableType, DataIdentifier[] dataIdentifiers){ @@ -236,14 +243,14 @@ private DataIdentifier getOneDIWithSpecificType(VariableType variableType, DataI } private Multi createExportListener(ExportSpecs exportSpecs, long jobID) throws Exception { - exportSpecs.setExportMetaData(new HumanReadableExportData("", "", "", new ArrayList<>(), "", "", false, dummyMaskInfo)); ExportResource.GeometrySpecDTO geometrySpecDTO = new ExportResource.GeometrySpecDTO(exportSpecs.getGeometrySpecs().getSelections(), exportSpecs.getGeometrySpecs().getAxis(), exportSpecs.getGeometrySpecs().getSliceNumber(), exportSpecs.getGeometrySpecs().getMode()); VCSimulationDataIdentifier vcSimulationDataIdentifier = (VCSimulationDataIdentifier) exportSpecs.getVCDataIdentifier(); ExportRequestListenerMQ.ExportJob exportJob = new ExportRequestListenerMQ.ExportJob(jobID, TestEndpointUtils.administratorUser, new AnnotatedFunction[]{}, vcSimulationDataIdentifier.getVcSimID(), vcSimulationDataIdentifier.getJobIndex(), exportSpecs.getFormat(), exportSpecs.getVariableSpecs(), exportSpecs.getTimeSpecs(), - geometrySpecDTO, exportSpecs.getFormatSpecificSpecs(), exportSpecs.getSimulationName(), exportSpecs.getContextName()); + geometrySpecDTO, exportSpecs.getFormatSpecificSpecs(), exportSpecs.getSimulationName(), exportSpecs.getContextName(), + bioModel.getVersion().getVersionKey(), null, bioModel.getSimulationContext(0).getMathDescription().getKey()); statusCreator.get().addServerExportListener(exportJob); return statusCreator.get().getSSEUsersExportStatus(TestEndpointUtils.administratorUser, exportJob.id()); diff --git a/vcell-rest/src/test/resources/simdata/Administrator/Tutorial_FRAP.vcml b/vcell-rest/src/test/resources/simdata/Administrator/Tutorial_FRAP.vcml new file mode 100644 index 0000000000..4839750961 --- /dev/null +++ b/vcell-rest/src/test/resources/simdata/Administrator/Tutorial_FRAP.vcml @@ -0,0 +1,262 @@ + + + + + cloned from 'Tutorial_FRAP' owned by user tutorial +cloned from 'Tutorial_FRAP' owned by user ACowan +cloned from 'Tutorial_FRAP' owned by user Education +cloned from 'Tutorial_FRAP' owned by user tutorial + + cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user ACowan +cloned from 'FRAP' owned by user Education +cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user susan + + Dextran + + + + + + + + + + + + cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user ACowan +cloned from 'FRAP' owned by user Education +cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user susan + + + + + + cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user ACowan +cloned from 'FRAP' owned by user Education +cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user susan + + cloned from 'FRAP_geometry171328045' owned by user tutorial +cloned from 'FRAP_geometry171328045' owned by user ACowan +cloned from 'FRAP_geometry' owned by user Education +cloned from 'FRAP_geometry' owned by user tutorial +cloned from 'FRAP_geometry' owned by user susan + + + + (((x * x) + (y * y)) < 100.0) + + + 1.0 + + + + + + + + + + + cloned from 'FRAP_geometry171328045' owned by user tutorial +cloned from 'FRAP_geometry171328045' owned by user ACowan +cloned from 'FRAP_geometry' owned by user Education +cloned from 'FRAP_geometry' owned by user tutorial +cloned from 'FRAP_geometry' owned by user susan + + + + + + + + + + + + + + + + (10.0 * ((x < - 5.0) || (x > 5.0) || (y < - 5.0) || (y > 5.0))) + 20.0 + + + + cloned from 'FRAP_130359' owned by user tutorial +cloned from 'FRAP_130359' owned by user ACowan +cloned from 'FRAP_130359' owned by user Education +cloned from 'FRAP_130359' owned by user tutorial +cloned from 'FRAP_130359' owned by user susan + 96485.3321 + 9.64853321E-5 + 1.0E-9 + 6.02214179E11 + 3.141592653589793 + 8314.46261815 + 300.0 + 1.0 + 20.0 + 1000.0 + 0.001660538783162726 + 0.0 + 1.0 + 1.0 + + (10.0 * ((x < - 5.0) || (x > 5.0) || (y < - 5.0) || (y > 5.0))) + (VolumePerUnitVolume_Cyt * vcRegionVolume('Cyt')) + (VolumePerUnitVolume_EC * vcRegionVolume('EC')) + (AreaPerUnitArea_PM * vcRegionArea('Cyt_EC_membrane')) + vcRegionArea('Cyt_EC_membrane') + vcRegionVolume('Cyt') + vcRegionVolume('EC') + + + + + + + + + 0.0 + Dex_diffusionRate + Dex_init_uM + + + + + + + + + + + + + + + + + + + 0.0 + 0.0 + + + + + + cloned from 'FRAP_130359' owned by user tutorial +cloned from 'FRAP_130359' owned by user ACowan +cloned from 'FRAP_130359' owned by user Education +cloned from 'FRAP_130359' owned by user tutorial +cloned from 'FRAP_130359' owned by user susan + + + + cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user ACowan +cloned from 'FRAP 1' owned by user Education +cloned from 'FRAP 1' owned by user tutorial +FRAP Simulation for tutorial. + + + + + + + 2 + + 1 + + + + + + + + + cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user ACowan +cloned from 'FRAP 1' owned by user Education +cloned from 'FRAP 1' owned by user tutorial +FRAP Simulation for tutorial. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user ACowan +cloned from 'FRAP' owned by user Education +cloned from 'FRAP' owned by user tutorial +cloned from 'FRAP' owned by user susan + + + + + + + + + cloned from 'Tutorial_FRAP' owned by user tutorial +cloned from 'Tutorial_FRAP' owned by user ACowan +cloned from 'Tutorial_FRAP' owned by user Education +cloned from 'Tutorial_FRAP' owned by user tutorial + + + + + + + + + + + + cloned from 'Tutorial_FRAP' owned by user tutorial + + + Dextran + + + Cytosol + + + Extracellular + + + + + + diff --git a/vcell-restclient/.openapi-generator/FILES b/vcell-restclient/.openapi-generator/FILES index 602361fc39..9b23d83a2f 100644 --- a/vcell-restclient/.openapi-generator/FILES +++ b/vcell-restclient/.openapi-generator/FILES @@ -19,8 +19,11 @@ docs/Curve.md docs/CurveSelectionInfo.md docs/DataIdentifier.md docs/DetailedState.md +docs/DifferentParameterValues.md docs/Domain.md docs/ExportEvent.md +docs/ExportFormat.md +docs/ExportHistory.md docs/ExportProgressType.md docs/ExportResourceApi.md docs/ExportableDataType.md @@ -137,8 +140,11 @@ src/main/java/org/vcell/restclient/model/Curve.java src/main/java/org/vcell/restclient/model/CurveSelectionInfo.java src/main/java/org/vcell/restclient/model/DataIdentifier.java src/main/java/org/vcell/restclient/model/DetailedState.java +src/main/java/org/vcell/restclient/model/DifferentParameterValues.java src/main/java/org/vcell/restclient/model/Domain.java src/main/java/org/vcell/restclient/model/ExportEvent.java +src/main/java/org/vcell/restclient/model/ExportFormat.java +src/main/java/org/vcell/restclient/model/ExportHistory.java src/main/java/org/vcell/restclient/model/ExportProgressType.java src/main/java/org/vcell/restclient/model/ExportableDataType.java src/main/java/org/vcell/restclient/model/Extent.java diff --git a/vcell-restclient/README.md b/vcell-restclient/README.md index d176009a22..33c1deb2b3 100644 --- a/vcell-restclient/README.md +++ b/vcell-restclient/README.md @@ -123,6 +123,8 @@ Class | Method | HTTP request | Description *ExportResourceApi* | [**exportN5WithHttpInfo**](docs/ExportResourceApi.md#exportN5WithHttpInfo) | **POST** /api/v1/export/N5 | *ExportResourceApi* | [**exportStatus**](docs/ExportResourceApi.md#exportStatus) | **GET** /api/v1/export/status | *ExportResourceApi* | [**exportStatusWithHttpInfo**](docs/ExportResourceApi.md#exportStatusWithHttpInfo) | **GET** /api/v1/export/status | +*ExportResourceApi* | [**getExportHistory**](docs/ExportResourceApi.md#getExportHistory) | **GET** /api/v1/export/history | +*ExportResourceApi* | [**getExportHistoryWithHttpInfo**](docs/ExportResourceApi.md#getExportHistoryWithHttpInfo) | **GET** /api/v1/export/history | *FieldDataResourceApi* | [**advancedCreate**](docs/FieldDataResourceApi.md#advancedCreate) | **POST** /api/v1/fieldData/advancedCreate | Create Field Data with granular detail in one request.The following files are accepted: .tif and .zip. *FieldDataResourceApi* | [**advancedCreateWithHttpInfo**](docs/FieldDataResourceApi.md#advancedCreateWithHttpInfo) | **POST** /api/v1/fieldData/advancedCreate | Create Field Data with granular detail in one request.The following files are accepted: .tif and .zip. *FieldDataResourceApi* | [**analyzeFile**](docs/FieldDataResourceApi.md#analyzeFile) | **POST** /api/v1/fieldData/analyzeFile | Analyze uploaded image file (Tiff, Zip, and Non-GPL BioFormats) and return field data. Color mapped images not supported (the colors in those images will be interpreted as separate channels). Filenames must be lowercase alphanumeric, and can contain underscores. @@ -233,8 +235,11 @@ Class | Method | HTTP request | Description - [CurveSelectionInfo](docs/CurveSelectionInfo.md) - [DataIdentifier](docs/DataIdentifier.md) - [DetailedState](docs/DetailedState.md) + - [DifferentParameterValues](docs/DifferentParameterValues.md) - [Domain](docs/Domain.md) - [ExportEvent](docs/ExportEvent.md) + - [ExportFormat](docs/ExportFormat.md) + - [ExportHistory](docs/ExportHistory.md) - [ExportProgressType](docs/ExportProgressType.md) - [ExportableDataType](docs/ExportableDataType.md) - [Extent](docs/Extent.md) diff --git a/vcell-restclient/api/openapi.yaml b/vcell-restclient/api/openapi.yaml index 6216886b8c..19cbedcf55 100644 --- a/vcell-restclient/api/openapi.yaml +++ b/vcell-restclient/api/openapi.yaml @@ -499,6 +499,47 @@ paths: - Export Resource x-content-type: application/json x-accepts: application/json + /api/v1/export/history: + get: + operationId: getExportHistory + parameters: + - explode: true + in: query + name: pageNumber + required: false + schema: + format: int32 + type: integer + style: form + responses: + "200": + content: + application/json: + schema: + items: + $ref: '#/components/schemas/ExportHistory' + type: array + description: OK + "401": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Not Authenticated + "403": + description: Not Allowed + "500": + content: + application/json: + schema: + $ref: '#/components/schemas/VCellHTTPError' + description: Data Access Exception + security: + - openId: + - user + tags: + - Export Resource + x-accepts: application/json /api/v1/export/status: get: description: Get the status of your export jobs past the timestamp (Unix epoch @@ -2879,6 +2920,19 @@ components: - WORKEREVENT_FAILURE - JOB_FAILED type: string + DifferentParameterValues: + example: + originalValue: originalValue + parameterName: parameterName + changedValue: changedValue + properties: + parameterName: + type: string + originalValue: + type: string + changedValue: + type: string + type: object Domain: example: name: name @@ -2896,8 +2950,12 @@ components: numChannels: 5 applicationType: applicationType differentParameterValues: - - differentParameterValues - - differentParameterValues + - originalValue: originalValue + parameterName: parameterName + changedValue: changedValue + - originalValue: originalValue + parameterName: parameterName + changedValue: changedValue serverSavedFileName: serverSavedFileName subVolume: key: subVolume @@ -2938,6 +2996,76 @@ components: humanReadableData: $ref: '#/components/schemas/HumanReadableExportData' type: object + ExportFormat: + enum: + - CSV + - HDF5 + - QUICKTIME + - GIF + - ANIMATED_GIF + - FORMAT_JPEG + - NRRD + - UCD + - VTK_UNSTRUCT + - VTK_IMAGE + - PLY + - N5 + type: string + ExportHistory: + example: + mathModelRef: mathModelRef + variables: + - variables + - variables + simulationRef: simulationRef + mathRef: mathRef + startTimeValue: 6.027456183070403 + endTimeValue: 1.4658129805029452 + uri: uri + modelName: modelName + exportDate: 2022-03-10T16:15:50Z + eventStatus: null + simName: simName + exportJobID: 0 + bioModelRef: bioModelRef + exportFormat: null + properties: + exportJobID: + format: int64 + type: integer + simulationRef: + type: string + bioModelRef: + type: string + mathModelRef: + type: string + mathRef: + type: string + exportFormat: + $ref: '#/components/schemas/ExportFormat' + exportDate: + example: 2022-03-10T16:15:50Z + format: date-time + type: string + uri: + type: string + simName: + type: string + modelName: + type: string + variables: + items: + type: string + type: array + startTimeValue: + format: double + type: number + endTimeValue: + format: double + type: number + eventStatus: + $ref: '#/components/schemas/ExportProgressType' + type: object ExportProgressType: enum: - EXPORT_START @@ -3501,8 +3629,12 @@ components: numChannels: 5 applicationType: applicationType differentParameterValues: - - differentParameterValues - - differentParameterValues + - originalValue: originalValue + parameterName: parameterName + changedValue: changedValue + - originalValue: originalValue + parameterName: parameterName + changedValue: changedValue serverSavedFileName: serverSavedFileName subVolume: key: subVolume @@ -3521,7 +3653,7 @@ components: type: string differentParameterValues: items: - type: string + $ref: '#/components/schemas/DifferentParameterValues' type: array applicationType: type: string @@ -3771,6 +3903,8 @@ components: variableNames: - variableNames - variableNames + bioModelKey: bioModelKey + mathDescriptionKey: mathDescriptionKey simulationName: simulationName geometrySpecs: selections: @@ -3881,6 +4015,7 @@ components: sliceNumber: 4 geometryMode: null axis: 1 + mathModelKey: mathModelKey outputContext: - functionName: functionName domain: @@ -4453,6 +4588,8 @@ components: variableNames: - variableNames - variableNames + bioModelKey: bioModelKey + mathDescriptionKey: mathDescriptionKey simulationName: simulationName geometrySpecs: selections: @@ -4563,6 +4700,7 @@ components: sliceNumber: 4 geometryMode: null axis: 1 + mathModelKey: mathModelKey outputContext: - functionName: functionName domain: @@ -4624,6 +4762,12 @@ components: $ref: '#/components/schemas/TimeSpecs' variableSpecs: $ref: '#/components/schemas/VariableSpecs' + bioModelKey: + type: string + mathModelKey: + type: string + mathDescriptionKey: + type: string type: object Status: enum: diff --git a/vcell-restclient/docs/DifferentParameterValues.md b/vcell-restclient/docs/DifferentParameterValues.md new file mode 100644 index 0000000000..cc41d6d764 --- /dev/null +++ b/vcell-restclient/docs/DifferentParameterValues.md @@ -0,0 +1,15 @@ + + +# DifferentParameterValues + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**parameterName** | **String** | | [optional] | +|**originalValue** | **String** | | [optional] | +|**changedValue** | **String** | | [optional] | + + + diff --git a/vcell-restclient/docs/ExportFormat.md b/vcell-restclient/docs/ExportFormat.md new file mode 100644 index 0000000000..56f1204e13 --- /dev/null +++ b/vcell-restclient/docs/ExportFormat.md @@ -0,0 +1,33 @@ + + +# ExportFormat + +## Enum + + +* `CSV` (value: `"CSV"`) + +* `HDF5` (value: `"HDF5"`) + +* `QUICKTIME` (value: `"QUICKTIME"`) + +* `GIF` (value: `"GIF"`) + +* `ANIMATED_GIF` (value: `"ANIMATED_GIF"`) + +* `FORMAT_JPEG` (value: `"FORMAT_JPEG"`) + +* `NRRD` (value: `"NRRD"`) + +* `UCD` (value: `"UCD"`) + +* `VTK_UNSTRUCT` (value: `"VTK_UNSTRUCT"`) + +* `VTK_IMAGE` (value: `"VTK_IMAGE"`) + +* `PLY` (value: `"PLY"`) + +* `N5` (value: `"N5"`) + + + diff --git a/vcell-restclient/docs/ExportHistory.md b/vcell-restclient/docs/ExportHistory.md new file mode 100644 index 0000000000..282b209b32 --- /dev/null +++ b/vcell-restclient/docs/ExportHistory.md @@ -0,0 +1,26 @@ + + +# ExportHistory + + +## Properties + +| Name | Type | Description | Notes | +|------------ | ------------- | ------------- | -------------| +|**exportJobID** | **Long** | | [optional] | +|**simulationRef** | **String** | | [optional] | +|**bioModelRef** | **String** | | [optional] | +|**mathModelRef** | **String** | | [optional] | +|**mathRef** | **String** | | [optional] | +|**exportFormat** | **ExportFormat** | | [optional] | +|**exportDate** | **OffsetDateTime** | | [optional] | +|**uri** | **String** | | [optional] | +|**simName** | **String** | | [optional] | +|**modelName** | **String** | | [optional] | +|**variables** | **List<String>** | | [optional] | +|**startTimeValue** | **Double** | | [optional] | +|**endTimeValue** | **Double** | | [optional] | +|**eventStatus** | **ExportProgressType** | | [optional] | + + + diff --git a/vcell-restclient/docs/ExportResourceApi.md b/vcell-restclient/docs/ExportResourceApi.md index f093dd744a..cb8abaddfd 100644 --- a/vcell-restclient/docs/ExportResourceApi.md +++ b/vcell-restclient/docs/ExportResourceApi.md @@ -8,6 +8,8 @@ All URIs are relative to *https://vcell.cam.uchc.edu* | [**exportN5WithHttpInfo**](ExportResourceApi.md#exportN5WithHttpInfo) | **POST** /api/v1/export/N5 | | | [**exportStatus**](ExportResourceApi.md#exportStatus) | **GET** /api/v1/export/status | | | [**exportStatusWithHttpInfo**](ExportResourceApi.md#exportStatusWithHttpInfo) | **GET** /api/v1/export/status | | +| [**getExportHistory**](ExportResourceApi.md#getExportHistory) | **GET** /api/v1/export/history | | +| [**getExportHistoryWithHttpInfo**](ExportResourceApi.md#getExportHistoryWithHttpInfo) | **GET** /api/v1/export/history | | @@ -302,3 +304,143 @@ ApiResponse<[**List<ExportEvent>**](ExportEvent.md)> | **403** | Not Allowed | - | | **500** | Data Access Exception | - | + +## getExportHistory + +> List getExportHistory(pageNumber) + + + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.ExportResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + ExportResourceApi apiInstance = new ExportResourceApi(defaultClient); + Integer pageNumber = 56; // Integer | + try { + List result = apiInstance.getExportHistory(pageNumber); + System.out.println(result); + } catch (ApiException e) { + System.err.println("Exception when calling ExportResourceApi#getExportHistory"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Reason: " + e.getResponseBody()); + System.err.println("Response headers: " + e.getResponseHeaders()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **pageNumber** | **Integer**| | [optional] | + +### Return type + +[**List<ExportHistory>**](ExportHistory.md) + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **500** | Data Access Exception | - | + +## getExportHistoryWithHttpInfo + +> ApiResponse> getExportHistory getExportHistoryWithHttpInfo(pageNumber) + + + +### Example + +```java +// Import classes: +import org.vcell.restclient.ApiClient; +import org.vcell.restclient.ApiException; +import org.vcell.restclient.ApiResponse; +import org.vcell.restclient.Configuration; +import org.vcell.restclient.auth.*; +import org.vcell.restclient.models.*; +import org.vcell.restclient.api.ExportResourceApi; + +public class Example { + public static void main(String[] args) { + ApiClient defaultClient = Configuration.getDefaultApiClient(); + defaultClient.setBasePath("https://vcell.cam.uchc.edu"); + + + ExportResourceApi apiInstance = new ExportResourceApi(defaultClient); + Integer pageNumber = 56; // Integer | + try { + ApiResponse> response = apiInstance.getExportHistoryWithHttpInfo(pageNumber); + System.out.println("Status code: " + response.getStatusCode()); + System.out.println("Response headers: " + response.getHeaders()); + System.out.println("Response body: " + response.getData()); + } catch (ApiException e) { + System.err.println("Exception when calling ExportResourceApi#getExportHistory"); + System.err.println("Status code: " + e.getCode()); + System.err.println("Response headers: " + e.getResponseHeaders()); + System.err.println("Reason: " + e.getResponseBody()); + e.printStackTrace(); + } + } +} +``` + +### Parameters + + +| Name | Type | Description | Notes | +|------------- | ------------- | ------------- | -------------| +| **pageNumber** | **Integer**| | [optional] | + +### Return type + +ApiResponse<[**List<ExportHistory>**](ExportHistory.md)> + + +### Authorization + +[openId](../README.md#openId) + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +### HTTP response details +| Status code | Description | Response headers | +|-------------|-------------|------------------| +| **200** | OK | - | +| **401** | Not Authenticated | - | +| **403** | Not Allowed | - | +| **500** | Data Access Exception | - | + diff --git a/vcell-restclient/docs/HumanReadableExportData.md b/vcell-restclient/docs/HumanReadableExportData.md index 24b2297849..b2584d2c2f 100644 --- a/vcell-restclient/docs/HumanReadableExportData.md +++ b/vcell-restclient/docs/HumanReadableExportData.md @@ -10,7 +10,7 @@ |**simulationName** | **String** | | [optional] | |**biomodelName** | **String** | | [optional] | |**applicationName** | **String** | | [optional] | -|**differentParameterValues** | **List<String>** | | [optional] | +|**differentParameterValues** | [**List<DifferentParameterValues>**](DifferentParameterValues.md) | | [optional] | |**applicationType** | **String** | | [optional] | |**serverSavedFileName** | **String** | | [optional] | |**nonSpatial** | **Boolean** | | [optional] | diff --git a/vcell-restclient/docs/StandardExportInfo.md b/vcell-restclient/docs/StandardExportInfo.md index 42fbfc49cb..459bcc7715 100644 --- a/vcell-restclient/docs/StandardExportInfo.md +++ b/vcell-restclient/docs/StandardExportInfo.md @@ -15,6 +15,9 @@ |**geometrySpecs** | [**GeometrySpecDTO**](GeometrySpecDTO.md) | | [optional] | |**timeSpecs** | [**TimeSpecs**](TimeSpecs.md) | | [optional] | |**variableSpecs** | [**VariableSpecs**](VariableSpecs.md) | | [optional] | +|**bioModelKey** | **String** | | [optional] | +|**mathModelKey** | **String** | | [optional] | +|**mathDescriptionKey** | **String** | | [optional] | diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/api/ExportResourceApi.java b/vcell-restclient/src/main/java/org/vcell/restclient/api/ExportResourceApi.java index 49c8e682c2..6cbab8d3c0 100644 --- a/vcell-restclient/src/main/java/org/vcell/restclient/api/ExportResourceApi.java +++ b/vcell-restclient/src/main/java/org/vcell/restclient/api/ExportResourceApi.java @@ -18,6 +18,7 @@ import org.vcell.restclient.Pair; import org.vcell.restclient.model.ExportEvent; +import org.vcell.restclient.model.ExportHistory; import org.vcell.restclient.model.N5ExportRequest; import org.vcell.restclient.model.VCellHTTPError; @@ -229,6 +230,88 @@ private HttpRequest.Builder exportStatusRequestBuilder(Long timestamp) throws Ap localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); + if (memberVarReadTimeout != null) { + localVarRequestBuilder.timeout(memberVarReadTimeout); + } + if (memberVarInterceptor != null) { + memberVarInterceptor.accept(localVarRequestBuilder); + } + return localVarRequestBuilder; + } + /** + * + * + * @param pageNumber (optional) + * @return List<ExportHistory> + * @throws ApiException if fails to make API call + */ + public List getExportHistory(Integer pageNumber) throws ApiException { + ApiResponse> localVarResponse = getExportHistoryWithHttpInfo(pageNumber); + return localVarResponse.getData(); + } + + /** + * + * + * @param pageNumber (optional) + * @return ApiResponse<List<ExportHistory>> + * @throws ApiException if fails to make API call + */ + public ApiResponse> getExportHistoryWithHttpInfo(Integer pageNumber) throws ApiException { + HttpRequest.Builder localVarRequestBuilder = getExportHistoryRequestBuilder(pageNumber); + try { + HttpResponse localVarResponse = memberVarHttpClient.send( + localVarRequestBuilder.build(), + HttpResponse.BodyHandlers.ofInputStream()); + if (memberVarResponseInterceptor != null) { + memberVarResponseInterceptor.accept(localVarResponse); + } + try { + if (localVarResponse.statusCode()/ 100 != 2) { + throw getApiException("getExportHistory", localVarResponse); + } + return new ApiResponse>( + localVarResponse.statusCode(), + localVarResponse.headers().map(), + localVarResponse.body() == null ? null : memberVarObjectMapper.readValue(localVarResponse.body(), new TypeReference>() {}) // closes the InputStream + ); + } finally { + } + } catch (IOException e) { + throw new ApiException(e); + } + catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new ApiException(e); + } + } + + private HttpRequest.Builder getExportHistoryRequestBuilder(Integer pageNumber) throws ApiException { + + HttpRequest.Builder localVarRequestBuilder = HttpRequest.newBuilder(); + + String localVarPath = "/api/v1/export/history"; + + List localVarQueryParams = new ArrayList<>(); + StringJoiner localVarQueryStringJoiner = new StringJoiner("&"); + String localVarQueryParameterBaseName; + localVarQueryParameterBaseName = "pageNumber"; + localVarQueryParams.addAll(ApiClient.parameterToPairs("pageNumber", pageNumber)); + + if (!localVarQueryParams.isEmpty() || localVarQueryStringJoiner.length() != 0) { + StringJoiner queryJoiner = new StringJoiner("&"); + localVarQueryParams.forEach(p -> queryJoiner.add(p.getName() + '=' + p.getValue())); + if (localVarQueryStringJoiner.length() != 0) { + queryJoiner.add(localVarQueryStringJoiner.toString()); + } + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath + '?' + queryJoiner.toString())); + } else { + localVarRequestBuilder.uri(URI.create(memberVarBaseUri + localVarPath)); + } + + localVarRequestBuilder.header("Accept", "application/json"); + localVarRequestBuilder.method("GET", HttpRequest.BodyPublishers.noBody()); if (memberVarReadTimeout != null) { localVarRequestBuilder.timeout(memberVarReadTimeout); diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/DifferentParameterValues.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/DifferentParameterValues.java new file mode 100644 index 0000000000..52e8f1d9c8 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/DifferentParameterValues.java @@ -0,0 +1,222 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * DifferentParameterValues + */ +@JsonPropertyOrder({ + DifferentParameterValues.JSON_PROPERTY_PARAMETER_NAME, + DifferentParameterValues.JSON_PROPERTY_ORIGINAL_VALUE, + DifferentParameterValues.JSON_PROPERTY_CHANGED_VALUE +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class DifferentParameterValues { + public static final String JSON_PROPERTY_PARAMETER_NAME = "parameterName"; + private String parameterName; + + public static final String JSON_PROPERTY_ORIGINAL_VALUE = "originalValue"; + private String originalValue; + + public static final String JSON_PROPERTY_CHANGED_VALUE = "changedValue"; + private String changedValue; + + public DifferentParameterValues() { + } + + public DifferentParameterValues parameterName(String parameterName) { + this.parameterName = parameterName; + return this; + } + + /** + * Get parameterName + * @return parameterName + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_PARAMETER_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getParameterName() { + return parameterName; + } + + + @JsonProperty(JSON_PROPERTY_PARAMETER_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setParameterName(String parameterName) { + this.parameterName = parameterName; + } + + + public DifferentParameterValues originalValue(String originalValue) { + this.originalValue = originalValue; + return this; + } + + /** + * Get originalValue + * @return originalValue + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_ORIGINAL_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getOriginalValue() { + return originalValue; + } + + + @JsonProperty(JSON_PROPERTY_ORIGINAL_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setOriginalValue(String originalValue) { + this.originalValue = originalValue; + } + + + public DifferentParameterValues changedValue(String changedValue) { + this.changedValue = changedValue; + return this; + } + + /** + * Get changedValue + * @return changedValue + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_CHANGED_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getChangedValue() { + return changedValue; + } + + + @JsonProperty(JSON_PROPERTY_CHANGED_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setChangedValue(String changedValue) { + this.changedValue = changedValue; + } + + + /** + * Return true if this DifferentParameterValues object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + DifferentParameterValues differentParameterValues = (DifferentParameterValues) o; + return Objects.equals(this.parameterName, differentParameterValues.parameterName) && + Objects.equals(this.originalValue, differentParameterValues.originalValue) && + Objects.equals(this.changedValue, differentParameterValues.changedValue); + } + + @Override + public int hashCode() { + return Objects.hash(parameterName, originalValue, changedValue); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class DifferentParameterValues {\n"); + sb.append(" parameterName: ").append(toIndentedString(parameterName)).append("\n"); + sb.append(" originalValue: ").append(toIndentedString(originalValue)).append("\n"); + sb.append(" changedValue: ").append(toIndentedString(changedValue)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `parameterName` to the URL query string + if (getParameterName() != null) { + joiner.add(String.format("%sparameterName%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getParameterName()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `originalValue` to the URL query string + if (getOriginalValue() != null) { + joiner.add(String.format("%soriginalValue%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getOriginalValue()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `changedValue` to the URL query string + if (getChangedValue() != null) { + joiner.add(String.format("%schangedValue%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getChangedValue()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/ExportFormat.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/ExportFormat.java new file mode 100644 index 0000000000..e2d6323f6e --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/ExportFormat.java @@ -0,0 +1,98 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +/** + * Gets or Sets ExportFormat + */ +public enum ExportFormat { + + CSV("CSV"), + + HDF5("HDF5"), + + QUICKTIME("QUICKTIME"), + + GIF("GIF"), + + ANIMATED_GIF("ANIMATED_GIF"), + + FORMAT_JPEG("FORMAT_JPEG"), + + NRRD("NRRD"), + + UCD("UCD"), + + VTK_UNSTRUCT("VTK_UNSTRUCT"), + + VTK_IMAGE("VTK_IMAGE"), + + PLY("PLY"), + + N5("N5"); + + private String value; + + ExportFormat(String value) { + this.value = value; + } + + @JsonValue + public String getValue() { + return value; + } + + @Override + public String toString() { + return String.valueOf(value); + } + + @JsonCreator + public static ExportFormat fromValue(String value) { + for (ExportFormat b : ExportFormat.values()) { + if (b.value.equals(value)) { + return b; + } + } + throw new IllegalArgumentException("Unexpected value '" + value + "'"); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + if (prefix == null) { + prefix = ""; + } + + return String.format("%s=%s", prefix, this.toString()); + } + +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/ExportHistory.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/ExportHistory.java new file mode 100644 index 0000000000..c8f1561c57 --- /dev/null +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/ExportHistory.java @@ -0,0 +1,635 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.util.StringJoiner; +import java.util.Objects; +import java.util.Map; +import java.util.HashMap; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.time.OffsetDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.vcell.restclient.model.ExportFormat; +import org.vcell.restclient.model.ExportProgressType; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; + + +/** + * ExportHistory + */ +@JsonPropertyOrder({ + ExportHistory.JSON_PROPERTY_EXPORT_JOB_I_D, + ExportHistory.JSON_PROPERTY_SIMULATION_REF, + ExportHistory.JSON_PROPERTY_BIO_MODEL_REF, + ExportHistory.JSON_PROPERTY_MATH_MODEL_REF, + ExportHistory.JSON_PROPERTY_MATH_REF, + ExportHistory.JSON_PROPERTY_EXPORT_FORMAT, + ExportHistory.JSON_PROPERTY_EXPORT_DATE, + ExportHistory.JSON_PROPERTY_URI, + ExportHistory.JSON_PROPERTY_SIM_NAME, + ExportHistory.JSON_PROPERTY_MODEL_NAME, + ExportHistory.JSON_PROPERTY_VARIABLES, + ExportHistory.JSON_PROPERTY_START_TIME_VALUE, + ExportHistory.JSON_PROPERTY_END_TIME_VALUE, + ExportHistory.JSON_PROPERTY_EVENT_STATUS +}) +@javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") +public class ExportHistory { + public static final String JSON_PROPERTY_EXPORT_JOB_I_D = "exportJobID"; + private Long exportJobID; + + public static final String JSON_PROPERTY_SIMULATION_REF = "simulationRef"; + private String simulationRef; + + public static final String JSON_PROPERTY_BIO_MODEL_REF = "bioModelRef"; + private String bioModelRef; + + public static final String JSON_PROPERTY_MATH_MODEL_REF = "mathModelRef"; + private String mathModelRef; + + public static final String JSON_PROPERTY_MATH_REF = "mathRef"; + private String mathRef; + + public static final String JSON_PROPERTY_EXPORT_FORMAT = "exportFormat"; + private ExportFormat exportFormat; + + public static final String JSON_PROPERTY_EXPORT_DATE = "exportDate"; + private OffsetDateTime exportDate; + + public static final String JSON_PROPERTY_URI = "uri"; + private String uri; + + public static final String JSON_PROPERTY_SIM_NAME = "simName"; + private String simName; + + public static final String JSON_PROPERTY_MODEL_NAME = "modelName"; + private String modelName; + + public static final String JSON_PROPERTY_VARIABLES = "variables"; + private List variables; + + public static final String JSON_PROPERTY_START_TIME_VALUE = "startTimeValue"; + private Double startTimeValue; + + public static final String JSON_PROPERTY_END_TIME_VALUE = "endTimeValue"; + private Double endTimeValue; + + public static final String JSON_PROPERTY_EVENT_STATUS = "eventStatus"; + private ExportProgressType eventStatus; + + public ExportHistory() { + } + + public ExportHistory exportJobID(Long exportJobID) { + this.exportJobID = exportJobID; + return this; + } + + /** + * Get exportJobID + * @return exportJobID + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_EXPORT_JOB_I_D) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Long getExportJobID() { + return exportJobID; + } + + + @JsonProperty(JSON_PROPERTY_EXPORT_JOB_I_D) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setExportJobID(Long exportJobID) { + this.exportJobID = exportJobID; + } + + + public ExportHistory simulationRef(String simulationRef) { + this.simulationRef = simulationRef; + return this; + } + + /** + * Get simulationRef + * @return simulationRef + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_SIMULATION_REF) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getSimulationRef() { + return simulationRef; + } + + + @JsonProperty(JSON_PROPERTY_SIMULATION_REF) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSimulationRef(String simulationRef) { + this.simulationRef = simulationRef; + } + + + public ExportHistory bioModelRef(String bioModelRef) { + this.bioModelRef = bioModelRef; + return this; + } + + /** + * Get bioModelRef + * @return bioModelRef + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_BIO_MODEL_REF) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getBioModelRef() { + return bioModelRef; + } + + + @JsonProperty(JSON_PROPERTY_BIO_MODEL_REF) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setBioModelRef(String bioModelRef) { + this.bioModelRef = bioModelRef; + } + + + public ExportHistory mathModelRef(String mathModelRef) { + this.mathModelRef = mathModelRef; + return this; + } + + /** + * Get mathModelRef + * @return mathModelRef + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_MATH_MODEL_REF) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getMathModelRef() { + return mathModelRef; + } + + + @JsonProperty(JSON_PROPERTY_MATH_MODEL_REF) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setMathModelRef(String mathModelRef) { + this.mathModelRef = mathModelRef; + } + + + public ExportHistory mathRef(String mathRef) { + this.mathRef = mathRef; + return this; + } + + /** + * Get mathRef + * @return mathRef + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_MATH_REF) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getMathRef() { + return mathRef; + } + + + @JsonProperty(JSON_PROPERTY_MATH_REF) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setMathRef(String mathRef) { + this.mathRef = mathRef; + } + + + public ExportHistory exportFormat(ExportFormat exportFormat) { + this.exportFormat = exportFormat; + return this; + } + + /** + * Get exportFormat + * @return exportFormat + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_EXPORT_FORMAT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public ExportFormat getExportFormat() { + return exportFormat; + } + + + @JsonProperty(JSON_PROPERTY_EXPORT_FORMAT) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setExportFormat(ExportFormat exportFormat) { + this.exportFormat = exportFormat; + } + + + public ExportHistory exportDate(OffsetDateTime exportDate) { + this.exportDate = exportDate; + return this; + } + + /** + * Get exportDate + * @return exportDate + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_EXPORT_DATE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public OffsetDateTime getExportDate() { + return exportDate; + } + + + @JsonProperty(JSON_PROPERTY_EXPORT_DATE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setExportDate(OffsetDateTime exportDate) { + this.exportDate = exportDate; + } + + + public ExportHistory uri(String uri) { + this.uri = uri; + return this; + } + + /** + * Get uri + * @return uri + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_URI) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getUri() { + return uri; + } + + + @JsonProperty(JSON_PROPERTY_URI) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setUri(String uri) { + this.uri = uri; + } + + + public ExportHistory simName(String simName) { + this.simName = simName; + return this; + } + + /** + * Get simName + * @return simName + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_SIM_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getSimName() { + return simName; + } + + + @JsonProperty(JSON_PROPERTY_SIM_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setSimName(String simName) { + this.simName = simName; + } + + + public ExportHistory modelName(String modelName) { + this.modelName = modelName; + return this; + } + + /** + * Get modelName + * @return modelName + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_MODEL_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getModelName() { + return modelName; + } + + + @JsonProperty(JSON_PROPERTY_MODEL_NAME) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setModelName(String modelName) { + this.modelName = modelName; + } + + + public ExportHistory variables(List variables) { + this.variables = variables; + return this; + } + + public ExportHistory addVariablesItem(String variablesItem) { + if (this.variables == null) { + this.variables = new ArrayList<>(); + } + this.variables.add(variablesItem); + return this; + } + + /** + * Get variables + * @return variables + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_VARIABLES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public List getVariables() { + return variables; + } + + + @JsonProperty(JSON_PROPERTY_VARIABLES) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setVariables(List variables) { + this.variables = variables; + } + + + public ExportHistory startTimeValue(Double startTimeValue) { + this.startTimeValue = startTimeValue; + return this; + } + + /** + * Get startTimeValue + * @return startTimeValue + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_START_TIME_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Double getStartTimeValue() { + return startTimeValue; + } + + + @JsonProperty(JSON_PROPERTY_START_TIME_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setStartTimeValue(Double startTimeValue) { + this.startTimeValue = startTimeValue; + } + + + public ExportHistory endTimeValue(Double endTimeValue) { + this.endTimeValue = endTimeValue; + return this; + } + + /** + * Get endTimeValue + * @return endTimeValue + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_END_TIME_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public Double getEndTimeValue() { + return endTimeValue; + } + + + @JsonProperty(JSON_PROPERTY_END_TIME_VALUE) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setEndTimeValue(Double endTimeValue) { + this.endTimeValue = endTimeValue; + } + + + public ExportHistory eventStatus(ExportProgressType eventStatus) { + this.eventStatus = eventStatus; + return this; + } + + /** + * Get eventStatus + * @return eventStatus + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_EVENT_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public ExportProgressType getEventStatus() { + return eventStatus; + } + + + @JsonProperty(JSON_PROPERTY_EVENT_STATUS) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setEventStatus(ExportProgressType eventStatus) { + this.eventStatus = eventStatus; + } + + + /** + * Return true if this ExportHistory object is equal to o. + */ + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + ExportHistory exportHistory = (ExportHistory) o; + return Objects.equals(this.exportJobID, exportHistory.exportJobID) && + Objects.equals(this.simulationRef, exportHistory.simulationRef) && + Objects.equals(this.bioModelRef, exportHistory.bioModelRef) && + Objects.equals(this.mathModelRef, exportHistory.mathModelRef) && + Objects.equals(this.mathRef, exportHistory.mathRef) && + Objects.equals(this.exportFormat, exportHistory.exportFormat) && + Objects.equals(this.exportDate, exportHistory.exportDate) && + Objects.equals(this.uri, exportHistory.uri) && + Objects.equals(this.simName, exportHistory.simName) && + Objects.equals(this.modelName, exportHistory.modelName) && + Objects.equals(this.variables, exportHistory.variables) && + Objects.equals(this.startTimeValue, exportHistory.startTimeValue) && + Objects.equals(this.endTimeValue, exportHistory.endTimeValue) && + Objects.equals(this.eventStatus, exportHistory.eventStatus); + } + + @Override + public int hashCode() { + return Objects.hash(exportJobID, simulationRef, bioModelRef, mathModelRef, mathRef, exportFormat, exportDate, uri, simName, modelName, variables, startTimeValue, endTimeValue, eventStatus); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append("class ExportHistory {\n"); + sb.append(" exportJobID: ").append(toIndentedString(exportJobID)).append("\n"); + sb.append(" simulationRef: ").append(toIndentedString(simulationRef)).append("\n"); + sb.append(" bioModelRef: ").append(toIndentedString(bioModelRef)).append("\n"); + sb.append(" mathModelRef: ").append(toIndentedString(mathModelRef)).append("\n"); + sb.append(" mathRef: ").append(toIndentedString(mathRef)).append("\n"); + sb.append(" exportFormat: ").append(toIndentedString(exportFormat)).append("\n"); + sb.append(" exportDate: ").append(toIndentedString(exportDate)).append("\n"); + sb.append(" uri: ").append(toIndentedString(uri)).append("\n"); + sb.append(" simName: ").append(toIndentedString(simName)).append("\n"); + sb.append(" modelName: ").append(toIndentedString(modelName)).append("\n"); + sb.append(" variables: ").append(toIndentedString(variables)).append("\n"); + sb.append(" startTimeValue: ").append(toIndentedString(startTimeValue)).append("\n"); + sb.append(" endTimeValue: ").append(toIndentedString(endTimeValue)).append("\n"); + sb.append(" eventStatus: ").append(toIndentedString(eventStatus)).append("\n"); + sb.append("}"); + return sb.toString(); + } + + /** + * Convert the given object to string with each line indented by 4 spaces + * (except the first line). + */ + private String toIndentedString(Object o) { + if (o == null) { + return "null"; + } + return o.toString().replace("\n", "\n "); + } + + /** + * Convert the instance into URL query string. + * + * @return URL query string + */ + public String toUrlQueryString() { + return toUrlQueryString(null); + } + + /** + * Convert the instance into URL query string. + * + * @param prefix prefix of the query string + * @return URL query string + */ + public String toUrlQueryString(String prefix) { + String suffix = ""; + String containerSuffix = ""; + String containerPrefix = ""; + if (prefix == null) { + // style=form, explode=true, e.g. /pet?name=cat&type=manx + prefix = ""; + } else { + // deepObject style e.g. /pet?id[name]=cat&id[type]=manx + prefix = prefix + "["; + suffix = "]"; + containerSuffix = "]"; + containerPrefix = "["; + } + + StringJoiner joiner = new StringJoiner("&"); + + // add `exportJobID` to the URL query string + if (getExportJobID() != null) { + joiner.add(String.format("%sexportJobID%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getExportJobID()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `simulationRef` to the URL query string + if (getSimulationRef() != null) { + joiner.add(String.format("%ssimulationRef%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getSimulationRef()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `bioModelRef` to the URL query string + if (getBioModelRef() != null) { + joiner.add(String.format("%sbioModelRef%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getBioModelRef()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `mathModelRef` to the URL query string + if (getMathModelRef() != null) { + joiner.add(String.format("%smathModelRef%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getMathModelRef()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `mathRef` to the URL query string + if (getMathRef() != null) { + joiner.add(String.format("%smathRef%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getMathRef()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `exportFormat` to the URL query string + if (getExportFormat() != null) { + joiner.add(String.format("%sexportFormat%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getExportFormat()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `exportDate` to the URL query string + if (getExportDate() != null) { + joiner.add(String.format("%sexportDate%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getExportDate()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `uri` to the URL query string + if (getUri() != null) { + joiner.add(String.format("%suri%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getUri()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `simName` to the URL query string + if (getSimName() != null) { + joiner.add(String.format("%ssimName%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getSimName()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `modelName` to the URL query string + if (getModelName() != null) { + joiner.add(String.format("%smodelName%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getModelName()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `variables` to the URL query string + if (getVariables() != null) { + for (int i = 0; i < getVariables().size(); i++) { + joiner.add(String.format("%svariables%s%s=%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), + URLEncoder.encode(String.valueOf(getVariables().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + } + + // add `startTimeValue` to the URL query string + if (getStartTimeValue() != null) { + joiner.add(String.format("%sstartTimeValue%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getStartTimeValue()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `endTimeValue` to the URL query string + if (getEndTimeValue() != null) { + joiner.add(String.format("%sendTimeValue%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getEndTimeValue()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `eventStatus` to the URL query string + if (getEventStatus() != null) { + joiner.add(String.format("%seventStatus%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getEventStatus()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + return joiner.toString(); + } +} + diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/HumanReadableExportData.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/HumanReadableExportData.java index 7137081d8e..30eb46ce83 100644 --- a/vcell-restclient/src/main/java/org/vcell/restclient/model/HumanReadableExportData.java +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/HumanReadableExportData.java @@ -29,6 +29,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import org.vcell.restclient.model.DifferentParameterValues; import com.fasterxml.jackson.annotation.JsonPropertyOrder; @@ -60,7 +61,7 @@ public class HumanReadableExportData { private String applicationName; public static final String JSON_PROPERTY_DIFFERENT_PARAMETER_VALUES = "differentParameterValues"; - private List differentParameterValues; + private List differentParameterValues; public static final String JSON_PROPERTY_APPLICATION_TYPE = "applicationType"; private String applicationType; @@ -161,12 +162,12 @@ public void setApplicationName(String applicationName) { } - public HumanReadableExportData differentParameterValues(List differentParameterValues) { + public HumanReadableExportData differentParameterValues(List differentParameterValues) { this.differentParameterValues = differentParameterValues; return this; } - public HumanReadableExportData addDifferentParameterValuesItem(String differentParameterValuesItem) { + public HumanReadableExportData addDifferentParameterValuesItem(DifferentParameterValues differentParameterValuesItem) { if (this.differentParameterValues == null) { this.differentParameterValues = new ArrayList<>(); } @@ -182,14 +183,14 @@ public HumanReadableExportData addDifferentParameterValuesItem(String differentP @JsonProperty(JSON_PROPERTY_DIFFERENT_PARAMETER_VALUES) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public List getDifferentParameterValues() { + public List getDifferentParameterValues() { return differentParameterValues; } @JsonProperty(JSON_PROPERTY_DIFFERENT_PARAMETER_VALUES) @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) - public void setDifferentParameterValues(List differentParameterValues) { + public void setDifferentParameterValues(List differentParameterValues) { this.differentParameterValues = differentParameterValues; } @@ -487,9 +488,10 @@ public String toUrlQueryString(String prefix) { // add `differentParameterValues` to the URL query string if (getDifferentParameterValues() != null) { for (int i = 0; i < getDifferentParameterValues().size(); i++) { - joiner.add(String.format("%sdifferentParameterValues%s%s=%s", prefix, suffix, - "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix), - URLEncoder.encode(String.valueOf(getDifferentParameterValues().get(i)), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + if (getDifferentParameterValues().get(i) != null) { + joiner.add(getDifferentParameterValues().get(i).toUrlQueryString(String.format("%sdifferentParameterValues%s%s", prefix, suffix, + "".equals(suffix) ? "" : String.format("%s%d%s", containerPrefix, i, containerSuffix)))); + } } } diff --git a/vcell-restclient/src/main/java/org/vcell/restclient/model/StandardExportInfo.java b/vcell-restclient/src/main/java/org/vcell/restclient/model/StandardExportInfo.java index 33cdf9aa5e..140dbba5bf 100644 --- a/vcell-restclient/src/main/java/org/vcell/restclient/model/StandardExportInfo.java +++ b/vcell-restclient/src/main/java/org/vcell/restclient/model/StandardExportInfo.java @@ -45,7 +45,10 @@ StandardExportInfo.JSON_PROPERTY_SIMULATION_JOB, StandardExportInfo.JSON_PROPERTY_GEOMETRY_SPECS, StandardExportInfo.JSON_PROPERTY_TIME_SPECS, - StandardExportInfo.JSON_PROPERTY_VARIABLE_SPECS + StandardExportInfo.JSON_PROPERTY_VARIABLE_SPECS, + StandardExportInfo.JSON_PROPERTY_BIO_MODEL_KEY, + StandardExportInfo.JSON_PROPERTY_MATH_MODEL_KEY, + StandardExportInfo.JSON_PROPERTY_MATH_DESCRIPTION_KEY }) @javax.annotation.Generated(value = "org.openapitools.codegen.languages.JavaClientCodegen") public class StandardExportInfo { @@ -73,6 +76,15 @@ public class StandardExportInfo { public static final String JSON_PROPERTY_VARIABLE_SPECS = "variableSpecs"; private VariableSpecs variableSpecs; + public static final String JSON_PROPERTY_BIO_MODEL_KEY = "bioModelKey"; + private String bioModelKey; + + public static final String JSON_PROPERTY_MATH_MODEL_KEY = "mathModelKey"; + private String mathModelKey; + + public static final String JSON_PROPERTY_MATH_DESCRIPTION_KEY = "mathDescriptionKey"; + private String mathDescriptionKey; + public StandardExportInfo() { } @@ -284,6 +296,81 @@ public void setVariableSpecs(VariableSpecs variableSpecs) { } + public StandardExportInfo bioModelKey(String bioModelKey) { + this.bioModelKey = bioModelKey; + return this; + } + + /** + * Get bioModelKey + * @return bioModelKey + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_BIO_MODEL_KEY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getBioModelKey() { + return bioModelKey; + } + + + @JsonProperty(JSON_PROPERTY_BIO_MODEL_KEY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setBioModelKey(String bioModelKey) { + this.bioModelKey = bioModelKey; + } + + + public StandardExportInfo mathModelKey(String mathModelKey) { + this.mathModelKey = mathModelKey; + return this; + } + + /** + * Get mathModelKey + * @return mathModelKey + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_MATH_MODEL_KEY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getMathModelKey() { + return mathModelKey; + } + + + @JsonProperty(JSON_PROPERTY_MATH_MODEL_KEY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setMathModelKey(String mathModelKey) { + this.mathModelKey = mathModelKey; + } + + + public StandardExportInfo mathDescriptionKey(String mathDescriptionKey) { + this.mathDescriptionKey = mathDescriptionKey; + return this; + } + + /** + * Get mathDescriptionKey + * @return mathDescriptionKey + **/ + @javax.annotation.Nullable + @JsonProperty(JSON_PROPERTY_MATH_DESCRIPTION_KEY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + + public String getMathDescriptionKey() { + return mathDescriptionKey; + } + + + @JsonProperty(JSON_PROPERTY_MATH_DESCRIPTION_KEY) + @JsonInclude(value = JsonInclude.Include.USE_DEFAULTS) + public void setMathDescriptionKey(String mathDescriptionKey) { + this.mathDescriptionKey = mathDescriptionKey; + } + + /** * Return true if this StandardExportInfo object is equal to o. */ @@ -303,12 +390,15 @@ public boolean equals(Object o) { Objects.equals(this.simulationJob, standardExportInfo.simulationJob) && Objects.equals(this.geometrySpecs, standardExportInfo.geometrySpecs) && Objects.equals(this.timeSpecs, standardExportInfo.timeSpecs) && - Objects.equals(this.variableSpecs, standardExportInfo.variableSpecs); + Objects.equals(this.variableSpecs, standardExportInfo.variableSpecs) && + Objects.equals(this.bioModelKey, standardExportInfo.bioModelKey) && + Objects.equals(this.mathModelKey, standardExportInfo.mathModelKey) && + Objects.equals(this.mathDescriptionKey, standardExportInfo.mathDescriptionKey); } @Override public int hashCode() { - return Objects.hash(outputContext, contextName, simulationName, simulationKey, simulationJob, geometrySpecs, timeSpecs, variableSpecs); + return Objects.hash(outputContext, contextName, simulationName, simulationKey, simulationJob, geometrySpecs, timeSpecs, variableSpecs, bioModelKey, mathModelKey, mathDescriptionKey); } @Override @@ -323,6 +413,9 @@ public String toString() { sb.append(" geometrySpecs: ").append(toIndentedString(geometrySpecs)).append("\n"); sb.append(" timeSpecs: ").append(toIndentedString(timeSpecs)).append("\n"); sb.append(" variableSpecs: ").append(toIndentedString(variableSpecs)).append("\n"); + sb.append(" bioModelKey: ").append(toIndentedString(bioModelKey)).append("\n"); + sb.append(" mathModelKey: ").append(toIndentedString(mathModelKey)).append("\n"); + sb.append(" mathDescriptionKey: ").append(toIndentedString(mathDescriptionKey)).append("\n"); sb.append("}"); return sb.toString(); } @@ -415,6 +508,21 @@ public String toUrlQueryString(String prefix) { joiner.add(getVariableSpecs().toUrlQueryString(prefix + "variableSpecs" + suffix)); } + // add `bioModelKey` to the URL query string + if (getBioModelKey() != null) { + joiner.add(String.format("%sbioModelKey%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getBioModelKey()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `mathModelKey` to the URL query string + if (getMathModelKey() != null) { + joiner.add(String.format("%smathModelKey%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getMathModelKey()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + + // add `mathDescriptionKey` to the URL query string + if (getMathDescriptionKey() != null) { + joiner.add(String.format("%smathDescriptionKey%s=%s", prefix, suffix, URLEncoder.encode(String.valueOf(getMathDescriptionKey()), StandardCharsets.UTF_8).replaceAll("\\+", "%20"))); + } + return joiner.toString(); } } diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/DifferentParameterValuesTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/DifferentParameterValuesTest.java new file mode 100644 index 0000000000..b39fe48557 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/DifferentParameterValuesTest.java @@ -0,0 +1,64 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.Arrays; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for DifferentParameterValues + */ +public class DifferentParameterValuesTest { + private final DifferentParameterValues model = new DifferentParameterValues(); + + /** + * Model tests for DifferentParameterValues + */ + @Test + public void testDifferentParameterValues() { + // TODO: test DifferentParameterValues + } + + /** + * Test the property 'parameterName' + */ + @Test + public void parameterNameTest() { + // TODO: test parameterName + } + + /** + * Test the property 'originalValue' + */ + @Test + public void originalValueTest() { + // TODO: test originalValue + } + + /** + * Test the property 'changedValue' + */ + @Test + public void changedValueTest() { + // TODO: test changedValue + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/ExportFormatTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/ExportFormatTest.java new file mode 100644 index 0000000000..9e8676431e --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/ExportFormatTest.java @@ -0,0 +1,32 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for ExportFormat + */ +public class ExportFormatTest { + /** + * Model tests for ExportFormat + */ + @Test + public void testExportFormat() { + // TODO: test ExportFormat + } + +} diff --git a/vcell-restclient/src/test/java/org/vcell/restclient/model/ExportHistoryTest.java b/vcell-restclient/src/test/java/org/vcell/restclient/model/ExportHistoryTest.java new file mode 100644 index 0000000000..316006b7a2 --- /dev/null +++ b/vcell-restclient/src/test/java/org/vcell/restclient/model/ExportHistoryTest.java @@ -0,0 +1,196 @@ +/* + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +package org.vcell.restclient.model; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonTypeName; +import com.fasterxml.jackson.annotation.JsonValue; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.vcell.restclient.model.DifferentParameterValues; +import org.vcell.restclient.model.ExportFormat; +import org.junit.Assert; +import org.junit.Ignore; +import org.junit.Test; + +/** + * Model tests for ExportHistory + */ +public class ExportHistoryTest { + private final ExportHistory model = new ExportHistory(); + + /** + * Model tests for ExportHistory + */ + @Test + public void testExportHistory() { + // TODO: test ExportHistory + } + + /** + * Test the property 'jobID' + */ + @Test + public void jobIDTest() { + // TODO: test jobID + } + + /** + * Test the property 'simulationRef' + */ + @Test + public void simulationRefTest() { + // TODO: test simulationRef + } + + /** + * Test the property 'exportFormat' + */ + @Test + public void exportFormatTest() { + // TODO: test exportFormat + } + + /** + * Test the property 'exportDate' + */ + @Test + public void exportDateTest() { + // TODO: test exportDate + } + + /** + * Test the property 'uri' + */ + @Test + public void uriTest() { + // TODO: test uri + } + + /** + * Test the property 'dataIdValue' + */ + @Test + public void dataIdValueTest() { + // TODO: test dataIdValue + } + + /** + * Test the property 'simName' + */ + @Test + public void simNameTest() { + // TODO: test simName + } + + /** + * Test the property 'appName' + */ + @Test + public void appNameTest() { + // TODO: test appName + } + + /** + * Test the property 'bioName' + */ + @Test + public void bioNameTest() { + // TODO: test bioName + } + + /** + * Test the property 'variables' + */ + @Test + public void variablesTest() { + // TODO: test variables + } + + /** + * Test the property 'parameterValues' + */ + @Test + public void parameterValuesTest() { + // TODO: test parameterValues + } + + /** + * Test the property 'startTimeValue' + */ + @Test + public void startTimeValueTest() { + // TODO: test startTimeValue + } + + /** + * Test the property 'endTimeValue' + */ + @Test + public void endTimeValueTest() { + // TODO: test endTimeValue + } + + /** + * Test the property 'savedFileNameValue' + */ + @Test + public void savedFileNameValueTest() { + // TODO: test savedFileNameValue + } + + /** + * Test the property 'applicationTypeValue' + */ + @Test + public void applicationTypeValueTest() { + // TODO: test applicationTypeValue + } + + /** + * Test the property 'nonSpatialValue' + */ + @Test + public void nonSpatialValueTest() { + // TODO: test nonSpatialValue + } + + /** + * Test the property 'zSlicesValue' + */ + @Test + public void zSlicesValueTest() { + // TODO: test zSlicesValue + } + + /** + * Test the property 'tSlicesValue' + */ + @Test + public void tSlicesValueTest() { + // TODO: test tSlicesValue + } + + /** + * Test the property 'numVariablesValue' + */ + @Test + public void numVariablesValueTest() { + // TODO: test numVariablesValue + } + +} diff --git a/vcell-server/src/main/java/cbit/sql/Field.java b/vcell-server/src/main/java/cbit/sql/Field.java index b7623636bd..0068eae74b 100644 --- a/vcell-server/src/main/java/cbit/sql/Field.java +++ b/vcell-server/src/main/java/cbit/sql/Field.java @@ -66,6 +66,8 @@ public enum SQLDataType { blob_bytea("blob","bytea",BasicDataType.BLOB), clob_text("clob","text",BasicDataType.CLOB), + + json("clob is json","jsonb", BasicDataType.CLOB), date("date","timestamp",BasicDataType.DATE); diff --git a/vcell-server/src/main/java/cbit/vcell/exports/ExportHistory.java b/vcell-server/src/main/java/cbit/vcell/exports/ExportHistory.java new file mode 100644 index 0000000000..7aa2227664 --- /dev/null +++ b/vcell-server/src/main/java/cbit/vcell/exports/ExportHistory.java @@ -0,0 +1,28 @@ +package cbit.vcell.exports; + +import cbit.vcell.export.server.ExportEnums; +import cbit.vcell.export.server.ExportFormat; +import org.vcell.util.document.KeyValue; + +import java.time.Instant; + +public record ExportHistory( + long exportJobID, + KeyValue simulationRef, + KeyValue bioModelRef, + KeyValue mathModelRef, + KeyValue mathRef, + ExportFormat exportFormat, + Instant exportDate, + String uri, + String simName, +// String appName, + String modelName, + String[] variables, +// List overrides, + double startTimeValue, + double endTimeValue, +// String applicationTypeValue, + ExportEnums.ExportProgressType eventStatus +) { +} diff --git a/vcell-server/src/main/java/cbit/vcell/exports/ExportHistoryDBDriver.java b/vcell-server/src/main/java/cbit/vcell/exports/ExportHistoryDBDriver.java new file mode 100644 index 0000000000..a559783336 --- /dev/null +++ b/vcell-server/src/main/java/cbit/vcell/exports/ExportHistoryDBDriver.java @@ -0,0 +1,95 @@ +package cbit.vcell.exports; + +import cbit.vcell.modeldb.*; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.vcell.db.DatabaseSyntax; +import org.vcell.db.KeyFactory; +import org.vcell.util.DataAccessException; +import org.vcell.util.DependencyException; +import org.vcell.util.ObjectNotFoundException; +import org.vcell.util.PermissionException; +import org.vcell.util.document.KeyValue; +import org.vcell.util.document.User; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +public class ExportHistoryDBDriver { + + /** + * LocalDBManager constructor comment. + */ + public ExportHistoryDBDriver(DatabaseSyntax databaseSyntax, KeyFactory keyFactory) { + + } + + private boolean isOracleConnection(Connection connection) throws SQLException { + String productName = connection.getMetaData().getDatabaseProductName().toLowerCase(); + return productName.contains("oracle"); + } + + public void addExportHistory(Connection conn, User user, ExportHistoryDBRep exportHistory, KeyFactory keyFactory) + throws SQLException, DependencyException, PermissionException, DataAccessException, ObjectNotFoundException { + + // 1) insert into vc_model_export_history + String ehSQL = ExportHistoryTable.table.getInsertSQL(); + KeyValue keyValue = keyFactory.getNewKey(conn); + + try (PreparedStatement ps = conn.prepareStatement(ehSQL)) { + ExportHistoryTable.table.bindForInsert(ps, + keyValue, + exportHistory.jobID(), + Integer.parseInt(user.getID().toString()), + exportHistory.bioModelRef() == null ? null : Integer.parseInt(exportHistory.bioModelRef().toString()), + exportHistory.mathModelRef() == null ? null : Integer.parseInt(exportHistory.mathModelRef().toString()), + Integer.parseInt(exportHistory.simulationRef().toString()), + Integer.parseInt(exportHistory.mathRef().toString()), + exportHistory.exportFormat(), + exportHistory.exportDate(), + exportHistory.uri(), + conn.createArrayOf("VARCHAR", exportHistory.variables()), + exportHistory.startTimeValue(), + exportHistory.endTimeValue(), + exportHistory.eventStatus().toString() + ); + ps.executeUpdate(); + } + + } + + public void deleteExportHistory(Connection conn, String uri) throws SQLException { + // Concern, data id could mean multiple items get deleted + String deleteSQL = "DELETE FROM " + ExportHistoryTable.table.tableName + " WHERE " + ExportHistoryTable.table.uri.getUnqualifiedColName() + " = ?"; + try (PreparedStatement psDel = conn.prepareStatement(deleteSQL)) { + psDel.setString(1, uri); + psDel.executeUpdate(); + } + } + + // sub selection of sim ref key for that export event, then tie it back to biomodel/sim for getting metadata (name, application, etc) + public List getExportHistoryForUser(Connection conn, User user, int pageNumber) throws SQLException, JsonProcessingException, DataAccessException { + String properSQL = "SELECT eh.*, sim." + SimulationTable.table.name.getUnqualifiedColName() + + " as sim_name, bio." + BioModelTable.table.name.getUnqualifiedColName() + + " as bio_name, math." + MathModelTable.table.name.getUnqualifiedColName() + + " as math_model_name, simContext." + SimContextTable.table.name.getUnqualifiedColName() + " as application_name" + + " FROM " + ExportHistoryTable.table.tableName + " eh " + + " INNER JOIN " + SimulationTable.table.tableName + " sim ON sim." + SimulationTable.table.id.getUnqualifiedColName() + " = eh." + ExportHistoryTable.table.simulationRef.getUnqualifiedColName() + + " LEFT JOIN " + BioModelTable.table.tableName + " bio ON bio." + BioModelTable.table.id.getUnqualifiedColName() + " = eh." + ExportHistoryTable.table.bioModelRef.getUnqualifiedColName() + + " LEFT JOIN " + MathDescTable.table.tableName + " math ON math." + MathModelTable.table.id.getUnqualifiedColName() + " = eh." + ExportHistoryTable.table.mathModelRef.getUnqualifiedColName() + + " LEFT JOIN " + SimContextTable.table.tableName + " simContext ON simContext." + SimContextTable.table.id.getUnqualifiedColName() + " = eh." + ExportHistoryTable.table.mathRef.getUnqualifiedColName() + + " WHERE " + ExportHistoryTable.table.userRef.getUnqualifiedColName() + " = ? ORDER BY " + ExportHistoryTable.table.exportDate.getUnqualifiedColName() + " DESC OFFSET ? ROWS FETCH NEXT 100 ROWS ONLY"; + + PreparedStatement ps = conn.prepareStatement(properSQL); + ps.setLong(1, Long.parseLong(user.getID().toString())); + pageNumber = (0 < pageNumber) && (pageNumber < 10000) ? pageNumber : 0; + ps.setInt(2, pageNumber * 100); + ResultSet resultSet = ps.executeQuery(); + List exportHistoryDBReps = new ArrayList<>(); + while (resultSet.next()) { + exportHistoryDBReps.add(ExportHistoryTable.table.getExportHistoryRecord(resultSet)); + } + return exportHistoryDBReps; + } + +} diff --git a/vcell-server/src/main/java/cbit/vcell/exports/ExportHistoryDBRep.java b/vcell-server/src/main/java/cbit/vcell/exports/ExportHistoryDBRep.java new file mode 100644 index 0000000000..156460bafe --- /dev/null +++ b/vcell-server/src/main/java/cbit/vcell/exports/ExportHistoryDBRep.java @@ -0,0 +1,58 @@ +package cbit.vcell.exports; + +import cbit.vcell.export.server.ExportEnums; +import cbit.vcell.export.server.ExportFormat; +import cbit.vcell.export.server.ExportSpecs; +import cbit.vcell.solver.VCSimulationDataIdentifier; +import org.vcell.util.document.KeyValue; + +import java.sql.Timestamp; +import java.time.Instant; +import java.util.List; + +public record ExportHistoryDBRep( + long jobID, + KeyValue bioModelRef, + KeyValue mathModelRef, + KeyValue simulationRef, + KeyValue mathRef, + ExportFormat exportFormat, + Timestamp exportDate, + String uri, + String[] variables, + double startTimeValue, + double endTimeValue, + ExportEnums.ExportProgressType eventStatus +) { + public boolean equals(ExportHistoryDBRep other){ + return this.jobID == other.jobID && + this.bioModelRef == other.bioModelRef() && + this.mathModelRef() == other.mathModelRef() && + this.simulationRef.equals(other.simulationRef) && + this.exportFormat.equals(other.exportFormat) && + this.exportDate.equals(other.exportDate) && + this.uri.equals(other.uri) && + List.of(this.variables).equals(List.of(other.variables)) && + Double.compare(this.startTimeValue, other.startTimeValue) == 0 && + Double.compare(this.endTimeValue, other.endTimeValue) == 0 && + this.eventStatus.equals(other.eventStatus); + } + + public static ExportHistoryDBRep fromExportSpec(ExportSpecs exportSpecs, String url, long jobID, VCSimulationDataIdentifier simDataId, ExportEnums.ExportProgressType eventStatus) { + double[] times = exportSpecs.getTimeSpecs().getAllTimes(); + return new ExportHistoryDBRep( + jobID, + exportSpecs.getBioModelKey(), + exportSpecs.getMathModelKey(), + simDataId.getSimulationKey(), + exportSpecs.getMathDescriptionKey(), + exportSpecs.getFormat(), + Timestamp.from(Instant.now()), + url, + exportSpecs.getVariableSpecs().getVariableNames(), + times[exportSpecs.getTimeSpecs().getBeginTimeIndex()], + times[exportSpecs.getTimeSpecs().getEndTimeIndex()], + eventStatus + ); + } +} diff --git a/vcell-server/src/main/java/cbit/vcell/exports/ExportHistoryTable.java b/vcell-server/src/main/java/cbit/vcell/exports/ExportHistoryTable.java new file mode 100644 index 0000000000..fa3f1e3ffb --- /dev/null +++ b/vcell-server/src/main/java/cbit/vcell/exports/ExportHistoryTable.java @@ -0,0 +1,159 @@ +package cbit.vcell.exports; + +import cbit.sql.Field; +import cbit.sql.Table; +import cbit.vcell.export.server.ExportEnums; +import cbit.vcell.export.server.ExportFormat; +import cbit.vcell.modeldb.*; +import org.vcell.util.DataAccessException; +import org.vcell.util.document.KeyValue; + +import java.sql.*; +import java.util.StringJoiner; + +public class ExportHistoryTable extends Table { + private static final String TABLE_NAME = "vc_simulation_export_job"; + + // public final Field id = new Field(id_ColumnName, Field.SQLDataType.integer,"PRIMARY KEY"); + + public final Field jobId = new Field("job_id", Field.SQLDataType.integer, "NOT NULL"); + + public final Field userRef = new Field("user_ref", Field.SQLDataType.integer, "NOT NULL " + UserTable.REF_TYPE); + public final Field bioModelRef = new Field("biomodel_ref", Field.SQLDataType.integer, BioModelTable.REF_TYPE); + public final Field mathModelRef = new Field("mathmodel_ref", Field.SQLDataType.integer, MathModelTable.REF_TYPE); + public final Field simulationRef = new Field("simulation_ref", Field.SQLDataType.integer, "NOT NULL " + SimulationTable.REF_TYPE); + public final Field mathRef = new Field("math_ref", Field.SQLDataType.integer, "NOT NULL " + MathDescTable.REF_TYPE); + + + public final Field exportFormat = new Field("export_format", Field.SQLDataType.varchar_50, "NOT NULL"); + public final Field exportDate = new Field("export_date", Field.SQLDataType.date, "NOT NULL"); + public final Field uri = new Field("uri", Field.SQLDataType.varchar_1024, "NOT NULL"); + + public final Field variables = new Field("variables", Field.SQLDataType.varchar2_4000, "[] NOT NULL"); + public final Field startTime = new Field("start_time", Field.SQLDataType.number_as_real, "NOT NULL"); + public final Field endTime = new Field("end_time", Field.SQLDataType.number_as_real, "NOT NULL"); + public final Field eventStatus = new Field("event_status", Field.SQLDataType.varchar_50, "NOT NULL"); + + + //public final Field insertDate = new Field("insert_date", Field.SQLDataType.date, "NOT NULL DEFAULT CURRENT_TIMESTAMP"); + + +// private final Field fields[] = {jobId, userRef, modelRef, exportFormat, exportDate, uri, +// dataId, simulationName, applicationName, biomodelName, variables, +// startTime, endTime, savedFileName, applicationType, nonSpatial, +// zSlices, tSlices, numVariables}; + + public static final ExportHistoryTable table = new ExportHistoryTable(); + + private ExportHistoryTable() { + super(TABLE_NAME); + // Minus id, which is added by the table abstract class + // note that primary key id cannot be placed in fields (will causes class initialization error), + Field[] customFields = { + // note that primary key id cannot be placed in fields (will causes class initialization error), + jobId, userRef, bioModelRef, mathModelRef, simulationRef, mathRef, + exportFormat, exportDate, uri, variables, + startTime, endTime, eventStatus + }; + addFields(customFields); + } + + public String getInsertSQL() { + + StringJoiner cols = new StringJoiner(",", "(", ")"); + Field[] fieldsToInsert = getFields(); + for (Field f : fieldsToInsert) { + cols.add(f.getUnqualifiedColName()); + } + + StringJoiner ph = new StringJoiner(",", "(", ")"); + for (int i = 0; i < fieldsToInsert.length; i++) { + ph.add("?"); + } + return "INSERT INTO " + TABLE_NAME + " " + cols.toString() + " VALUES " + ph.toString(); + } + + public void bindForInsert( + PreparedStatement ps, + KeyValue keyValue, + long jobIdValue, + int userRefValue, + Integer bioModelRef, + Integer mathModelRef, + int simulationRef, + int mathRef, + ExportFormat fmt, + Timestamp exportDateValue, + String uriValue, + Array variables, + double startTimeValue, + double endTimeValue, + String eventStatusValue + ) throws SQLException { + int i = 1; + ps.setInt (i++, Integer.parseInt(keyValue.toString())); + ps.setLong (i++, jobIdValue); + ps.setLong (i++, userRefValue); + if (bioModelRef != null) {ps.setLong(i++, bioModelRef);} else { + ps.setNull(i++, java.sql.Types.INTEGER); + } + if (mathModelRef != null) {ps.setLong(i++, mathModelRef);} else { + ps.setNull(i++, java.sql.Types.INTEGER); + } + ps.setLong (i++, simulationRef); + ps.setLong (i++, mathRef); + ps.setString (i++, fmt.name()); + ps.setTimestamp (i++, exportDateValue); + ps.setString (i++, uriValue); + ps.setArray (i++, variables); + ps.setDouble (i++, startTimeValue); + ps.setDouble (i++, endTimeValue); + ps.setString (i++, eventStatusValue); + } + + public ExportHistory getExportHistoryRecord(ResultSet rset) throws SQLException, SQLException, DataAccessException { + + long simulationRef = rset.getLong(this.simulationRef.getUnqualifiedColName()); + long mathRef = rset.getLong(this.mathRef.getUnqualifiedColName()); + Long bioModelRef = (Long) rset.getObject(this.bioModelRef.getUnqualifiedColName()); + Long mathModelRef = (Long) rset.getObject(this.mathModelRef.getUnqualifiedColName()); + // enums & timestamps + ExportFormat fmt = ExportFormat.valueOf(rset.getString(this.exportFormat.getUnqualifiedColName())); + Timestamp date = rset.getTimestamp(this.exportDate.getUnqualifiedColName()); + + // strings + long jobId = rset.getLong(this.jobId.getUnqualifiedColName()); + String uriVal = rset.getString(this.uri.getUnqualifiedColName()); + String simNameVal = rset.getString("sim_name"); + String mathModelNameVal = rset.getString("math_model_name"); + String bioNameVal = rset.getString("bio_name"); + String modelName = mathModelNameVal == null ? bioNameVal : mathModelNameVal; + + String[] variables = (String[]) rset.getArray(this.variables.getUnqualifiedColName()).getArray(); + + // numeric ranges + double startBt = rset.getDouble(this.startTime.getUnqualifiedColName()); + double endBt = rset.getDouble(this.endTime.getUnqualifiedColName()); + + // more strings & flags + String eventStatusVal = rset.getString(this.eventStatus.getUnqualifiedColName()); + + +// String mathOverrides = rset.getString("mathOverrides"); +// mathOverrides = mathOverrides == null ? rset.getString("mathOverridesSML") : mathOverrides; +// mathOverrides = mathOverrides == null ? rset.getString("mathOverridesLRG") : mathOverrides; +// List overrides = MathOverrides.parseOverrideElementsFromVCML(new CommentStringTokenizer(mathOverrides)); + +// String childSummary = rset.getString("childSummarySML"); +// childSummary = childSummary == null ? rset.getString("childSummaryLRG") : childSummary; +// BioModelChildSummary bioModelChildSummary = BioModelChildSummary.fromDatabaseSerialization(childSummary); + + + return new ExportHistory( + jobId, new KeyValue("" + simulationRef), bioModelRef == null ? null : new KeyValue("" + bioModelRef), + mathModelRef == null ? null : new KeyValue("" + mathModelRef), new KeyValue("" + mathRef), fmt, date.toInstant(), + uriVal, simNameVal, modelName, variables, + startBt, endBt, ExportEnums.ExportProgressType.valueOf(eventStatusVal) + ); + } +} diff --git a/vcell-server/src/main/java/cbit/vcell/modeldb/DBTopLevel.java b/vcell-server/src/main/java/cbit/vcell/modeldb/DBTopLevel.java index f00a579010..d5c7ac473c 100644 --- a/vcell-server/src/main/java/cbit/vcell/modeldb/DBTopLevel.java +++ b/vcell-server/src/main/java/cbit/vcell/modeldb/DBTopLevel.java @@ -15,6 +15,9 @@ import cbit.sql.QueryHashtable; import cbit.sql.RecordChangedException; import cbit.vcell.biomodel.BioModelMetaData; +import cbit.vcell.exports.ExportHistory; +import cbit.vcell.exports.ExportHistoryDBDriver; +import cbit.vcell.exports.ExportHistoryDBRep; import cbit.vcell.field.FieldDataAllDBEntries; import cbit.vcell.field.FieldDataExternalDataIDEntry; import cbit.vcell.field.io.CopyFieldDataResult; @@ -38,6 +41,7 @@ import java.sql.Connection; import java.sql.SQLException; +import java.util.List; import java.util.TreeMap; import java.util.Vector; /** @@ -53,6 +57,7 @@ public class DBTopLevel extends AbstractDBTopLevel{ private final BioModelDbDriver bioModelDB; private final MathModelDbDriver mathModelDB; private final UserDbDriver userDB; + private final ExportHistoryDBDriver exportHistoryDBDriver; // private DBCacheTable dbCacheTable = null; private static final int SQL_ERROR_CODE_BADCONNECTION = 1010; //?????????????????????????????????????? @@ -75,6 +80,7 @@ public class DBTopLevel extends AbstractDBTopLevel{ this.userDB = new UserDbDriver(); this.bioModelDB = new BioModelDbDriver(databaseSyntax,keyFactory); this.mathModelDB = new MathModelDbDriver(databaseSyntax, keyFactory); + this.exportHistoryDBDriver = new ExportHistoryDBDriver(databaseSyntax, keyFactory); } @@ -2255,4 +2261,51 @@ public SimulationRep getSimulationRep(KeyValue simKey, boolean bEnableRetry) thr } } + public void insertExportHistory(User user, ExportHistoryDBRep exportHistoryValues, boolean bEnableRetry) throws SQLException, DataAccessException { + Object lock = new Object(); + Connection con = conFactory.getConnection(lock); + try { + exportHistoryDBDriver.addExportHistory(con, user, exportHistoryValues, conFactory.getKeyFactory()); + } catch (Throwable e) { + lg.error(e.getMessage(),e); + try { + con.rollback(); + }catch (Throwable rbe){ + lg.error("exception during rollback, bEnableRetry = "+bEnableRetry, rbe); + } + if (bEnableRetry && isBadConnection(con)) { + conFactory.failed(con,lock); + insertExportHistory(user, exportHistoryValues, false); + }else{ + handle_DataAccessException_SQLException(e); + } + }finally{ + conFactory.release(con,lock); + } + } + + public List getUsersExportHistory(User user, int pagingNumber, boolean bEnableRetry) throws SQLException, DataAccessException { + Object lock = new Object(); + Connection con = conFactory.getConnection(lock); + try { + return exportHistoryDBDriver.getExportHistoryForUser(con, user, pagingNumber); + } catch (Throwable e) { + lg.error(e.getMessage(),e); + try { + con.rollback(); + }catch (Throwable rbe){ + lg.error("exception during rollback, bEnableRetry = "+bEnableRetry, rbe); + } + if (bEnableRetry && isBadConnection(con)) { + conFactory.failed(con,lock); + return getUsersExportHistory(user, pagingNumber,false); + }else{ + handle_DataAccessException_SQLException(e); + return null; // never gets here; + } + }finally{ + conFactory.release(con,lock); + } + } + } diff --git a/vcell-server/src/main/java/cbit/vcell/modeldb/DatabaseServerImpl.java b/vcell-server/src/main/java/cbit/vcell/modeldb/DatabaseServerImpl.java index a131f8f40c..1bf8e4c848 100644 --- a/vcell-server/src/main/java/cbit/vcell/modeldb/DatabaseServerImpl.java +++ b/vcell-server/src/main/java/cbit/vcell/modeldb/DatabaseServerImpl.java @@ -15,6 +15,8 @@ import cbit.sql.QueryHashtable; import cbit.util.xml.XmlUtil; import cbit.vcell.biomodel.BioModelMetaData; +import cbit.vcell.exports.ExportHistory; +import cbit.vcell.exports.ExportHistoryDBRep; import cbit.vcell.field.FieldDataAllDBEntries; import cbit.vcell.field.FieldDataExternalDataIDEntry; import cbit.vcell.field.io.CopyFieldDataResult; @@ -1355,4 +1357,21 @@ public BigString saveVCImageAs(User user, BigString vcImageXML, java.lang.String } } + public void addExportHistory(User user, ExportHistoryDBRep exportHistory) throws DataAccessException { + try { + dbTop.insertExportHistory(user, exportHistory, true); + } catch (SQLException e) { + throw new DataAccessException(e); + } + } + + public List getUsersExportHistory(User user, int pageNumber) throws DataAccessException { + try { + return dbTop.getUsersExportHistory(user, pageNumber,true); + } catch (SQLException e) { + throw new DataAccessException(e); + } + } + + } diff --git a/vcell-server/src/main/java/cbit/vcell/modeldb/SQLCreateAllTables.java b/vcell-server/src/main/java/cbit/vcell/modeldb/SQLCreateAllTables.java index 58eb9648ee..c504b938ab 100644 --- a/vcell-server/src/main/java/cbit/vcell/modeldb/SQLCreateAllTables.java +++ b/vcell-server/src/main/java/cbit/vcell/modeldb/SQLCreateAllTables.java @@ -12,6 +12,7 @@ import cbit.sql.Field; import cbit.sql.Table; +import cbit.vcell.exports.ExportHistoryTable; import cbit.vcell.resource.PropertyLoader; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -205,6 +206,8 @@ private static void destroyAndRecreateTables(ConnectionFactory conFactory, KeyFa createIndex(con,"geom_imageref",cbit.vcell.modeldb.GeometryTable.table,cbit.vcell.modeldb.GeometryTable.table.imageRef, dbSyntax); createIndex(con,"mathdesc_geomref",cbit.vcell.modeldb.MathDescTable.table,cbit.vcell.modeldb.MathDescTable.table.geometryRef, dbSyntax); createIndex(con,"simcstat_simcref",cbit.vcell.modeldb.SimContextStatTable.table,cbit.vcell.modeldb.SimContextStatTable.table.simContextRef, dbSyntax); + createIndex(con, "export_job_time", ExportHistoryTable.table, ExportHistoryTable.table.exportDate, dbSyntax); + createIndex(con, "export_job_userref", ExportHistoryTable.table, ExportHistoryTable.table.userRef, dbSyntax); } con.commit(); } catch (SQLException exc) { @@ -376,6 +379,7 @@ public static Table[] getVCellTables() { cbit.vcell.modeldb.VCMetaDataTable.table, // new cbit.vcell.modeldb.SimDelFromDiskTable.table, // new UserIdentityTable.table, + ExportHistoryTable.table // new }; return tables; } @@ -402,6 +406,8 @@ public static void writeScript(DatabaseSyntax dbSyntax, boolean bootstrapData, W scriptWriter.write(getCreateIndexSQL("geom_imageref", GeometryTable.table, GeometryTable.table.imageRef) + ";\n"); scriptWriter.write(getCreateIndexSQL("mathdesc_geomref", MathDescTable.table, MathDescTable.table.geometryRef) + ";\n"); scriptWriter.write(getCreateIndexSQL("simcstat_simcref", SimContextStatTable.table, SimContextStatTable.table.simContextRef) + ";\n"); + scriptWriter.write(getCreateIndexSQL("export_job_userref", ExportHistoryTable.table, ExportHistoryTable.table.userRef) + ";\n"); + scriptWriter.write(getCreateIndexSQL("export_job_time", ExportHistoryTable.table, ExportHistoryTable.table.exportDate) + ";\n"); scriptWriter.write("\n"); if (bootstrapData) { KeyFactory bootstrapKeyFactory = new KeyFactory() { diff --git a/webapp-ng/src/app/core/modules/openapi/.openapi-generator/FILES b/webapp-ng/src/app/core/modules/openapi/.openapi-generator/FILES index 1787f0845d..200e968142 100644 --- a/webapp-ng/src/app/core/modules/openapi/.openapi-generator/FILES +++ b/webapp-ng/src/app/core/modules/openapi/.openapi-generator/FILES @@ -46,8 +46,11 @@ model/curve-selection-info.ts model/curve.ts model/data-identifier.ts model/detailed-state.ts +model/different-parameter-values.ts model/domain.ts model/export-event.ts +model/export-format.ts +model/export-history.ts model/export-progress-type.ts model/exportable-data-type.ts model/extent.ts diff --git a/webapp-ng/src/app/core/modules/openapi/api/export-resource.service.ts b/webapp-ng/src/app/core/modules/openapi/api/export-resource.service.ts index a911b3fc48..5a9cee11ac 100644 --- a/webapp-ng/src/app/core/modules/openapi/api/export-resource.service.ts +++ b/webapp-ng/src/app/core/modules/openapi/api/export-resource.service.ts @@ -21,6 +21,8 @@ import { Observable } from 'rxjs'; // @ts-ignore import { ExportEvent } from '../model/export-event'; // @ts-ignore +import { ExportHistory } from '../model/export-history'; +// @ts-ignore import { N5ExportRequest } from '../model/n5-export-request'; // @ts-ignore import { VCellHTTPError } from '../model/v-cell-http-error'; @@ -237,4 +239,71 @@ export class ExportResourceService implements ExportResourceServiceInterface { ); } + /** + * @param pageNumber + * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body. + * @param reportProgress flag to report request and response progress. + */ + public getExportHistory(pageNumber?: number, observe?: 'body', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>; + public getExportHistory(pageNumber?: number, observe?: 'response', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>>; + public getExportHistory(pageNumber?: number, observe?: 'events', reportProgress?: boolean, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable>>; + public getExportHistory(pageNumber?: number, observe: any = 'body', reportProgress: boolean = false, options?: {httpHeaderAccept?: 'application/json', context?: HttpContext}): Observable { + + let localVarQueryParameters = new HttpParams({encoder: this.encoder}); + if (pageNumber !== undefined && pageNumber !== null) { + localVarQueryParameters = this.addToHttpParams(localVarQueryParameters, + pageNumber, 'pageNumber'); + } + + let localVarHeaders = this.defaultHeaders; + + let localVarCredential: string | undefined; + // authentication (openId) required + localVarCredential = this.configuration.lookupCredential('openId'); + if (localVarCredential) { + } + + let localVarHttpHeaderAcceptSelected: string | undefined = options && options.httpHeaderAccept; + if (localVarHttpHeaderAcceptSelected === undefined) { + // to determine the Accept header + const httpHeaderAccepts: string[] = [ + 'application/json' + ]; + localVarHttpHeaderAcceptSelected = this.configuration.selectHeaderAccept(httpHeaderAccepts); + } + if (localVarHttpHeaderAcceptSelected !== undefined) { + localVarHeaders = localVarHeaders.set('Accept', localVarHttpHeaderAcceptSelected); + } + + let localVarHttpContext: HttpContext | undefined = options && options.context; + if (localVarHttpContext === undefined) { + localVarHttpContext = new HttpContext(); + } + + + let responseType_: 'text' | 'json' | 'blob' = 'json'; + if (localVarHttpHeaderAcceptSelected) { + if (localVarHttpHeaderAcceptSelected.startsWith('text')) { + responseType_ = 'text'; + } else if (this.configuration.isJsonMime(localVarHttpHeaderAcceptSelected)) { + responseType_ = 'json'; + } else { + responseType_ = 'blob'; + } + } + + let localVarPath = `/api/v1/export/history`; + return this.httpClient.request>('get', `${this.configuration.basePath}${localVarPath}`, + { + context: localVarHttpContext, + params: localVarQueryParameters, + responseType: responseType_, + withCredentials: this.configuration.withCredentials, + headers: localVarHeaders, + observe: observe, + reportProgress: reportProgress + } + ); + } + } diff --git a/webapp-ng/src/app/core/modules/openapi/api/export-resource.serviceInterface.ts b/webapp-ng/src/app/core/modules/openapi/api/export-resource.serviceInterface.ts index 05c50e07c3..c3bd1435ed 100644 --- a/webapp-ng/src/app/core/modules/openapi/api/export-resource.serviceInterface.ts +++ b/webapp-ng/src/app/core/modules/openapi/api/export-resource.serviceInterface.ts @@ -14,6 +14,7 @@ import { HttpHeaders } from '@angular/comm import { Observable } from 'rxjs'; import { ExportEvent } from '../model/models'; +import { ExportHistory } from '../model/models'; import { N5ExportRequest } from '../model/models'; import { VCellHTTPError } from '../model/models'; @@ -40,4 +41,11 @@ export interface ExportResourceServiceInterface { */ exportStatus(timestamp?: number, extraHttpRequestParams?: any): Observable>; + /** + * + * + * @param pageNumber + */ + getExportHistory(pageNumber?: number, extraHttpRequestParams?: any): Observable>; + } diff --git a/webapp-ng/src/app/core/modules/openapi/model/different-parameter-values.ts b/webapp-ng/src/app/core/modules/openapi/model/different-parameter-values.ts new file mode 100644 index 0000000000..d2457537f4 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/different-parameter-values.ts @@ -0,0 +1,19 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export interface DifferentParameterValues { + parameterName?: string; + originalValue?: string; + changedValue?: string; +} + diff --git a/webapp-ng/src/app/core/modules/openapi/model/export-format.ts b/webapp-ng/src/app/core/modules/openapi/model/export-format.ts new file mode 100644 index 0000000000..d63836fc72 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/export-format.ts @@ -0,0 +1,30 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ + + +export type ExportFormat = 'CSV' | 'HDF5' | 'QUICKTIME' | 'GIF' | 'ANIMATED_GIF' | 'FORMAT_JPEG' | 'NRRD' | 'UCD' | 'VTK_UNSTRUCT' | 'VTK_IMAGE' | 'PLY' | 'N5'; + +export const ExportFormat = { + Csv: 'CSV' as ExportFormat, + Hdf5: 'HDF5' as ExportFormat, + Quicktime: 'QUICKTIME' as ExportFormat, + Gif: 'GIF' as ExportFormat, + AnimatedGif: 'ANIMATED_GIF' as ExportFormat, + FormatJpeg: 'FORMAT_JPEG' as ExportFormat, + Nrrd: 'NRRD' as ExportFormat, + Ucd: 'UCD' as ExportFormat, + VtkUnstruct: 'VTK_UNSTRUCT' as ExportFormat, + VtkImage: 'VTK_IMAGE' as ExportFormat, + Ply: 'PLY' as ExportFormat, + N5: 'N5' as ExportFormat +}; + diff --git a/webapp-ng/src/app/core/modules/openapi/model/export-history.ts b/webapp-ng/src/app/core/modules/openapi/model/export-history.ts new file mode 100644 index 0000000000..41cab3eae6 --- /dev/null +++ b/webapp-ng/src/app/core/modules/openapi/model/export-history.ts @@ -0,0 +1,35 @@ +/** + * VCell API + * VCell API + * + * The version of the OpenAPI document: 1.0.1 + * Contact: vcell_support@uchc.com + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +import { ExportProgressType } from './export-progress-type'; +import { ExportFormat } from './export-format'; + + +export interface ExportHistory { + exportJobID?: number; + simulationRef?: string; + bioModelRef?: string; + mathModelRef?: string; + mathRef?: string; + exportFormat?: ExportFormat; + exportDate?: string; + uri?: string; + simName?: string; + modelName?: string; + variables?: Array; + startTimeValue?: number; + endTimeValue?: number; + eventStatus?: ExportProgressType; +} +export namespace ExportHistory { +} + + diff --git a/webapp-ng/src/app/core/modules/openapi/model/human-readable-export-data.ts b/webapp-ng/src/app/core/modules/openapi/model/human-readable-export-data.ts index dae9f03882..a4f97b2481 100644 --- a/webapp-ng/src/app/core/modules/openapi/model/human-readable-export-data.ts +++ b/webapp-ng/src/app/core/modules/openapi/model/human-readable-export-data.ts @@ -9,13 +9,14 @@ * https://openapi-generator.tech * Do not edit the class manually. */ +import { DifferentParameterValues } from './different-parameter-values'; export interface HumanReadableExportData { simulationName?: string; biomodelName?: string; applicationName?: string; - differentParameterValues?: Array; + differentParameterValues?: Array; applicationType?: string; serverSavedFileName?: string; nonSpatial?: boolean; diff --git a/webapp-ng/src/app/core/modules/openapi/model/models.ts b/webapp-ng/src/app/core/modules/openapi/model/models.ts index e3cb4a1eef..d4cc51f075 100644 --- a/webapp-ng/src/app/core/modules/openapi/model/models.ts +++ b/webapp-ng/src/app/core/modules/openapi/model/models.ts @@ -14,8 +14,11 @@ export * from './curve'; export * from './curve-selection-info'; export * from './data-identifier'; export * from './detailed-state'; +export * from './different-parameter-values'; export * from './domain'; export * from './export-event'; +export * from './export-format'; +export * from './export-history'; export * from './export-progress-type'; export * from './exportable-data-type'; export * from './extent'; diff --git a/webapp-ng/src/app/core/modules/openapi/model/standard-export-info.ts b/webapp-ng/src/app/core/modules/openapi/model/standard-export-info.ts index 868436953c..a8732c9263 100644 --- a/webapp-ng/src/app/core/modules/openapi/model/standard-export-info.ts +++ b/webapp-ng/src/app/core/modules/openapi/model/standard-export-info.ts @@ -24,5 +24,8 @@ export interface StandardExportInfo { geometrySpecs?: GeometrySpecDTO; timeSpecs?: TimeSpecs; variableSpecs?: VariableSpecs; + bioModelKey?: string; + mathModelKey?: string; + mathDescriptionKey?: string; }