package org.openehr.rm.binding; import java.io.File; import java.io.InputStream; import java.util.*; import org.apache.commons.io.FileUtils; import org.apache.commons.jxpath.JXPathContext; import org.openehr.am.archetype.Archetype; import org.openehr.rm.Attribute; import org.openehr.rm.common.archetyped.Archetyped; import org.openehr.rm.composition.Composition; import org.openehr.rm.datastructure.itemstructure.ItemTree; import org.openehr.rm.datastructure.itemstructure.representation.Cluster; import org.openehr.rm.datastructure.itemstructure.representation.Element; import org.openehr.rm.datastructure.itemstructure.representation.Item; import org.openehr.rm.datatypes.quantity.DvQuantity; import org.openehr.rm.datatypes.text.CodePhrase; import org.openehr.rm.datatypes.text.DvCodedText; import org.openehr.rm.datatypes.text.DvText; import org.openehr.rm.support.measurement.MeasurementService; public class XPathTest extends DADLBindingTestBase { public void testCreatePathMapWithOrderSet() throws Exception { Composition composition = (Composition) bind("order_set1.dadl"); assertEquals(3, composition.getContent().size()); } public void testGetValue() throws Exception { ItemTree tree = createTree(); JXPathContext context = JXPathContext.newContext(tree); assertTrue(context.getValue("/items[2]") instanceof Cluster); assertEquals("LDL cholesterol", context.getValue("/items[2]/items[2]/name/value")); } public void testAttributeItemsExistsInCluster() throws Exception { RMInspector inspector = RMInspector.getInstance(); Map<String, Attribute> attributeMap = inspector.attributeMap(Cluster.class); assertTrue(attributeMap.containsKey("items")); } public void testCreatePathMapWithDefaultTree() throws Exception { ItemTree tree = createTree(); XPathUtil util = new XPathUtil(); Map<String, Set<String>> actual = util.extractPaths(tree); assertEquals(5, actual.size()); // first element Set<String> set = actual.get("/items[at0001]"); assertEquals(1, set.size()); assertEquals("/items[1]", set.toArray()[0]); // second element set = actual.get("/items[at0005]/items[at0002]"); assertEquals(1, set.size()); assertEquals("/items[2]/items[1]", set.toArray()[0]); // third element set = actual.get("/items[at0005]/items[at0003]"); assertEquals(1, set.size()); assertEquals("/items[2]/items[2]", set.toArray()[0]); // forth element set = actual.get("/items[at0005]/items[at0004]"); assertEquals(1, set.size()); assertEquals("/items[2]/items[3]", set.toArray()[0]); // fifth element set = actual.get("/items[at0006]"); assertEquals(1, set.size()); assertEquals("/items[3]", set.toArray()[0]); } public void testCreatePathMapWithRepeatedCluster() throws Exception { ItemTree tree = createTreeWithRepeatedCluster(); XPathUtil util = new XPathUtil(); Map<String, Set<String>> actual = util.extractPaths(tree); assertEquals(5, actual.size()); // first element Set<String> set = actual.get("/items[at0001]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[1]")); // second element set = actual.get("/items[at0005]/items[at0002]"); assertEquals(2, set.size()); assertTrue(set.contains("/items[2]/items[1]")); assertTrue(set.contains("/items[3]/items[1]")); // third element set = actual.get("/items[at0005]/items[at0003]"); assertEquals(2, set.size()); assertTrue(set.contains("/items[2]/items[2]")); assertTrue(set.contains("/items[3]/items[2]")); // forth element set = actual.get("/items[at0005]/items[at0004]"); assertEquals(2, set.size()); assertTrue(set.contains("/items[2]/items[3]")); assertTrue(set.contains("/items[3]/items[3]")); // fifth element set = actual.get("/items[at0006]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[4]")); } public void testCreatePathMapWithRepeatedSampleElement() throws Exception { ItemTree tree = createTreeWithRepeatedElement(); XPathUtil util = new XPathUtil(); Map<String, Set<String>> actual = util.extractPaths(tree); assertEquals(5, actual.size()); // first element, and its copy Set<String> set = actual.get("/items[at0001]"); assertEquals(2, set.size()); assertTrue(set.contains("/items[1]")); assertTrue(set.contains("/items[2]")); // second element set = actual.get("/items[at0005]/items[at0002]"); assertEquals(1, set.size()); assertEquals("/items[3]/items[1]", set.toArray()[0]); // third element set = actual.get("/items[at0005]/items[at0003]"); assertEquals(1, set.size()); assertEquals("/items[3]/items[2]", set.toArray()[0]); // forth element set = actual.get("/items[at0005]/items[at0004]"); assertEquals(1, set.size()); assertEquals("/items[3]/items[3]", set.toArray()[0]); // fifth element set = actual.get("/items[at0006]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[4]")); } public void testExtratRootPathWithOneSlot() throws Exception { ItemTree tree = (ItemTree) bind("tree_slot.dadl"); Set<String> paths = new XPathUtil().extractRootXPaths(tree); assertEquals(1, paths.size()); assertTrue(paths.contains("/items[4]")); } public void testExtratRootPathWithTwoSlots() throws Exception { ItemTree tree = (ItemTree) bind("tree_2_slots.dadl"); Set<String> paths = new XPathUtil().extractRootXPaths(tree); assertEquals(2, paths.size()); assertTrue(paths.contains("/items[4]")); assertTrue(paths.contains("/items[5]")); } public void testExtracRootPathWithNestedSlot() throws Exception { ItemTree tree = (ItemTree) bind("tree_nested_slot.dadl"); Set<String> paths = new XPathUtil().extractRootXPaths(tree); assertEquals(1, paths.size()); assertTrue(paths.contains("/items[4]")); } public void testExtracRootPathWithDoubleNestedSlot() throws Exception { ItemTree tree = (ItemTree) bind("tree_nested_slot2.dadl"); Set<String> paths = new XPathUtil().extractRootXPaths(tree); assertEquals(1, paths.size()); assertTrue(paths.contains("/items[4]")); } public void testCreatePathMapWithSlottedCluster() throws Exception { ItemTree tree = (ItemTree) bind("tree_slot.dadl"); XPathUtil util = new XPathUtil(); Map<String, Set<String>> actual = util.extractPaths(tree); assertEquals(8, actual.size()); // first element Set<String> set = actual.get("/items[at0001]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[1]")); // second element set = actual.get("/items[at0005]/items[at0002]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[2]/items[1]")); // third element set = actual.get("/items[at0005]/items[at0003]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[2]/items[2]")); // forth element set = actual.get("/items[at0005]/items[at0004]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[2]/items[3]")); // fifth element set = actual.get("/items[at0006]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[3]")); // 6th element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[at0002]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[4]/items[1]")); // 7th element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[at0003]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[4]/items[2]")); // 8th element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[at0004]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[4]/items[3]")); } public void testCreatePathMapWithNestedClusters() throws Exception { ItemTree tree = (ItemTree) bind("tree_nested_slot3.dadl"); XPathUtil util = new XPathUtil(); Map<String, Set<String>> actual = util.extractPaths(tree); assertEquals(4, actual.size()); // first element Set<String> set = actual.get("/items[at0001]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[1]")); // second element set = actual.get("/items[at0005]/items[at0002]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[2]/items[1]")); // third element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[at0002]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[3]/items[1]")); // forth element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[adl-test-CLUSTER.test_cluster.v1]/items[at0002]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[3]/items[2]/items[1]")); } public void testCreatePathMapDoubleNestedClusters() throws Exception { ItemTree tree = (ItemTree) bind("tree_nested_slot4.dadl"); XPathUtil util = new XPathUtil(); Map<String, Set<String>> actual = util.extractPaths(tree); assertEquals(4, actual.size()); // first element Set<String> set = actual.get("/items[at0001]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[1]")); // second element set = actual.get("/items[at0005]/items[at0002]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[2]/items[1]")); // third element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[at0002]"); assertEquals(2, set.size()); assertTrue(set.contains("/items[3]/items[1]")); assertTrue(set.contains("/items[4]/items[1]")); // forth element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[adl-test-CLUSTER.test_cluster.v1]/items[at0002]"); assertEquals(2, set.size()); assertTrue(set.contains("/items[3]/items[2]/items[1]")); assertTrue(set.contains("/items[4]/items[2]/items[1]")); } public void testCreatePathMapWithTwoSlottedClusters() throws Exception { ItemTree tree = createRootTreeWithTwoSlottedClusters(); XPathUtil util = new XPathUtil(); Map<String, Set<String>> actual = util.extractPaths(tree); assertEquals(8, actual.size()); // first element Set<String> set = actual.get("/items[at0001]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[1]")); // second element set = actual.get("/items[at0005]/items[at0002]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[2]/items[1]")); // third element set = actual.get("/items[at0005]/items[at0003]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[2]/items[2]")); // forth element set = actual.get("/items[at0005]/items[at0004]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[2]/items[3]")); // fifth element set = actual.get("/items[at0006]"); assertEquals(1, set.size()); assertTrue(set.contains("/items[3]")); // 6th element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[at0002]"); assertEquals(2, set.size()); assertTrue(set.contains("/items[4]/items[1]")); assertTrue(set.contains("/items[5]/items[1]")); // 7th element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[at0003]"); assertEquals(2, set.size()); assertTrue(set.contains("/items[4]/items[2]")); assertTrue(set.contains("/items[5]/items[2]")); // 8th element set = actual.get("/items[adl-test-CLUSTER.test_cluster.v1]/items[at0004]"); assertEquals(2, set.size()); assertTrue(set.contains("/items[4]/items[3]")); assertTrue(set.contains("/items[5]/items[3]")); } private InputStream loadFromClasspath(String adl) throws Exception { return this.getClass().getClassLoader().getResourceAsStream(adl); } public void testExtractXPaths() throws Exception { ItemTree tree = createTree(); XPathUtil util = new XPathUtil(); Set<String> actual = util.extractXPaths(tree); assertEquals(5, actual.size()); assertTrue(actual.contains("/items[1]")); assertTrue(actual.contains("/items[2]/items[1]")); assertTrue(actual.contains("/items[2]/items[2]")); assertTrue(actual.contains("/items[2]/items[3]")); assertTrue(actual.contains("/items[3]")); } // the nested structure shouldn't produce more xpath of elements public void testExtractXPathsWithNestedSlot() throws Exception { ItemTree tree = (ItemTree) bind("tree_nested_slot.dadl"); XPathUtil util = new XPathUtil(); Set<String> actual = util.extractXPaths(tree); assertEquals(5, actual.size()); assertTrue(actual.contains("/items[1]")); assertTrue(actual.contains("/items[2]/items[1]")); assertTrue(actual.contains("/items[2]/items[2]")); assertTrue(actual.contains("/items[2]/items[3]")); assertTrue(actual.contains("/items[3]")); } /** * /sample * /lipid studies/total cholesterol * /lipid studies/ldl cholesterol * /lipid studies/hdl cholesterol * /comment */ private ItemTree createTree() { List<Item> items = new ArrayList<Item>(); items.add(sampleElement()); items.add(cluster()); items.add(commentElement()); return new ItemTree("at0007", new DvText("biochemstry result"), items); } /** * /items[at0001, 'sample'] * /items[at0005, 'lipid studies']/items[at0002, 'total cholesterol'] * /items[at0005, 'lipid studies']/items[at0003, 'ldl cholesterol'] * /items[at0005, 'lipid studies']/items[at0004, 'hdl cholesterol'] * /items[at0006, 'comment'] * /items[adl-test-CLUSTER.test_cluster.v1, 'test cluster']/items[at0002, 'element 1'] * /items[adl-test-CLUSTER.test_cluster.v1, 'test cluster']/items[at0003, 'element 2'] * /items[adl-test-CLUSTER.test_cluster.v1, 'test cluster']/items[at0004, 'element 3'] */ private ItemTree createRootTreeWithTwoSlottedClusters() throws Exception { List<Item> items = new ArrayList<Item>(); items.add(sampleElement()); items.add(cluster()); items.add(commentElement()); items.add(slottedCluster()); items.add(slottedCluster()); String aid = "adl-test-ITEM_TREE.test_tree.v1"; Archetyped details = new Archetyped(aid, "1.0.1"); ItemTree tree = new ItemTree(null, aid, new DvText("biochemstry result"), details, null, null, null, items); writeDADL("tree_2_slots.dadl", tree); return tree; } private void writeDADL(String name, Object obj) throws Exception { DADLBinding binding = new DADLBinding(); List<String> lines = binding.toDADL(obj); FileUtils.writeLines(new File(name), lines); } /** * /sample * /sample (repeated) * /lipid studies/total cholesterol * /lipid studies/ldl cholesterol * /lipid studies/hdl cholesterol * /comment */ private ItemTree createTreeWithRepeatedElement() { Element comment = new Element("at0006", new DvText("comment"), new DvText( "high cardiac risk")); List<Item> items = new ArrayList<Item>(); items.add(sampleElement()); // repeated sample element items.add(sampleElement()); items.add(cluster()); items.add(comment); return new ItemTree("at0007", new DvText("biochemstry result"), items); } private Element sampleElement() { return new Element("at0001", new DvText("sample"), new DvCodedText( "serum", new CodePhrase("terminology", "111"))); } private Element commentElement() { return new Element("at0006", new DvText("comment"), new DvText( "high cardiac risk")); } /** * /sample * /lipid studies/total cholesterol * /lipid studies/ldl cholesterol * /lipid studies/hdl cholesterol * /lipid studies (repeated)/total cholesterol * /lipid studies (repeated)/ldl cholesterol * /lipid studies (repeated)/hdl cholesterol * /comment */ private ItemTree createTreeWithRepeatedCluster() { ItemTree itemTree; Element sample; Element comment; sample = new Element("at0001", new DvText("sample"), new DvCodedText( "serum", new CodePhrase("terminology", "111"))); // comment comment = new Element("at0006", new DvText("comment"), new DvText( "high cardiac risk")); List<Item> items = new ArrayList<Item>(); items.add(sample); items.add(cluster()); // repeated cluster items.add(cluster()); items.add(comment); itemTree = new ItemTree("at0007", new DvText("biochemstry result"), items); return itemTree; } private Cluster cluster() { Element totalCholesterol; Element ldlCholesterol; Element hdlCholesterol; MeasurementService measureServ = TestMeasurementService.getInstance(); totalCholesterol = new Element("at0002", new DvText("total cholesterol"), new DvQuantity("mmol/L", 6.1, measureServ)); ldlCholesterol = new Element("at0003", new DvText("LDL cholesterol"), new DvQuantity("mmol/L", 0.9, measureServ)); hdlCholesterol = new Element("at0004", new DvText("HDL cholesterol"), new DvQuantity("mmol/L", 5.2, measureServ)); List<Item> items = new ArrayList<Item>(); items.add(totalCholesterol); items.add(ldlCholesterol); items.add(hdlCholesterol); return new Cluster("at0005", new DvText("lipid studies"), items); } private Cluster slottedCluster() { String archetypeId = "adl-test-CLUSTER.test_cluster.v1"; Element e1 = new Element("at0002", new DvText("element 1"), new DvText("element 1")); Element e2 = new Element("at0003", new DvText("element 2"), new DvText("element 2")); Element e3 = new Element("at0004", new DvText("element 3"), new DvText("element 3")); List<Item> items = new ArrayList<Item>(); items.add(e1); items.add(e2); items.add(e3); Archetyped details = new Archetyped("adl-test-CLUSTER.test_cluster.v1", "1.0.1"); Cluster cluster = new Cluster(null, archetypeId, new DvText("test cluster"), details, null, null, null, items); cluster.setOriginalArchetypeNodeId("at1025"); return cluster; } private static class TestMeasurementService implements MeasurementService { /* fields */ /** * Returns True if the units string according to the HL7 UCUM * specification. * * @param units * @return true if units valid * @throws IllegalArgumentException * if units null */ public boolean isValidUnitsString(String units) { return true; } /** * Return True if two units strings correspond to the same measured * property. * * @param units1 * @param units2 * @return true if two units equal * @throws IllegalArgumentException * if units1 or units2 null */ public boolean unitsEquivalent(String units1, String units2) { return true; } /** * Return a new instance of test measurement service * * @return */ public static MeasurementService getInstance() { return new TestMeasurementService(); } @Override public boolean unitsComparable(String units1, String units2) { return true; } @Override public int compare(String units1, Double value1, String units2, Double value2) { return 0; } } }