Skip to content

Commit

Permalink
WIP inner join 2
Browse files Browse the repository at this point in the history
  • Loading branch information
stempler committed Feb 7, 2024
1 parent c6e943c commit 9fb0cc4
Show file tree
Hide file tree
Showing 30 changed files with 867 additions and 12 deletions.
18 changes: 18 additions & 0 deletions common/plugins/eu.esdihumboldt.hale.common.align/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -375,6 +375,24 @@
<parameterBinding>
</parameterBinding>
</functionParameter>
<functionParameter
deprecated="false"
description="If enabled a result is created only if all Join conditions are met"
label="Inner Join"
maxOccurrence="1"
minOccurrence="0"
name="innerJoin"
scriptable="false">
<parameterBinding
class="java.lang.Boolean">
</parameterBinding>
<valueDescriptor
default="false"
defaultDescription="Default behavior is that a result is created for every instance of the Join&apos;s focus type"
sample="true"
sampleDescription="Only create a result from the Join if there are linked instances for all Join conditions">
</valueDescriptor>
</functionParameter>
</typeFunction>
<propertyFunction
category="eu.esdihumboldt.hale.align.general"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,19 @@ protected String getExplanation(Cell cell, boolean html, ServiceProvider service
}
sb.append('\n');

// inner join

boolean innerJoin = CellUtil.getFirstParameter(cell, PARAMETER_INNER_JOIN)
.as(Boolean.class, false);
if (innerJoin) {
sb.append(getMessage("innerjoin", locale));
}
else {
sb.append(MessageFormat.format(getMessage("leftjoin", locale),
formatEntity(join.getTypes().get(0), html, false, locale)));
}
sb.append("\n\n");

// finalize

String explanation = sb.toString();
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
main=Joins the types {0} based on the following conditions:
innerjoin=The transformation is only done for instances where all of the conditions are met.
leftjoin=The transformation is done for every instance of type {0}, regardless which join conditions are met.
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
main=Führt Objekte der Objektarten {0} unter folgenden Bedingungen zusammen:
innerjoin=Die Transformation wird nur für Objekte ausgeführt, für die alle Bedingungen erfüllt sind.
leftjoin=Die Transformation wird für alle Objekte vom Typ {0} ausgeführt, unabhängig davon welche Bedingungen erfüllt werden.
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public ResourceIterator<FamilyInstance> partitionInstances(InstanceCollection in
String transformationIdentifier, TransformationEngine engine,
ListMultimap<String, ParameterValue> transformationParameters,
Map<String, String> executionParameters, TransformationLog log)
throws TransformationException {
throws TransformationException {

if (transformationParameters == null
|| !transformationParameters.containsKey(PARAMETER_JOIN)
Expand Down Expand Up @@ -122,7 +122,13 @@ public ResourceIterator<FamilyInstance> partitionInstances(InstanceCollection in
}
}

return new IndexJoinIterator(startInstances, joinDefinition, indexService);
boolean innerJoin = false; // default to false if not specified
List<ParameterValue> innerJoinValues = transformationParameters.get(PARAMETER_INNER_JOIN);
if (!innerJoinValues.isEmpty()) {
innerJoin = innerJoinValues.get(0).as(Boolean.class, innerJoin);
}

return new IndexJoinIterator(startInstances, joinDefinition, indexService, innerJoin);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,46 +36,51 @@
import eu.esdihumboldt.hale.common.instance.index.InstanceIndexService;
import eu.esdihumboldt.hale.common.instance.model.FamilyInstance;
import eu.esdihumboldt.hale.common.instance.model.ResolvableInstanceReference;
import eu.esdihumboldt.hale.common.instance.model.impl.GenericResourceIteratorAdapter;
import eu.esdihumboldt.hale.common.instance.model.impl.FilterResourceIteratorAdapter;

/**
* Iterator used by {@link IndexJoinHandler}
*
* @author Florian Esser
*/
class IndexJoinIterator
extends GenericResourceIteratorAdapter<ResolvableInstanceReference, FamilyInstance> {
extends FilterResourceIteratorAdapter<ResolvableInstanceReference, FamilyInstance> {

private final JoinDefinition joinDefinition;
private final InstanceIndexService index;

private final boolean innerJoin;

protected IndexJoinIterator(Collection<ResolvableInstanceReference> startInstances,
JoinDefinition joinDefinition, InstanceIndexService index) {
JoinDefinition joinDefinition, InstanceIndexService index, boolean innerJoin) {
super(startInstances.iterator());
this.joinDefinition = joinDefinition;
this.index = index;
this.innerJoin = innerJoin;
}

/**
* @see eu.esdihumboldt.hale.common.instance.model.impl.GenericResourceIteratorAdapter#convert(java.lang.Object)
*/
@Override
protected FamilyInstance convert(ResolvableInstanceReference next) {
FamilyInstance base = new FamilyInstanceImpl(next.resolve());
base.getId();
FamilyInstance[] currentInstances = new FamilyInstance[joinDefinition.directParent.length];
currentInstances[0] = base;

join(currentInstances, 0);
if (!join(currentInstances, 0)) {
// skip this instance
return null;
}

return base;
}

/**
* Joins all direct children of the given type to currentInstances.
*
* @return if the instance should be skipped
*/
@SuppressWarnings("javadoc")
private void join(FamilyInstance[] currentInstances, int currentType) {
private boolean join(FamilyInstance[] currentInstances, int currentType) {
// Join all types that are direct children of the last type.
for (int i = currentType + 1; i < joinDefinition.directParent.length; i++) {
if (joinDefinition.directParent[i] == currentType) {
Expand Down Expand Up @@ -148,12 +153,21 @@ private void join(FamilyInstance[] currentInstances, int currentType) {
child = new FamilyInstanceImpl(ref.resolve());
parent.addChild(child);
currentInstances[i] = child;
join(currentInstances, i);
if (!join(currentInstances, i)) {
return false;
}
}
currentInstances[i] = null;
}
else {
if (innerJoin) {
return false;
}
}
}
}

return true;
}

/**
Expand Down
18 changes: 18 additions & 0 deletions cst/plugins/eu.esdihumboldt.cst.functions.groovy/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,24 @@
ref="text">
</parameterComplexValue>
</functionParameter>
<functionParameter
deprecated="false"
description="If enabled a result is created only if all Join conditions are met"
label="Inner Join"
maxOccurrence="1"
minOccurrence="0"
name="innerJoin"
scriptable="false">
<parameterBinding
class="java.lang.Boolean">
</parameterBinding>
<valueDescriptor
default="false"
defaultDescription="Default behavior is that a result is created for every instance of the Join&apos;s focus type"
sample="true"
sampleDescription="Only create a result from the Join if there are linked instances for all Join conditions">
</valueDescriptor>
</functionParameter>
</typeFunction>
</extension>
<extension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,40 @@ public void testInnerJoin() throws Exception {
testTransform(TransformationExamples.getExample(TransformationExamples.INNER_JOIN));
}

/**
* Test a Join that has the innerJoin flag enabled. Multiple types are
* joined to the join focus, not joins at second level.
*
* @throws Exception if an error occurs executing the test
*/
@Test
public void testInnerJoinFirstLevel() throws Exception {
testTransform(
TransformationExamples.getExample(TransformationExamples.INNER_JOIN_FIRST_LEVEL));
}

/**
* Test a Join that has the innerJoin flag enabled. Conditions are bound to
* some of the joined types.
*
* @throws Exception if an error occurs executing the test
*/
@Test
public void testInnerJoinConditions() throws Exception {
testTransform(
TransformationExamples.getExample(TransformationExamples.INNER_JOIN_CONDITIONS));
}

/**
* Test a Join that does not have the innerJoin flag enabled.
*
* @throws Exception if an error occurs executing the test
*/
@Test
public void testJoin() throws Exception {
testTransform(TransformationExamples.getExample(TransformationExamples.JOIN));
}

@Override
protected List<Instance> transformData(TransformationExample example) throws Exception {
ConceptualSchemaTransformer transformer = new ConceptualSchemaTransformer();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,9 @@ abstract class TransformationExamples {
public static final String XSL_XPATH_1 = 'xpath1'

public static final String INNER_JOIN = 'inner_join'
public static final String INNER_JOIN_FIRST_LEVEL = 'inner_join_first_level'
public static final String INNER_JOIN_CONDITIONS = 'inner_join_conditions'
public static final String JOIN = 'join'

/**
* Internal example map.
Expand Down Expand Up @@ -230,7 +233,10 @@ abstract class TransformationExamples {
(XSL_XPATH_1): defaultExample(XSL_XPATH_1),

// builder based examples
(INNER_JOIN): builderExample(INNER_JOIN)
(INNER_JOIN): builderExample(INNER_JOIN),
(INNER_JOIN_FIRST_LEVEL): builderExample(INNER_JOIN_FIRST_LEVEL),
(INNER_JOIN_CONDITIONS): builderExample(INNER_JOIN_CONDITIONS),
(JOIN): builderExample(JOIN)
];

static def defaultExample(String folder) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<hale-project version="5.1.0.qualifier">
<name>mapping</name>
<author>hale</author>
<created>2024-02-07T10:28:58.718+01:00</created>
<modified>2024-02-07T13:02:59.850+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/cst/plugins/eu.esdihumboldt.cst.test/testdata/inner_join_conditions/mapping.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">ec2ec25e-5940-4b91-8ccd-9ea9455a3dbc</setting>
<setting name="source">source-schema.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">646e49d6-a2f9-462c-8bfb-e6a2a47abef1</setting>
<setting name="source">target-schema.groovy</setting>
<setting name="contentType">eu.esdihumboldt.hale.io.schemabuilder</setting>
</resource>
<resource action-id="eu.esdihumboldt.hale.io.instance.read.source" provider-id="eu.esdihumboldt.hale.io.instancebuilder">
<setting name="charset">UTF-8</setting>
<setting name="resourceId">95bd5843-dfc0-43be-a901-03e7b843d44a</setting>
<setting name="source">source-instances.groovy</setting>
<setting name="contentType">eu.esdihumboldt.hale.io.instancebuilder</setting>
</resource>
<file name="alignment.xml" location="mapping.halex.alignment.xml"/>
<file name="styles.sld" location="mapping.halex.styles.sld"/>
</hale-project>
Loading

0 comments on commit 9fb0cc4

Please sign in to comment.