diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/entrypoint.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/entrypoint.py index 12b5fa31ac52634d336d59ad14ef4843ccee051c..4246513622100f1dc7cab2efc43b83ec0a7a1408 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/entrypoint.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/entrypoint.py @@ -1,26 +1,50 @@ from ch.ethz.sis.openbis.generic.asapi.v3.dto.operation import SynchronousOperationExecutionOptions -from parsers import get_creations_from, CreationToOperationParser +from parsers import get_creations_from, CreationOrUpdateToOperationParser from processors import OpenbisDuplicatesHandler, PropertiesLabelHandler, DuplicatesHandler, unify_properties_representation_of from search_engines import SearchEngine from utils import FileHandler +from ch.systemsx.cisd.common.exceptions import UserFailureException def process(context, parameters): - xls_byte_arrays = parameters.get('xls') - scripts = parameters.get('scripts') + """ + Excel import AS service. + For extensive documentation of usage and Excel layout, + please visit https://wiki-bsse.ethz.ch/display/openBISDoc/Excel+import+service + + :param context: Standard Openbis AS Service context object + :param parameters: Contains two elemens + { + 'xls' : excel byte blob, - mandatory + 'scripts': { - optional + file path: loaded file + }, + update_mode: [IGNORE_EXISTING|FAIL_IF_EXISTS|UPDATE_IF_EXISTS] - optional, default FAIL_IF_EXISTS + This only takes duplicates that are ON THE SERVER + } + :return: Openbis's execute operations result string. It should contain report on what was created. + """ + xls_byte_arrays = parameters.get('xls', None) + scripts = parameters.get('scripts', {}) + update_mode = parameters.get('update_mode', None) + if xls_byte_arrays is None: + raise UserFailureException('Excel sheet has not been provided. "xls" parameter is None') + if update_mode not in ['IGNORE_EXISTING', 'FAIL_IF_EXISTS', 'UPDATE_IF_EXISTS']: + raise UserFailureException('Update mode has to be one of following: IGNORE_EXISTING FAIL_IF_EXISTS UPDATE_IF_EXISTS but was ' + (str(update_mode) if update_mode else 'None')) creations = get_creations_from(xls_byte_arrays, FileHandler(scripts)) distinct_creations = DuplicatesHandler.get_distinct_creations(creations) sessionToken = context.sessionToken api = context.applicationService search_engine = SearchEngine(api, sessionToken) existing_elements = search_engine.find_all_existing_elements(distinct_creations) - server_duplicates_handler = OpenbisDuplicatesHandler(distinct_creations, existing_elements) - creations = server_duplicates_handler.remove_existing_elements_from_creations() - creations = server_duplicates_handler.rewrite_parentchild_creationid_to_permid() entity_kinds = search_engine.find_existing_entity_kind_definitions_for(creations) existing_vocabularies = search_engine.find_all_existing_vocabularies() existing_unified_kinds = unify_properties_representation_of(creations, entity_kinds, existing_vocabularies, existing_elements) creations = PropertiesLabelHandler.rewrite_property_labels_to_codes(creations, existing_unified_kinds) - operations = CreationToOperationParser.parse(creations) + server_duplicates_handler = OpenbisDuplicatesHandler(distinct_creations, existing_elements, update_mode) + creations = server_duplicates_handler.rewrite_parentchild_creationid_to_permid() + creations = server_duplicates_handler.handle_existing_elements_in_creations() + operations = CreationOrUpdateToOperationParser.parse(creations) res = str(api.executeOperations(sessionToken, operations, SynchronousOperationExecutionOptions()).getResults()) return res + diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/__init__.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/__init__.py index 8bd51a73523de48430e7220196cd52e007bd61ae..68c228b00d131a0bd6f4f01d37fb5c0c477599ea 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/__init__.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/__init__.py @@ -1,4 +1,4 @@ -from .creation_to_operation import CreationToOperationParser +from .creation_to_operation import CreationOrUpdateToOperationParser from .definition_to_creation import DefinitionToCreationParser from .definition_to_creation import VocabularyDefinitionToCreationParser, \ PropertyTypeDefinitionToCreationParser, SampleTypeDefinitionToCreationParser, ExperimentTypeDefinitionToCreationParser, \ @@ -7,4 +7,4 @@ from .definition_to_creation import VocabularyDefinitionToCreationParser, \ from .excel_to_poi import ExcelToPoiParser from .excels_to_creations_parser import get_creations_from from .poi_to_definition import PoiToDefinitionParser - +from .creation_to_update import CreationToUpdateParser diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_operation/__init__.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_operation/__init__.py index da17c96a5342705fbffea8a907ef83535f0c39a5..468cbe7706388e7b069095321368be90d87cf460 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_operation/__init__.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_operation/__init__.py @@ -1 +1 @@ -from .creation_to_operation import CreationToOperationParser \ No newline at end of file +from .creation_to_operation import CreationOrUpdateToOperationParser \ No newline at end of file diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_operation/creation_to_operation.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_operation/creation_to_operation.py index 3baf8f307b88656295af994c4f37d6f1933f62c6..a97ddef851ec16226f7a79eb00835b6326c3033a 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_operation/creation_to_operation.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_operation/creation_to_operation.py @@ -9,9 +9,24 @@ from ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.create import CreateVoc from ..definition_to_creation import VocabularyDefinitionToCreationParser, PropertyTypeDefinitionToCreationParser, SampleTypeDefinitionToCreationParser, \ ExperimentTypeDefinitionToCreationParser, DatasetTypeDefinitionToCreationParser, SpaceDefinitionToCreationParser, \ ProjectDefinitionToCreationParser, ExperimentDefinitionToCreationParser, ScriptDefinitionToCreationParser, SampleDefinitionToCreationParser +from ..creation_to_update import VocabularyCreationToUpdateParser, VocabularyTermCreationToUpdateParser, \ + PropertyTypeCreationToUpdateParser, SampleTypeCreationToUpdateParser, ExperimentTypeCreationToUpdateParser, \ + DatasetTypeCreationToUpdateParser, SpaceCreationToUpdateParser, ProjectCreationToUpdateParser, ExperimentCreationToUpdateParser, \ + SampleCreationToUpdateParser, ScriptCreationToUpdateParser +from ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.update import UpdateVocabulariesOperation, \ + UpdateVocabularyTermsOperation +from ch.ethz.sis.openbis.generic.asapi.v3.dto.property.update import UpdatePropertyTypesOperation +from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.update import UpdateSampleTypesOperation, \ + UpdateSamplesOperation +from ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.update import UpdateExperimentTypesOperation, \ + UpdateExperimentsOperation +from ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.update import UpdateDataSetTypesOperation +from ch.ethz.sis.openbis.generic.asapi.v3.dto.space.update import UpdateSpacesOperation +from ch.ethz.sis.openbis.generic.asapi.v3.dto.project.update import UpdateProjectsOperation +from ch.ethz.sis.openbis.generic.asapi.v3.dto.plugin.update import UpdatePluginsOperation -class CreationToOperationParser(object): +class CreationOrUpdateToOperationParser(object): @staticmethod def parse(creations): @@ -36,4 +51,27 @@ class CreationToOperationParser(object): creation_operations.append(CreateSamplesOperation(creations[SampleDefinitionToCreationParser.type])) if ScriptDefinitionToCreationParser.type in creations: creation_operations.append(CreatePluginsOperation(creations[ScriptDefinitionToCreationParser.type])) + if VocabularyCreationToUpdateParser.type in creations: + creation_operations.append(UpdateVocabulariesOperation(creations[VocabularyCreationToUpdateParser.type])) + if VocabularyTermCreationToUpdateParser.type in creations: + creation_operations.append(UpdateVocabularyTermsOperation(creations[VocabularyTermCreationToUpdateParser.type])) + if PropertyTypeCreationToUpdateParser.type in creations: + creation_operations.append(UpdatePropertyTypesOperation(creations[PropertyTypeCreationToUpdateParser.type])) + if SampleTypeCreationToUpdateParser.type in creations: + creation_operations.append(UpdateSampleTypesOperation(creations[SampleTypeCreationToUpdateParser.type])) + if ExperimentTypeCreationToUpdateParser.type in creations: + creation_operations.append(UpdateExperimentTypesOperation(creations[ExperimentTypeCreationToUpdateParser.type])) + if DatasetTypeCreationToUpdateParser.type in creations: + creation_operations.append(UpdateDataSetTypesOperation(creations[DatasetTypeCreationToUpdateParser.type])) + if SpaceCreationToUpdateParser.type in creations: + creation_operations.append(UpdateSpacesOperation(creations[SpaceCreationToUpdateParser.type])) + if ProjectCreationToUpdateParser.type in creations: + creation_operations.append(UpdateProjectsOperation(creations[ProjectCreationToUpdateParser.type])) + if ExperimentCreationToUpdateParser.type in creations: + creation_operations.append(UpdateExperimentsOperation(creations[ExperimentCreationToUpdateParser.type])) + if SampleCreationToUpdateParser.type in creations: + creation_operations.append(UpdateSamplesOperation(creations[SampleCreationToUpdateParser.type])) + if ScriptCreationToUpdateParser.type in creations: + creation_operations.append(UpdatePluginsOperation(creations[ScriptCreationToUpdateParser.type])) + return creation_operations diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_update/__init__.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_update/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..5f9b15609c7cc3b308a4d795a92264a01de12b59 --- /dev/null +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_update/__init__.py @@ -0,0 +1,5 @@ +from .update_parsers import VocabularyCreationToUpdateParser, VocabularyTermCreationToUpdateParser, \ + PropertyTypeCreationToUpdateParser, SampleTypeCreationToUpdateParser, ExperimentTypeCreationToUpdateParser, \ + DatasetTypeCreationToUpdateParser, SpaceCreationToUpdateParser, ProjectCreationToUpdateParser, ExperimentCreationToUpdateParser, \ + SampleCreationToUpdateParser, ScriptCreationToUpdateParser +from .creation_to_update import CreationToUpdateParser diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_update/creation_to_update.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_update/creation_to_update.py new file mode 100644 index 0000000000000000000000000000000000000000..29e055982b9142c004d9eb07a7265b14bdcc351d --- /dev/null +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_update/creation_to_update.py @@ -0,0 +1,36 @@ +from utils.openbis_utils import create_sample_identifier_string +from .update_parsers import CreationToUpdateParserFactory +from ..definition_to_creation import SampleDefinitionToCreationParser, ScriptDefinitionToCreationParser + + +class CreationToUpdateParser(object): + + @staticmethod + def parse(creations_that_exist, existing_elements): + updates = {} + for creation_type, creations in creations_that_exist.items(): + parsers = CreationToUpdateParserFactory.get_parsers(creation_type) + for creation in creations: + existing_element = get_existing_element_based_on(creation_type, creation, existing_elements[creation_type]) + if existing_element: + for parser in parsers: + update = parser.parse(creation, existing_element) + update_type = parser.get_type() + if update_type not in updates: + updates[update_type] = [] + updates[update_type].extend(update if type(update) == list else [update]) + + return updates + + +def get_existing_element_based_on(creation_type, creation, existing_elements): + if creation_type == SampleDefinitionToCreationParser.type: + existing_element = list(filter(lambda existing_element: creation.code is not None and create_sample_identifier_string(creation) == existing_element.identifier.identifier, existing_elements)) + else: + if creation_type == ScriptDefinitionToCreationParser.type: + attr = 'name' + else: + attr = 'code' + existing_element = list(filter(lambda existing_element: getattr(creation, attr) == getattr(existing_element, attr), existing_elements)) + return None if len(existing_element) == 0 else existing_element[0] + diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_update/update_parsers.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_update/update_parsers.py new file mode 100644 index 0000000000000000000000000000000000000000..401c2552fc211bf333354b5e58de2e582b4b889e --- /dev/null +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/creation_to_update/update_parsers.py @@ -0,0 +1,221 @@ +from ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.update import VocabularyUpdate, VocabularyTermUpdate +from ch.ethz.sis.openbis.generic.asapi.v3.dto.property.update import PropertyTypeUpdate +from ch.ethz.sis.openbis.generic.asapi.v3.dto.sample.update import SampleTypeUpdate, SampleUpdate +from ch.ethz.sis.openbis.generic.asapi.v3.dto.common.update import ListUpdateValue +from ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.update import ExperimentTypeUpdate, ExperimentUpdate +from ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.update import DataSetTypeUpdate +from ch.ethz.sis.openbis.generic.asapi.v3.dto.space.update import SpaceUpdate +from ch.ethz.sis.openbis.generic.asapi.v3.dto.project.update import ProjectUpdate +from ch.ethz.sis.openbis.generic.asapi.v3.dto.plugin.update import PluginUpdate +from java.lang import UnsupportedOperationException +from ..definition_to_creation import VocabularyDefinitionToCreationParser, PropertyTypeDefinitionToCreationParser, SampleTypeDefinitionToCreationParser, \ + ExperimentTypeDefinitionToCreationParser, DatasetTypeDefinitionToCreationParser, SpaceDefinitionToCreationParser, \ + ProjectDefinitionToCreationParser, ExperimentDefinitionToCreationParser, ScriptDefinitionToCreationParser, SampleDefinitionToCreationParser + + +class CreationToUpdateParserFactory(object): + + @staticmethod + def get_parsers(creation_type): + if creation_type == VocabularyDefinitionToCreationParser.type: + return [VocabularyCreationToUpdateParser(), VocabularyTermCreationToUpdateParser()] + elif creation_type == PropertyTypeDefinitionToCreationParser.type: + return [PropertyTypeCreationToUpdateParser()] + elif creation_type == SampleTypeDefinitionToCreationParser.type: + return [SampleTypeCreationToUpdateParser()] + elif creation_type == ExperimentTypeDefinitionToCreationParser.type: + return [ExperimentTypeCreationToUpdateParser()] + elif creation_type == DatasetTypeDefinitionToCreationParser.type: + return [DatasetTypeCreationToUpdateParser()] + elif creation_type == SpaceDefinitionToCreationParser.type: + return [SpaceCreationToUpdateParser()] + elif creation_type == ProjectDefinitionToCreationParser.type: + return [ProjectCreationToUpdateParser()] + elif creation_type == ExperimentDefinitionToCreationParser.type: + return [ExperimentCreationToUpdateParser()] + elif creation_type == SampleDefinitionToCreationParser.type: + return [SampleCreationToUpdateParser()] + elif creation_type == ScriptDefinitionToCreationParser.type: + return [ScriptCreationToUpdateParser()] + else: + raise UnsupportedOperationException( + "Creation type of " + creation_type + " is not supported.") + + +class VocabularyCreationToUpdateParser(object): + type = "VocabularyUpdate" + + def parse(self, creation, existing_vocabulary): + vocabulary_update = VocabularyUpdate() + vocabulary_update.vocabularyId = existing_vocabulary.permId + vocabulary_update.setDescription(creation.description) + return vocabulary_update + + def get_type(self): + return VocabularyCreationToUpdateParser.type + + +class VocabularyTermCreationToUpdateParser(object): + type = "VocabularyTermUpdate" + + def parse(self, creation, existing_vocabulary): + vocabulary_term_updates = [] + for term in creation.terms: + existing_term = next((existing_term for existing_term in existing_vocabulary.terms if existing_term.code == term.code), None) + if existing_term: + vocabulary_term_update = VocabularyTermUpdate() + vocabulary_term_update.vocabularyTermId = existing_term.permId + vocabulary_term_update.setLabel(term.label) + vocabulary_term_update.setDescription(term.description) + vocabulary_term_updates.append(vocabulary_term_update) + return vocabulary_term_updates + + def get_type(self): + return VocabularyTermCreationToUpdateParser.type + + +class PropertyTypeCreationToUpdateParser(object): + type = "PropertyTypeUpdate" + + def parse(self, creation, existing_property_type): + property_type_update = PropertyTypeUpdate() + property_type_update.typeId = existing_property_type.permId + property_type_update.setLabel(creation.label) + property_type_update.setDescription(creation.description) + return property_type_update + + def get_type(self): + return PropertyTypeCreationToUpdateParser.type + + +class EntityTypeCreationToUpdateParser(object): + + def parseAssignments(self, creation, existing_entity_type): + assignments_update = ListUpdateValue() + for property_assignment in existing_entity_type.propertyAssignments: + assignments_update.remove(property_assignment.permId) + for property_assignment in creation.propertyAssignments: + assignments_update.add(property_assignment) + return assignments_update.getActions() + + +class SampleTypeCreationToUpdateParser(EntityTypeCreationToUpdateParser): + type = "SampleTypeUpdate" + + def parse(self, creation, existing_sample_type): + sample_type_update = SampleTypeUpdate() + sample_type_update.typeId = existing_sample_type.permId + sample_type_update.setAutoGeneratedCode(creation.autoGeneratedCode) + sample_type_update.setGeneratedCodePrefix(creation.generatedCodePrefix) + sample_type_update.setDescription(creation.description) + sample_type_update.setValidationPluginId(creation.validationPluginId) + sample_type_update.setPropertyAssignmentActions(self.parseAssignments(creation, existing_sample_type)) + + return sample_type_update + + def get_type(self): + return SampleTypeCreationToUpdateParser.type + + +class ExperimentTypeCreationToUpdateParser(EntityTypeCreationToUpdateParser): + type = "ExperimentTypeUpdate" + + def parse(self, creation, existing_experiment_type): + experiment_type_update = ExperimentTypeUpdate() + experiment_type_update.typeId = existing_experiment_type.permId + experiment_type_update.setDescription(creation.description) + experiment_type_update.setValidationPluginId(creation.validationPluginId) + assignments_update = ListUpdateValue() + experiment_type_update.setPropertyAssignmentActions(self.parseAssignments(creation, existing_experiment_type)) + return experiment_type_update + + def get_type(self): + return ExperimentTypeCreationToUpdateParser.type + + +class DatasetTypeCreationToUpdateParser(EntityTypeCreationToUpdateParser): + type = "DatasetTypeUpdate" + + def parse(self, creation, existing_dataset_type): + dataset_type_update = DataSetTypeUpdate() + dataset_type_update.typeId = existing_dataset_type.permId + dataset_type_update.setValidationPluginId(creation.validationPluginId) + assignments_update = ListUpdateValue() + dataset_type_update.setPropertyAssignmentActions(self.parseAssignments(creation, existing_dataset_type)) + return dataset_type_update + + def get_type(self): + return DatasetTypeCreationToUpdateParser.type + + +class SpaceCreationToUpdateParser(object): + type = "SpaceUpdate" + + def parse(self, creation, existing_space): + space_update = SpaceUpdate() + space_update.spaceId = existing_space.permId + space_update.setDescription(creation.description) + return space_update + + def get_type(self): + return SpaceCreationToUpdateParser.type + + +class ProjectCreationToUpdateParser(object): + type = "ProjectUpdate" + + def parse(self, creation, existing_project): + project_update = ProjectUpdate() + project_update.projectId = existing_project.permId + project_update.setDescription(creation.description) + project_update.setSpaceId(creation.spaceId) + return project_update + + def get_type(self): + return ProjectCreationToUpdateParser.type + + +class ExperimentCreationToUpdateParser(object): + type = "ExperimentUpdate" + + def parse(self, creation, existing_experiment): + experiment_update = ExperimentUpdate() + experiment_update.experimentId = existing_experiment.permId + experiment_update.setProjectId(creation.projectId) + experiment_update.setProperties(creation.properties) + return experiment_update + + def get_type(self): + return ExperimentCreationToUpdateParser.type + + +class SampleCreationToUpdateParser(object): + type = "SampleUpdate" + + def parse(self, creation, existing_sample): + sample_update = SampleUpdate() + sample_update.sampleId = existing_sample.permId + sample_update.setExperimentId(creation.experimentId) + sample_update.setProjectId(creation.projectId) + sample_update.setSpaceId(creation.spaceId) + sample_update.setProperties(creation.properties) + sample_update.sampleId = creatiuon.parentIds + sample_update.sampleId = creatiuon.childIds + return sample_update + + def get_type(self): + return SampleCreationToUpdateParser.type + + +class ScriptCreationToUpdateParser(object): + type = "ScriptUpdate" + + def parse(self, creation, existing_plugin): + script_update = PluginUpdate() + script_update.pluginId = existing_plugin.permId + script_update.setScript(creation.script) + return script_update + + def get_type(self): + return ScriptCreationToUpdateParser.type + diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/definition_to_creation/creation_parsers.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/definition_to_creation/creation_parsers.py index 897f5c31fdc67804a4adf48f534847596e5d3c60..50dfb21a8e7554d3cd4be17da0b56c2bb275c5ad 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/definition_to_creation/creation_parsers.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/parsers/definition_to_creation/creation_parsers.py @@ -16,9 +16,12 @@ from ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.create import Vocabular from ch.ethz.sis.openbis.generic.asapi.v3.dto.vocabulary.id import VocabularyPermId from java.lang import UnsupportedOperationException from utils.openbis_utils import is_internal_namespace, get_script_name_for +from ch.systemsx.cisd.common.exceptions import UserFailureException def get_boolean_from_string(text): + if text.lower() not in [u'true', u'false']: + raise UserFailureException("Boolean field should either be 'true' or 'false' (case insensitive) but was " + text) return True if text and text.lower() == u'true' else False @@ -49,14 +52,10 @@ class DefinitionToCreationParserFactory(object): return [PropertyTypeDefinitionToCreationParser()] else: raise UnsupportedOperationException( - "Definition of " + str(definition.type) + " is not supported (probably yet).") + "Definition of " + str(definition.type) + " is not supported.") -class DefinitionToCreationParser(object): - pass - - -class PropertyTypeDefinitionToCreationParser(DefinitionToCreationParser): +class PropertyTypeDefinitionToCreationParser(object): type = "PropertyTypeCreation" def parse(self, definition): @@ -78,7 +77,7 @@ class PropertyTypeDefinitionToCreationParser(DefinitionToCreationParser): return PropertyTypeDefinitionToCreationParser.type -class VocabularyDefinitionToCreationParser(DefinitionToCreationParser): +class VocabularyDefinitionToCreationParser(object): type = "VocabularyCreation" def parse(self, definition): @@ -104,7 +103,7 @@ class VocabularyDefinitionToCreationParser(DefinitionToCreationParser): return VocabularyDefinitionToCreationParser.type -class PropertyAssignmentDefinitionToCreationParser(DefinitionToCreationParser): +class PropertyAssignmentDefinitionToCreationParser(object): type = "PropertyAssignmentCreation" def parse(self, prop): @@ -126,7 +125,7 @@ class PropertyAssignmentDefinitionToCreationParser(DefinitionToCreationParser): return PropertyAssignmentDefinitionToCreationParser.type -class SampleTypeDefinitionToCreationParser(DefinitionToCreationParser): +class SampleTypeDefinitionToCreationParser(object): type = "SampleTypeCreation" def parse(self, definition): @@ -135,6 +134,7 @@ class SampleTypeDefinitionToCreationParser(DefinitionToCreationParser): sample_creation.code = code should_auto_generate_codes = get_boolean_from_string(definition.attributes.get(u'auto generate codes')) sample_creation.autoGeneratedCode = should_auto_generate_codes + sample_creation.description = definition.attributes.get(u'description') generatedCodePrefix = definition.attributes.get(u'generated code prefix') if generatedCodePrefix is not None: sample_creation.generatedCodePrefix = generatedCodePrefix @@ -155,13 +155,14 @@ class SampleTypeDefinitionToCreationParser(DefinitionToCreationParser): return SampleTypeDefinitionToCreationParser.type -class ExperimentTypeDefinitionToCreationParser(DefinitionToCreationParser): +class ExperimentTypeDefinitionToCreationParser(object): type = "ExperimentTypeCreation" def parse(self, definition): code = definition.attributes.get(u'code') experiment_type_creation = ExperimentTypeCreation() experiment_type_creation.code = code + experiment_type_creation.description = definition.attributes.get(u'description') if u'validation script' in definition.attributes and definition.attributes.get(u'validation script') is not None: validation_script_path = definition.attributes.get(u'validation script') experiment_type_creation.validationPluginId = PluginPermId(get_script_name_for(code, validation_script_path)) @@ -179,13 +180,14 @@ class ExperimentTypeDefinitionToCreationParser(DefinitionToCreationParser): return ExperimentTypeDefinitionToCreationParser.type -class DatasetTypeDefinitionToCreationParser(DefinitionToCreationParser): +class DatasetTypeDefinitionToCreationParser(object): type = "DatasetTypeCreation" def parse(self, definition): dataset_type_creation = DataSetTypeCreation() code = definition.attributes.get(u'code') dataset_type_creation.code = code + dataset_type_creation.description = definition.attributes.get(u'description') if u'validation script' in definition.attributes and definition.attributes.get(u'validation script') is not None: validation_script_path = definition.attributes.get(u'validation script') dataset_type_creation.validationPluginId = PluginPermId(get_script_name_for(code, validation_script_path)) @@ -203,7 +205,7 @@ class DatasetTypeDefinitionToCreationParser(DefinitionToCreationParser): return DatasetTypeDefinitionToCreationParser.type -class SpaceDefinitionToCreationParser(DefinitionToCreationParser): +class SpaceDefinitionToCreationParser(object): type = "SpaceCreation" def parse(self, definition): @@ -221,7 +223,7 @@ class SpaceDefinitionToCreationParser(DefinitionToCreationParser): return SpaceDefinitionToCreationParser.type -class ProjectDefinitionToCreationParser(DefinitionToCreationParser): +class ProjectDefinitionToCreationParser(object): type = "ProjectCreation" def parse(self, definition): @@ -240,12 +242,12 @@ class ProjectDefinitionToCreationParser(DefinitionToCreationParser): return ProjectDefinitionToCreationParser.type -class ExperimentDefinitionToCreationParser(DefinitionToCreationParser): +class ExperimentDefinitionToCreationParser(object): type = "ExperimentCreation" def parse(self, definition): experiments = [] - mandatory_attributes = [u'code', u'project'] + project_attributes = [u'code', u'project'] for experiment_properties in definition.properties: experiment_creation = ExperimentCreation() experiment_creation.typeId = EntityTypePermId(definition.attributes.get(u'experiment type')) @@ -254,7 +256,7 @@ class ExperimentDefinitionToCreationParser(DefinitionToCreationParser): creation_id = experiment_properties.get(u'code') experiment_creation.creationId = CreationId(creation_id) for prop, value in experiment_properties.items(): - if prop not in mandatory_attributes: + if prop not in project_attributes: experiment_creation.setProperty(prop, value) experiments.append(experiment_creation) return experiments @@ -263,12 +265,12 @@ class ExperimentDefinitionToCreationParser(DefinitionToCreationParser): return ExperimentDefinitionToCreationParser.type -class SampleDefinitionToCreationParser(DefinitionToCreationParser): +class SampleDefinitionToCreationParser(object): type = "SampleCreation" def parse(self, definition): samples = [] - mandatory_attributes = [u'$', u'code', u'space', u'project', u'experiment', u'auto generate code', u'parents', + sample_attributes = [u'$', u'code', u'space', u'project', u'experiment', u'auto generate code', u'parents', u'children'] for sample_properties in definition.properties: sample_creation = SampleCreation() @@ -303,7 +305,7 @@ class SampleDefinitionToCreationParser(DefinitionToCreationParser): sample_creation.childIds = child_creationids for prop, value in sample_properties.items(): - if prop not in mandatory_attributes: + if prop not in sample_attributes: sample_creation.setProperty(prop, value) samples.append(sample_creation) return samples @@ -312,7 +314,7 @@ class SampleDefinitionToCreationParser(DefinitionToCreationParser): return SampleDefinitionToCreationParser.type -class ScriptDefinitionToCreationParser(DefinitionToCreationParser): +class ScriptDefinitionToCreationParser(object): type = "ScriptCreation" def __init__(self, context=None): diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/processors/openbis_duplicates_handler.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/processors/openbis_duplicates_handler.py index 4b04c23a42cb1b6c49edfbd53cc682b3c7c44ebd..1674b636e0e4406a4320c4950592503fe5521a37 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/processors/openbis_duplicates_handler.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/processors/openbis_duplicates_handler.py @@ -1,26 +1,31 @@ from parsers import SpaceDefinitionToCreationParser, ProjectDefinitionToCreationParser, \ - ExperimentDefinitionToCreationParser, ScriptDefinitionToCreationParser, SampleDefinitionToCreationParser + ExperimentDefinitionToCreationParser, ScriptDefinitionToCreationParser, SampleDefinitionToCreationParser, CreationToUpdateParser from utils.openbis_utils import create_sample_identifier_string +FAIL_IF_EXISTS = "FAIL_IF_EXISTS" +IGNORE_EXISTING = "IGNORE_EXISTING" +UPDATE_IF_EXISTS = "UPDATE_IF_EXISTS" + class OpenbisDuplicatesHandler(object): - def __init__(self, creations, existing_elements): + def __init__(self, creations, existing_elements, duplicates_strategy=FAIL_IF_EXISTS): self.creations = creations self.existing_elements = existing_elements + self.duplicates_strategy = duplicates_strategy def rewrite_parentchild_creationid_to_permid(self): if ProjectDefinitionToCreationParser.type in self.creations: for creation in self.creations[ProjectDefinitionToCreationParser.type]: for existing_element in self.existing_elements[SpaceDefinitionToCreationParser.type]: - if existing_element.code == creation.spaceId.creationId: + if existing_element.code == str(creation.spaceId): creation.spaceId = existing_element.permId break if ExperimentDefinitionToCreationParser.type in self.creations: for creation in self.creations[ExperimentDefinitionToCreationParser.type]: for existing_element in self.existing_elements[ProjectDefinitionToCreationParser.type]: - if existing_element.code == creation.projectId.creationId: + if existing_element.code == str(creation.projectId): creation.projectId = existing_element.permId break if SampleDefinitionToCreationParser.type in self.creations: @@ -79,20 +84,64 @@ class OpenbisDuplicatesHandler(object): return self.creations - def remove_existing_elements_from_creations(self): - for creations_type, existing_elements in self.existing_elements.items(): - if not creations_type in self.creations: - continue - if creations_type == SampleDefinitionToCreationParser.type: - existing_object_codes = [obj.identifier.identifier for obj in existing_elements] - self.creations[creations_type] = list(filter( - lambda creation: creation.code is None or create_sample_identifier_string( - creation) not in existing_object_codes, self.creations[creations_type])) - else: - distinct_property_name = self._get_distinct_property_name(creations_type) - self.creations[creations_type] = self._filter_creations_from_existing_objects(creations_type, - existing_elements, - distinct_property_name) + def handle_existing_elements_in_creations(self): + + if self.duplicates_strategy == UPDATE_IF_EXISTS: + duplicates_list = {} + for creations_type, existing_elements in self.existing_elements.items(): + if not creations_type in self.creations: + continue + if creations_type == SampleDefinitionToCreationParser.type: + existing_object_codes = [obj.identifier.identifier for obj in existing_elements] + duplicates_list[creations_type] = list(filter( + lambda creation: creation.code is not None or create_sample_identifier_string( + creation) in existing_object_codes, self.creations[creations_type])) + self.creations[creations_type] = list(filter( + lambda creation: creation.code is None or create_sample_identifier_string( + creation) not in existing_object_codes, self.creations[creations_type])) + else: + distinct_property_name = self._get_distinct_property_name(creations_type) + duplicates_list[creations_type] = self.get_creations_for_existing_objects(creations_type, existing_elements, distinct_property_name) + self.creations[creations_type] = self._filter_creations_from_existing_objects(creations_type, + existing_elements, + distinct_property_name) + + updates = CreationToUpdateParser.parse(duplicates_list, self.existing_elements) + for update_type, update in updates.items(): + self.creations[update_type] = update + + if self.duplicates_strategy == FAIL_IF_EXISTS: + duplicates_list = {} + for creations_type, existing_elements in self.existing_elements.items(): + if not creations_type in self.creations: + continue + if creations_type == SampleDefinitionToCreationParser.type: + existing_object_codes = [obj.identifier.identifier for obj in existing_elements] + duplicates = list(filter(lambda creation: creation.code is not None and create_sample_identifier_string(creation) in existing_object_codes, self.creations[creations_type])) + if duplicates: + duplicates_list[creations_type] = duplicates + else: + distinct_property_name = self._get_distinct_property_name(creations_type) + duplicates = self.get_creations_for_existing_objects(creations_type, existing_elements, distinct_property_name) + if duplicates: + duplicates_list[creations_type] = duplicates + if duplicates_list: + raise Exception("Some of the objects you are trying to create already exist on the server. An error is being thrown when FAIL_IF_EXISTS flag is on. Existing elements are: " + str(duplicates_list)) + + if self.duplicates_strategy == IGNORE_EXISTING: + for creations_type, existing_elements in self.existing_elements.items(): + if not creations_type in self.creations: + continue + if creations_type == SampleDefinitionToCreationParser.type: + existing_object_codes = [obj.identifier.identifier for obj in existing_elements] + self.creations[creations_type] = list(filter( + lambda creation: creation.code is None or create_sample_identifier_string( + creation) not in existing_object_codes, self.creations[creations_type])) + else: + distinct_property_name = self._get_distinct_property_name(creations_type) + self.creations[creations_type] = self._filter_creations_from_existing_objects(creations_type, + existing_elements, + distinct_property_name) return self.creations def _get_distinct_property_name(self, creation_type): @@ -105,3 +154,8 @@ class OpenbisDuplicatesHandler(object): existing_object_codes = [getattr(obj, attr) for obj in existing_objects] return list(filter(lambda creation: getattr(creation, attr) not in existing_object_codes, self.creations[creations_type])) + + def get_creations_for_existing_objects(self, creations_type, existing_objects, attr): + existing_object_codes = [getattr(obj, attr) for obj in existing_objects] + return list(filter(lambda creation: getattr(creation, attr) in existing_object_codes, + self.creations[creations_type])) diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/processors/representation_unifier.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/processors/representation_unifier.py index c11a1fa124bdad229d14261a41c4e38d04f972d5..212990fe3ac610dbfdd62b690ba8adb6ba4635b4 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/processors/representation_unifier.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/processors/representation_unifier.py @@ -34,7 +34,7 @@ def _extract_creations_with_properties(creations_map): return dict((key, value) for (key, value) in creations_map.iteritems() if key in property_types_with_properties) -def getValue(dictionary, key): +def get_value(dictionary, key): if not key in dictionary: dictionary[key] = {} return dictionary[key] @@ -45,7 +45,7 @@ def _fill_properties_from_existing_entity_types(properties, entity_types_map): for entity_type in entity_types: entity_kind = entity_and_type_uniform_mapping[creation_type] new_key = entity_kind, entity_type.code - props = getValue(properties, new_key) + props = get_value(properties, new_key) for property_assignment in entity_type.propertyAssignments: property_type = property_assignment.propertyType props[property_type.label.lower()] = property_type @@ -90,7 +90,7 @@ def _fill_properties_from_creations(properties, creations, existing_vocabularies for creation in creationsList: entity_kind = entity_and_type_uniform_mapping[creations_type] new_key = entity_kind, creation.code - props = getValue(properties, new_key) + props = get_value(properties, new_key) if creations_type == PropertyTypeDefinitionToCreationParser.type: props[creation.label.lower()] = creation props[creation.code.lower()] = creation diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/search_engines/search_criteria_factory.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/search_engines/search_criteria_factory.py index 5a9a76933767bfe6cd6f47d60db328948dd70401..dbe9c3ff628fa64429bf8f36504a713bcd9e35fc 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/search_engines/search_criteria_factory.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/search_engines/search_criteria_factory.py @@ -66,17 +66,17 @@ class SampleCreationSampleSearchCriteria(object): if creation.code is not None: search_criteria.withCode().thatEquals(creation.code) if creation.experimentId is not None: - search_criteria.withExperiment().withCode().thatEquals(creation.experimentId.creationId) + search_criteria.withExperiment().withCode().thatEquals(str(creation.experimentId)) else: search_criteria.withoutExperiment() if creation.projectId is not None: - search_criteria.withProject().withCode().thatEquals(creation.projectId.creationId) + search_criteria.withProject().withCode().thatEquals(str(creation.projectId)) else: search_criteria.withoutProject() if creation.spaceId is not None: - search_criteria.withSpace().withCode().thatEquals(creation.spaceId.creationId) + search_criteria.withSpace().withCode().thatEquals(str(creation.spaceId)) else: search_criteria.withoutSpace() search_criterias.append(search_criteria) diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/search_engines/search_engine.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/search_engines/search_engine.py index 89c180acf4ed7003939cc49e30fbaae3630ae7a4..f578bdc50acf9248d22d106269472d363cc60f13 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/search_engines/search_engine.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/search_engines/search_engine.py @@ -100,13 +100,21 @@ class SearchEngine(): def find_all_existing_elements(self, creations): property_type_fetch_options = PropertyTypeFetchOptions() property_type_fetch_options.withVocabulary().withTerms() + vocabulary_fetch_options = VocabularyFetchOptions() + vocabulary_fetch_options.withTerms() + sample_type_fetch_options = SampleTypeFetchOptions() + sample_type_fetch_options.withPropertyAssignments().withPropertyType() + experiment_type_fetch_options = ExperimentTypeFetchOptions() + experiment_type_fetch_options.withPropertyAssignments().withPropertyType() + dataset_type_fetch_options = DataSetTypeFetchOptions() + dataset_type_fetch_options.withPropertyAssignments().withPropertyType() search_strategy = [ { 'creations_type': VocabularyDefinitionToCreationParser.type, 'search_criteria_build_strategy' : DefaultCreationElementSearchCriteria, 'search_criteria_class' : VocabularySearchCriteria, 'search_operation':SearchVocabulariesOperation, - 'fetch_options':VocabularyFetchOptions() + 'fetch_options':vocabulary_fetch_options }, { 'creations_type': SampleDefinitionToCreationParser.type, @@ -127,21 +135,21 @@ class SearchEngine(): 'search_criteria_build_strategy' : DefaultCreationElementSearchCriteria, 'search_criteria_class' : SampleTypeSearchCriteria, 'search_operation': SearchSampleTypesOperation, - 'fetch_options': SampleTypeFetchOptions() + 'fetch_options': sample_type_fetch_options }, { 'creations_type': ExperimentTypeDefinitionToCreationParser.type, 'search_criteria_build_strategy' : DefaultCreationElementSearchCriteria, 'search_criteria_class' : ExperimentTypeSearchCriteria, 'search_operation': SearchExperimentTypesOperation, - 'fetch_options': ExperimentTypeFetchOptions() + 'fetch_options': experiment_type_fetch_options }, { 'creations_type': DatasetTypeDefinitionToCreationParser.type, 'search_criteria_build_strategy' : DefaultCreationElementSearchCriteria, 'search_criteria_class' : DataSetTypeSearchCriteria, 'search_operation': SearchDataSetTypesOperation, - 'fetch_options': DataSetTypeFetchOptions() + 'fetch_options': dataset_type_fetch_options }, { 'creations_type': SpaceDefinitionToCreationParser.type, diff --git a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/utils/openbis_utils.py b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/utils/openbis_utils.py index 32a0b334c8f8595d1b3e0acce7866f93163658cf..b6ea48327c7c7bc92f8769683f2a79780141270f 100644 --- a/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/utils/openbis_utils.py +++ b/openbis_standard_technologies/dist/core-plugins/xls-import/1/as/services/xls-import-api/utils/openbis_utils.py @@ -11,8 +11,8 @@ def get_script_name_for(owner_code, script_path): def create_sample_identifier_string(sample_creation): - spaceId = sample_creation.spaceId.creationId if sample_creation.spaceId is not None else None - projectId = sample_creation.projectId.creationId if sample_creation.projectId is not None else None + spaceId = str(sample_creation.spaceId) if sample_creation.spaceId is not None else None + projectId = str(sample_creation.projectId) if sample_creation.projectId is not None else None code = sample_creation.code sample_identifier = SampleIdentifier(spaceId, projectId, None, code) return sample_identifier.identifier diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportDatasetTypesTest.java b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportDatasetTypesTest.java index f5436657b69312da800689c90793c6e97a1f372b..cb757b07a82fc05373ec3653545987d6ee7c6702 100644 --- a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportDatasetTypesTest.java +++ b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportDatasetTypesTest.java @@ -1,9 +1,13 @@ package ch.ethz.sis.openbis.systemtest.plugin.excelimport; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; import java.io.IOException; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -16,6 +20,8 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSetType; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.DataType; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyAssignment; import ch.ethz.sis.openbis.generic.server.asapi.v3.IApplicationServerInternalApi; import ch.systemsx.cisd.common.exceptions.UserFailureException; @@ -40,6 +46,8 @@ public class ImportDatasetTypesTest extends AbstractImportTest private static final String DATASET_WITHOUT_PROPERTIES = "dataset_types/no_properties.xls"; + private static final String DATASET_TYPES_UPDATE = "dataset_types/normal_dataset_update.xls"; + private static String FILES_DIR; private String sessionToken; @@ -49,8 +57,6 @@ public class ImportDatasetTypesTest extends AbstractImportTest { String f = ImportDatasetTypesTest.class.getName().replace(".", "/"); FILES_DIR = f.substring(0, f.length() - ImportDatasetTypesTest.class.getSimpleName().length()) + "/test_files/"; - System.out.println(FILES_DIR); - System.out.println("SEE ME MY DEAR FRIEND"); } @BeforeMethod @@ -61,20 +67,38 @@ public class ImportDatasetTypesTest extends AbstractImportTest @Test @DirtiesContext - public void testNormalDatasetsTypesAreCreated() throws IOException + public void testNormalDatasetTypesAreCreated() throws Exception { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, DATASET_TYPES_XLS))); // WHEN DataSetType rawData = TestUtils.getDatasetType(v3api, sessionToken, "RAW_DATA"); + List<String> propertyNames = Arrays.asList("$NAME", "NOTES"); + List<PropertyAssignment> propertyAssignments = TestUtils.extractAndSortPropertyAssignmentsPerGivenPropertyName(rawData, propertyNames); + PropertyAssignment nameProperty = propertyAssignments.get(0); + PropertyAssignment notesProperty = propertyAssignments.get(1); // THEN assertEquals(rawData.getCode(), "RAW_DATA"); assertEquals(rawData.getPropertyAssignments().size(), 2); + assertFalse(nameProperty.isMandatory()); + assertTrue(nameProperty.isShowInEditView()); + assertEquals(nameProperty.getSection(), "General information"); + assertEquals(nameProperty.getPropertyType().getLabel(), "Name"); + assertEquals(nameProperty.getPropertyType().getDataType(), DataType.VARCHAR); + assertEquals(nameProperty.getPropertyType().getDescription(), "Name"); + assertEquals(nameProperty.getPlugin(), null); + assertFalse(notesProperty.isMandatory()); + assertTrue(notesProperty.isShowInEditView()); + assertEquals(notesProperty.getSection(), "Comments"); + assertEquals(notesProperty.getPropertyType().getLabel(), "Notes"); + assertEquals(notesProperty.getPropertyType().getDataType(), DataType.MULTILINE_VARCHAR); + assertEquals(notesProperty.getPropertyType().getDescription(), "Notes"); + assertEquals(notesProperty.getPlugin(), null); } @Test @DirtiesContext - public void testDatasetsWithoutPropertiesTypesAreCreated() throws IOException + public void testDatasetTypesWithoutPropertiesTypesAreCreated() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, DATASET_WITHOUT_PROPERTIES))); @@ -87,15 +111,46 @@ public class ImportDatasetTypesTest extends AbstractImportTest @Test @DirtiesContext - public void testSampleTypesWithValidationScript() throws IOException + public void testDatasetTypesWithValidationScript() throws Exception { // GIVEN TestUtils.createFrom(v3api, sessionToken, TestUtils.getValidationPluginMap(), Paths.get(FilenameUtils.concat(FILES_DIR, DATASET_WITH_VALIDATION_SCRIPT))); // WHEN - DataSetType collection = TestUtils.getDatasetType(v3api, sessionToken, "RAW_DATA"); + DataSetType rawData = TestUtils.getDatasetType(v3api, sessionToken, "RAW_DATA"); + // THEN + assertEquals(rawData.getValidationPlugin().getName().toUpperCase(), "RAW_DATA.VALID"); + } + + @Test + @DirtiesContext + public void testDatasetTypesUpdate() throws Exception + { + // GIVEN + TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, DATASET_TYPES_XLS))); + // WHEN + TestUtils.createFrom(v3api, sessionToken, TestUtils.getDynamicPluginMap(), UpdateMode.UPDATE_IF_EXISTS, + Paths.get(FilenameUtils.concat(FILES_DIR, DATASET_TYPES_UPDATE))); + DataSetType rawData = TestUtils.getDatasetType(v3api, sessionToken, "RAW_DATA"); + List<String> propertyNames = Arrays.asList("$NAME", "NOTES"); + List<PropertyAssignment> propertyAssignments = TestUtils.extractAndSortPropertyAssignmentsPerGivenPropertyName(rawData, propertyNames); + PropertyAssignment nameProperty = propertyAssignments.get(0); + PropertyAssignment notesProperty = propertyAssignments.get(1); // THEN - assertEquals(collection.getValidationPlugin().getName().toUpperCase(), "RAW_DATA.VALID"); + assertTrue(nameProperty.isMandatory()); + assertFalse(nameProperty.isShowInEditView()); + assertEquals(nameProperty.getSection(), "Comments"); + assertEquals(nameProperty.getPropertyType().getLabel(), "NameUpdate"); + assertEquals(nameProperty.getPropertyType().getDataType(), DataType.VARCHAR); + assertEquals(nameProperty.getPropertyType().getDescription(), "NameDescriptionUpdate"); + assertEquals(nameProperty.getPlugin().getName().toUpperCase(), "$NAME.DYNAMIC"); + assertFalse(notesProperty.isMandatory()); + assertTrue(notesProperty.isShowInEditView()); + assertEquals(notesProperty.getSection(), "Comments"); + assertEquals(notesProperty.getPropertyType().getLabel(), "Notes"); + assertEquals(notesProperty.getPropertyType().getDataType(), DataType.MULTILINE_VARCHAR); + assertEquals(notesProperty.getPropertyType().getDescription(), "Notes"); + assertEquals(notesProperty.getPlugin(), null); } @Test(expectedExceptions = UserFailureException.class) diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportExperimentTypesTest.java b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportExperimentTypesTest.java index 99010317951ca59f376a98f62e0bed6b8d29e0e0..72694de3994860825a87b26931a7d75c99312bd2 100644 --- a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportExperimentTypesTest.java +++ b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportExperimentTypesTest.java @@ -1,9 +1,13 @@ package ch.ethz.sis.openbis.systemtest.plugin.excelimport; import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; import java.io.IOException; import java.nio.file.Paths; +import java.util.Arrays; +import java.util.List; import org.apache.commons.io.FilenameUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -16,6 +20,8 @@ import org.testng.annotations.BeforeMethod; import org.testng.annotations.Test; import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.ExperimentType; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.DataType; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyAssignment; import ch.ethz.sis.openbis.generic.server.asapi.v3.IApplicationServerInternalApi; import ch.systemsx.cisd.common.exceptions.UserFailureException; @@ -33,6 +39,8 @@ public class ImportExperimentTypesTest extends AbstractImportTest private static final String EXPERIMENT_TYPES_XLS = "experiment_types/normal_experiment.xls"; + private static final String EXPERIMENT_TYPES_UPDATE = "experiment_types/normal_experiment_update.xls"; + private static final String EXPERIMENT_NO_CODE = "experiment_types/no_code.xls"; private static final String EXPERIMENT_WITH_VALIDATION_SCRIPT = "experiment_types/with_validation_script.xls"; @@ -56,14 +64,66 @@ public class ImportExperimentTypesTest extends AbstractImportTest @Test @DirtiesContext - public void testNormalExperimentTypesAreCreated() throws IOException + public void testNormalExperimentTypesAreCreated() throws Exception { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_TYPES_XLS))); // WHEN ExperimentType collection = TestUtils.getExperimentType(v3api, sessionToken, "COLLECTION"); + List<String> propertyNames = Arrays.asList("$NAME", "DEFAULT_OBJECT_TYPE"); + List<PropertyAssignment> propertyAssignments = TestUtils.extractAndSortPropertyAssignmentsPerGivenPropertyName(collection, propertyNames); + PropertyAssignment nameProperty = propertyAssignments.get(0); + PropertyAssignment defaultObjectTypeProperty = propertyAssignments.get(1); // THEN assertEquals(collection.getCode(), "COLLECTION"); + assertEquals(collection.getPropertyAssignments().size(), 2); + assertFalse(nameProperty.isMandatory()); + assertTrue(nameProperty.isShowInEditView()); + assertEquals(nameProperty.getSection(), "General information"); + assertEquals(nameProperty.getPropertyType().getLabel(), "Name"); + assertEquals(nameProperty.getPropertyType().getDataType(), DataType.VARCHAR); + assertEquals(nameProperty.getPropertyType().getDescription(), "Name"); + assertEquals(nameProperty.getPlugin(), null); + assertFalse(defaultObjectTypeProperty.isMandatory()); + assertTrue(defaultObjectTypeProperty.isShowInEditView()); + assertEquals(defaultObjectTypeProperty.getSection(), "General information"); + assertEquals(defaultObjectTypeProperty.getPropertyType().getLabel(), "Default"); + assertEquals(defaultObjectTypeProperty.getPropertyType().getDataType(), DataType.VARCHAR); + assertEquals(defaultObjectTypeProperty.getPropertyType().getDescription(), + "Enter the code of the object type for which the collection is used"); + assertEquals(defaultObjectTypeProperty.getPlugin(), null); + } + + @Test + @DirtiesContext + public void testExperimentTypesUpdate() throws Exception + { + // GIVEN + TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_TYPES_XLS))); + // WHEN + TestUtils.createFrom(v3api, sessionToken, TestUtils.getDynamicPluginMap(), UpdateMode.UPDATE_IF_EXISTS, + Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_TYPES_UPDATE))); + ExperimentType collection = TestUtils.getExperimentType(v3api, sessionToken, "COLLECTION"); + List<String> propertyNames = Arrays.asList("$NAME", "DEFAULT_OBJECT_TYPE"); + List<PropertyAssignment> propertyAssignments = TestUtils.extractAndSortPropertyAssignmentsPerGivenPropertyName(collection, propertyNames); + PropertyAssignment nameProperty = propertyAssignments.get(0); + PropertyAssignment defaultObjectTypeProperty = propertyAssignments.get(1); + // THEN + assertTrue(nameProperty.isMandatory()); + assertFalse(nameProperty.isShowInEditView()); + assertEquals(nameProperty.getSection(), "Comments"); + assertEquals(nameProperty.getPropertyType().getLabel(), "NameUpdate"); + assertEquals(nameProperty.getPropertyType().getDataType(), DataType.VARCHAR); + assertEquals(nameProperty.getPropertyType().getDescription(), "NameUpdateDescription"); + assertEquals(nameProperty.getPlugin().getName().toUpperCase(), "$NAME.DYNAMIC"); + assertFalse(defaultObjectTypeProperty.isMandatory()); + assertTrue(defaultObjectTypeProperty.isShowInEditView()); + assertEquals(defaultObjectTypeProperty.getSection(), "General information"); + assertEquals(defaultObjectTypeProperty.getPropertyType().getLabel(), "Default"); + assertEquals(defaultObjectTypeProperty.getPropertyType().getDataType(), DataType.VARCHAR); + assertEquals(defaultObjectTypeProperty.getPropertyType().getDescription(), + "Enter the code of the object type for which the collection is used"); + assertEquals(defaultObjectTypeProperty.getPlugin(), null); } @Test diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportExperimentsTest.java b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportExperimentsTest.java index cbf5a4114bb870ebbbaca669283fc3ac1994d5e5..55f21af7fac615b0d077d23562e13af4559ab896 100644 --- a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportExperimentsTest.java +++ b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/ImportExperimentsTest.java @@ -63,6 +63,8 @@ public class ImportExperimentsTest extends AbstractImportTest private static final String EXPERIMENT_TYPE = "experiments/experiment_type.xls"; + private static final String EXPERIMENT_UPDATE = "experiments/update.xls"; + private static String FILES_DIR; private String sessionToken; @@ -82,7 +84,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreated() throws IOException + public void testExperimentsAreCreated() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_XLS))); @@ -97,7 +99,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedSecondExperiment() throws IOException + public void testExperimentsAreCreatedSecondExperiment() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_XLS))); @@ -112,7 +114,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWithEverythingOnServer() throws IOException + public void testExperimentsAreCreatedWithEverythingOnServer() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_TYPE))); @@ -130,7 +132,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWithEverythingOnServerAndInXls() throws IOException + public void testExperimentsAreCreatedWithEverythingOnServerAndInXls() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_TYPE))); @@ -164,7 +166,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWithTypeOnServer() throws IOException + public void testExperimentsAreCreatedWithTypeOnServer() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_TYPE))); @@ -180,7 +182,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWithTypeOnServerAndInXls() throws IOException + public void testExperimentsAreCreatedWithTypeOnServerAndInXls() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_TYPE))); @@ -204,7 +206,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWhenNonMandatoryPropertiesAreNotProvided() throws IOException + public void testExperimentsAreCreatedWhenNonMandatoryPropertiesAreNotProvided() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENTS_WITH_NON_MANDATORY_PROPERTY_MISSING))); @@ -225,7 +227,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWithSpaceAndProjectOnServer() throws IOException + public void testExperimentsAreCreatedWithSpaceAndProjectOnServer() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, SPACE))); @@ -242,7 +244,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWithSpaceOnServer() throws IOException + public void testExperimentsAreCreatedWithSpaceOnServer() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, SPACE))); @@ -258,7 +260,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWithTypeAndSpaceOnServer() throws IOException + public void testExperimentsAreCreatedWithTypeAndSpaceOnServer() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_TYPE))); @@ -281,7 +283,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedIfMandatoryPropertyArePresent() throws IOException + public void testExperimentsAreCreatedIfMandatoryPropertyArePresent() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENTS_WITH_MANDATORY_PROPERTY_PRESENT))); @@ -296,7 +298,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWhenPropertiesAreAddressedByLabelsWithTypeInXls() throws IOException + public void testExperimentsAreCreatedWhenPropertiesAreAddressedByLabelsWithTypeInXls() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENTS_PROPERTIES_COLUMNS_AS_LABELS))); @@ -311,7 +313,7 @@ public class ImportExperimentsTest extends AbstractImportTest @Test @DirtiesContext - public void testProjectsAreCreatedWhenPropertiesAreAddressedByLabelsWithTypeOnServer() throws IOException + public void testExperimentsAreCreatedWhenPropertiesAreAddressedByLabelsWithTypeOnServer() throws IOException { // GIVEN TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_TYPE))); @@ -326,4 +328,19 @@ public class ImportExperimentsTest extends AbstractImportTest assertEquals(experiment.getProperties().get("DEFAULT_OBJECT_TYPE"), "OBJECT_TYPE"); } +// @Test +// @DirtiesContext +// public void testExperimentsUpdate() throws Exception +// { +// // GIVEN +// TestUtils.createFrom(v3api, sessionToken, Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_XLS))); +// // WHEN +// TestUtils.createFrom(v3api, sessionToken, TestUtils.getDynamicPluginMap(), UpdateMode.UPDATE_IF_EXISTS, +// Paths.get(FilenameUtils.concat(FILES_DIR, EXPERIMENT_UPDATE))); +// Experiment experiment = TestUtils.getExperiment(v3api, sessionToken, "TEST_EXPERIMENT", "TEST_PROJECT", "TEST_SPACE"); +// // THEN +// assertEquals(experiment.getProperties().get("$NAME"), "NameUpdate"); +// assertEquals(experiment.getProperties().get("DEFAULT_OBJECT_TYPE"), "DefaultObjectTypeUpdate"); +// } + } diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/TestUtils.java b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/TestUtils.java index cd10c5cf5514ca8d6935c14eb09f88e47b10f905..4d772ca22b93d7595579be34ad5d6081f1df20fc 100644 --- a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/TestUtils.java +++ b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/TestUtils.java @@ -5,6 +5,7 @@ import java.io.IOException; import java.io.InputStream; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -13,6 +14,7 @@ import java.util.stream.Collectors; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringUtils; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.interfaces.IEntityType; import ch.ethz.sis.openbis.generic.asapi.v3.dto.common.search.SearchResult; import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.DataSetType; import ch.ethz.sis.openbis.generic.asapi.v3.dto.dataset.fetchoptions.DataSetTypeFetchOptions; @@ -27,6 +29,7 @@ import ch.ethz.sis.openbis.generic.asapi.v3.dto.experiment.search.ExperimentType import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.Project; import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.fetchoptions.ProjectFetchOptions; import ch.ethz.sis.openbis.generic.asapi.v3.dto.project.search.ProjectSearchCriteria; +import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyAssignment; import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.PropertyType; import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyAssignmentFetchOptions; import ch.ethz.sis.openbis.generic.asapi.v3.dto.property.fetchoptions.PropertyTypeFetchOptions; @@ -52,6 +55,7 @@ import ch.ethz.sis.openbis.generic.server.asapi.v3.IApplicationServerInternalApi public class TestUtils { + private static final String UPDATE_MODE = "update_mode"; public static final String XLS_PARAM = "xls"; @@ -291,11 +295,18 @@ public class TestUtils } CustomASServiceExecutionOptions options = new CustomASServiceExecutionOptions(); options.withParameter(XLS_PARAM, excels); + options.withParameter(UPDATE_MODE, UpdateMode.IGNORE_EXISTING.name()); return (String) v3api.executeCustomASService(sessionToken, new CustomASServiceCode(XLS_IMPORT_API), options); } static String createFrom(IApplicationServerInternalApi v3api, String sessionToken, Map<String, String> scripts, Path... xls_paths) throws IOException + { + return TestUtils.createFrom(v3api, sessionToken, scripts, UpdateMode.IGNORE_EXISTING, xls_paths); + } + + static String createFrom(IApplicationServerInternalApi v3api, String sessionToken, Map<String, String> scripts, UpdateMode updateMode, + Path... xls_paths) throws IOException { List<byte[]> excels = new ArrayList<>(); for (Path xls_path : xls_paths) @@ -306,6 +317,7 @@ public class TestUtils CustomASServiceExecutionOptions options = new CustomASServiceExecutionOptions(); options.withParameter(XLS_PARAM, excels); options.withParameter(SCRIPTS_PARAM, scripts); + options.withParameter(UPDATE_MODE, updateMode.name()); return (String) v3api.executeCustomASService(sessionToken, new CustomASServiceCode(XLS_IMPORT_API), options); } @@ -345,6 +357,24 @@ public class TestUtils return permId; } + static List<PropertyAssignment> extractAndSortPropertyAssignmentsPerGivenPropertyName(IEntityType rawData, List<String> propertyNames) + throws Exception + { + List<PropertyAssignment> propertyAssignments = rawData.getPropertyAssignments(); + List<PropertyAssignment> sortedPropertyAssignments = propertyNames.stream().map(propertyName -> { + return propertyAssignments.stream().filter(prop -> prop.getPropertyType().getPermId().toString().equals(propertyName)).findFirst().get(); + }).collect(Collectors.toList()); + + if (sortedPropertyAssignments.stream().anyMatch(property -> property == null)) + { + throw new Exception("Some properties are missing" + + "\nFollowing properties are expected " + Arrays.toString(propertyNames.toArray()) + + "\n Available properties are: " + Arrays.toString(propertyAssignments.toArray())); + } + + return sortedPropertyAssignments; + } + private static byte[] readData(Path xls_path) throws IOException { String path = xls_path.toString(); diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/UpdateMode.java b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/UpdateMode.java new file mode 100644 index 0000000000000000000000000000000000000000..21a3953f25378a13b6f8a3ed1e2e446c04a37cbf --- /dev/null +++ b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/UpdateMode.java @@ -0,0 +1,8 @@ +package ch.ethz.sis.openbis.systemtest.plugin.excelimport; + +public enum UpdateMode +{ + IGNORE_EXISTING, + FAIL_IF_EXISTS, + UPDATE_IF_EXISTS +} diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/normal_dataset.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/normal_dataset.xls index d72039c8ae394e9954c07af64559e7d34a812961..f8e3a5bbe47105e81cda8862e43ada1d25fc6e24 100644 Binary files a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/normal_dataset.xls and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/normal_dataset.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/normal_dataset_update.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/normal_dataset_update.xls new file mode 100644 index 0000000000000000000000000000000000000000..50a97ff6953cd07c43e40c726e438f5e7741d5b5 Binary files /dev/null and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/normal_dataset_update.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/with_validation.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/with_validation.xls index cdee2cb18599a074ff8c34a4666c7a46027d080c..dc995c0ebc3b57dbc16e91b6a81eb3a8d0ef62bb 100644 Binary files a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/with_validation.xls and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/dataset_types/with_validation.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiment_types/normal_experiment.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiment_types/normal_experiment.xls index d3c3dda61bd16fa12d7ab9bbaf65cba6ba70caa2..166c329684354e9de6cd843ebb64be76e7d42dd3 100644 Binary files a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiment_types/normal_experiment.xls and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiment_types/normal_experiment.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiment_types/normal_experiment_update.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiment_types/normal_experiment_update.xls new file mode 100644 index 0000000000000000000000000000000000000000..0003395592d9e7a8b9028261c5b751f941133ad9 Binary files /dev/null and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiment_types/normal_experiment_update.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/all_elsewhere.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/all_elsewhere.xls index fa502e8210ac48b660a275973dd373cabdbc351a..e77ea3d64d128a9d68fffd1b1c5bb263509a635a 100644 Binary files a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/all_elsewhere.xls and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/all_elsewhere.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/all_inside.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/all_inside.xls index 48fe7da35a0f258b912a5449d61a69dab46ebc64..2cdc04fa337cb059283d37111cefeb6a58df0a4f 100644 Binary files a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/all_inside.xls and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/all_inside.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/experiment_type.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/experiment_type.xls index 79d7b595f514ef121fb09f982c5e9ec1f50efe05..7e0e081f622fd8364a6aac0f5ec97637867b69cc 100644 Binary files a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/experiment_type.xls and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/experiment_type.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/update.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/update.xls new file mode 100644 index 0000000000000000000000000000000000000000..ee288657dcd346e5ca8fcabab7d1d5cf78ebf366 Binary files /dev/null and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/experiments/update.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/projects/update.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/projects/update.xls new file mode 100644 index 0000000000000000000000000000000000000000..7a765adc13bca5255e056d87d5e6b3691c5f288b Binary files /dev/null and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/projects/update.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/projects/with_spaces.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/projects/with_spaces.xls index 124040d0a40c49d88cec4de77dab2616c88e355f..013883b578b58cccd9ea0608cf0da8cd59a6afe7 100644 Binary files a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/projects/with_spaces.xls and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/projects/with_spaces.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/property_types/normal_property_type_update.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/property_types/normal_property_type_update.xls new file mode 100644 index 0000000000000000000000000000000000000000..ab44836f66a09cca10ebc7673b198bc0c3aa3b9e Binary files /dev/null and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/property_types/normal_property_type_update.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/sample_types/normal_samples.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/sample_types/normal_samples.xls index 26f1ce1b3d41182ad5ee0b16def5a35afd8ced4a..70dd4fda799214430d0e0db047b8883e1aa40e7c 100644 Binary files a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/sample_types/normal_samples.xls and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/sample_types/normal_samples.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/sample_types/normal_samples_update.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/sample_types/normal_samples_update.xls new file mode 100644 index 0000000000000000000000000000000000000000..efcc3f96d5d86b5c61899ba67585348e7962f5d1 Binary files /dev/null and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/sample_types/normal_samples_update.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/samples/all_in.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/samples/all_in.xls index dd6d161dee473e898ceb5a6e6bf0c54127cb3cb9..dffff5e4c4410802f6916b91d1dc60bd69143c83 100644 Binary files a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/samples/all_in.xls and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/samples/all_in.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/samples/update.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/samples/update.xls new file mode 100644 index 0000000000000000000000000000000000000000..a67f52a107c781417c43a750d1c57b8308704e2c Binary files /dev/null and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/samples/update.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/spaces/normal_spaces_update.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/spaces/normal_spaces_update.xls new file mode 100644 index 0000000000000000000000000000000000000000..5b8856014351f19ad564a6b9b04521cac2ea38f3 Binary files /dev/null and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/spaces/normal_spaces_update.xls differ diff --git a/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/vocabularies/normal_vocab_update.xls b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/vocabularies/normal_vocab_update.xls new file mode 100644 index 0000000000000000000000000000000000000000..9a321de1c61d450714968700314bc69197eb16ec Binary files /dev/null and b/openbis_standard_technologies/sourceTest/java/ch/ethz/sis/openbis/systemtest/plugin/excelimport/test_files/vocabularies/normal_vocab_update.xls differ