Skip to content

Commit

Permalink
feat: support "inner join" in spatial join function
Browse files Browse the repository at this point in the history
  • Loading branch information
stempler committed Feb 20, 2024
1 parent 967a0dc commit 5423c78
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 10 deletions.
18 changes: 18 additions & 0 deletions cst/plugins/eu.esdihumboldt.cst.functions.geometric/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,24 @@
scriptable="false">
<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>
</extension>
<extension
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,19 @@

import javax.xml.namespace.QName;

import org.locationtech.jts.geom.Geometry;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimap;
import org.locationtech.jts.geom.Geometry;

import de.fhg.igd.geom.BoundingBox;
import de.fhg.igd.geom.Localizable;
import eu.esdihumboldt.cst.functions.geometric.join.SpatialJoinParameter.SpatialJoinCondition;
import eu.esdihumboldt.cst.functions.geometric.join.SpatialRelationEvaluator.StandardRelation;
import eu.esdihumboldt.hale.common.align.model.AlignmentUtil;
import eu.esdihumboldt.hale.common.align.model.ParameterValue;
import eu.esdihumboldt.hale.common.align.model.functions.JoinFunction;
import eu.esdihumboldt.hale.common.align.model.impl.PropertyEntityDefinition;
import eu.esdihumboldt.hale.common.align.model.impl.TypeEntityDefinition;
import eu.esdihumboldt.hale.common.align.transformation.engine.TransformationEngine;
Expand All @@ -56,7 +58,7 @@
import eu.esdihumboldt.hale.common.instance.model.InstanceReference;
import eu.esdihumboldt.hale.common.instance.model.ResolvableInstanceReference;
import eu.esdihumboldt.hale.common.instance.model.ResourceIterator;
import eu.esdihumboldt.hale.common.instance.model.impl.GenericResourceIteratorAdapter;
import eu.esdihumboldt.hale.common.instance.model.impl.FilterResourceIteratorAdapter;
import eu.esdihumboldt.hale.common.schema.geometry.GeometryProperty;

/**
Expand Down Expand Up @@ -142,12 +144,19 @@ public ResourceIterator<FamilyInstance> partitionInstances(InstanceCollection in
iterator.close();
}

return new SpatialJoinIterator(instances, startInstances, directParent, services,
joinTable);
boolean innerJoin = false; // default to false if not specified
List<ParameterValue> innerJoinValues = transformationParameters
.get(JoinFunction.PARAMETER_INNER_JOIN);
if (!innerJoinValues.isEmpty()) {
innerJoin = innerJoinValues.get(0).as(Boolean.class, innerJoin);
}

return new SpatialJoinIterator(instances, startInstances, directParent, services, joinTable,
innerJoin);
}

private class SpatialJoinIterator
extends GenericResourceIteratorAdapter<InstanceReference, FamilyInstance> {
extends FilterResourceIteratorAdapter<InstanceReference, FamilyInstance> {

private final InstanceCollection instances;
// type -> direct-parent
Expand All @@ -156,15 +165,19 @@ private class SpatialJoinIterator
private final ServiceProvider provider;
private final Map<Integer, Multimap<Integer, SpatialJoinCondition>> joinTable;

private final boolean innerJoin;

protected SpatialJoinIterator(InstanceCollection instances,
Collection<InstanceReference> startInstances, int[] parent,
ServiceProvider provider,
Map<Integer, Multimap<Integer, SpatialJoinCondition>> joinTable) {
Map<Integer, Multimap<Integer, SpatialJoinCondition>> joinTable,
boolean innerJoin) {
super(startInstances.iterator());
this.instances = instances;
this.parent = parent;
this.provider = provider;
this.joinTable = joinTable;
this.innerJoin = innerJoin;
}

/**
Expand All @@ -176,13 +189,20 @@ protected FamilyInstance convert(InstanceReference next) {
FamilyInstance[] currentInstances = new FamilyInstance[parent.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.
private void join(FamilyInstance[] currentInstances, int currentType) {
/**
* Joins all direct children of the given type to currentInstances.
*
* @return if the instance should be skipped
*/
private boolean join(FamilyInstance[] currentInstances, int currentType) {
@SuppressWarnings("unchecked")
SpatialIndexService<Localizable, Localizable> index = provider
.getService(SpatialIndexService.class);
Expand Down Expand Up @@ -281,13 +301,24 @@ private void join(FamilyInstance[] currentInstances, int currentType) {
FamilyInstance child = new FamilyInstanceImpl(inst);
parent.addChild(child);
currentInstances[i] = child;
join(currentInstances, i);
if (!join(currentInstances, i)) {
return false;
}
}
currentInstances[i] = null;
}
else {
if (innerJoin) {
// no instances for this link
return false;
}
}
}
}

return true;
}

}

/**
Expand Down

0 comments on commit 5423c78

Please sign in to comment.