-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
233 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
fhirpath/src/main/java/au/csiro/pathling/fhirpath/execution/JoinSet.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package au.csiro.pathling.fhirpath.execution; | ||
|
||
import static java.util.stream.Collectors.mapping; | ||
|
||
import au.csiro.pathling.fhirpath.execution.DataRoot.JoinRoot; | ||
import jakarta.annotation.Nonnull; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import java.util.function.Predicate; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
import lombok.AccessLevel; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Value; | ||
|
||
@Value() | ||
@AllArgsConstructor(access = AccessLevel.PRIVATE) | ||
public class JoinSet { | ||
|
||
@Nonnull | ||
DataRoot master; | ||
|
||
@Nonnull | ||
List<JoinSet> children; | ||
|
||
|
||
@Nonnull | ||
public static JoinSet of(@Nonnull final DataRoot master, @Nonnull final List<JoinSet> children) { | ||
children.forEach(child -> { | ||
if (child.getMaster() instanceof JoinRoot jr) { | ||
if (!jr.getMaster().equals(master)) { | ||
throw new IllegalArgumentException( | ||
"Cannot have a join set when child master is differnt than set parent"); | ||
} | ||
} else { | ||
throw new IllegalArgumentException("Child must be a join root"); | ||
} | ||
}); | ||
return new JoinSet(master, children); | ||
} | ||
|
||
@Nonnull | ||
public static JoinSet of(@Nonnull final DataRoot master) { | ||
return new JoinSet(master, List.of()); | ||
} | ||
|
||
@Nonnull | ||
private static Stream<DataRoot> toStream(@Nonnull final DataRoot dataRoot) { | ||
if (dataRoot instanceof JoinRoot jr) { | ||
return Stream.concat(toStream(jr.getMaster()), Stream.of(dataRoot)); | ||
} | ||
return Stream.of(dataRoot); | ||
} | ||
|
||
@Nonnull | ||
static List<DataRoot> toPath(@Nonnull final DataRoot root) { | ||
return toStream(root).toList(); | ||
} | ||
|
||
@Nonnull | ||
public static List<JoinSet> mergeRoots(@Nonnull final List<List<DataRoot>> paths) { | ||
// convert to paths and then group by recurively by common prefixes | ||
// we have got it already somwhere else | ||
final Map<DataRoot, List<List<DataRoot>>> suffixesByHeads = paths.stream() | ||
.filter(Predicate.not(List::isEmpty)) | ||
.collect(Collectors.groupingBy( | ||
path -> path.get(0), | ||
mapping(path -> path.subList(1, path.size()), Collectors.toList()) | ||
)); | ||
|
||
return suffixesByHeads.entrySet().stream() | ||
.map(entry -> JoinSet.of(entry.getKey(), mergeRoots(entry.getValue()))) | ||
.toList(); | ||
} | ||
|
||
@Nonnull | ||
public static List<JoinSet> mergeRoots(@Nonnull final Set<DataRoot> roots) { | ||
// convert to paths and then group by recurively by common prefixes | ||
// we have got it already somwhere else | ||
return mergeRoots(roots.stream().map(JoinSet::toPath).toList()); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
97 changes: 97 additions & 0 deletions
97
fhirpath/src/test/java/au/csiro/pathling/fhirpath/execution/JoinSetTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,97 @@ | ||
package au.csiro.pathling.fhirpath.execution; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
|
||
import au.csiro.pathling.fhirpath.execution.DataRoot.ResolveRoot; | ||
import au.csiro.pathling.fhirpath.execution.DataRoot.ResourceRoot; | ||
import au.csiro.pathling.fhirpath.execution.DataRoot.ReverseResolveRoot; | ||
import java.util.List; | ||
import java.util.Set; | ||
import org.hl7.fhir.r4.model.Enumerations.ResourceType; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class JoinSetTest { | ||
|
||
|
||
@Test | ||
void testSingleResourcePath() { | ||
|
||
final List<DataRoot> result = JoinSet.toPath( | ||
ResourceRoot.of(ResourceType.PATIENT)); | ||
assertEquals(List.of(ResourceRoot.of(ResourceType.PATIENT)), result); | ||
} | ||
|
||
@Test | ||
void testReverseResolvePath() { | ||
final List<DataRoot> result = JoinSet.toPath( | ||
ReverseResolveRoot.of(ResourceRoot.of(ResourceType.PATIENT), ResourceType.CONDITION, | ||
"subject")); | ||
assertEquals(List.of( | ||
ResourceRoot.of(ResourceType.PATIENT), | ||
ReverseResolveRoot.of(ResourceRoot.of(ResourceType.PATIENT), ResourceType.CONDITION, | ||
"subject") | ||
), result); | ||
} | ||
|
||
@Test | ||
void singleResourceRoots() { | ||
final List<JoinSet> result = JoinSet.mergeRoots( | ||
Set.of( | ||
ResourceRoot.of(ResourceType.PATIENT), | ||
ResourceRoot.of(ResourceType.CONDITION) | ||
) | ||
); | ||
System.out.println(result); | ||
} | ||
|
||
@Test | ||
void singleReverseResolvePath() { | ||
final List<JoinSet> result = JoinSet.mergeRoots( | ||
Set.of( | ||
ReverseResolveRoot.of(ResourceRoot.of(ResourceType.PATIENT), ResourceType.CONDITION, | ||
"subject") | ||
) | ||
); | ||
System.out.println(result); | ||
} | ||
|
||
@Test | ||
void nestedRoots() { | ||
final List<JoinSet> result = JoinSet.mergeRoots( | ||
Set.of( | ||
ResourceRoot.of(ResourceType.PATIENT), | ||
ReverseResolveRoot.of(ResourceRoot.of(ResourceType.PATIENT), ResourceType.CONDITION, | ||
"subject"), | ||
ReverseResolveRoot.of(ResourceRoot.of(ResourceType.PATIENT), ResourceType.ENCOUNTER, | ||
"subject") | ||
) | ||
); | ||
System.out.println(result); | ||
} | ||
@Test | ||
void complexNestedRoots() { | ||
|
||
final ResourceRoot mainRoot1 = ResourceRoot.of(ResourceType.PATIENT); | ||
final DataRoot root_1_1 = ReverseResolveRoot.of(mainRoot1, ResourceType.CONDITION, "subject"); | ||
final DataRoot root_1_2 = ReverseResolveRoot.of(mainRoot1, ResourceType.ENCOUNTER, "subject"); | ||
final DataRoot root_1_2_1 = ResolveRoot.of(root_1_2, ResourceType.OBSERVATION, "observations"); | ||
|
||
System.out.println(JoinSet.toPath(root_1_2_1)); | ||
|
||
|
||
final List<JoinSet> result = JoinSet.mergeRoots( | ||
Set.of( | ||
mainRoot1, | ||
root_1_1, | ||
root_1_2, | ||
root_1_2_1 | ||
) | ||
); | ||
|
||
|
||
System.out.println(result); | ||
} | ||
|
||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters