diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/MasterDataParser.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/MasterDataParser.java index 07fbd48d609f98ab63c65299537f15fe79103f81..58dd1b31517b223581b2959ed845fe455d727324 100644 --- a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/MasterDataParser.java +++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/MasterDataParser.java @@ -274,11 +274,7 @@ public class MasterDataParser private String getAttribute(Element termElement, String attr) { Node node = termElement.getAttributes().getNamedItem(attr); - if (node != null) - { - return node.getTextContent().trim(); - } - return null; + return node != null ? node.getTextContent() : null; } private void parseMaterialTypes(NodeList matTypesNode) throws XPathExpressionException @@ -297,11 +293,7 @@ public class MasterDataParser MaterialType materialType = new MaterialType(); materialType.setCode(nameTranslator.translate(getAttribute(materialTypeElement, "code"))); materialType.setDescription(getAttribute(materialTypeElement, "description")); - String validationPluginName = getAttribute(materialTypeElement, "validationPlugin"); - if (validationPluginName != null) - { - materialType.setValidationScript(validationPlugins.get(validationPluginName)); - } + materialType.setValidationScript(getValidationPlugin(materialTypeElement)); materialTypes.put(materialType.getCode(), materialType); parsePropertyAssignments(EntityKind.MATERIAL, materialType, materialTypeElement); @@ -324,11 +316,7 @@ public class MasterDataParser ExperimentType expType = new ExperimentType(); expType.setCode(nameTranslator.translate(getAttribute(expTypeElement, "code"))); expType.setDescription(getAttribute(expTypeElement, "description")); - String validationPluginName = getAttribute(expTypeElement, "validationPlugin"); - if (validationPluginName != null) - { - expType.setValidationScript(validationPlugins.get(validationPluginName)); - } + expType.setValidationScript(getValidationPlugin(expTypeElement)); experimentTypes.put(expType.getCode(), expType); parsePropertyAssignments(EntityKind.EXPERIMENT, expType, expTypeElement); @@ -358,11 +346,7 @@ public class MasterDataParser sampleType.setSubcodeUnique(Boolean.valueOf(getAttribute(sampleTypeElement, "subcodeUnique"))); sampleType.setAutoGeneratedCode(Boolean.valueOf(getAttribute(sampleTypeElement, "autoGeneratedCode"))); sampleType.setGeneratedCodePrefix(getAttribute(sampleTypeElement, "generatedCodePrefix")); - String validationPluginName = getAttribute(sampleTypeElement, "validationPlugin"); - if (validationPluginName != null) - { - sampleType.setValidationScript(validationPlugins.get(validationPluginName)); - } + sampleType.setValidationScript(getValidationPlugin(sampleTypeElement)); sampleTypes.put(sampleType.getCode(), sampleType); parsePropertyAssignments(EntityKind.SAMPLE, sampleType, sampleTypeElement); @@ -396,16 +380,22 @@ public class MasterDataParser dataSetType.setMainDataSetPath(mainDataSetPath); } dataSetType.setDeletionDisallow(Boolean.valueOf(getAttribute(dataSetTypeElement, "deletionDisallowed"))); - String validationPluginName = getAttribute(dataSetTypeElement, "validationPlugin"); - if (validationPluginName != null) - { - dataSetType.setValidationScript(validationPlugins.get(validationPluginName)); - } + dataSetType.setValidationScript(getValidationPlugin(dataSetTypeElement)); dataSetTypes.put(dataSetType.getCode(), dataSetType); parsePropertyAssignments(EntityKind.DATA_SET, dataSetType, dataSetTypeElement); } } + + private Script getValidationPlugin(Element element) + { + String name = getAttribute(element, "validationPlugin"); + if (StringUtils.isBlank(name)) + { + return null; + } + return validationPlugins.get(nameTranslator.translate(name)); + } private void parsePropertyAssignments(EntityKind entityKind, EntityType entityType, Element entityTypeElement) throws XPathExpressionException diff --git a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/ResourceListParser.java b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/ResourceListParser.java index 813b26fed372d956497ca6f552f457dcd086e669..e07a2fa9586ca1350831d5e9038cc1f5b81e1bbb 100644 --- a/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/ResourceListParser.java +++ b/datastore_server/source/java/ch/ethz/sis/openbis/generic/server/dss/plugins/sync/harvester/synchronizer/ResourceListParser.java @@ -333,10 +333,8 @@ public class ResourceListParser { return null; } - } else - { - return val.trim(); - } + } + return val; } private String extractAttribute(Node xdNode, String attrName) throws IllegalArgumentException diff --git a/integration-tests/source/systemtest/testcase.py b/integration-tests/source/systemtest/testcase.py index 9e2d80762a25acb3badc5d03b8b107c39a8dc6ef..8dc20bec753fe635ed371ffe489d717b84493411 100644 --- a/integration-tests/source/systemtest/testcase.py +++ b/integration-tests/source/systemtest/testcase.py @@ -1,3 +1,4 @@ +import difflib import re import os import os.path @@ -142,7 +143,9 @@ class TestCase(object): """ rendered_expected = self._render(expected) if expected != actual: - self.fail("%s\n expected: <%s>\n but was: <%s>" % (itemName, rendered_expected, self._render(actual))) + rendered_actual = self._render(actual) + diff = difflib.ndiff(rendered_expected.splitlines(), rendered_actual.splitlines()) + self.fail("%s\n Differences:\n%s" % (itemName, '\n'.join(diff))) return False elif verbose: util.printAndFlush("%s as expected: <%s>" % (itemName, rendered_expected)) diff --git a/integration-tests/test_openbis_sync_big.py b/integration-tests/test_openbis_sync_big.py index 4030366aeb6f02f417865368299162f59e2511d6..7c3b10355175573bd65a7a209a1488851407e176 100755 --- a/integration-tests/test_openbis_sync_big.py +++ b/integration-tests/test_openbis_sync_big.py @@ -37,6 +37,7 @@ DATA_SOURCE_AS_PORT = '9000' DATA_SOURCE_DSS_PORT = '9001' HARVESTER_AS_PORT = '9002' HARVESTER_DSS_PORT = '9003' +TYPE_PREFIX = 'DS1_' class TestCase(systemtest.testcase.TestCase): @@ -56,11 +57,11 @@ class TestCase(systemtest.testcase.TestCase): def executeInDevMode(self): openbis_data_source = self.createOpenbisController('data_source', port=DATA_SOURCE_AS_PORT, dropDatabases=False) # self._drop_test_examples(openbis_data_source) -# openbis_harvester = self.createOpenbisController('harvester', port=HARVESTER_AS_PORT, dropDatabases=False) - openbis_harvester = self._setupOpenbisHarvester() - openbis_harvester.allUp() + openbis_harvester = self.createOpenbisController('harvester', port=HARVESTER_AS_PORT, dropDatabases=False) +# openbis_harvester = self._setupOpenbisHarvester() +# openbis_harvester.allUp() - self._waitUntilSyncIsFinished(openbis_harvester) +# self._waitUntilSyncIsFinished(openbis_harvester) self._checkData(openbis_data_source, openbis_harvester) def _drop_test_examples(self, openbis): @@ -134,17 +135,61 @@ class TestCase(systemtest.testcase.TestCase): return next_words def _checkData(self, openbis_data_source, openbis_harvester): - material_types = openbis_data_source.queryDatabase('openbis', 'select code, description from material_types order by code') - self.assertEquals("Material types on data source", - [['COMPOUND', 'Compound'], ['CONTROL', 'Control of a control layout'], - ['GENE', 'Gene'], ['GENE-RELATION', 'links to genes'], ['SIRNA', 'Oligo nucleotide']], - material_types) - material_types = openbis_harvester.queryDatabase('openbis', - "select code, description from material_types where code like 'DS1_%' order by code") - self.assertEquals("Synched material types on harvester", - [['DS1_COMPOUND', 'Compound'], ['DS1_CONTROL', 'Control of a control layout'], - ['DS1_GENE', 'Gene'], ['DS1_GENE-RELATION', 'links to genes'], ['DS1_SIRNA', 'Oligo nucleotide']], - material_types) + self._compareDataBases("Vocabularies", openbis_data_source, openbis_harvester, "openbis", + "select '{0}' || code as code, description, source_uri, is_managed_internally, " + + " is_internal_namespace, is_chosen_from_list " + + "from controlled_vocabularies where code like '{1}%' order by code") + self._compareDataBases("Property types", openbis_data_source, openbis_harvester, "openbis", + "select '{0}' || t.code as code,dt.code as data_type, '{0}' || v.code as vocabulary, " + + " '{0}' || mt.code as material, t.label, t.description, " + + " t.is_managed_internally, t.is_internal_namespace, t.schema, t.transformation " + + "from property_types t join data_types dt on t.daty_id = dt.id " + + "left join controlled_vocabularies v on t.covo_id = v.id " + + "left join material_types mt on t.maty_prop_id = mt.id " + + "where t.code like '{1}%' order by t.code") + self._compareDataBases("Material types", openbis_data_source, openbis_harvester, "openbis", + "select '{0}' || t.code as code, t.description, s.name as validation_script " + + "from material_types t left join scripts s on t.validation_script_id = s.id " + + "where t.code like '{1}%' order by t.code") + self._compareDataBases("Experiment types", openbis_data_source, openbis_harvester, "openbis", + "select '{0}' || t.code as code, t.description, s.name as validation_script " + + "from experiment_types t left join scripts s on t.validation_script_id = s.id " + + "where t.code like '{1}%' order by t.code") + self._compareDataBases("Sample types", openbis_data_source, openbis_harvester, "openbis", + "select '{0}' || code as code, t.description, is_listable, generated_from_depth, part_of_depth " + + " is_auto_generated_code, generated_code_prefix, is_subcode_unique, inherit_properties, " + + " show_parent_metadata, s.name as validation_script " + + "from sample_types t left join scripts s on t.validation_script_id = s.id " + + "where code like '{1}%' order by code") + self._compareDataBases("Data set types", openbis_data_source, openbis_harvester, "openbis", + "select '{0}' || code as code, t.description, main_ds_pattern, main_ds_path, " + + " deletion_disallow, s.name as validation_script " + + "from data_set_types t left join scripts s on t.validation_script_id = s.id " + + "where code like '{1}%' order by code") + self._compareDataBases("Plugins", openbis_data_source, openbis_harvester, "openbis", + "select '{0}' || name as name, description, script_type, plugin_type, entity_kind, is_available, " + + " length(script) as script_length, md5(script) as script_hash " + + "from scripts where name like '{1}%' order by name") + self._compareDataBases("Material properties", openbis_data_source, openbis_harvester, "openbis", + "select '{0}' || m.code as material, '{0}' || t.code as type, '{0}' || pt.code as property, " + + " concat(mp.value, cvt.code, '{0}' || m2.code) as value " + + "from materials m join material_properties mp on mp.mate_id = m.id " + + "left join controlled_vocabulary_terms cvt on mp.cvte_id = cvt.id " + + "left join materials m2 on mp.mate_prop_id = m2.id " + + "join material_type_property_types etpt on mp.mtpt_id = etpt.id " + + "join material_types t on etpt.maty_id = t.id " + + "join property_types pt on etpt.prty_id = pt.id " + + "order by m.code, pt.code") + self._compareDataBases("Experiment properties", openbis_data_source, openbis_harvester, "openbis", + "select e.code as experiment, '{0}' || t.code as type, '{0}' || pt.code as property, " + + " concat(ep.value, cvt.code, m.code) as value " + + "from experiments e join experiment_properties ep on ep.expe_id = e.id " + + "left join controlled_vocabulary_terms cvt on ep.cvte_id = cvt.id " + + "left join materials m on ep.mate_prop_id = m.id " + + "join experiment_type_property_types etpt on ep.etpt_id = etpt.id " + + "join experiment_types t on etpt.exty_id = t.id " + + "join property_types pt on etpt.prty_id = pt.id " + + "order by e.code, pt.code") self._compareDataBases("Number of samples per experiment", openbis_data_source, openbis_harvester, "openbis", "select p.code as project, e.code as experiment, count(*) as number_of_samples " + "from experiments e join projects p on e.proj_id = p.id " @@ -153,28 +198,50 @@ class TestCase(systemtest.testcase.TestCase): + "group by p.code, e.code order by p.code, e.code") self._compareDataBases("Attachments", openbis_data_source, openbis_harvester, "openbis", "select e.code as experiment, p.code as project, s.code as sample, " - + "a.file_name, a.version, a.title, a.description, length(value), md5(value) " + + " a.file_name, a.version, a.title, a.description, length(value) as attachment_length, " + + " md5(value) as attachment_hash " + "from attachments a join attachment_contents c on a.exac_id = c.id " + "left join experiments e on a.expe_id = e.id " + "left join projects p on a.proj_id = p.id " + "left join samples s on a.samp_id = s.id order by a.file_name, a.version") + self._compareDataBases("Sample properties", openbis_data_source, openbis_harvester, "openbis", + "select s.code as sample, '{0}' || t.code as type, '{0}' || pt.code as property, " + + " concat(sp.value, cvt.code, m.code) as value " + + "from samples s join sample_properties sp on sp.samp_id = s.id " + + "left join controlled_vocabulary_terms cvt on sp.cvte_id = cvt.id " + + "left join materials m on sp.mate_prop_id = m.id " + + "join sample_type_property_types stpt on sp.stpt_id = stpt.id " + + "join sample_types t on stpt.saty_id = t.id " + + "join property_types pt on stpt.prty_id = pt.id " + + "where expe_id in (select id from experiments where code = 'TEST-EXPERIMENT') " + + "order by s.code, pt.code") self._compareDataBases("Data sets", openbis_data_source, openbis_harvester, "openbis", - "select d.code, s.code, e.code " + "select d.code as data_set, s.code as sample, e.code as experiment " + "from data d left join samples s on d.samp_id = s.id " + "left join experiments e on d.expe_id=e.id order by d.code") + self._compareDataBases("Data set properties", openbis_data_source, openbis_harvester, "openbis", + "select d.code as data_set, '{0}' || t.code as type, '{0}' || pt.code as property, " + + " concat(dp.value, cvt.code, m.code) as value " + + "from data d join data_set_properties dp on dp.ds_id = d.id " + + "left join controlled_vocabulary_terms cvt on dp.cvte_id = cvt.id " + + "left join materials m on dp.mate_prop_id = m.id " + + "join data_set_type_property_types dtpt on dp.dstpt_id = dtpt.id " + + "join data_set_types t on dtpt.dsty_id = t.id " + + "join property_types pt on dtpt.prty_id = pt.id " + + "order by d.code, pt.code") self._compareDataBases("Data set sizes", openbis_data_source, openbis_harvester, "pathinfo", - "select d.code, file_name, size_in_bytes " + "select d.code as data_set, file_name, size_in_bytes " + "from data_set_files f join data_sets d on f.dase_id=d.id where parent_id is null " + "order by d.code") self._compareDataBases("Data set relationships", openbis_data_source, openbis_harvester, "openbis", - "select p.code, c.code, t.code " + "select p.code as parent, c.code as child, t.code as relationship_type " + "from data_set_relationships r join data p on r.data_id_parent = p.id " + "join data c on r.data_id_child = c.id " + "join relationship_types t on r.relationship_id = t.id order by p.code, c.code") def _compareDataBases(self, name, openbis_data_source, openbis_harvester, databaseType, sql): - expectedContent = openbis_data_source.queryDatabase(databaseType, sql) - synchedContent = openbis_harvester.queryDatabase(databaseType, sql) + expectedContent = openbis_data_source.queryDatabase(databaseType, sql.format(TYPE_PREFIX, ""), showHeaders = True) + synchedContent = openbis_harvester.queryDatabase(databaseType, sql.format("", TYPE_PREFIX), showHeaders = True) self.assertEquals(name, expectedContent, synchedContent) def _setupOpenbisDataSource(self):