From 591b6440e6f1e5c8586e4baa89334ba6ed3f2905 Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Mon, 5 Feb 2024 11:27:01 +0100 Subject: [PATCH 01/13] WIP test case --- .../test/impl/JoinRetainConditionsTest.groovy | 91 +++++++++++++++ .../ABC-to-S.halex | 27 +++++ .../ABC-to-S.halex.alignment.xml | 106 ++++++++++++++++++ .../ABC-to-S.halex.styles.sld | 3 + .../retain-join-conditions-retype/ABC.groovy | 15 +++ .../S-to-T.halex | 27 +++++ .../S-to-T.halex.alignment.xml | 67 +++++++++++ .../S-to-T.halex.styles.sld | 3 + .../retain-join-conditions-retype/S.groovy | 7 ++ .../retain-join-conditions-retype/T.groovy | 7 ++ 10 files changed, 353 insertions(+) create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex.alignment.xml create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex.styles.sld create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC.groovy create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.alignment.xml create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.styles.sld create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S.groovy create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/T.groovy diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy new file mode 100644 index 0000000000..89be9a0ac5 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2024 wetransform GmbH + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution. If not, see <http://www.gnu.org/licenses/>. + * + * Contributors: + * wetransform GmbH <http://www.wetransform.to> + */ + +package eu.esdihumboldt.hale.common.align.merge.test.impl + +import static org.junit.Assert.* + +import org.junit.Test + +import eu.esdihumboldt.hale.common.align.io.impl.JaxbAlignmentIO +import eu.esdihumboldt.hale.common.align.merge.test.AbstractMergeCellMigratorTest +import eu.esdihumboldt.hale.common.align.model.functions.join.JoinParameter + +/** + * Test for retaining conditions during Merge. + * + * @author Simon Templer + */ +class JoinRetainConditionsTest extends AbstractMergeCellMigratorTest { + + @Test + void testRetypeCondition() { + def toMigrate = this.class.getResource('/testcases/retain-join-conditions-retype/S-to-T.halex') + def cellId = 'SabcT' + + def matching = this.class.getResource('/testcases/retain-join-conditions-retype/ABC-to-S.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + + // filter + assertEquals(1, migrated.size()) + JaxbAlignmentIO.printCell(migrated[0], System.out) + + /* + assertNotNull(migrated[0].source) + assertEquals(2, migrated[0].source.size()) + Collection<? extends Entity> source = migrated[0].source.values() + ((Collection<Entity>) source).each { e -> + def filter = e.definition.filter + if (e.definition.definition.displayName == 'A1') { + // expect filter to have been propagated to A1 + assertNotNull(filter) + //assertEquals('a1 <> \'NIL\'', filter.filterTerm) + assertEquals('NOT (a1 = \'NIL\')', filter.filterTerm) + } + else { + // no filter should be present + assertNull(filter) + } + } + JoinParameter param = CellUtil.getFirstParameter(migrated[0], JoinFunction.PARAMETER_JOIN).as(JoinParameter) + assertJoinOrder(param, ['A1', 'A2']) + // there should be a condition on the join focus, also in the order + assertNotNull(param.types[0].filter) + // there should also be a filter in the condition + def base = param.conditions.collect { it.baseProperty }.findAll { it.type.displayName == 'A1' }.toList() + assertEquals(1, base.size()) + assertNotNull(base[0].filter) + // there should be a message about the condition having been translated automatically + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) + */ + } + + // helpers + + void assertJoinOrder(JoinParameter param, List<String> expected) { + def names = [] + param.types?.each { type -> + names << type.type.name.localPart + } + + assertEquals(expected, names) + } +} diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex new file mode 100644 index 0000000000..1ec3f6a8e7 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<hale-project version="5.1.0.qualifier"> + <name>ABC to S (matching)</name> + <author>Simon Templer</author> + <created>2018-01-10T16:17:32.757+01:00</created> + <modified>2024-02-05T11:12:38.984+01:00</modified> + <save-config action-id="project.save" provider-id="eu.esdihumboldt.hale.io.project.hale25.xml.writer"> + <setting name="charset">UTF-8</setting> + <setting name="projectFiles.separate">false</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.project.hale25.xml</setting> + <setting name="target">file:/home/simon/repos/hale/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex</setting> + </save-config> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.source" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">6534b899-7ef3-4ead-8e4f-9af3af16f030</setting> + <setting name="source">ABC.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.target" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">67afcd12-5dd4-4adc-ab52-042786a4b3af</setting> + <setting name="source">S.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <file name="alignment.xml" location="ABC-to-S.halex.alignment.xml"/> + <file name="styles.sld" location="ABC-to-S.halex.styles.sld"/> +</hale-project> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex.alignment.xml b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex.alignment.xml new file mode 100644 index 0000000000..afdede245f --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex.alignment.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<alignment xmlns="http://www.esdi-humboldt.eu/hale/alignment"> + <cell relation="eu.esdihumboldt.hale.align.join" id="C052fa5be-faf8-441e-9e55-bd4a6d271834" priority="normal"> + <source name="types"> + <class> + <type name="B" ns="ABC"/> + </class> + </source> + <source name="types"> + <class> + <type name="C" ns="ABC"/> + </class> + </source> + <source name="types"> + <class> + <type name="A" ns="ABC"/> + </class> + </source> + <target> + <class> + <type name="S" ns="S"/> + </class> + </target> + <complexParameter name="join"> + <jp:join-parameter xmlns:jp="http://www.esdi-humboldt.eu/hale/join"> + <class> + <type name="A" ns="ABC"/> + </class> + <class> + <type name="B" ns="ABC"/> + </class> + <class> + <type name="C" ns="ABC"/> + </class> + <jp:condition> + <property> + <type name="A" ns="ABC"/> + <child name="a" ns="ABC"/> + </property> + <property> + <type name="B" ns="ABC"/> + <child name="a" ns="ABC"/> + </property> + </jp:condition> + <jp:condition> + <property> + <type name="B" ns="ABC"/> + <child name="b" ns="ABC"/> + </property> + <property> + <type name="C" ns="ABC"/> + <child name="b" ns="ABC"/> + </property> + </jp:condition> + </jp:join-parameter> + </complexParameter> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C10d44c4c-8346-48ec-bff9-0b5f305f82c8" priority="normal"> + <source> + <property> + <type name="A" ns="ABC"/> + <child name="a" ns="ABC"/> + </property> + </source> + <target> + <property> + <type name="S" ns="S"/> + <child name="a" ns="S"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C531ccec5-b548-49ce-8aac-e2b74c9b6b93" priority="normal"> + <source> + <property> + <type name="B" ns="ABC"/> + <child name="b" ns="ABC"/> + </property> + </source> + <target> + <property> + <type name="S" ns="S"/> + <child name="b" ns="S"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C2636c3cf-fc30-418d-b22b-803c794c0fa4" priority="normal"> + <source> + <property> + <type name="C" ns="ABC"/> + <child name="c" ns="ABC"/> + </property> + </source> + <target> + <property> + <type name="S" ns="S"/> + <child name="c" ns="S"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> +</alignment> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex.styles.sld b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex.styles.sld new file mode 100644 index 0000000000..ad34f540f6 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC-to-S.halex.styles.sld @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?><sld:UserStyle xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> + <sld:Name>Default Styler</sld:Name> +</sld:UserStyle> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC.groovy new file mode 100644 index 0000000000..29f9fb2411 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/ABC.groovy @@ -0,0 +1,15 @@ +schema('ABC') { + A { + a() + } + + B { + a() + b(cardinality: '?') + } + + C { + b() + c(cardinality: '?') + } +} \ No newline at end of file diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex new file mode 100644 index 0000000000..98d774624f --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<hale-project version="5.1.0.qualifier"> + <name>S to T (to be migrated)</name> + <author>Simon Templer</author> + <created>2018-01-10T16:26:35.275+01:00</created> + <modified>2024-02-05T11:15:17.691+01:00</modified> + <save-config action-id="project.save" provider-id="eu.esdihumboldt.hale.io.project.hale25.xml.writer"> + <setting name="charset">UTF-8</setting> + <setting name="projectFiles.separate">false</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.project.hale25.xml</setting> + <setting name="target">file:/home/simon/repos/hale/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex</setting> + </save-config> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.source" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">bafa16f0-75ed-44e3-a0ed-10e5410d044d</setting> + <setting name="source">S.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.target" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">e13b67b2-8b9a-45eb-b812-c8c675028b48</setting> + <setting name="source">T.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <file name="alignment.xml" location="S-to-T.halex.alignment.xml"/> + <file name="styles.sld" location="S-to-T.halex.styles.sld"/> +</hale-project> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.alignment.xml b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.alignment.xml new file mode 100644 index 0000000000..a37cb59750 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.alignment.xml @@ -0,0 +1,67 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<alignment xmlns="http://www.esdi-humboldt.eu/hale/alignment"> + <cell relation="eu.esdihumboldt.hale.align.retype" id="SabcT" priority="normal"> + <source> + <class> + <type name="S" ns="S"> + <condition lang="ECQL">a <> '100' AND (b = '1000' OR b = '1001') AND c IS NOT NULL</condition> + </type> + </class> + </source> + <target> + <class> + <type name="T" ns="T"/> + </class> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C5a797cd6-1a6b-4692-ad14-115fd819a068" priority="normal"> + <source> + <property> + <type name="S" ns="S"/> + <child name="a" ns="S"/> + </property> + </source> + <target> + <property> + <type name="T" ns="T"/> + <child name="a" ns="T"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="Cda0bda4c-63b9-4120-ad93-df726cbad7d6" priority="normal"> + <source> + <property> + <type name="S" ns="S"/> + <child name="b" ns="S"/> + </property> + </source> + <target> + <property> + <type name="T" ns="T"/> + <child name="b" ns="T"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="Ce600b8bf-fdd8-447b-aa31-074fd48b431e" priority="normal"> + <source> + <property> + <type name="S" ns="S"/> + <child name="c" ns="S"/> + </property> + </source> + <target> + <property> + <type name="T" ns="T"/> + <child name="c" ns="T"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> +</alignment> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.styles.sld b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.styles.sld new file mode 100644 index 0000000000..ad34f540f6 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.styles.sld @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?><sld:UserStyle xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> + <sld:Name>Default Styler</sld:Name> +</sld:UserStyle> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S.groovy new file mode 100644 index 0000000000..1b76c88047 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S.groovy @@ -0,0 +1,7 @@ +schema('S') { + S { + a() + b(cardinality: '?') + c(cardinality: '?') + } +} diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/T.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/T.groovy new file mode 100644 index 0000000000..f34690fedc --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/T.groovy @@ -0,0 +1,7 @@ +schema('T') { + T { + a() + b(cardinality: '?') + c(cardinality: '?') + } +} From a692fe87a44b0123cf26774c408503d049f9b8d3 Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Tue, 6 Feb 2024 16:53:19 +0100 Subject: [PATCH 02/13] WIP merge --- .../test/impl/JoinRetainConditionsTest.groovy | 107 ++++++++++----- .../merge/functions/JoinMergeMigrator.java | 2 +- .../merge/impl/AbstractMergeCellMigrator.java | 122 +++++++++++++++++- .../align/merge/impl/AbstractMigration.groovy | 23 ++-- .../merge/impl/DefaultSchemaMigration.groovy | 3 +- .../align/merge/impl/MatchingMigration.groovy | 23 +++- .../align/instance/EntityAwareFilter.java | 7 +- .../align/migrate/AlignmentMigration.java | 17 ++- .../align/migrate/impl/UnmigratedCell.java | 3 +- .../common/filter/AbstractGeotoolsFilter.java | 112 +++++++++++++++- .../internal/EntityReplacementVisitor.java | 88 ++++++++++++- .../service/align/migrate/UserMigration.java | 4 +- 12 files changed, 443 insertions(+), 68 deletions(-) diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy index 89be9a0ac5..48de315fa4 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy @@ -21,6 +21,9 @@ import org.junit.Test import eu.esdihumboldt.hale.common.align.io.impl.JaxbAlignmentIO import eu.esdihumboldt.hale.common.align.merge.test.AbstractMergeCellMigratorTest +import eu.esdihumboldt.hale.common.align.model.CellUtil +import eu.esdihumboldt.hale.common.align.model.Entity +import eu.esdihumboldt.hale.common.align.model.functions.JoinFunction import eu.esdihumboldt.hale.common.align.model.functions.join.JoinParameter /** @@ -45,37 +48,79 @@ class JoinRetainConditionsTest extends AbstractMergeCellMigratorTest { assertEquals(1, migrated.size()) JaxbAlignmentIO.printCell(migrated[0], System.out) - /* - assertNotNull(migrated[0].source) - assertEquals(2, migrated[0].source.size()) - Collection<? extends Entity> source = migrated[0].source.values() - ((Collection<Entity>) source).each { e -> - def filter = e.definition.filter - if (e.definition.definition.displayName == 'A1') { - // expect filter to have been propagated to A1 - assertNotNull(filter) - //assertEquals('a1 <> \'NIL\'', filter.filterTerm) - assertEquals('NOT (a1 = \'NIL\')', filter.filterTerm) - } - else { - // no filter should be present - assertNull(filter) - } - } - JoinParameter param = CellUtil.getFirstParameter(migrated[0], JoinFunction.PARAMETER_JOIN).as(JoinParameter) - assertJoinOrder(param, ['A1', 'A2']) - // there should be a condition on the join focus, also in the order - assertNotNull(param.types[0].filter) - // there should also be a filter in the condition - def base = param.conditions.collect { it.baseProperty }.findAll { it.type.displayName == 'A1' }.toList() - assertEquals(1, base.size()) - assertNotNull(base[0].filter) - // there should be a message about the condition having been translated automatically - def messages = getMigrationMessages(migrated[0]) - assertTrue(messages.any { msg -> - msg.text.toLowerCase().contains('condition') - }) - */ + def expectedFilterA = 'NOT (a = \'100\')' + def expectedFilterB = '(b IN (\'1000\',\'1001\'))' + def expectedFilterC = 'NOT (c IS NULL)' + + assertNotNull(migrated[0].source) + assertEquals(3, migrated[0].source.size()) + Collection<? extends Entity> source = migrated[0].source.values() + ((Collection<Entity>) source).each { e -> + def filter = e.definition.filter + if (e.definition.definition.displayName == 'A') { + // expect filter part to have been propagated to A + assertNotNull(filter) + assertEquals(expectedFilterA, filter.filterTerm) + } + else if (e.definition.definition.displayName == 'B') { + // expect filter part to have been propagated to A + assertNotNull(filter) + assertEquals(expectedFilterB, filter.filterTerm) + } + else if (e.definition.definition.displayName == 'C') { + // expect filter part to have been propagated to A + assertNotNull(filter) + assertEquals(expectedFilterC, filter.filterTerm) + } + else { + fail('Unexpected entity') + } + } + JoinParameter param = CellUtil.getFirstParameter(migrated[0], JoinFunction.PARAMETER_JOIN).as(JoinParameter) + assertJoinOrder(param, ['A', 'B', 'C']) + + // there should be a condition on all join types, also in the order + def filter = param.types[0].filter + assertNotNull(filter) + assertEquals(expectedFilterA, filter.filterTerm) + + filter = param.types[1].filter + assertNotNull(filter) + assertEquals(expectedFilterB, filter.filterTerm) + + filter = param.types[2].filter + assertNotNull(filter) + assertEquals(expectedFilterC, filter.filterTerm) + + // there should also be a filter in the condition for each type + + // base properties + def base = param.conditions.collect { it.baseProperty }.findAll { it.type.displayName == 'A' }.toList() + assertEquals(1, base.size()) + assertNotNull(base[0].filter) + assertEquals(expectedFilterA, base[0].filter.filterTerm) + + base = param.conditions.collect { it.baseProperty }.findAll { it.type.displayName == 'B' }.toList() + assertEquals(1, base.size()) + assertNotNull(base[0].filter) + assertEquals(expectedFilterB, base[0].filter.filterTerm) + + // join properties + def join = param.conditions.collect { it.joinProperty }.findAll { it.type.displayName == 'B' }.toList() + assertEquals(1, join.size()) + assertNotNull(join[0].filter) + assertEquals(expectedFilterB, join[0].filter.filterTerm) + + join = param.conditions.collect { it.joinProperty }.findAll { it.type.displayName == 'C' }.toList() + assertEquals(1, join.size()) + assertNotNull(join[0].filter) + assertEquals(expectedFilterC, join[0].filter.filterTerm) + + // there should be a message about the condition having been translated automatically + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) } // helpers diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinMergeMigrator.java b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinMergeMigrator.java index 97825d437c..3eacaad6cf 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinMergeMigrator.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinMergeMigrator.java @@ -190,7 +190,7 @@ private void addSources(MutableCell cell, EntityDefinition source, Cell match, if (transferContext.test(entity.getDefinition())) { // transfer filter and contexts if possible EntityDefinition withContexts = AbstractMigration.translateContexts(source, - entity.getDefinition(), migration, log); + entity.getDefinition(), migration, null, log); if (withContexts.getFilter() != null) { context.addTypeFilter(withContexts.getType(), withContexts.getFilter()); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMergeCellMigrator.java b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMergeCellMigrator.java index b7f7692b8d..f4e9e8e6f6 100755 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMergeCellMigrator.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMergeCellMigrator.java @@ -20,7 +20,9 @@ import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.Optional; import java.util.Set; @@ -60,6 +62,7 @@ import eu.esdihumboldt.hale.common.core.report.SimpleLog; import eu.esdihumboldt.hale.common.instance.model.Filter; import eu.esdihumboldt.hale.common.schema.model.PropertyDefinition; +import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; import eu.esdihumboldt.hale.common.schema.model.constraint.type.GeometryType; /** @@ -155,8 +158,8 @@ else if (isDirectMatch(originalCell)) { AlignmentMigration cellMigration = new AbstractMigration() { @Override - protected Optional<EntityDefinition> findMatch( - EntityDefinition entity) { + protected Optional<EntityDefinition> findMatch(EntityDefinition entity, + TypeDefinition preferRoot) { Entity target = CellUtil.getFirstEntity(originalCell.getTarget()); if (target != null) { return Optional.ofNullable(target.getDefinition()); @@ -357,7 +360,7 @@ else if (newSource.size() == 1) { Entity singleSource = CellUtil.getFirstEntity(newSource); if (singleSource != null) { EntityDefinition transferedSource = AbstractMigration.translateContexts( - original, singleSource.getDefinition(), migration, log); + original, singleSource.getDefinition(), migration, null, log); ListMultimap<String, Entity> s = ArrayListMultimap.create(); s.put(newSource.keySet().iterator().next(), AlignmentUtil.createEntity(transferedSource)); @@ -371,11 +374,19 @@ else if (newSource.size() == 1) { // sources? // XXX for now only special case handling to support - // XtraServer use case + // XtraServer use case - if not enabled, continue if (applySourceContextsToJoinFocus(newCell, originalSource, migration, log)) { return; } + /* + * Generic handling of source contexts for Join that tries + * to split filters and apply parts to each source type. + */ + if (applySourceContextsToJoin(newCell, originalSource, migration, log)) { + return; + } + // no idea where to add contexts -> report log.warn( "Any conditions/contexts on the original source have been dropped because the new mapping has multiple sources and it is not clear where they should be attached: " @@ -385,6 +396,107 @@ else if (newSource.size() == 1) { } } + /** + * Apply source conditions to joined types. + * + * @param newCell the new cell to update the sources + * @param originalSource the original source + * @param migration the alignment migration + * @param log the operation log + * @return if the method handled the context transfer + */ + private boolean applySourceContextsToJoin(MutableCell newCell, Entity originalSource, + AlignmentMigration migration, SimpleLog log) { + String function = newCell.getTransformationIdentifier(); + switch (function) { + case GroovyJoin.ID: + case JoinFunction.ID: + break; + default: + return false; + } + + JoinParameter joinConfig = CellUtil.getFirstParameter(newCell, JoinFunction.PARAMETER_JOIN) + .as(JoinParameter.class); + + if (joinConfig == null || joinConfig.getTypes() == null + || joinConfig.getTypes().isEmpty()) { + return false; + } + + List<TypeDefinition> joinTypes = joinConfig.getTypes().stream() + .map(TypeEntityDefinition::getDefinition).toList(); + Map<TypeDefinition, Filter> joinTypeFilters = new HashMap<TypeDefinition, Filter>(); + + // transfer context for each Join source type + newCell.setSource(ArrayListMultimap.create(Multimaps.transformValues(newCell.getSource(), + new com.google.common.base.Function<Entity, Entity>() { + + @Override + public Entity apply(Entity input) { + TypeDefinition inputType = input.getDefinition().getType(); + if (input.getDefinition().getPropertyPath().isEmpty() + && joinTypes.contains(inputType)) { + EntityDefinition transferedSource = AbstractMigration.translateContexts( + originalSource.getDefinition(), input.getDefinition(), + migration, inputType, log); + joinTypeFilters.put(inputType, transferedSource.getFilter()); + return AlignmentUtil.createEntity(transferedSource); + } + else { + return input; + } + } + }))); + + // fix filter in order and conditions + // XXX only works like this because a type currently can only be present + // once in the source + if (!joinTypeFilters.isEmpty()) { + // order + List<TypeEntityDefinition> types = new ArrayList<>(); + for (int i = 0; i < joinConfig.getTypes().size(); i++) { + TypeEntityDefinition type = joinConfig.getTypes().get(i); + Filter filter = joinTypeFilters.get(type.getType()); + if (filter != null) { + type = new TypeEntityDefinition(type.getDefinition(), type.getSchemaSpace(), + filter); + } + types.add(type); + } + + // conditions + Set<JoinCondition> conditions = joinConfig.getConditions().stream().map(c -> { + Filter baseFilter = joinTypeFilters.get(c.baseProperty.getType()); + Filter joinFilter = joinTypeFilters.get(c.joinProperty.getType()); + + if (baseFilter != null || joinFilter != null) { + return new JoinCondition(applyFilter(c.baseProperty, baseFilter), + applyFilter(c.joinProperty, joinFilter)); + } + else { + return c; + } + }).collect(Collectors.toSet()); + + JoinParameter newConfig = new JoinParameter(types, conditions); + + ListMultimap<String, ParameterValue> modParams = ArrayListMultimap + .create(newCell.getTransformationParameters()); + List<ParameterValue> joinParams = modParams.get(JoinFunction.PARAMETER_JOIN); + if (!joinParams.isEmpty()) { + JoinParameter joinParam = joinParams.get(0).as(JoinParameter.class); + if (joinParam != null) { + joinParams.clear(); + joinParams.add(new ParameterValue(Value.complex(newConfig))); + } + } + newCell.setTransformationParameters(modParams); + } + + return true; + } + /** * Handle special case of applying source contexts to the entity that is the * Join focus. @@ -431,7 +543,7 @@ public Entity apply(Entity input) { && input.getDefinition().getType().equals(focus.getType())) { EntityDefinition transferedSource = AbstractMigration.translateContexts( originalSource.getDefinition(), input.getDefinition(), - migration, log); + migration, focus.getType(), log); focusFilter.set(transferedSource.getFilter()); return AlignmentUtil.createEntity(transferedSource); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy index 014a1706df..a79b5516ee 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy @@ -26,6 +26,7 @@ import eu.esdihumboldt.hale.common.core.report.SimpleLog import eu.esdihumboldt.hale.common.instance.extension.filter.FilterDefinitionManager import eu.esdihumboldt.hale.common.schema.SchemaSpaceID import eu.esdihumboldt.hale.common.schema.model.PropertyDefinition +import eu.esdihumboldt.hale.common.schema.model.TypeDefinition import eu.esdihumboldt.hale.common.schema.model.constraint.type.GeometryType import groovy.transform.CompileStatic @@ -40,18 +41,19 @@ abstract class AbstractMigration implements AlignmentMigration { /** * Find a match for the given entity * @param entity the entity + * @param preferRoot hint on which entity to prefer if there are multiple matches * @return the match if found */ - protected abstract Optional<EntityDefinition> findMatch(EntityDefinition entity); + protected abstract Optional<EntityDefinition> findMatch(EntityDefinition entity, TypeDefinition preferRoot); @Override - Optional<EntityDefinition> entityReplacement(EntityDefinition entity, SimpleLog log) { + Optional<EntityDefinition> entityReplacement(EntityDefinition entity, TypeDefinition preferRoot, SimpleLog log) { EntityDefinition defaultEntity = AlignmentUtil.getAllDefaultEntity(entity) - Optional<EntityDefinition> matchedEntity = findMatch(defaultEntity) + Optional<EntityDefinition> matchedEntity = findMatch(defaultEntity, preferRoot) // special case handling if (!matchedEntity.isPresent()) { - matchedEntity = findParentMatch(defaultEntity) + matchedEntity = findParentMatch(defaultEntity, preferRoot) if (matchedEntity.present) { log.warn "Inaccurate match of $entity to ${matchedEntity.get()} via parent entity" } @@ -60,7 +62,7 @@ abstract class AbstractMigration implements AlignmentMigration { if (matchedEntity.present) { // entity contained contexts -> translate them if possible - matchedEntity = Optional.ofNullable(translateContexts(entity, matchedEntity.get(), this, log)); + matchedEntity = Optional.ofNullable(translateContexts(entity, matchedEntity.get(), this, preferRoot, log)); } if (!matchedEntity.isPresent()) { @@ -71,7 +73,7 @@ abstract class AbstractMigration implements AlignmentMigration { } static EntityDefinition translateContexts(EntityDefinition original, EntityDefinition target, - AlignmentMigration migration, SimpleLog log) { + AlignmentMigration migration, TypeDefinition preferRoot, SimpleLog log) { def defaultEntity = AlignmentUtil.getAllDefaultEntity(original) if (original.filter) { @@ -92,7 +94,7 @@ abstract class AbstractMigration implements AlignmentMigration { if (!sameEntity(original, target)) { // replacements in filter if possible if (filter instanceof EntityAwareFilter) { - def migrated = ((EntityAwareFilter) filter).migrateFilter(AlignmentUtil.getTypeEntity(original), migration, log) + def migrated = ((EntityAwareFilter) filter).migrateFilter(AlignmentUtil.getTypeEntity(original), migration, preferRoot, log) if (migrated.present) { filter = migrated.get() //TODO mark automatically migrated? @@ -206,10 +208,10 @@ abstract class AbstractMigration implements AlignmentMigration { } } - protected Optional<EntityDefinition> findParentMatch(EntityDefinition entity) { + protected Optional<EntityDefinition> findParentMatch(EntityDefinition entity, TypeDefinition preferRoot) { //XXX only allow parent matches for specific cases right now if (!(entity.definition instanceof PropertyDefinition) || - !((PropertyDefinition) entity.definition).propertyType.getConstraint(GeometryType).isGeometry()) { + !((PropertyDefinition) entity.definition).propertyType.getConstraint(GeometryType).isGeometry()) { // not a geometry return Optional.empty() } @@ -217,7 +219,7 @@ abstract class AbstractMigration implements AlignmentMigration { while (entity != null) { entity = AlignmentUtil.getParent(entity) - def matchedEntity = findMatch(entity); + def matchedEntity = findMatch(entity, preferRoot); if (matchedEntity.present) { return matchedEntity } @@ -225,5 +227,4 @@ abstract class AbstractMigration implements AlignmentMigration { return Optional.empty() } - } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/DefaultSchemaMigration.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/DefaultSchemaMigration.groovy index aa7031ca00..0eff252a04 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/DefaultSchemaMigration.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/DefaultSchemaMigration.groovy @@ -44,7 +44,7 @@ class DefaultSchemaMigration implements AlignmentMigration { } @Override - public Optional<EntityDefinition> entityReplacement(EntityDefinition entity, SimpleLog log) { + public Optional<EntityDefinition> entityReplacement(EntityDefinition entity, TypeDefinition preferRoot, SimpleLog log) { // default behavior - try to find entity in new schema, based on names w/o namespace @@ -184,5 +184,4 @@ class DefaultSchemaMigration implements AlignmentMigration { candidate } - } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/MatchingMigration.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/MatchingMigration.groovy index 5075af47e1..4847f9a3c0 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/MatchingMigration.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/MatchingMigration.groovy @@ -22,6 +22,7 @@ import eu.esdihumboldt.hale.common.align.model.Cell import eu.esdihumboldt.hale.common.align.model.EntityDefinition import eu.esdihumboldt.hale.common.headless.impl.ProjectTransformationEnvironment; import eu.esdihumboldt.hale.common.schema.SchemaSpaceID +import eu.esdihumboldt.hale.common.schema.model.TypeDefinition import groovy.transform.CompileStatic;;; /** @@ -41,12 +42,30 @@ class MatchingMigration extends AbstractMigration { this.reverse = reverse } - protected Optional<EntityDefinition> findMatch(EntityDefinition entity) { + @Override + protected Optional<EntityDefinition> findMatch(EntityDefinition entity, TypeDefinition preferRoot) { findMatches(entity).flatMap({ list -> - list ? Optional.ofNullable(((List<EntityDefinition>)list)[0]) : Optional.empty() + findPreferredCandidate((List<EntityDefinition>)list, preferRoot) } as Function) } + private Optional<EntityDefinition> findPreferredCandidate(Collection<EntityDefinition> entities, TypeDefinition preferRoot) { + if (entities.empty) { + return Optional.empty() + } + + /* + * Note: preferRoot is used here to for example pick a specific type from a Join cell's sources + */ + def firstPreferred = entities.find { EntityDefinition it -> it.type == preferRoot } + if (firstPreferred) { + Optional.of(firstPreferred) + } + else { + Optional.of(entities.iterator().next()) + } + } + public Optional<List<EntityDefinition>> findMatches(EntityDefinition entity) { if (reverse) { // match to target diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/instance/EntityAwareFilter.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/instance/EntityAwareFilter.java index 43c3e3376a..ceea97bc43 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/instance/EntityAwareFilter.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/instance/EntityAwareFilter.java @@ -22,6 +22,7 @@ import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.core.report.SimpleLog; import eu.esdihumboldt.hale.common.instance.model.Filter; +import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; /** * Extended filter interface for filters aware of referenced entities. @@ -42,7 +43,7 @@ public interface EntityAwareFilter extends Filter { /** * States if the filter supports migration via - * {@link #migrateFilter(EntityDefinition, AlignmentMigration, SimpleLog)} + * {@link #migrateFilter(EntityDefinition, AlignmentMigration, TypeDefinition, SimpleLog)} * * @return <code>true</code> if migration is supported, <code>false</code> * otherwise @@ -55,10 +56,12 @@ public interface EntityAwareFilter extends Filter { * * @param context the entity context * @param migration the alignment migration + * @param preferRoot hint on which entity to prefer if there are multiple + * matches * @param log the operation log * @return the migrated filter, if migration is possible */ Optional<Filter> migrateFilter(EntityDefinition context, AlignmentMigration migration, - SimpleLog log); + TypeDefinition preferRoot, SimpleLog log); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/AlignmentMigration.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/AlignmentMigration.java index c65ef04431..ff37f622b4 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/AlignmentMigration.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/AlignmentMigration.java @@ -19,6 +19,7 @@ import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.core.report.SimpleLog; +import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; /** * Interface describing an alignment migration. @@ -34,6 +35,20 @@ public interface AlignmentMigration { * @param log the migration process log (may be cell specific) * @return the replacement entity, if the entity should be replaced */ - Optional<EntityDefinition> entityReplacement(EntityDefinition entity, SimpleLog log); + default Optional<EntityDefinition> entityReplacement(EntityDefinition entity, SimpleLog log) { + return entityReplacement(entity, null, log); + } + + /** + * Yields a replacement for an entity existing in a given alignment. + * + * @param entity the entity to replace + * @param preferRoot hint on which entity to prefer if there are multiple + * matches + * @param log the migration process log (may be cell specific) + * @return the replacement entity, if the entity should be replaced + */ + Optional<EntityDefinition> entityReplacement(EntityDefinition entity, TypeDefinition preferRoot, + SimpleLog log); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/UnmigratedCell.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/UnmigratedCell.java index 371ab0d75c..5bd1f0a3c0 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/UnmigratedCell.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/UnmigratedCell.java @@ -29,6 +29,7 @@ import eu.esdihumboldt.hale.common.align.model.MutableCell; import eu.esdihumboldt.hale.common.align.model.impl.MutableCellDecorator; import eu.esdihumboldt.hale.common.core.report.SimpleLog; +import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; /** * Decorator for a {@link MutableCell} that allows to do lazy migration. @@ -82,7 +83,7 @@ public MutableCell migrate(Map<EntityDefinition, EntityDefinition> additionalMap @Override public Optional<EntityDefinition> entityReplacement(EntityDefinition entity, - SimpleLog log) { + TypeDefinition preferRoot, SimpleLog log) { return Optional.ofNullable(joinedMappings.get(entity)); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java index bd3880fdc4..4eb3df6f62 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java +++ b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java @@ -16,14 +16,20 @@ package eu.esdihumboldt.hale.common.filter; +import java.util.ArrayList; +import java.util.Deque; +import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; import javax.xml.namespace.QName; +import org.geotools.factory.CommonFactoryFinder; import org.geotools.filter.FilterAttributeExtractor; import org.geotools.filter.text.cql2.CQLException; +import org.geotools.util.factory.GeoTools; +import org.opengis.filter.And; import org.opengis.filter.Filter; import org.opengis.filter.expression.PropertyName; @@ -39,6 +45,7 @@ import eu.esdihumboldt.hale.common.filter.internal.EntityReplacementVisitor; import eu.esdihumboldt.hale.common.instance.helper.PropertyResolver; import eu.esdihumboldt.hale.common.instance.model.Instance; +import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; import eu.esdihumboldt.util.groovy.paths.Path; /** @@ -179,15 +186,84 @@ public List<Optional<EntityDefinition>> getReferencedEntities(EntityDefinition c @Override public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter( - EntityDefinition context, AlignmentMigration migration, SimpleLog log) { + EntityDefinition context, AlignmentMigration migration, TypeDefinition preferRoot, + SimpleLog log) { + // split filter (AND operands) + List<Filter> andParts = splitAnd(internFilter); + + // migrate each filter part + List<Filter> acceptedParts = new ArrayList<>(); + for (Filter part : andParts) { + EntityReplacementVisitor visitor = new EntityReplacementVisitor(migration, + name -> resolveProperty(name, context, log), preferRoot, log); + Object extraData = null; + Filter copy = (Filter) part.accept(visitor, extraData); + + /* + * Determine if part is relevant. Only accept filter parts that are + * not exclusively updated with other types than `preferRoot`. (This + * is used to handle the different types from a Join individually) + * + * TODO is usage of preferRoot OK or should we have an additional + * parameter to control this behavior? + * + * Inform about parts that are dropped) + */ + TypeDefinition focusType = preferRoot; + String messagePrefix = (focusType == null) ? "" : focusType.getDisplayName() + ": "; + if (visitor.isAllMismatches(focusType)) { + // drop if there were no successful replacements at all + if (andParts.size() == 1) { + try { + log.warn( + "{0}The filter \"{1}\" was removed because no matches for the respective properties were found", + messagePrefix, toFilterTerm(part)); + } catch (CQLException e) { + log.error( + "{0}The filter was removed because no matches for the respective properties were found; error converting filter to string", + messagePrefix, e); + } + } + else { + try { + log.warn( + "{0}The filter operand \"{1}\" part of the filter''s AND condition was removed because no matches for the respective properties were found", + messagePrefix, toFilterTerm(part)); + } catch (CQLException e) { + log.error( + "{0}A filter operand part of the filter's AND condition was removed because no matches for the respective properties were found; error converting filter part to string", + messagePrefix, e); + } + } + } + else { + acceptedParts.add(copy); + + // log if there are replacements that don't match the focus type + if (focusType != null) { + List<EntityDefinition> otherReplacements = visitor.getReplacements().stream() + .filter(entity -> !focusType.equals(entity.getType())).toList(); + if (!otherReplacements.isEmpty()) { + try { + log.warn( + "{0}The filter operand \"{1}\" part of the filter''s AND condition contains references related to other types than {2}", + messagePrefix, toFilterTerm(part), focusType.getDisplayName()); + } catch (CQLException e) { + log.error( + "{0}A filter operand part of the filter's AND condition contains references related to other types than {1}; error converting filter part to string", + messagePrefix, focusType.getDisplayName(), e); + } + } + } + } + } - EntityReplacementVisitor visitor = new EntityReplacementVisitor(migration, - name -> resolveProperty(name, context, log), log); - Object extraData = null; - Filter copy = (Filter) internFilter.accept(visitor, extraData); + // combine accepted filter parts + Filter combined = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()) + .and(acceptedParts); try { - String filterString = toFilterTerm(copy); + String filterString = toFilterTerm(combined); return Optional.of(buildFilter(filterString)); } catch (CQLException e) { log.error("Filter could not be automatically migrated", e); @@ -195,6 +271,30 @@ public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter } } + /** + * Split a filter into separate AND conditions. + * + * @param filter the filter to split + * @return the split filters as list + */ + private List<Filter> splitAnd(Filter filter) { + List<Filter> result = new ArrayList<>(); + + Deque<Filter> toCheck = new LinkedList<>(); + toCheck.add(filter); + while (!toCheck.isEmpty()) { + Filter f = toCheck.poll(); + if (f instanceof And) { + toCheck.addAll(((And) f).getChildren()); + } + else { + result.add(f); + } + } + + return result; + } + /** * Resolve a property name based on the given context. * diff --git a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/internal/EntityReplacementVisitor.java b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/internal/EntityReplacementVisitor.java index 6e3c5cf736..adff175940 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/internal/EntityReplacementVisitor.java +++ b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/internal/EntityReplacementVisitor.java @@ -15,7 +15,10 @@ package eu.esdihumboldt.hale.common.filter.internal; +import java.util.Collections; +import java.util.LinkedHashSet; import java.util.Optional; +import java.util.Set; import java.util.function.Function; import java.util.stream.Collectors; @@ -26,6 +29,7 @@ import eu.esdihumboldt.hale.common.align.model.AlignmentUtil; import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.core.report.SimpleLog; +import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; /** * Filter visitor that replaces entities in filters with their @@ -37,19 +41,33 @@ public class EntityReplacementVisitor extends DuplicatingFilterVisitor { private final AlignmentMigration migration; private final Function<PropertyName, Optional<EntityDefinition>> resolveProperty; + private final TypeDefinition preferRoot; private final SimpleLog log; + // counter for total attempted replacements (where the original could be + // resolved) + private int total = 0; + // counter for successful replacements + private int matched = 0; + + private final Set<EntityDefinition> mismatches = new LinkedHashSet<>(); + private final Set<EntityDefinition> replacements = new LinkedHashSet<>(); + /** * Create an entity replacement visitor. * * @param migration the alignment migration * @param resolveProperty the function resolving a property to an entity + * @param preferRoot hint on which entity to prefer if there are multiple + * matches * @param log the operation log */ public EntityReplacementVisitor(AlignmentMigration migration, - Function<PropertyName, Optional<EntityDefinition>> resolveProperty, SimpleLog log) { + Function<PropertyName, Optional<EntityDefinition>> resolveProperty, + TypeDefinition preferRoot, SimpleLog log) { this.migration = migration; this.resolveProperty = resolveProperty; + this.preferRoot = preferRoot; this.log = log; } @@ -58,10 +76,21 @@ public Object visit(PropertyName expression, Object extraData) { Optional<EntityDefinition> resolved = resolveProperty.apply(expression) .map(p -> AlignmentUtil.getAllDefaultEntity(p)); if (resolved.isPresent()) { - Optional<EntityDefinition> replace = migration.entityReplacement(resolved.get(), log); - if (replace.isPresent() && !resolved.get().equals(replace.get())) { - return getFactory(extraData).property(toPropertyName(replace.get()), - expression.getNamespaceContext()); + total++; + + Optional<EntityDefinition> replace = migration.entityReplacement(resolved.get(), + preferRoot, log); + if (replace.isPresent()) { + matched++; + replacements.add(replace.get()); + + if (!resolved.get().equals(replace.get())) { + return getFactory(extraData).property(toPropertyName(replace.get()), + expression.getNamespaceContext()); + } + } + else { + mismatches.add(resolved.get()); } } else { @@ -81,4 +110,53 @@ private String toPropertyName(EntityDefinition entityDefinition) { return name; } + /** + * @return if none the attempted replacements matched. + */ + public boolean isAllMismatches() { + return total > 0 && matched == 0; + } + + /** + * @return if there were any failed attempted replacements + */ + public boolean hasMismatches() { + return !mismatches.isEmpty(); + } + + /** + * @return the set of entities where no replacement was found + */ + public Set<EntityDefinition> getMismatches() { + return Collections.unmodifiableSet(mismatches); + } + + /** + * @return the set of entities that served as replacement + */ + public Set<EntityDefinition> getReplacements() { + return Collections.unmodifiableSet(replacements); + } + + /** + * Determine if related to an expected parent type all replacement attempts + * were mismatches or matching entities with a different parent type. + * + * @param expectedParent the expected parent type + * @return + */ + public boolean isAllMismatches(TypeDefinition expectedParent) { + if (expectedParent == null) { + return isAllMismatches(); + } + + if (total > 0) { + return !replacements.stream() + .anyMatch(entity -> expectedParent.equals(entity.getType())); + } + else { + return false; + } + } + } diff --git a/ui/plugins/eu.esdihumboldt.hale.ui/src/eu/esdihumboldt/hale/ui/service/align/migrate/UserMigration.java b/ui/plugins/eu.esdihumboldt.hale.ui/src/eu/esdihumboldt/hale/ui/service/align/migrate/UserMigration.java index d04fbbcd68..1f42a8bbcf 100644 --- a/ui/plugins/eu.esdihumboldt.hale.ui/src/eu/esdihumboldt/hale/ui/service/align/migrate/UserMigration.java +++ b/ui/plugins/eu.esdihumboldt.hale.ui/src/eu/esdihumboldt/hale/ui/service/align/migrate/UserMigration.java @@ -25,6 +25,7 @@ import eu.esdihumboldt.hale.common.align.model.impl.TypeEntityDefinition; import eu.esdihumboldt.hale.common.core.report.SimpleLog; import eu.esdihumboldt.hale.common.schema.SchemaSpaceID; +import eu.esdihumboldt.hale.common.schema.model.TypeDefinition; import eu.esdihumboldt.hale.ui.service.align.resolver.UserFallbackEntityResolver; import eu.esdihumboldt.hale.ui.service.align.resolver.internal.EntityCandidates; @@ -53,7 +54,8 @@ public UserMigration(SchemaSpaceID schemaSpace) { } @Override - public Optional<EntityDefinition> entityReplacement(EntityDefinition entity, SimpleLog log) { + public Optional<EntityDefinition> entityReplacement(EntityDefinition entity, + TypeDefinition preferRoot, SimpleLog log) { // use functionality from entity resolver if (entity instanceof TypeEntityDefinition) { From b4d532b54e6ca49bba088296dcefc615dad91e02 Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Tue, 6 Feb 2024 20:29:17 +0100 Subject: [PATCH 03/13] WIP 2 --- .../impl/DefaultMergeCellMigratorTest.groovy | 3 +- .../test/impl/JoinRetainConditionsTest.groovy | 56 +++++++++++++++++++ .../retain-condition-join/B-to-C.halex | 4 +- .../B-to-C.halex.alignment.xml | 6 +- .../B-to-C.halex.styles.sld | 3 - .../align/merge/impl/AbstractMigration.groovy | 5 ++ .../common/filter/AbstractGeotoolsFilter.java | 4 ++ 7 files changed, 71 insertions(+), 10 deletions(-) diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy index e4f4ac5a1d..02f0c4d4e8 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy @@ -583,7 +583,8 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { def filter = e.definition.filter if (e.definition.definition.name.localPart == 'A5') { assertNotNull(filter) - assertEquals('ba = \'test\' AND NOT (bb = \'test\')', filter.filterTerm) + // assertEquals('ba = \'test\' AND NOT (bb = \'test\')', filter.filterTerm) + assertEquals('ba = \'test\' and bb <> \'test\'', filter.filterTerm) } else { assertNull(filter) diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy index 48de315fa4..35077a2390 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy @@ -123,6 +123,62 @@ class JoinRetainConditionsTest extends AbstractMergeCellMigratorTest { }) } + @Test + void testJoinCondition() { + def toMigrate = this.class.getResource('/testcases/retain-condition-join/B-to-C.halex') + def cellId = 'B1toC1' + + def matching = this.class.getResource('/testcases/retain-condition-join/A-to-B.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + + // filter + assertEquals(1, migrated.size()) + JaxbAlignmentIO.printCell(migrated[0], System.out) + + assertNotNull(migrated[0].source) + assertEquals(2, migrated[0].source.size()) + Collection<? extends Entity> source = migrated[0].source.values() + ((Collection<Entity>) source).each { e -> + def filter = e.definition.filter + if (e.definition.definition.displayName == 'A1') { + // expect filter to have been propagated to A1 + assertNotNull(filter) + //assertEquals('a1 <> \'NIL\'', filter.filterTerm) + assertEquals('NOT (a1 = \'NIL\')', filter.filterTerm) + } + else { + assertEquals('A2', e.definition.definition.displayName) + + // there should be no filter + assertNull(filter) + } + } + + JoinParameter param = CellUtil.getFirstParameter(migrated[0], JoinFunction.PARAMETER_JOIN).as(JoinParameter) + assertJoinOrder(param, ['A1', 'A2']) + + // there should be a condition on the join focus, also in the order + assertNotNull(param.types[0].filter) + + // there should also be a filter in the condition + def base = param.conditions.collect { it.baseProperty }.findAll { it.type.displayName == 'A1' }.toList() + assertEquals(1, base.size()) + assertNotNull(base[0].filter) + + // there should be a message about the condition having been translated automatically + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) + // there should be a message about the filter being removed from A2 + assertTrue(messages.any { msg -> + msg.text.startsWith('A2') && msg.text.toLowerCase().contains('was removed') + }) + } + // helpers void assertJoinOrder(JoinParameter param, List<String> expected) { diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex index e42552830d..ff4af6c277 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<hale-project version="3.5.0.qualifier"> +<hale-project version="5.1.0.qualifier"> <name>B to C (to be migrated)</name> <author>Simon Templer</author> <created>2018-01-10T16:26:35.275+01:00</created> - <modified>2018-07-17T14:47:20.404+02:00</modified> + <modified>2024-02-06T20:10:09.235+01:00</modified> <save-config action-id="project.save" provider-id="eu.esdihumboldt.hale.io.project.hale25.xml.writer"> <setting name="charset">UTF-8</setting> <setting name="projectFiles.separate">false</setting> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex.alignment.xml b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex.alignment.xml index 8a9f9d4248..17d2d9d3fd 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex.alignment.xml +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex.alignment.xml @@ -118,10 +118,8 @@ <cell relation="eu.esdihumboldt.hale.align.rename" id="B6b7toC4c4" priority="normal"> <source> <property> - <type name="B6" ns="B"> - <condition lang="ECQL">b6 <> 10</condition> - </type> - <child name="b3" ns="B"/> + <type name="B6" ns="B"/> + <child name="b6" ns="B"/> </property> </source> <target> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex.styles.sld b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex.styles.sld index e80edb03f6..ad34f540f6 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex.styles.sld +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-condition-join/B-to-C.halex.styles.sld @@ -1,6 +1,3 @@ <?xml version="1.0" encoding="UTF-8"?><sld:UserStyle xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> <sld:Name>Default Styler</sld:Name> - <sld:FeatureTypeStyle> - <sld:Name>name</sld:Name> - </sld:FeatureTypeStyle> </sld:UserStyle> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy index a79b5516ee..9e0305bc78 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy @@ -99,6 +99,11 @@ abstract class AbstractMigration implements AlignmentMigration { filter = migrated.get() //TODO mark automatically migrated? } + else { + // drop filter (should have been documented by migrateFilter call above) + //TODO discern between filter dropped vs. error when migrating filter? (see AbstractGeotoolsFilter#migrateFilter) + filter = null + } } // mark unsafe if entity is not the same diff --git a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java index 4eb3df6f62..57be597a9e 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java +++ b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java @@ -258,6 +258,10 @@ public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter } } + if (acceptedParts.isEmpty()) { + return Optional.empty(); + } + // combine accepted filter parts Filter combined = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()) .and(acceptedParts); From 1106a19b1615788b4aa101488ab5d6d0d6ce70d0 Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Wed, 7 Feb 2024 09:36:31 +0100 Subject: [PATCH 04/13] WIP test fixes --- .../impl/DefaultMergeCellMigratorTest.groovy | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy index 02f0c4d4e8..4794bd0c6f 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy @@ -446,6 +446,16 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { assertEquals(expectedFilter, filter.filterTerm) } + @CompileStatic(TypeCheckingMode.SKIP) + private void filterCheckNull(Cell migrated) { + JaxbAlignmentIO.printCell(migrated, System.out) + + // the condition should be present on the source + def source = CellUtil.getFirstEntity(migrated.source).definition + def filter = source.propertyPath.empty ? source.filter : source.propertyPath[0].condition?.filter + assertNull(filter) + } + @Test void testTypeFilter1() { def toMigrate = this.class.getResource('/testcases/type-filter/B-to-C.halex') @@ -481,13 +491,18 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { // filter assertEquals(1, migrated.size()) - filterCheck(migrated[0], "bb = 'test'") // the filter should be retained + // filter is now dropped (because bb is not mapped for B2) + filterCheckNull(migrated[0]) + // filterCheck(migrated[0], "bb = 'test'") // the filter should be retained // there should be a message about the condition def messages = getMigrationMessages(migrated[0]) assertTrue(messages.any { msg -> msg.text.toLowerCase().contains('condition') }) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('removed because no matches') + }) } @Test From d5574d814a2d075ca5e68a5ac96d48bd68406888 Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Tue, 12 Mar 2024 15:05:22 +0100 Subject: [PATCH 05/13] fix: don't close PrintStream when using printCell ...to avoid closing System.out which is used in most cases as target for printing a Cell in tests, which lead to incomplete output from tests. --- .../META-INF/MANIFEST.MF | 1 + .../common/align/io/impl/JaxbAlignmentIO.java | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/META-INF/MANIFEST.MF b/common/plugins/eu.esdihumboldt.hale.common.align/META-INF/MANIFEST.MF index 3adb7e08d2..eec7c07d4a 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/META-INF/MANIFEST.MF +++ b/common/plugins/eu.esdihumboldt.hale.common.align/META-INF/MANIFEST.MF @@ -51,6 +51,7 @@ Import-Package: com.google.common.base;version="1.6.0", eu.esdihumboldt.util.io, javax.annotation;version="[1.2.0,1.2.0]", net.jcip.annotations, + org.apache.commons.io.output, org.apache.commons.lang;version="2.4.0", org.locationtech.jts.geom, org.slf4j;version="1.5.11", diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/io/impl/JaxbAlignmentIO.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/io/impl/JaxbAlignmentIO.java index bed39c7e0e..d2f1386118 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/io/impl/JaxbAlignmentIO.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/io/impl/JaxbAlignmentIO.java @@ -19,8 +19,11 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.PrintStream; import java.net.URI; +import org.apache.commons.io.output.CloseShieldOutputStream; + import eu.esdihumboldt.hale.common.align.io.EntityResolver; import eu.esdihumboldt.hale.common.align.io.impl.internal.AlignmentToJaxb; import eu.esdihumboldt.hale.common.align.io.impl.internal.JaxbToAlignment; @@ -171,7 +174,21 @@ public static void save(AlignmentType alignment, IOReporter reporter, OutputStre } /** - * Print a cell to an output stream (intended for tests/debugging). + * Print a cell to a {@link PrintStream} (intended for tests/debugging). The + * stream is prevented from being closed, which is intended to prevent for + * instance System.out from being closed. + * + * @param cell the cell to print + * @param out the output stream + * @throws Exception if an error occurs trying to print the cell + */ + public static void printCell(MutableCell cell, PrintStream out) throws Exception { + printCell(cell, CloseShieldOutputStream.wrap(out)); + } + + /** + * Print a cell to an output stream (intended for tests/debugging). The + * stream is closed when the cell was written. * * @param cell the cell to print * @param out the output stream From 4d1b37a598613cf53ae619b2d43dc400623d1626 Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Tue, 12 Mar 2024 15:32:05 +0100 Subject: [PATCH 06/13] WIP test for property parent condition --- .../test/impl/JoinRetainConditionsTest.groovy | 75 +++++++++++++++++++ .../S-to-T.halex | 4 +- .../S-to-T.halex.alignment.xml | 10 ++- 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy index 35077a2390..f3fc666644 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy @@ -123,6 +123,81 @@ class JoinRetainConditionsTest extends AbstractMergeCellMigratorTest { }) } + /** + * Test if conditions on the type are properly migrated for property relations. + */ + @Test + void testRetypeConditionRenameTypeFiltered() { + def toMigrate = this.class.getResource('/testcases/retain-join-conditions-retype/S-to-T.halex') + def cellId = 'aRename' + + def matching = this.class.getResource('/testcases/retain-join-conditions-retype/ABC-to-S.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + + // filter + assertEquals(1, migrated.size()) + JaxbAlignmentIO.printCell(migrated[0], System.out) + + def expectedFilterA = 'NOT (a = \'100\')' + + assertNotNull(migrated[0].source) + assertEquals(1, migrated[0].source.size()) + Collection<? extends Entity> source = migrated[0].source.values() + ((Collection<Entity>) source).each { e -> + def filter = e.definition.filter + if (e.definition.type.displayName == 'A') { + // expect filter part to have been propagated to A + assertNotNull(filter) + assertEquals(expectedFilterA, filter.filterTerm) + } + else { + fail('Unexpected entity') + } + } + + // there should be a message about the condition having been translated automatically + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) + } + + /** + * Test that a property relation that previously had no type filter still has no type filter after migration. + */ + @Test + void testRetypeConditionRenameTypeInherited() { + def toMigrate = this.class.getResource('/testcases/retain-join-conditions-retype/S-to-T.halex') + def cellId = 'bRename' + + def matching = this.class.getResource('/testcases/retain-join-conditions-retype/ABC-to-S.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + + // filter + assertEquals(1, migrated.size()) + JaxbAlignmentIO.printCell(migrated[0], System.out) + + assertNotNull(migrated[0].source) + assertEquals(1, migrated[0].source.size()) + Collection<? extends Entity> source = migrated[0].source.values() + ((Collection<Entity>) source).each { e -> + def filter = e.definition.filter + if (e.definition.type.displayName == 'B') { + // there should be no filter + assertNull(filter) + } + else { + fail('Unexpected entity') + } + } + } + @Test void testJoinCondition() { def toMigrate = this.class.getResource('/testcases/retain-condition-join/B-to-C.halex') diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex index 98d774624f..1e62ad98f6 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex @@ -1,9 +1,9 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<hale-project version="5.1.0.qualifier"> +<hale-project version="5.2.0.qualifier"> <name>S to T (to be migrated)</name> <author>Simon Templer</author> <created>2018-01-10T16:26:35.275+01:00</created> - <modified>2024-02-05T11:15:17.691+01:00</modified> + <modified>2024-03-12T13:27:44.936+01:00</modified> <save-config action-id="project.save" provider-id="eu.esdihumboldt.hale.io.project.hale25.xml.writer"> <setting name="charset">UTF-8</setting> <setting name="projectFiles.separate">false</setting> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.alignment.xml b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.alignment.xml index a37cb59750..ab1ed4de7c 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.alignment.xml +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype/S-to-T.halex.alignment.xml @@ -16,10 +16,12 @@ <parameter value="false" name="ignoreNamespaces"/> <parameter value="false" name="structuralRename"/> </cell> - <cell relation="eu.esdihumboldt.hale.align.rename" id="C5a797cd6-1a6b-4692-ad14-115fd819a068" priority="normal"> + <cell relation="eu.esdihumboldt.hale.align.rename" id="aRename" priority="normal"> <source> <property> - <type name="S" ns="S"/> + <type name="S" ns="S"> + <condition lang="ECQL">a <> '100' AND (b = '1000' OR b = '1001') AND c IS NOT NULL</condition> + </type> <child name="a" ns="S"/> </property> </source> @@ -32,7 +34,7 @@ <parameter value="false" name="ignoreNamespaces"/> <parameter value="false" name="structuralRename"/> </cell> - <cell relation="eu.esdihumboldt.hale.align.rename" id="Cda0bda4c-63b9-4120-ad93-df726cbad7d6" priority="normal"> + <cell relation="eu.esdihumboldt.hale.align.rename" id="bRename" priority="normal"> <source> <property> <type name="S" ns="S"/> @@ -48,7 +50,7 @@ <parameter value="false" name="ignoreNamespaces"/> <parameter value="false" name="structuralRename"/> </cell> - <cell relation="eu.esdihumboldt.hale.align.rename" id="Ce600b8bf-fdd8-447b-aa31-074fd48b431e" priority="normal"> + <cell relation="eu.esdihumboldt.hale.align.rename" id="cRename" priority="normal"> <source> <property> <type name="S" ns="S"/> From e5625820911e500d960192099d2d1db14b52ee4f Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Tue, 12 Mar 2024 16:18:03 +0100 Subject: [PATCH 07/13] build(deps): update equinox-test update site --- platform/hale-platform.target | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/platform/hale-platform.target b/platform/hale-platform.target index dc448faab3..287d3591f2 100644 --- a/platform/hale-platform.target +++ b/platform/hale-platform.target @@ -43,10 +43,6 @@ <repository location="http://build-artifacts.wetransform.to/p2/mirror/gef-legacy-releases/"/> <unit id="org.eclipse.gef.all.feature.group" version="3.11.0.201606061308"/> </location> - <location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit"> - <repository location="http://build-artifacts.wetransform.to/p2/equinox-test/build_4"/> - <unit id="de.fhg.igd.equinox.test.feature.feature.group" version="1.2.0.202203220819"/> - </location> <location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit"> <repository location="http://build-artifacts.wetransform.to/p2/offline-resources/current"/> <unit id="to.wetransform.offlineresources.feature.feature.group" version="2024.3.8.bnd-W1hqew"/> @@ -55,5 +51,9 @@ <repository location="https://gitlab.wetransform.to/hale/hale-build-support/raw/0342a0f0c4f57a1ec4109f1fbe6e6fecd7dc722b/updatesites/platform"/> <unit id="eu.esdihumboldt.hale.platform.feature.group" version="5.0.0.i20240220"/> </location> + <location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit"> + <repository location="http://build-artifacts.wetransform.to/p2/equinox-test/1.2.0.20240312"/> + <unit id="de.fhg.igd.equinox.test.feature.feature.group" version="1.2.0.202403121501"/> + </location> </locations> </target> \ No newline at end of file From c8ff2c8b5d37234412d556b39e1c7e651e0655cf Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Tue, 12 Mar 2024 17:08:45 +0100 Subject: [PATCH 08/13] WIP another test --- .../test/impl/JoinRetainConditionsTest.groovy | 43 +++++++ .../ABC-to-S.halex | 27 +++++ .../ABC-to-S.halex.alignment.xml | 106 ++++++++++++++++++ .../ABC-to-S.halex.styles.sld | 3 + .../retain-join-conditions-retype2/ABC.groovy | 15 +++ .../S-to-T.halex | 27 +++++ .../S-to-T.halex.alignment.xml | 69 ++++++++++++ .../S-to-T.halex.styles.sld | 3 + .../retain-join-conditions-retype2/S.groovy | 7 ++ .../retain-join-conditions-retype2/T.groovy | 7 ++ 10 files changed, 307 insertions(+) create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex.alignment.xml create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex.styles.sld create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC.groovy create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex.alignment.xml create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex.styles.sld create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S.groovy create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/T.groovy diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy index f3fc666644..efb6e2ab7d 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/JoinRetainConditionsTest.groovy @@ -165,6 +165,49 @@ class JoinRetainConditionsTest extends AbstractMergeCellMigratorTest { }) } + /** + * Test if conditions on the type are properly migrated for property relations. + * Migrating conditions involves replacing property names in the filter. + */ + @Test + void testRetypeConditionRenameTypeFilteredTranslated() { + def toMigrate = this.class.getResource('/testcases/retain-join-conditions-retype2/S-to-T.halex') + def cellId = 'aRename' + + def matching = this.class.getResource('/testcases/retain-join-conditions-retype2/ABC-to-S.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + + // filter + assertEquals(1, migrated.size()) + JaxbAlignmentIO.printCell(migrated[0], System.out) + + def expectedFilterA = 'NOT (a = \'100\')' + + assertNotNull(migrated[0].source) + assertEquals(1, migrated[0].source.size()) + Collection<? extends Entity> source = migrated[0].source.values() + ((Collection<Entity>) source).each { e -> + def filter = e.definition.filter + if (e.definition.type.displayName == 'A') { + // expect filter part to have been propagated to A + assertNotNull(filter) + assertEquals(expectedFilterA, filter.filterTerm) + } + else { + fail('Unexpected entity') + } + } + + // there should be a message about the condition having been translated automatically + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) + } + /** * Test that a property relation that previously had no type filter still has no type filter after migration. */ diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex new file mode 100644 index 0000000000..ea371d8f71 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<hale-project version="5.1.0.qualifier"> + <name>ABC to S (matching)</name> + <author>Simon Templer</author> + <created>2018-01-10T16:17:32.757+01:00</created> + <modified>2024-02-05T11:12:38.984+01:00</modified> + <save-config action-id="project.save" provider-id="eu.esdihumboldt.hale.io.project.hale25.xml.writer"> + <setting name="charset">UTF-8</setting> + <setting name="projectFiles.separate">false</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.project.hale25.xml</setting> + <setting name="target">file:/home/simon/repos/hale/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex</setting> + </save-config> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.source" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">6534b899-7ef3-4ead-8e4f-9af3af16f030</setting> + <setting name="source">ABC.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.target" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">67afcd12-5dd4-4adc-ab52-042786a4b3af</setting> + <setting name="source">S.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <file name="alignment.xml" location="ABC-to-S.halex.alignment.xml"/> + <file name="styles.sld" location="ABC-to-S.halex.styles.sld"/> +</hale-project> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex.alignment.xml b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex.alignment.xml new file mode 100644 index 0000000000..1e8f3bc303 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex.alignment.xml @@ -0,0 +1,106 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<alignment xmlns="http://www.esdi-humboldt.eu/hale/alignment"> + <cell relation="eu.esdihumboldt.hale.align.join" id="C052fa5be-faf8-441e-9e55-bd4a6d271834" priority="normal"> + <source name="types"> + <class> + <type name="B" ns="ABC"/> + </class> + </source> + <source name="types"> + <class> + <type name="C" ns="ABC"/> + </class> + </source> + <source name="types"> + <class> + <type name="A" ns="ABC"/> + </class> + </source> + <target> + <class> + <type name="S" ns="S"/> + </class> + </target> + <complexParameter name="join"> + <jp:join-parameter xmlns:jp="http://www.esdi-humboldt.eu/hale/join"> + <class> + <type name="A" ns="ABC"/> + </class> + <class> + <type name="B" ns="ABC"/> + </class> + <class> + <type name="C" ns="ABC"/> + </class> + <jp:condition> + <property> + <type name="A" ns="ABC"/> + <child name="a" ns="ABC"/> + </property> + <property> + <type name="B" ns="ABC"/> + <child name="a" ns="ABC"/> + </property> + </jp:condition> + <jp:condition> + <property> + <type name="B" ns="ABC"/> + <child name="b" ns="ABC"/> + </property> + <property> + <type name="C" ns="ABC"/> + <child name="b" ns="ABC"/> + </property> + </jp:condition> + </jp:join-parameter> + </complexParameter> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C10d44c4c-8346-48ec-bff9-0b5f305f82c8" priority="normal"> + <source> + <property> + <type name="A" ns="ABC"/> + <child name="a" ns="ABC"/> + </property> + </source> + <target> + <property> + <type name="S" ns="S"/> + <child name="sourceA" ns="S"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C531ccec5-b548-49ce-8aac-e2b74c9b6b93" priority="normal"> + <source> + <property> + <type name="B" ns="ABC"/> + <child name="b" ns="ABC"/> + </property> + </source> + <target> + <property> + <type name="S" ns="S"/> + <child name="sourceB" ns="S"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C2636c3cf-fc30-418d-b22b-803c794c0fa4" priority="normal"> + <source> + <property> + <type name="C" ns="ABC"/> + <child name="c" ns="ABC"/> + </property> + </source> + <target> + <property> + <type name="S" ns="S"/> + <child name="sourceC" ns="S"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> +</alignment> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex.styles.sld b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex.styles.sld new file mode 100644 index 0000000000..ad34f540f6 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC-to-S.halex.styles.sld @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?><sld:UserStyle xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> + <sld:Name>Default Styler</sld:Name> +</sld:UserStyle> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC.groovy new file mode 100644 index 0000000000..29f9fb2411 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/ABC.groovy @@ -0,0 +1,15 @@ +schema('ABC') { + A { + a() + } + + B { + a() + b(cardinality: '?') + } + + C { + b() + c(cardinality: '?') + } +} \ No newline at end of file diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex new file mode 100644 index 0000000000..ead9673df5 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<hale-project version="5.2.0.qualifier"> + <name>S to T (to be migrated)</name> + <author>Simon Templer</author> + <created>2018-01-10T16:26:35.275+01:00</created> + <modified>2024-03-12T13:27:44.936+01:00</modified> + <save-config action-id="project.save" provider-id="eu.esdihumboldt.hale.io.project.hale25.xml.writer"> + <setting name="charset">UTF-8</setting> + <setting name="projectFiles.separate">false</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.project.hale25.xml</setting> + <setting name="target">file:/home/simon/repos/hale/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex</setting> + </save-config> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.source" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">bafa16f0-75ed-44e3-a0ed-10e5410d044d</setting> + <setting name="source">S.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.target" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">e13b67b2-8b9a-45eb-b812-c8c675028b48</setting> + <setting name="source">T.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <file name="alignment.xml" location="S-to-T.halex.alignment.xml"/> + <file name="styles.sld" location="S-to-T.halex.styles.sld"/> +</hale-project> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex.alignment.xml b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex.alignment.xml new file mode 100644 index 0000000000..b999738459 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex.alignment.xml @@ -0,0 +1,69 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<alignment xmlns="http://www.esdi-humboldt.eu/hale/alignment"> + <cell relation="eu.esdihumboldt.hale.align.retype" id="SabcT" priority="normal"> + <source> + <class> + <type name="S" ns="S"> + <condition lang="ECQL">sourceA <> '100' AND (sourceB = '1000' OR sourceB = '1001') AND sourceC IS NOT NULL</condition> + </type> + </class> + </source> + <target> + <class> + <type name="T" ns="T"/> + </class> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="aRename" priority="normal"> + <source> + <property> + <type name="S" ns="S"> + <condition lang="ECQL">sourceA <> '100' AND (sourceB = '1000' OR sourceB = '1001') AND sourceC IS NOT NULL</condition> + </type> + <child name="sourceA" ns="S"/> + </property> + </source> + <target> + <property> + <type name="T" ns="T"/> + <child name="targetA" ns="T"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="bRename" priority="normal"> + <source> + <property> + <type name="S" ns="S"/> + <child name="sourceB" ns="S"/> + </property> + </source> + <target> + <property> + <type name="T" ns="T"/> + <child name="targetB" ns="T"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="cRename" priority="normal"> + <source> + <property> + <type name="S" ns="S"/> + <child name="sourceC" ns="S"/> + </property> + </source> + <target> + <property> + <type name="T" ns="T"/> + <child name="targetC" ns="T"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> +</alignment> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex.styles.sld b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex.styles.sld new file mode 100644 index 0000000000..ad34f540f6 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S-to-T.halex.styles.sld @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?><sld:UserStyle xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> + <sld:Name>Default Styler</sld:Name> +</sld:UserStyle> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S.groovy new file mode 100644 index 0000000000..65cdddccbc --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/S.groovy @@ -0,0 +1,7 @@ +schema('S') { + S { + sourceA() + sourceB(cardinality: '?') + sourceC(cardinality: '?') + } +} diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/T.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/T.groovy new file mode 100644 index 0000000000..2bbca8b4ba --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/retain-join-conditions-retype2/T.groovy @@ -0,0 +1,7 @@ +schema('T') { + T { + targetA() + targetB(cardinality: '?') + targetC(cardinality: '?') + } +} From 6b37a3deeb0375770e09ca50f0bea006944713c8 Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Tue, 12 Mar 2024 17:09:04 +0100 Subject: [PATCH 09/13] WIP testing property filter translation --- .../align/merge/impl/AbstractMigration.groovy | 13 ++++++++++++- .../hale/common/filter/AbstractGeotoolsFilter.java | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy index 9e0305bc78..da09cb1065 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy @@ -22,6 +22,7 @@ import eu.esdihumboldt.hale.common.align.model.ChildContext import eu.esdihumboldt.hale.common.align.model.Condition import eu.esdihumboldt.hale.common.align.model.EntityDefinition import eu.esdihumboldt.hale.common.align.model.impl.PropertyEntityDefinition +import eu.esdihumboldt.hale.common.align.model.impl.TypeEntityDefinition import eu.esdihumboldt.hale.common.core.report.SimpleLog import eu.esdihumboldt.hale.common.instance.extension.filter.FilterDefinitionManager import eu.esdihumboldt.hale.common.schema.SchemaSpaceID @@ -62,6 +63,8 @@ abstract class AbstractMigration implements AlignmentMigration { if (matchedEntity.present) { // entity contained contexts -> translate them if possible + //XXX target was determined (matchedEntity), do we need to know about how the match was found, e.g. if it was a join? + matchedEntity = Optional.ofNullable(translateContexts(entity, matchedEntity.get(), this, preferRoot, log)); } @@ -94,7 +97,15 @@ abstract class AbstractMigration implements AlignmentMigration { if (!sameEntity(original, target)) { // replacements in filter if possible if (filter instanceof EntityAwareFilter) { - def migrated = ((EntityAwareFilter) filter).migrateFilter(AlignmentUtil.getTypeEntity(original), migration, preferRoot, log) + // def migrated = ((EntityAwareFilter) filter).migrateFilter(AlignmentUtil.getTypeEntity(original), migration, preferRoot, log) + + if (preferRoot == null) { + TypeEntityDefinition originalType = AlignmentUtil.getTypeEntity(original) + //FIXME if match for originalType is a Join and then set preferRoot to target type? + } + + //FIXME for testing, replace preferRoot by target + def migrated = ((EntityAwareFilter) filter).migrateFilter(AlignmentUtil.getTypeEntity(original), migration, target.type, log) if (migrated.present) { filter = migrated.get() //TODO mark automatically migrated? diff --git a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java index 57be597a9e..fad0964202 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java +++ b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java @@ -188,7 +188,15 @@ public List<Optional<EntityDefinition>> getReferencedEntities(EntityDefinition c public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter( EntityDefinition context, AlignmentMigration migration, TypeDefinition preferRoot, SimpleLog log) { + // TODO pass in target entity or target type, so we can use that + // information to determine, if filter conditions actually apply + // XXX can preferRoot be used or do we need to differ due to Join? + // split filter (AND operands) + // TODO split based on different operand based on if there is a join or + // not + // FIXME what about properties related to a Join -> we want to drop the + // AND parts - how do we know the context is a join? List<Filter> andParts = splitAnd(internFilter); // migrate each filter part From eb02a86d0763364087f1c06d43bdaf39ce640d5b Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Wed, 13 Mar 2024 10:19:12 +0100 Subject: [PATCH 10/13] WIP filter splitting based on join information, restrict property filter migration to parent type --- .../align/merge/functions/JoinContext.java | 5 +- .../merge/functions/JoinMergeMigrator.java | 9 ++- .../merge/impl/AbstractMergeCellMigrator.java | 29 ++++--- .../align/merge/impl/AbstractMigration.groovy | 36 ++++----- .../align/merge/impl/MatchingMigration.groovy | 43 +++++++++-- .../align/instance/EntityAwareFilter.java | 9 ++- .../align/migrate/AlignmentMigration.java | 4 +- .../common/align/migrate/EntityMatch.groovy | 54 +++++++++++++ .../migrate/impl/DefaultCellMigrator.java | 5 +- .../align/migrate/impl/UnmigratedCell.java | 6 +- .../functions/FormattedStringMigrator.java | 6 +- .../model/functions/join/JoinMigrator.java | 10 ++- .../model/functions/merge/MergeMigrator.java | 4 +- .../META-INF/MANIFEST.MF | 3 +- .../common/filter/AbstractGeotoolsFilter.java | 75 ++++++++++++------- .../internal/EntityReplacementVisitor.java | 10 ++- .../service/align/migrate/UserMigration.java | 7 +- 17 files changed, 223 insertions(+), 92 deletions(-) create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/EntityMatch.groovy diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinContext.java b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinContext.java index a199bea7e9..385bd7b64c 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinContext.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinContext.java @@ -33,6 +33,7 @@ import eu.esdihumboldt.cst.functions.groovy.GroovyJoin; import eu.esdihumboldt.hale.common.align.merge.MergeUtil; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.model.AlignmentUtil; import eu.esdihumboldt.hale.common.align.model.Cell; import eu.esdihumboldt.hale.common.align.model.CellUtil; @@ -245,12 +246,12 @@ private PropertyEntityDefinition processOriginalConditionProperty( }); if (!isStripped) { return (PropertyEntityDefinition) migration.entityReplacement(property, log) - .orElse(property); + .map(EntityMatch::getMatch).orElse(property); } else { EntityDefinition stripped = AlignmentUtil.getAllDefaultEntity(property); return (PropertyEntityDefinition) migration.entityReplacement(stripped, log) - .orElse(stripped); + .map(EntityMatch::getMatch).orElse(stripped); } } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinMergeMigrator.java b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinMergeMigrator.java index 3eacaad6cf..64b0e17124 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinMergeMigrator.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/functions/JoinMergeMigrator.java @@ -29,6 +29,7 @@ import eu.esdihumboldt.hale.common.align.merge.impl.AbstractMergeCellMigrator; import eu.esdihumboldt.hale.common.align.merge.impl.AbstractMigration; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.model.AlignmentUtil; import eu.esdihumboldt.hale.common.align.model.Cell; import eu.esdihumboldt.hale.common.align.model.CellUtil; @@ -188,9 +189,13 @@ private void addSources(MutableCell cell, EntityDefinition source, Cell match, Entity entity = entry.getValue(); if (transferContext.test(entity.getDefinition())) { + // XXX should the match be marked as from a Join? Unclear in + // this context + EntityMatch e = EntityMatch.of(entity.getDefinition()); + // transfer filter and contexts if possible - EntityDefinition withContexts = AbstractMigration.translateContexts(source, - entity.getDefinition(), migration, null, log); + EntityDefinition withContexts = AbstractMigration + .translateContexts(source, e, migration, null, log).getMatch(); if (withContexts.getFilter() != null) { context.addTypeFilter(withContexts.getType(), withContexts.getFilter()); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMergeCellMigrator.java b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMergeCellMigrator.java index f4e9e8e6f6..23cdc486ad 100755 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMergeCellMigrator.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMergeCellMigrator.java @@ -41,6 +41,7 @@ import eu.esdihumboldt.hale.common.align.merge.MergeUtil; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; import eu.esdihumboldt.hale.common.align.migrate.CellMigrator; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.migrate.MigrationOptions; import eu.esdihumboldt.hale.common.align.migrate.impl.DefaultCellMigrator; import eu.esdihumboldt.hale.common.align.migrate.impl.MigrationOptionsImpl; @@ -158,11 +159,12 @@ else if (isDirectMatch(originalCell)) { AlignmentMigration cellMigration = new AbstractMigration() { @Override - protected Optional<EntityDefinition> findMatch(EntityDefinition entity, + protected Optional<EntityMatch> findMatch(EntityDefinition entity, TypeDefinition preferRoot) { Entity target = CellUtil.getFirstEntity(originalCell.getTarget()); if (target != null) { - return Optional.ofNullable(target.getDefinition()); + return Optional + .ofNullable(EntityMatch.of(target.getDefinition())); } return Optional.empty(); } @@ -360,7 +362,8 @@ else if (newSource.size() == 1) { Entity singleSource = CellUtil.getFirstEntity(newSource); if (singleSource != null) { EntityDefinition transferedSource = AbstractMigration.translateContexts( - original, singleSource.getDefinition(), migration, null, log); + original, EntityMatch.of(singleSource.getDefinition()), migration, + null, log).getMatch(); ListMultimap<String, Entity> s = ArrayListMultimap.create(); s.put(newSource.keySet().iterator().next(), AlignmentUtil.createEntity(transferedSource)); @@ -437,9 +440,12 @@ public Entity apply(Entity input) { TypeDefinition inputType = input.getDefinition().getType(); if (input.getDefinition().getPropertyPath().isEmpty() && joinTypes.contains(inputType)) { - EntityDefinition transferedSource = AbstractMigration.translateContexts( - originalSource.getDefinition(), input.getDefinition(), - migration, inputType, log); + EntityDefinition transferedSource = AbstractMigration + .translateContexts(originalSource.getDefinition(), + new EntityMatch(input.getDefinition(), + joinTypes.size() > 0, true), + migration, inputType, log) + .getMatch(); joinTypeFilters.put(inputType, transferedSource.getFilter()); return AlignmentUtil.createEntity(transferedSource); } @@ -533,6 +539,8 @@ private boolean applySourceContextsToJoinFocus(MutableCell newCell, Entity origi TypeEntityDefinition focus = joinConfig.getTypes().iterator().next(); AtomicReference<Filter> focusFilter = new AtomicReference<>(); + boolean multipleSources = newCell.getSource().size() > 0; + // transfer context newCell.setSource(ArrayListMultimap.create(Multimaps.transformValues(newCell.getSource(), new com.google.common.base.Function<Entity, Entity>() { @@ -541,9 +549,12 @@ private boolean applySourceContextsToJoinFocus(MutableCell newCell, Entity origi public Entity apply(Entity input) { if (input.getDefinition().getPropertyPath().isEmpty() && input.getDefinition().getType().equals(focus.getType())) { - EntityDefinition transferedSource = AbstractMigration.translateContexts( - originalSource.getDefinition(), input.getDefinition(), - migration, focus.getType(), log); + EntityDefinition transferedSource = AbstractMigration + .translateContexts(originalSource.getDefinition(), + new EntityMatch(input.getDefinition(), multipleSources, + true), + migration, focus.getType(), log) + .getMatch(); focusFilter.set(transferedSource.getFilter()); return AlignmentUtil.createEntity(transferedSource); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy index da09cb1065..20c114995c 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/AbstractMigration.groovy @@ -17,12 +17,12 @@ package eu.esdihumboldt.hale.common.align.merge.impl import eu.esdihumboldt.hale.common.align.instance.EntityAwareFilter import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch import eu.esdihumboldt.hale.common.align.model.AlignmentUtil import eu.esdihumboldt.hale.common.align.model.ChildContext import eu.esdihumboldt.hale.common.align.model.Condition import eu.esdihumboldt.hale.common.align.model.EntityDefinition import eu.esdihumboldt.hale.common.align.model.impl.PropertyEntityDefinition -import eu.esdihumboldt.hale.common.align.model.impl.TypeEntityDefinition import eu.esdihumboldt.hale.common.core.report.SimpleLog import eu.esdihumboldt.hale.common.instance.extension.filter.FilterDefinitionManager import eu.esdihumboldt.hale.common.schema.SchemaSpaceID @@ -45,12 +45,12 @@ abstract class AbstractMigration implements AlignmentMigration { * @param preferRoot hint on which entity to prefer if there are multiple matches * @return the match if found */ - protected abstract Optional<EntityDefinition> findMatch(EntityDefinition entity, TypeDefinition preferRoot); + protected abstract Optional<EntityMatch> findMatch(EntityDefinition entity, TypeDefinition preferRoot); @Override - Optional<EntityDefinition> entityReplacement(EntityDefinition entity, TypeDefinition preferRoot, SimpleLog log) { + Optional<EntityMatch> entityReplacement(EntityDefinition entity, TypeDefinition preferRoot, SimpleLog log) { EntityDefinition defaultEntity = AlignmentUtil.getAllDefaultEntity(entity) - Optional<EntityDefinition> matchedEntity = findMatch(defaultEntity, preferRoot) + Optional<EntityMatch> matchedEntity = findMatch(defaultEntity, preferRoot) // special case handling if (!matchedEntity.isPresent()) { @@ -62,9 +62,6 @@ abstract class AbstractMigration implements AlignmentMigration { if (matchedEntity.present) { // entity contained contexts -> translate them if possible - - //XXX target was determined (matchedEntity), do we need to know about how the match was found, e.g. if it was a join? - matchedEntity = Optional.ofNullable(translateContexts(entity, matchedEntity.get(), this, preferRoot, log)); } @@ -75,14 +72,15 @@ abstract class AbstractMigration implements AlignmentMigration { return matchedEntity } - static EntityDefinition translateContexts(EntityDefinition original, EntityDefinition target, + static EntityMatch translateContexts(EntityDefinition original, EntityMatch target, AlignmentMigration migration, TypeDefinition preferRoot, SimpleLog log) { def defaultEntity = AlignmentUtil.getAllDefaultEntity(original) + def targetEntity = target.getMatch() if (original.filter) { // what about if match has filter? - if (target.filter && original.filter != target.filter) { + if (targetEntity.filter && original.filter != targetEntity.filter) { def filterString = FilterDefinitionManager.instance.asString(original.filter) def msg = "Filter condition applied to the original source type has been dropped because a filter already existed for the entity it was replaced with. Please check if you need to change the condition to match both original conditions." if (filterString) { @@ -94,18 +92,16 @@ abstract class AbstractMigration implements AlignmentMigration { // apply filter to entity def filter = original.filter - if (!sameEntity(original, target)) { + if (!sameEntity(original, targetEntity)) { // replacements in filter if possible if (filter instanceof EntityAwareFilter) { - // def migrated = ((EntityAwareFilter) filter).migrateFilter(AlignmentUtil.getTypeEntity(original), migration, preferRoot, log) - if (preferRoot == null) { - TypeEntityDefinition originalType = AlignmentUtil.getTypeEntity(original) - //FIXME if match for originalType is a Join and then set preferRoot to target type? + // set preferRoot to target type + // to restrict conditions to the type they may reference + preferRoot = targetEntity.type } - //FIXME for testing, replace preferRoot by target - def migrated = ((EntityAwareFilter) filter).migrateFilter(AlignmentUtil.getTypeEntity(original), migration, target.type, log) + def migrated = ((EntityAwareFilter) filter).migrateFilter(AlignmentUtil.getTypeEntity(original), target, migration, preferRoot, log) if (migrated.present) { filter = migrated.get() //TODO mark automatically migrated? @@ -122,17 +118,17 @@ abstract class AbstractMigration implements AlignmentMigration { } // add filter to match - target = AlignmentUtil.createEntity(target.type, target.propertyPath, + targetEntity = AlignmentUtil.createEntity(targetEntity.type, targetEntity.propertyPath, SchemaSpaceID.SOURCE, filter) } } if (original.propertyPath && original != defaultEntity) { // likely a context was present - target = applyContexts(target, original, log) + targetEntity = applyContexts(targetEntity, original, log) } - return target + return target.withMatch(targetEntity) } /** @@ -224,7 +220,7 @@ abstract class AbstractMigration implements AlignmentMigration { } } - protected Optional<EntityDefinition> findParentMatch(EntityDefinition entity, TypeDefinition preferRoot) { + protected Optional<EntityMatch> findParentMatch(EntityDefinition entity, TypeDefinition preferRoot) { //XXX only allow parent matches for specific cases right now if (!(entity.definition instanceof PropertyDefinition) || !((PropertyDefinition) entity.definition).propertyType.getConstraint(GeometryType).isGeometry()) { diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/MatchingMigration.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/MatchingMigration.groovy index 4847f9a3c0..d63bae6174 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/MatchingMigration.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge/src/eu/esdihumboldt/hale/common/align/merge/impl/MatchingMigration.groovy @@ -17,6 +17,7 @@ package eu.esdihumboldt.hale.common.align.merge.impl import java.util.function.Function +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch import eu.esdihumboldt.hale.common.align.model.AlignmentUtil import eu.esdihumboldt.hale.common.align.model.Cell import eu.esdihumboldt.hale.common.align.model.EntityDefinition @@ -43,26 +44,52 @@ class MatchingMigration extends AbstractMigration { } @Override - protected Optional<EntityDefinition> findMatch(EntityDefinition entity, TypeDefinition preferRoot) { + protected Optional<EntityMatch> findMatch(EntityDefinition entity, TypeDefinition preferRoot) { findMatches(entity).flatMap({ list -> - findPreferredCandidate((List<EntityDefinition>)list, preferRoot) + findPreferredCandidate((List<EntityDefinition>)list, entity, preferRoot) } as Function) } - private Optional<EntityDefinition> findPreferredCandidate(Collection<EntityDefinition> entities, TypeDefinition preferRoot) { + private Optional<EntityMatch> findPreferredCandidate(Collection<EntityDefinition> entities, EntityDefinition original, TypeDefinition preferRoot) { if (entities.empty) { return Optional.empty() } + boolean multiple = entities.size() > 1 + boolean join = false + + if (original.propertyPath.isEmpty()) { + // this is about a type entity + + /* + * Currently, because findMatches only considers cases where exactly one cell is present, + * we can assume that if there are multiple candidates that there is a join for the match. + */ + join = multiple + } + else { + // this is about a property entity + + /* + * For a property we need to determine if the respective type match is part of a join + * and use that information. + */ + def typeEntity = AlignmentUtil.getTypeEntity(original) + def typeMatch = findMatch(typeEntity, preferRoot) + if (typeMatch.isPresent()) { + join = typeMatch.get().matchPartOfJoin + } + } + + /* * Note: preferRoot is used here to for example pick a specific type from a Join cell's sources */ def firstPreferred = entities.find { EntityDefinition it -> it.type == preferRoot } - if (firstPreferred) { - Optional.of(firstPreferred) - } - else { - Optional.of(entities.iterator().next()) + def match = firstPreferred ? Optional.of(firstPreferred) : Optional.of(entities.iterator().next()) + + match.map { + new EntityMatch(it, multiple, join) } } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/instance/EntityAwareFilter.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/instance/EntityAwareFilter.java index ceea97bc43..17c0f56284 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/instance/EntityAwareFilter.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/instance/EntityAwareFilter.java @@ -19,6 +19,7 @@ import java.util.Optional; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.core.report.SimpleLog; import eu.esdihumboldt.hale.common.instance.model.Filter; @@ -43,7 +44,7 @@ public interface EntityAwareFilter extends Filter { /** * States if the filter supports migration via - * {@link #migrateFilter(EntityDefinition, AlignmentMigration, TypeDefinition, SimpleLog)} + * {@link #migrateFilter(EntityDefinition, EntityMatch, AlignmentMigration, TypeDefinition, SimpleLog)} * * @return <code>true</code> if migration is supported, <code>false</code> * otherwise @@ -55,13 +56,15 @@ public interface EntityAwareFilter extends Filter { * migration. * * @param context the entity context + * @param targetMatch the match representing the entity the filter is + * applied to * @param migration the alignment migration * @param preferRoot hint on which entity to prefer if there are multiple * matches * @param log the operation log * @return the migrated filter, if migration is possible */ - Optional<Filter> migrateFilter(EntityDefinition context, AlignmentMigration migration, - TypeDefinition preferRoot, SimpleLog log); + Optional<Filter> migrateFilter(EntityDefinition context, EntityMatch targetMatch, + AlignmentMigration migration, TypeDefinition preferRoot, SimpleLog log); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/AlignmentMigration.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/AlignmentMigration.java index ff37f622b4..52eee484bc 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/AlignmentMigration.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/AlignmentMigration.java @@ -35,7 +35,7 @@ public interface AlignmentMigration { * @param log the migration process log (may be cell specific) * @return the replacement entity, if the entity should be replaced */ - default Optional<EntityDefinition> entityReplacement(EntityDefinition entity, SimpleLog log) { + default Optional<EntityMatch> entityReplacement(EntityDefinition entity, SimpleLog log) { return entityReplacement(entity, null, log); } @@ -48,7 +48,7 @@ default Optional<EntityDefinition> entityReplacement(EntityDefinition entity, Si * @param log the migration process log (may be cell specific) * @return the replacement entity, if the entity should be replaced */ - Optional<EntityDefinition> entityReplacement(EntityDefinition entity, TypeDefinition preferRoot, + Optional<EntityMatch> entityReplacement(EntityDefinition entity, TypeDefinition preferRoot, SimpleLog log); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/EntityMatch.groovy b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/EntityMatch.groovy new file mode 100644 index 0000000000..e9d222601a --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/EntityMatch.groovy @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024 wetransform GmbH + * + * All rights reserved. This program and the accompanying materials are made + * available under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution. If not, see <http://www.gnu.org/licenses/>. + * + * Contributors: + * wetransform GmbH <http://www.wetransform.to> + */ + +package eu.esdihumboldt.hale.common.align.migrate + +import eu.esdihumboldt.hale.common.align.model.EntityDefinition +import groovy.transform.CompileStatic +import groovy.transform.Immutable + +/** + * Type representing an entity match in an alignment migration with additional information. + * + * @author Simon Templer + */ +@CompileStatic +@Immutable(knownImmutableClasses = [EntityDefinition.class]) +class EntityMatch { + EntityDefinition match + boolean multipleCandidates + boolean matchPartOfJoin + + /** + * Create a copy of the match replacing the matched entity. + * + * @param newMatch the entity to use as new match + * @return the copy of the match with the replaced entity + */ + EntityMatch withMatch(EntityDefinition newMatch) { + return new EntityMatch(newMatch, multipleCandidates, matchPartOfJoin) + } + + /** + * Create an entity match using the provided entity with default values assuming + * there is only this candidate and there is no join involved. + * + * @param match the entity to use for the match + * @return the entity match using the provided entity + */ + static EntityMatch of(EntityDefinition match) { + return new EntityMatch(match, false, false) + } +} diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/DefaultCellMigrator.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/DefaultCellMigrator.java index 2cee521a51..ea95417315 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/DefaultCellMigrator.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/DefaultCellMigrator.java @@ -25,6 +25,7 @@ import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; import eu.esdihumboldt.hale.common.align.migrate.CellMigrator; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.migrate.MigrationOptions; import eu.esdihumboldt.hale.common.align.model.Cell; import eu.esdihumboldt.hale.common.align.model.Entity; @@ -60,9 +61,9 @@ public MutableCell updateCell(final Cell originalCell, final AlignmentMigration public Entity transformEntry(String key, Entity value) { EntityDefinition org = value.getDefinition(); - Optional<EntityDefinition> replace = migration.entityReplacement(org, cellLog); + Optional<EntityMatch> replace = migration.entityReplacement(org, cellLog); - EntityDefinition entity = replace.orElse(org); + EntityDefinition entity = replace.map(m -> m.getMatch()).orElse(org); // FIXME what about null replacements / removals? if (!Objects.equal(entity, org)) { diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/UnmigratedCell.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/UnmigratedCell.java index 5bd1f0a3c0..2284ef999a 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/UnmigratedCell.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/migrate/impl/UnmigratedCell.java @@ -24,6 +24,7 @@ import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigrationNameLookupSupport; import eu.esdihumboldt.hale.common.align.migrate.CellMigrator; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.migrate.MigrationOptions; import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.align.model.MutableCell; @@ -82,9 +83,10 @@ public MutableCell migrate(Map<EntityDefinition, EntityDefinition> additionalMap AlignmentMigration migration = new AlignmentMigrationNameLookupSupport() { @Override - public Optional<EntityDefinition> entityReplacement(EntityDefinition entity, + public Optional<EntityMatch> entityReplacement(EntityDefinition entity, TypeDefinition preferRoot, SimpleLog log) { - return Optional.ofNullable(joinedMappings.get(entity)); + return Optional + .ofNullable(new EntityMatch(joinedMappings.get(entity), false, false)); } @Override diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/FormattedStringMigrator.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/FormattedStringMigrator.java index cf151635eb..b618cb21e9 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/FormattedStringMigrator.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/FormattedStringMigrator.java @@ -28,11 +28,11 @@ import com.google.common.collect.ListMultimap; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.migrate.MigrationOptions; import eu.esdihumboldt.hale.common.align.migrate.impl.DefaultCellMigrator; import eu.esdihumboldt.hale.common.align.model.Cell; import eu.esdihumboldt.hale.common.align.model.Entity; -import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.align.model.MutableCell; import eu.esdihumboldt.hale.common.align.model.ParameterValue; import eu.esdihumboldt.hale.common.align.model.annotations.messages.CellLog; @@ -85,8 +85,8 @@ private String convertPattern(String pattern, ListMultimap<String, ? extends Ent Map<String, Object> replacements = new HashMap<>(); for (PropertyEntityDefinition var : oldVars) { - Optional<EntityDefinition> replacement = migration.entityReplacement(var, log); - replacement.ifPresent(repl -> { + Optional<EntityMatch> replacement = migration.entityReplacement(var, log); + replacement.map(m -> m.getMatch()).ifPresent(repl -> { String newName = repl.getDefinition().getName().getLocalPart(); // XXX there might be name conflicts - check for those or use // long names? diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/join/JoinMigrator.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/join/JoinMigrator.java index 5d1cc10562..2e66689f40 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/join/JoinMigrator.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/join/JoinMigrator.java @@ -23,6 +23,7 @@ import com.google.common.collect.ListMultimap; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.migrate.MigrationOptions; import eu.esdihumboldt.hale.common.align.migrate.impl.DefaultCellMigrator; import eu.esdihumboldt.hale.common.align.model.Cell; @@ -80,14 +81,17 @@ private JoinParameter convertJoinParameter(JoinParameter joinParam, AlignmentMigration migration, MigrationOptions options, SimpleLog log) { List<TypeEntityDefinition> types = joinParam.getTypes().stream().map(type -> { - return (TypeEntityDefinition) migration.entityReplacement(type, log).orElse(type); + return (TypeEntityDefinition) migration.entityReplacement(type, log) + .map(EntityMatch::getMatch).orElse(type); }).collect(Collectors.toList()); Set<JoinCondition> conditions = joinParam.getConditions().stream().map(condition -> { PropertyEntityDefinition baseProperty = (PropertyEntityDefinition) migration - .entityReplacement(condition.baseProperty, log).orElse(condition.baseProperty); + .entityReplacement(condition.baseProperty, log).map(EntityMatch::getMatch) + .orElse(condition.baseProperty); PropertyEntityDefinition joinProperty = (PropertyEntityDefinition) migration - .entityReplacement(condition.joinProperty, log).orElse(condition.joinProperty); + .entityReplacement(condition.joinProperty, log).map(EntityMatch::getMatch) + .orElse(condition.joinProperty); JoinCondition result = new JoinCondition(baseProperty, joinProperty); return result; }).collect(Collectors.toSet()); diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/merge/MergeMigrator.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/merge/MergeMigrator.java index 706dfbe129..6157ebcbf0 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/merge/MergeMigrator.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/functions/merge/MergeMigrator.java @@ -27,6 +27,7 @@ import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigrationNameLookupSupport; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.migrate.MigrationOptions; import eu.esdihumboldt.hale.common.align.migrate.impl.DefaultCellMigrator; import eu.esdihumboldt.hale.common.align.model.Cell; @@ -106,7 +107,8 @@ private ParameterValue convertProperty(ParameterValue value, AlignmentMigration return value; } - Optional<EntityDefinition> replacement = migration.entityReplacement(entity, log); + Optional<EntityDefinition> replacement = migration.entityReplacement(entity, log) + .map(EntityMatch::getMatch); if (replacement.isPresent()) { return convertProperty(value, replacement.get(), log); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.filter/META-INF/MANIFEST.MF b/common/plugins/eu.esdihumboldt.hale.common.filter/META-INF/MANIFEST.MF index def593b6ad..9e3e50a3fa 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.filter/META-INF/MANIFEST.MF +++ b/common/plugins/eu.esdihumboldt.hale.common.filter/META-INF/MANIFEST.MF @@ -23,6 +23,7 @@ Export-Package: eu.esdihumboldt.hale.common.filter, eu.esdihumboldt.hale.common.filter.definition Require-Bundle: org.opengis;bundle-version="29.1.0", eu.esdihumboldt.util.groovy, - org.geotools;bundle-version="29.1.0" + org.geotools;bundle-version="29.1.0", + groovy;bundle-version="2.5.19" Bundle-Vendor: data harmonisation panel Automatic-Module-Name: eu.esdihumboldt.hale.common.filter diff --git a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java index fad0964202..c8c1e8d37d 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java +++ b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/AbstractGeotoolsFilter.java @@ -31,6 +31,7 @@ import org.geotools.util.factory.GeoTools; import org.opengis.filter.And; import org.opengis.filter.Filter; +import org.opengis.filter.Or; import org.opengis.filter.expression.PropertyName; import de.fhg.igd.slf4jplus.ALogger; @@ -40,6 +41,7 @@ import eu.esdihumboldt.hale.common.align.groovy.accessor.internal.EntityAccessorUtil; import eu.esdihumboldt.hale.common.align.instance.EntityAwareFilter; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.core.report.SimpleLog; import eu.esdihumboldt.hale.common.filter.internal.EntityReplacementVisitor; @@ -59,6 +61,10 @@ public abstract class AbstractGeotoolsFilter implements eu.esdihumboldt.hale.common.instance.model.Filter, EntityAwareFilter { + private static enum SplitType { + AND, OR + } + private static final ALogger log = ALoggerFactory.getLogger(AbstractGeotoolsFilter.class); private final String filterTerm; @@ -186,22 +192,18 @@ public List<Optional<EntityDefinition>> getReferencedEntities(EntityDefinition c @Override public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter( - EntityDefinition context, AlignmentMigration migration, TypeDefinition preferRoot, - SimpleLog log) { - // TODO pass in target entity or target type, so we can use that - // information to determine, if filter conditions actually apply - // XXX can preferRoot be used or do we need to differ due to Join? + EntityDefinition context, EntityMatch targetMatch, AlignmentMigration migration, + TypeDefinition preferRoot, SimpleLog log) { + // determine how to split filter + boolean join = targetMatch.isMatchPartOfJoin(); + SplitType splitType = join ? SplitType.AND : SplitType.OR; - // split filter (AND operands) - // TODO split based on different operand based on if there is a join or - // not - // FIXME what about properties related to a Join -> we want to drop the - // AND parts - how do we know the context is a join? - List<Filter> andParts = splitAnd(internFilter); + // split filter + List<Filter> filterParts = splitFilter(internFilter, splitType); // migrate each filter part List<Filter> acceptedParts = new ArrayList<>(); - for (Filter part : andParts) { + for (Filter part : filterParts) { EntityReplacementVisitor visitor = new EntityReplacementVisitor(migration, name -> resolveProperty(name, context, log), preferRoot, log); Object extraData = null; @@ -210,18 +212,19 @@ public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter /* * Determine if part is relevant. Only accept filter parts that are * not exclusively updated with other types than `preferRoot`. (This - * is used to handle the different types from a Join individually) + * is used to handle the different types from a Join individually, + * also for properties that are mapped in the same context) * * TODO is usage of preferRoot OK or should we have an additional * parameter to control this behavior? * - * Inform about parts that are dropped) + * Inform about parts that are dropped */ TypeDefinition focusType = preferRoot; String messagePrefix = (focusType == null) ? "" : focusType.getDisplayName() + ": "; if (visitor.isAllMismatches(focusType)) { // drop if there were no successful replacements at all - if (andParts.size() == 1) { + if (filterParts.size() == 1) { try { log.warn( "{0}The filter \"{1}\" was removed because no matches for the respective properties were found", @@ -235,12 +238,12 @@ public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter else { try { log.warn( - "{0}The filter operand \"{1}\" part of the filter''s AND condition was removed because no matches for the respective properties were found", - messagePrefix, toFilterTerm(part)); + "{0}The filter operand \"{1}\" part of the filter''s {2} condition was removed because no matches for the respective properties were found", + messagePrefix, toFilterTerm(part), splitType); } catch (CQLException e) { log.error( - "{0}A filter operand part of the filter's AND condition was removed because no matches for the respective properties were found; error converting filter part to string", - messagePrefix, e); + "{0}A filter operand part of the filter's {1} condition was removed because no matches for the respective properties were found; error converting filter part to string", + messagePrefix, splitType, e); } } } @@ -254,12 +257,13 @@ public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter if (!otherReplacements.isEmpty()) { try { log.warn( - "{0}The filter operand \"{1}\" part of the filter''s AND condition contains references related to other types than {2}", - messagePrefix, toFilterTerm(part), focusType.getDisplayName()); + "{0}The filter operand \"{1}\" part of the filter''s {3} condition contains references related to other types than {2}", + messagePrefix, toFilterTerm(part), focusType.getDisplayName(), + splitType); } catch (CQLException e) { log.error( - "{0}A filter operand part of the filter's AND condition contains references related to other types than {1}; error converting filter part to string", - messagePrefix, focusType.getDisplayName(), e); + "{0}A filter operand part of the filter's {2} condition contains references related to other types than {1}; error converting filter part to string", + messagePrefix, focusType.getDisplayName(), splitType, e); } } } @@ -271,8 +275,19 @@ public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter } // combine accepted filter parts - Filter combined = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()) - .and(acceptedParts); + Filter combined; + switch (splitType) { + case AND: + combined = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()) + .and(acceptedParts); + break; + case OR: + combined = CommonFactoryFinder.getFilterFactory2(GeoTools.getDefaultHints()) + .or(acceptedParts); + break; + default: + throw new IllegalStateException("Unsupported filter split type " + splitType); + } try { String filterString = toFilterTerm(combined); @@ -284,21 +299,25 @@ public Optional<eu.esdihumboldt.hale.common.instance.model.Filter> migrateFilter } /** - * Split a filter into separate AND conditions. + * Split a filter into separate AND or OR conditions. * * @param filter the filter to split + * @param splitType on which operation to split * @return the split filters as list */ - private List<Filter> splitAnd(Filter filter) { + private List<Filter> splitFilter(Filter filter, SplitType splitType) { List<Filter> result = new ArrayList<>(); Deque<Filter> toCheck = new LinkedList<>(); toCheck.add(filter); while (!toCheck.isEmpty()) { Filter f = toCheck.poll(); - if (f instanceof And) { + if (SplitType.AND.equals(splitType) && f instanceof And) { toCheck.addAll(((And) f).getChildren()); } + else if (SplitType.OR.equals(splitType) && f instanceof Or) { + toCheck.addAll(((Or) f).getChildren()); + } else { result.add(f); } diff --git a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/internal/EntityReplacementVisitor.java b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/internal/EntityReplacementVisitor.java index adff175940..18f99cbd94 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/internal/EntityReplacementVisitor.java +++ b/common/plugins/eu.esdihumboldt.hale.common.filter/src/eu/esdihumboldt/hale/common/filter/internal/EntityReplacementVisitor.java @@ -26,6 +26,7 @@ import org.opengis.filter.expression.PropertyName; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.model.AlignmentUtil; import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.core.report.SimpleLog; @@ -78,8 +79,8 @@ public Object visit(PropertyName expression, Object extraData) { if (resolved.isPresent()) { total++; - Optional<EntityDefinition> replace = migration.entityReplacement(resolved.get(), - preferRoot, log); + Optional<EntityDefinition> replace = migration + .entityReplacement(resolved.get(), preferRoot, log).map(EntityMatch::getMatch); if (replace.isPresent()) { matched++; replacements.add(replace.get()); @@ -143,7 +144,10 @@ public Set<EntityDefinition> getReplacements() { * were mismatches or matching entities with a different parent type. * * @param expectedParent the expected parent type - * @return + * @return <code>true</code> if related to the given expected parent type + * all replacement attempts were mismatches or matching entities + * with a different parent type, <code>false</code> if there were + * successful matches with the given parent type */ public boolean isAllMismatches(TypeDefinition expectedParent) { if (expectedParent == null) { diff --git a/ui/plugins/eu.esdihumboldt.hale.ui/src/eu/esdihumboldt/hale/ui/service/align/migrate/UserMigration.java b/ui/plugins/eu.esdihumboldt.hale.ui/src/eu/esdihumboldt/hale/ui/service/align/migrate/UserMigration.java index 1f42a8bbcf..f6f84f37b6 100644 --- a/ui/plugins/eu.esdihumboldt.hale.ui/src/eu/esdihumboldt/hale/ui/service/align/migrate/UserMigration.java +++ b/ui/plugins/eu.esdihumboldt.hale.ui/src/eu/esdihumboldt/hale/ui/service/align/migrate/UserMigration.java @@ -18,6 +18,7 @@ import java.util.Optional; import eu.esdihumboldt.hale.common.align.migrate.AlignmentMigration; +import eu.esdihumboldt.hale.common.align.migrate.EntityMatch; import eu.esdihumboldt.hale.common.align.model.EntityDefinition; import eu.esdihumboldt.hale.common.align.model.Property; import eu.esdihumboldt.hale.common.align.model.Type; @@ -54,7 +55,7 @@ public UserMigration(SchemaSpaceID schemaSpace) { } @Override - public Optional<EntityDefinition> entityReplacement(EntityDefinition entity, + public Optional<EntityMatch> entityReplacement(EntityDefinition entity, TypeDefinition preferRoot, SimpleLog log) { // use functionality from entity resolver @@ -62,14 +63,14 @@ public Optional<EntityDefinition> entityReplacement(EntityDefinition entity, EntityDefinition candidate = entity; Type type = UserFallbackEntityResolver.resolveType((TypeEntityDefinition) entity, candidate, schemaSpace); - return Optional.ofNullable(type).map(e -> e.getDefinition()); + return Optional.ofNullable(type).map(e -> EntityMatch.of(e.getDefinition())); } else if (entity instanceof PropertyEntityDefinition) { EntityDefinition candidate = entity; candidate = EntityCandidates.find((PropertyEntityDefinition) entity); Property property = UserFallbackEntityResolver .resolveProperty((PropertyEntityDefinition) entity, candidate, schemaSpace); - return Optional.ofNullable(property).map(e -> e.getDefinition()); + return Optional.ofNullable(property).map(e -> EntityMatch.of(e.getDefinition())); } else { log.error("Unrecognised entity type: " + entity.getClass()); From 90ba5bf56140586716956e056761746a614c55de Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Wed, 13 Mar 2024 11:16:10 +0100 Subject: [PATCH 11/13] WIP fix tests --- .../impl/DefaultMergeCellMigratorTest.groovy | 171 ++++++- .../type-filter-props-mapped/A-to-B.halex | 27 ++ .../A-to-B.halex.alignment.xml | 422 ++++++++++++++++++ .../A-to-B.halex.styles.sld | 3 + .../type-filter-props-mapped/A.groovy | 36 ++ .../type-filter-props-mapped/B-to-C.halex | 27 ++ .../B-to-C.halex.alignment.xml | 190 ++++++++ .../B-to-C.halex.styles.sld | 3 + .../type-filter-props-mapped/B.groovy | 43 ++ .../type-filter-props-mapped/C.groovy | 43 ++ 10 files changed, 955 insertions(+), 10 deletions(-) create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex.alignment.xml create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex.styles.sld create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A.groovy create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex.alignment.xml create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex.styles.sld create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B.groovy create mode 100644 common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/C.groovy diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy index 4794bd0c6f..9416cd71bd 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/src/eu/esdihumboldt/hale/common/align/merge/test/impl/DefaultMergeCellMigratorTest.groovy @@ -446,6 +446,16 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { assertEquals(expectedFilter, filter.filterTerm) } + @CompileStatic(TypeCheckingMode.SKIP) + private void typeFilterCheck(Cell migrated, String expectedFilter) { + JaxbAlignmentIO.printCell(migrated, System.out) + + // the condition should be present on the source + def source = CellUtil.getFirstEntity(migrated.source).definition + assertNotNull(source.filter) + assertEquals(expectedFilter, source.filter.filterTerm) + } + @CompileStatic(TypeCheckingMode.SKIP) private void filterCheckNull(Cell migrated) { JaxbAlignmentIO.printCell(migrated, System.out) @@ -493,7 +503,6 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { assertEquals(1, migrated.size()) // filter is now dropped (because bb is not mapped for B2) filterCheckNull(migrated[0]) - // filterCheck(migrated[0], "bb = 'test'") // the filter should be retained // there should be a message about the condition def messages = getMigrationMessages(migrated[0]) @@ -506,7 +515,28 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { } @Test - @CompileStatic(TypeCheckingMode.SKIP) + void testTypeFilter2Present() { + def toMigrate = this.class.getResource('/testcases/type-filter-props-mapped/B-to-C.halex') + def cellId = 'B2-C2' // Retype + + def matching = this.class.getResource('/testcases/type-filter-props-mapped/A-to-B.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + + // filter + assertEquals(1, migrated.size()) + filterCheck(migrated[0], "ab = 'test'") + + // there should be a message about the condition + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) + } + + @Test void testTypeFilter2Property() { def toMigrate = this.class.getResource('/testcases/type-filter/B-to-C.halex') def cellId = 'B2C2a' // Rename @@ -517,11 +547,34 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { // do checks - // type filter should be retained - def source = CellUtil.getFirstEntity(migrated[0].source).definition - def filter = source.filter - assertNotNull(filter) - assertEquals("bb = 'test'", filter.filterTerm) + // filter is now dropped (because bb is not mapped for B2) + assertEquals(1, migrated.size()) + filterCheckNull(migrated[0]) + + // there should be a message about the condition + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('removed because no matches') + }) + } + + @Test + void testTypeFilter2PropertyPresent() { + def toMigrate = this.class.getResource('/testcases/type-filter-props-mapped/B-to-C.halex') + def cellId = 'B2C2a' // Rename + + def matching = this.class.getResource('/testcases/type-filter-props-mapped/A-to-B.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + + // filter + assertEquals(1, migrated.size()) + typeFilterCheck(migrated[0], "ab = 'test'") // there should be a message about the condition def messages = getMigrationMessages(migrated[0]) @@ -541,9 +594,34 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { // do checks + // filter is now dropped (because bc is not mapped for B3) + assertEquals(1, migrated.size()) + filterCheckNull(migrated[0]) + + // there should be a message about the condition + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('removed because no matches') + }) + } + + @Test + void testTypeFilter3Present() { + def toMigrate = this.class.getResource('/testcases/type-filter-props-mapped/B-to-C.halex') + def cellId = 'B3-C3' // Merge + + def matching = this.class.getResource('/testcases/type-filter-props-mapped/A-to-B.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + // filter assertEquals(1, migrated.size()) - filterCheck(migrated[0], "bc = 'test'") + filterCheck(migrated[0], "ac = 'test'") // there should be a message about the condition def messages = getMigrationMessages(migrated[0]) @@ -587,6 +665,46 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { // do checks + // filter + assertEquals(1, migrated.size()) + JaxbAlignmentIO.printCell(migrated[0], System.out) + // expect filters to be present on A5 source + assertNotNull(migrated[0].source) + assertEquals(2, migrated[0].source.size()) + Collection<? extends Entity> source = migrated[0].source.values() + ((Collection<Entity>) source).each { e -> + def filter = e.definition.filter + if (e.definition.definition.name.localPart == 'A5') { + // filter is now dropped (because ba and bb are not mapped for B5) + assertNull(filter) + } + else { + assertNull(filter) + } + } + + // there should be a message about the conditions being dropped + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('removed because no matches') + }) + } + + @CompileStatic(TypeCheckingMode.SKIP) + @Test + void testTypeFilter5Present() { + def toMigrate = this.class.getResource('/testcases/type-filter-props-mapped/B-to-C.halex') + def cellId = 'Join' // Join + + def matching = this.class.getResource('/testcases/type-filter-props-mapped/A-to-B.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + // filter assertEquals(1, migrated.size()) JaxbAlignmentIO.printCell(migrated[0], System.out) @@ -598,8 +716,8 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { def filter = e.definition.filter if (e.definition.definition.name.localPart == 'A5') { assertNotNull(filter) - // assertEquals('ba = \'test\' AND NOT (bb = \'test\')', filter.filterTerm) - assertEquals('ba = \'test\' and bb <> \'test\'', filter.filterTerm) + assertEquals('(aa = \'test\' AND NOT (ab = \'test\'))', filter.filterTerm) + // assertEquals('aa = \'test\' and ab <> \'test\'', filter.filterTerm) } else { assertNull(filter) @@ -624,6 +742,39 @@ class DefaultMergeCellMigratorTest extends AbstractMergeCellMigratorTest { // do checks + // filter + assertEquals(1, migrated.size()) + JaxbAlignmentIO.printCell(migrated[0], System.out) + // expect filters to be present on both sources + assertNotNull(migrated[0].source) + assertEquals(2, migrated[0].source.size()) + Collection<? extends Entity> source = migrated[0].source.values() + ((Collection<Entity>) source).each { e -> + def filter = e.definition.filter + assertNull(filter) + } + + // there should be a message about the conditions being dropped + def messages = getMigrationMessages(migrated[0]) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('condition') + }) + assertTrue(messages.any { msg -> + msg.text.toLowerCase().contains('removed because no matches') + }) + } + + @Test + void testTypeFilter6Present() { + def toMigrate = this.class.getResource('/testcases/type-filter-props-mapped/B-to-C.halex') + def cellId = 'GJoin' // Groovy Join + + def matching = this.class.getResource('/testcases/type-filter-props-mapped/A-to-B.halex') + + def migrated = merge(cellId, toMigrate, matching) + + // do checks + // filter assertEquals(1, migrated.size()) JaxbAlignmentIO.printCell(migrated[0], System.out) diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex new file mode 100644 index 0000000000..600daa4e90 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<hale-project version="5.2.0.qualifier"> + <name>A to B (matching)</name> + <author>Simon Templer</author> + <created>2018-01-10T16:17:32.757+01:00</created> + <modified>2024-03-13T10:56:32.007+01:00</modified> + <save-config action-id="project.save" provider-id="eu.esdihumboldt.hale.io.project.hale25.xml.writer"> + <setting name="charset">UTF-8</setting> + <setting name="projectFiles.separate">false</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.project.hale25.xml</setting> + <setting name="target">file:/home/simon/repos/hale/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex</setting> + </save-config> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.source" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">6534b899-7ef3-4ead-8e4f-9af3af16f030</setting> + <setting name="source">A.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.target" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">67afcd12-5dd4-4adc-ab52-042786a4b3af</setting> + <setting name="source">B.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <file name="alignment.xml" location="A-to-B.halex.alignment.xml"/> + <file name="styles.sld" location="A-to-B.halex.styles.sld"/> +</hale-project> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex.alignment.xml b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex.alignment.xml new file mode 100644 index 0000000000..386c1e1f5b --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex.alignment.xml @@ -0,0 +1,422 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<alignment xmlns="http://www.esdi-humboldt.eu/hale/alignment"> + <cell relation="eu.esdihumboldt.hale.align.retype" id="Cf7686d9a-bb20-4379-af80-0e1c97973d12" priority="normal"> + <source> + <class> + <type name="A1" ns="A"/> + </class> + </source> + <target> + <class> + <type name="B1" ns="B"/> + </class> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="Cfbb81893-6860-4c32-9819-11e3036a212e" priority="normal"> + <source> + <property> + <type name="A1" ns="A"/> + <child name="aa" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B1" ns="B"/> + <child name="ba" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + <documentation>Notes from match</documentation> + </cell> + <cell relation="eu.esdihumboldt.cst.functions.groovy" id="Caed2942c-b8ee-40c8-ac31-e58a433d5e2a" priority="normal"> + <source name="var"> + <property> + <type name="A1" ns="A"/> + <child name="ab" ns="A"/> + </property> + </source> + <target name="result"> + <property> + <type name="B1" ns="B"/> + <child name="bb" ns="B"/> + </property> + </target> + <complexParameter name="script"> + <core:text xmlns:core="http://www.esdi-humboldt.eu/hale/core" xml:space="preserve">ab + 'ist doof'</core:text> + </complexParameter> + <parameter value="false" name="variablesAsInstances"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C4ee1954f-e373-4dde-b54e-9e13b5865984" priority="normal"> + <source> + <property> + <type name="A1" ns="A"/> + <child name="ac" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B1" ns="B"/> + <child name="bc" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C65d966ef-02b9-4867-924b-699bda8cd50f" priority="normal"> + <source> + <property> + <type name="A1" ns="A"/> + <child name="ad" ns="A"> + <condition lang="CQL">value = 'green lantern'</condition> + </child> + </property> + </source> + <target> + <property> + <type name="B1" ns="B"/> + <child name="bd" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.cst.functions.groovy.retype" id="C4b534860-3b4f-4a21-a629-eaae9f5723b8" priority="normal"> + <source> + <class> + <type name="A2" ns="A"/> + </class> + </source> + <target> + <class> + <type name="B2" ns="B"/> + </class> + </target> + <complexParameter name="script"> + <core:text xmlns:core="http://www.esdi-humboldt.eu/hale/core" xml:space="preserve"> +_target { +} +</core:text> + </complexParameter> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C5e180246-7d8f-487b-bb16-98d113c363f3" priority="normal"> + <source> + <property> + <type name="A2" ns="A"/> + <child name="aa" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B2" ns="B"/> + <child name="ba" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="Ca9b31be4-01ca-4d2d-b8d1-170320ff487e" priority="normal"> + <source> + <property> + <type name="A2" ns="A"/> + <child name="ab" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B2" ns="B"/> + <child name="bb" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="Cfea966bc-0b98-45fd-aea1-b48dc86e32df" priority="normal"> + <source> + <property> + <type name="A2" ns="A"/> + <child name="ac" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B2" ns="B"/> + <child name="bc" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="Ce4961fc4-f0c4-4d4f-be47-11cd2bf564a6" priority="normal"> + <source> + <property> + <type name="A2" ns="A"/> + <child name="ad" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B2" ns="B"/> + <child name="bd" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.cst.functions.groovy.merge" id="C9d1e6f1f-d6e7-4a3f-b1e9-10e8ebf848db" priority="normal"> + <source> + <class> + <type name="A3" ns="A"/> + </class> + </source> + <target> + <class> + <type name="B3" ns="B"/> + </class> + </target> + <parameter value="{A}ac" name="additional_property"/> + <parameter value="false" name="auto_detect"/> + <parameter value="{A}aa" name="property"/> + <complexParameter name="script"> + <core:text xmlns:core="http://www.esdi-humboldt.eu/hale/core" xml:space="preserve"> +_target { +} +</core:text> + </complexParameter> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C15932119-ea58-41ab-9710-c1c35b89659a" priority="normal"> + <source> + <property> + <type name="A3" ns="A"/> + <child name="aa" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B3" ns="B"/> + <child name="ba" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C24e030f2-3d15-48f6-8d95-adf44d05fcca" priority="normal"> + <source> + <property> + <type name="A3" ns="A"/> + <child name="ab" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B3" ns="B"/> + <child name="bb" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="Cad8e6c27-7fc0-47dc-81ea-d93aaa21d11a" priority="normal"> + <source> + <property> + <type name="A3" ns="A"/> + <child name="ac" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B3" ns="B"/> + <child name="bc" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C0c3c5c99-5f32-4181-a945-1a0e126413b2" priority="normal"> + <source> + <property> + <type name="A3" ns="A"/> + <child name="ad" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B3" ns="B"/> + <child name="bd" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.cst.functions.groovy.create" id="C152e75fb-dfee-4fc8-be6b-bbe815be4efa" priority="normal"> + <target> + <class> + <type name="B4" ns="B"/> + </class> + </target> + <complexParameter name="script"> + <core:text xmlns:core="http://www.esdi-humboldt.eu/hale/core" xml:space="preserve"> +_target { +} +</core:text> + </complexParameter> + </cell> + <cell relation="eu.esdihumboldt.hale.align.retype" id="C0b890e00-fea3-4172-a3ba-b36873e98b64" priority="normal"> + <source> + <class> + <type name="A5" ns="A"/> + </class> + </source> + <target> + <class> + <type name="B5" ns="B"/> + </class> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C870abb59-cc8f-4578-bb17-98b71478e0aa" priority="normal"> + <source> + <property> + <type name="A5" ns="A"/> + <child name="aa" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B5" ns="B"/> + <child name="ba" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C743ed0c2-3aa8-4161-aaa1-7a8c10b9a7a5" priority="normal"> + <source> + <property> + <type name="A5" ns="A"/> + <child name="ab" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B5" ns="B"/> + <child name="bb" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="Cfa4549d1-b263-48dc-bc36-abf4bd0bf9f8" priority="normal"> + <source> + <property> + <type name="A5" ns="A"/> + <child name="ac" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B5" ns="B"/> + <child name="bc" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="Cbfd0ace3-6c89-47c0-9d55-ac2560a28d34" priority="normal"> + <source> + <property> + <type name="A5" ns="A"/> + <child name="ad" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B5" ns="B"/> + <child name="bd" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.retype" id="C673337ac-a66b-4918-b924-d1518314d09e" priority="normal"> + <source> + <class> + <type name="A6" ns="A"/> + </class> + </source> + <target> + <class> + <type name="B6" ns="B"/> + </class> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C6502f0c5-95d6-4aa4-b522-2d3f87975e75" priority="normal"> + <source> + <property> + <type name="A6" ns="A"/> + <child name="aa" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B6" ns="B"/> + <child name="ba" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C724efad0-65ab-4b17-9106-9929f11f3c8c" priority="normal"> + <source> + <property> + <type name="A6" ns="A"/> + <child name="ab" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B6" ns="B"/> + <child name="bb" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C33296870-ac93-4224-95ea-6c7b9fd27fb6" priority="normal"> + <source> + <property> + <type name="A6" ns="A"/> + <child name="ac" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B6" ns="B"/> + <child name="bc" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="C1fb210bb-4d69-4119-a382-48414a7dd106" priority="normal"> + <source> + <property> + <type name="A6" ns="A"/> + <child name="ad" ns="A"/> + </property> + </source> + <target> + <property> + <type name="B6" ns="B"/> + <child name="bd" ns="B"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> +</alignment> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex.styles.sld b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex.styles.sld new file mode 100644 index 0000000000..ad34f540f6 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A-to-B.halex.styles.sld @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?><sld:UserStyle xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> + <sld:Name>Default Styler</sld:Name> +</sld:UserStyle> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A.groovy new file mode 100644 index 0000000000..ed44fadde7 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/A.groovy @@ -0,0 +1,36 @@ +schema('A') { + A1 { + aa() + ab() + ac() + ad() + } + + A2 { + aa() + ab() + ac() + ad() + } + + A3 { + aa() + ab() + ac() + ad() + } + + A5 { + aa() + ab() + ac() + ad() + } + + A6 { + aa() + ab() + ac() + ad() + } +} \ No newline at end of file diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex new file mode 100644 index 0000000000..b64bd20f0f --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex @@ -0,0 +1,27 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<hale-project version="5.2.0.qualifier"> + <name>B to C (to be migrated)</name> + <author>Simon Templer</author> + <created>2018-01-10T16:26:35.275+01:00</created> + <modified>2024-03-13T10:57:03.028+01:00</modified> + <save-config action-id="project.save" provider-id="eu.esdihumboldt.hale.io.project.hale25.xml.writer"> + <setting name="charset">UTF-8</setting> + <setting name="projectFiles.separate">false</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.project.hale25.xml</setting> + <setting name="target">file:/home/simon/repos/hale/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex</setting> + </save-config> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.source" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">bafa16f0-75ed-44e3-a0ed-10e5410d044d</setting> + <setting name="source">B.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <resource action-id="eu.esdihumboldt.hale.io.schema.read.target" provider-id="eu.esdihumboldt.hale.io.schemabuilder"> + <setting name="charset">UTF-8</setting> + <setting name="resourceId">e13b67b2-8b9a-45eb-b812-c8c675028b48</setting> + <setting name="source">C.groovy</setting> + <setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting> + </resource> + <file name="alignment.xml" location="B-to-C.halex.alignment.xml"/> + <file name="styles.sld" location="B-to-C.halex.styles.sld"/> +</hale-project> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex.alignment.xml b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex.alignment.xml new file mode 100644 index 0000000000..75a706d161 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex.alignment.xml @@ -0,0 +1,190 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?> +<alignment xmlns="http://www.esdi-humboldt.eu/hale/alignment"> + <cell relation="eu.esdihumboldt.cst.functions.groovy.retype" id="B1-C1" priority="normal"> + <source> + <class> + <type name="B1" ns="B"> + <condition lang="CQL">ba = 'test'</condition> + </type> + </class> + </source> + <target> + <class> + <type name="C1" ns="C"/> + </class> + </target> + <complexParameter name="script"> + <core:text xmlns:core="http://www.esdi-humboldt.eu/hale/core" xml:space="preserve"> +_target { +} +</core:text> + </complexParameter> + <documentation>B1 to C1</documentation> + </cell> + <cell relation="eu.esdihumboldt.hale.align.retype" id="B2-C2" priority="normal"> + <source> + <class> + <type name="B2" ns="B"> + <condition lang="CQL">bb = 'test'</condition> + </type> + </class> + </source> + <target> + <class> + <type name="C2" ns="C"/> + </class> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + <documentation>B2 to C2</documentation> + </cell> + <cell relation="eu.esdihumboldt.hale.align.rename" id="B2C2a" priority="normal"> + <source> + <property> + <type name="B2" ns="B"> + <condition lang="CQL">bb = 'test'</condition> + </type> + <child name="ba" ns="B"/> + </property> + </source> + <target> + <property> + <type name="C2" ns="C"/> + <child name="ca" ns="C"/> + </property> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.merge" id="B3-C3" priority="normal"> + <source> + <class> + <type name="B3" ns="B"> + <condition lang="CQL">bc = 'test'</condition> + </type> + </class> + </source> + <target> + <class> + <type name="C3" ns="C"/> + </class> + </target> + <parameter value="false" name="auto_detect"/> + <parameter value="{B}bc" name="property"/> + </cell> + <cell relation="eu.esdihumboldt.hale.align.retype" id="B4-C4" priority="normal"> + <source> + <class> + <type name="B4" ns="B"> + <condition lang="CQL">bd = 'test'</condition> + </type> + </class> + </source> + <target> + <class> + <type name="C4" ns="C"/> + </class> + </target> + <parameter value="false" name="ignoreNamespaces"/> + <parameter value="false" name="structuralRename"/> + <documentation>B4 to C4</documentation> + </cell> + <cell relation="eu.esdihumboldt.cst.functions.groovy.join" id="GJoin" priority="normal"> + <source name="types"> + <class> + <type name="B5" ns="B"> + <condition lang="CQL">ba = 'test' and bb <> 'test'</condition> + </type> + </class> + </source> + <source name="types"> + <class> + <type name="B6" ns="B"> + <condition lang="CQL">bc = 'test' and bd <> 'test'</condition> + </type> + </class> + </source> + <target> + <class> + <type name="C5" ns="C"/> + </class> + </target> + <complexParameter name="join"> + <jp:join-parameter xmlns:jp="http://www.esdi-humboldt.eu/hale/join"> + <class> + <type name="B5" ns="B"> + <condition lang="CQL">ba = 'test' and bb <> 'test'</condition> + </type> + </class> + <class> + <type name="B6" ns="B"> + <condition lang="CQL">bc = 'test' and bd <> 'test'</condition> + </type> + </class> + <jp:condition> + <property> + <type name="B5" ns="B"> + <condition lang="CQL">ba = 'test' and bb <> 'test'</condition> + </type> + <child name="ba" ns="B"/> + </property> + <property> + <type name="B6" ns="B"> + <condition lang="CQL">bc = 'test' and bd <> 'test'</condition> + </type> + <child name="ba" ns="B"/> + </property> + </jp:condition> + </jp:join-parameter> + </complexParameter> + <complexParameter name="script"> + <core:text xmlns:core="http://www.esdi-humboldt.eu/hale/core" xml:space="preserve"> +_target { +} +</core:text> + </complexParameter> + </cell> + <cell relation="eu.esdihumboldt.hale.align.join" id="Join" priority="normal"> + <source name="types"> + <class> + <type name="B5" ns="B"> + <condition lang="CQL">ba = 'test' and bb <> 'test'</condition> + </type> + </class> + </source> + <source name="types"> + <class> + <type name="B6" ns="B"/> + </class> + </source> + <target> + <class> + <type name="C6" ns="C"/> + </class> + </target> + <complexParameter name="join"> + <jp:join-parameter xmlns:jp="http://www.esdi-humboldt.eu/hale/join"> + <class> + <type name="B5" ns="B"> + <condition lang="CQL">ba = 'test' and bb <> 'test'</condition> + </type> + </class> + <class> + <type name="B6" ns="B"/> + </class> + <jp:condition> + <property> + <type name="B5" ns="B"> + <condition lang="CQL">ba = 'test' and bb <> 'test'</condition> + </type> + <child name="bb" ns="B"/> + </property> + <property> + <type name="B6" ns="B"/> + <child name="bb" ns="B"/> + </property> + </jp:condition> + </jp:join-parameter> + </complexParameter> + </cell> +</alignment> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex.styles.sld b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex.styles.sld new file mode 100644 index 0000000000..ad34f540f6 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B-to-C.halex.styles.sld @@ -0,0 +1,3 @@ +<?xml version="1.0" encoding="UTF-8"?><sld:UserStyle xmlns="http://www.opengis.net/sld" xmlns:sld="http://www.opengis.net/sld" xmlns:gml="http://www.opengis.net/gml" xmlns:ogc="http://www.opengis.net/ogc"> + <sld:Name>Default Styler</sld:Name> +</sld:UserStyle> diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B.groovy new file mode 100644 index 0000000000..eac2f7358d --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/B.groovy @@ -0,0 +1,43 @@ +schema('B') { + B1 { + ba() + bb() + bc() + bd() + } + + B2 { + ba() + bb() + bc() + bd() + } + + B3 { + ba() + bb() + bc() + bd() + } + + B4 { + ba() + bb() + bc() + bd() + } + + B5 { + ba() + bb() + bc() + bd() + } + + B6 { + ba() + bb() + bc() + bd() + } +} \ No newline at end of file diff --git a/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/C.groovy b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/C.groovy new file mode 100644 index 0000000000..529a699424 --- /dev/null +++ b/common/plugins/eu.esdihumboldt.hale.common.align.merge.test/testcases/type-filter-props-mapped/C.groovy @@ -0,0 +1,43 @@ +schema('C') { + C1 { + ca() + cb() + cc() + cd() + } + + C2 { + ca() + cb() + cc() + cd() + } + + C3 { + ca() + cb() + cc() + cd() + } + + C4 { + ca() + cb() + cc() + cd() + } + + C5 { + ca() + cb() + cc() + cd() + } + + C6 { + ca() + cb() + cc() + cd() + } +} \ No newline at end of file From 0e0ccd88579234fd74951350b5d4473514858757 Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Wed, 13 Mar 2024 11:52:48 +0100 Subject: [PATCH 12/13] fixup! build(deps): update equinox-test update site --- platform/hale-platform.target | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platform/hale-platform.target b/platform/hale-platform.target index 287d3591f2..ef157877aa 100644 --- a/platform/hale-platform.target +++ b/platform/hale-platform.target @@ -52,8 +52,8 @@ <unit id="eu.esdihumboldt.hale.platform.feature.group" version="5.0.0.i20240220"/> </location> <location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit"> - <repository location="http://build-artifacts.wetransform.to/p2/equinox-test/1.2.0.20240312"/> - <unit id="de.fhg.igd.equinox.test.feature.feature.group" version="1.2.0.202403121501"/> + <repository location="http://build-artifacts.wetransform.to/p2/equinox-test/96b3ede3cee11a98a1290edc330e421bb6ae2c86"/> + <unit id="de.fhg.igd.equinox.test.feature.feature.group" version="1.2.0.202403131049"/> </location> </locations> </target> \ No newline at end of file From ac5662e7e6e9ed2b1f3b436b40d1a05e45e04d97 Mon Sep 17 00:00:00 2001 From: Simon Templer <simon@wetransform.to> Date: Wed, 13 Mar 2024 15:36:48 +0100 Subject: [PATCH 13/13] fix: allow filtering for joins ...when selecting a source type in the alignment view. Before no results would be shown because the internal check expects all types to match while in the view only one can be specified. --- .../align/model/impl/DefaultAlignment.java | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/impl/DefaultAlignment.java b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/impl/DefaultAlignment.java index 1c04a450be..d41590778f 100644 --- a/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/impl/DefaultAlignment.java +++ b/common/plugins/eu.esdihumboldt.hale.common.align/src/eu/esdihumboldt/hale/common/align/model/impl/DefaultAlignment.java @@ -419,9 +419,32 @@ public Collection<? extends Cell> getTypeCells(Cell queryCell) { .getDefinition().getType(); if (target == null || DefinitionUtil.isSuperType(target, typeCellTarget)) { // target matches - if (sources.isEmpty() || matchesSources(typeCell.getSource(), sources)) { - // source matches, too - result.add(typeCell); + + if (sources.size() == 1) { + /* + * Special case handling when there is exactly one type, + * that in this case also allows to find a Join that only + * uses one of the types. + * + * Unclear if this is intended, but the else case does not + * yield any results in such cases, which could be due to + * the implementation of `matchesSources` in that case being + * focused on property relations. + */ + TypeEntityDefinition type = sources.iterator().next(); + if (sources.isEmpty() || matchesSources(type, + typeCell.getSource().values().stream() + .map(e -> AlignmentUtil.getTypeEntity(e.getDefinition())) + .toList())) { + // source matches, too + result.add(typeCell); + } + } + else { + if (sources.isEmpty() || matchesSources(typeCell.getSource(), sources)) { + // source matches, too + result.add(typeCell); + } } } }