/** * Trim the path to the depth required * * @param depth the depth * @return the path up to the depth given, if the path is shorter the whole path is returned */ public SelectorPath toDepth(int depth) { return new SelectorPath(path.subList(0, Math.min(depth, path.size()))); }
/** * Generate the covered paths, reducing to the lowest depth. * * @param structureHierarchy the structure hierarchy * @param coveredStructures the covered structures * @param depth the maximum depth * @return list of paths for the covered structures */ private List<String> generateCoveredPaths( ItemHierarchy<Structure> structureHierarchy, List<Structure> coveredStructures, int depth) { LinkedHashSet<String> collect = coveredStructures .stream() .map(s -> structureHierarchy.getSelectorPath(s).toDepth(depth).toString()) .collect(Collectors.toCollection(LinkedHashSet::new)); Builder<String> builder = ImmutableList.<String>builder(); String parent = collect.iterator().next(); builder.add(parent); for (String path : collect) { if (!path.startsWith(parent)) { builder.add(path); parent = path; } } return builder.build(); }
/** * Step one part of the path * * @return new path of remaining parts */ public SelectorPath step() { return new SelectorPath(path.subList(Math.min(getDepth(), 1), getDepth())); }
/** * Parses the selector string and returns an ordered List of {@link SelectorPart} objects that * represent each clause between <code>><code> symbols. * * @param value the value * @return the list * @throws InvalidParameterException the invalid parameter exception */ public static SelectorPath parse(String value) throws InvalidParameterException { List<SelectorPart> selectorParts = new ArrayList<>(); if (value == null) { return new SelectorPath(selectorParts); } String[] parts = value.split("\\s*>\\s*"); for (String part : parts) { if (StringUtils.isNotEmpty(part)) { int colon = part.indexOf(':'); if (colon != -1) { String[] typeAndQualifier = part.split(":"); selectorParts.add(new SelectorPart(getType(typeAndQualifier[0]), typeAndQualifier[1])); } else { selectorParts.add(new SelectorPart(getType(part))); } } } return new SelectorPath(selectorParts); }
/** * Make fields from definitions and look up the location in the structure * * @param structureHierarchy the structure hierarchy * @param fields the fields * @return the list of configurations */ private List<TemplateFieldConfiguration> makeFields( final CoveringStructureHierarchy structureHierarchy, Collection<TemplateFieldDefinition> definitions) { List<TemplateFieldConfiguration> fields = new ArrayList<>(); for (TemplateFieldDefinition templateFieldDefinition : definitions) { String fieldPath = structureHierarchy.generatePath(templateFieldDefinition).toString(); TemplateFieldConfiguration field = makeField(templateFieldDefinition, fieldPath); fields.add(field); } return fields; }
@Test public void testCanRepeatFromStartOfDocument() throws InvalidParameterException { SelectorPath maximal = SelectorPath.parse("Document > Heading"); RepeatSearch repeatUnit = new RepeatSearch(ImmutableList.of(maximal), maximal); Optional<Structure> repeat1 = recordStructureManager.repeatRecord(Optional.empty(), repeatUnit, true); assertTrue(repeat1.isPresent()); assertEquals(heading1, repeat1.get()); Optional<Structure> repeat2 = recordStructureManager.repeatRecord(repeat1, repeatUnit, false); assertFalse(repeat2.isPresent()); }
preceding.isPresent() ? structureHierarchy.getSelectorPath(preceding.get()).toString() : ""; following.isPresent() ? structureHierarchy.getSelectorPath(following.get()).toString() : ""; if (coveringStructure.isPresent() && coveredStructures.contains(coveringStructure.get())) { Structure repeatingUnit = coveringStructure.get(); minimalRepeat = structureHierarchy.getSelectorPath(repeatingUnit).toString();
/** * Parses the selector string and returns an ordered List of {@link SelectorPart} objects that * represent each clause between <code>><code> symbols. * * @param value the value * @return the list * @throws InvalidParameterException the invalid parameter exception */ public static SelectorPath parse(String value) throws InvalidParameterException { List<SelectorPart> selectorParts = new ArrayList<>(); if (value == null) { return new SelectorPath(selectorParts); } String[] parts = value.split("\\s*>\\s*"); for (String part : parts) { if (StringUtils.isNotEmpty(part)) { int colon = part.indexOf(':'); if (colon != -1) { String[] typeAndQualifier = part.split(":"); selectorParts.add(new SelectorPart(getType(typeAndQualifier[0]), typeAndQualifier[1])); } else { selectorParts.add(new SelectorPart(getType(part))); } } } return new SelectorPath(selectorParts); }
@Test public void testCanGetAfterMissingRepeat() throws InvalidParameterException { SelectorPath minimal = SelectorPath.parse("Document > Paragraph"); RepeatSearch repeatUnit = new RepeatSearch(ImmutableList.of(minimal), minimal); recordStructureManager.repeatRecord(Optional.empty(), repeatUnit, true); Optional<Structure> adjusted = recordStructureManager.select("Document > Paragraph:nth-of-type(2)"); assertTrue(adjusted.isPresent()); assertEquals(paragraph1, adjusted.get()); } }
/** * Trim the path to the depth required * * @param depth the depth * @return the path up to the depth given, if the path is shorter the whole path is returned */ public SelectorPath toDepth(int depth) { return new SelectorPath(path.subList(0, Math.min(depth, path.size()))); }
/** * Step one part of the path * * @return new path of remaining parts */ public SelectorPath step() { return new SelectorPath(path.subList(Math.min(getDepth(), 1), getDepth())); }
@Test public void testGenerateNestedToDepth1() { Section section = new Section(jCas); section.setBegin(0); section.setDepth(1); section.setEnd(TEXT.length()); section.addToIndexes(); Paragraph paragraph1 = new Paragraph(jCas); paragraph1.setBegin(0); paragraph1.setDepth(2); paragraph1.setEnd(20); paragraph1.addToIndexes(); Paragraph paragraph2 = new Paragraph(jCas); paragraph2.setBegin(20); paragraph2.setDepth(2); paragraph2.setEnd(TEXT.length()); paragraph2.addToIndexes(); ItemHierarchy<Structure> structureHierarchy = StructureHierarchy.build(jCas, structuralClasses); SelectorPath path1 = structureHierarchy.getSelectorPath(paragraph1); SelectorPath path2 = structureHierarchy.getSelectorPath(paragraph1); assertEquals("Section:nth-of-type(1)", path1.toDepth(1).toString()); assertEquals("Section:nth-of-type(1)", path2.toDepth(1).toString()); }
@Test public void testGenerateTwo() { Paragraph paragraph1 = new Paragraph(jCas); paragraph1.setBegin(0); paragraph1.setDepth(1); paragraph1.setEnd(20); paragraph1.addToIndexes(); Paragraph paragraph2 = new Paragraph(jCas); paragraph2.setBegin(20); paragraph2.setDepth(1); paragraph2.setEnd(TEXT.length()); paragraph2.addToIndexes(); ItemHierarchy<Structure> structureHierarchy = StructureHierarchy.build(jCas, structuralClasses); SelectorPath path1 = structureHierarchy.getSelectorPath(paragraph1); SelectorPath path2 = structureHierarchy.getSelectorPath(paragraph2); assertEquals("Paragraph:nth-of-type(1)", path1.toString()); assertEquals("Paragraph:nth-of-type(2)", path2.toString()); }
@Test public void testCanNotRepeatMissingStructure() throws InvalidParameterException { SelectorPath minimal = SelectorPath.parse("Table"); RepeatSearch repeatSearch = new RepeatSearch(ImmutableList.of(minimal), minimal); Optional<Structure> structure = recordStructureManager.select("Document > Heading"); assertFalse(recordStructureManager.repeatRecord(structure, repeatSearch, true).isPresent()); }
@Override public void head(Node<Structure> node, int depth) { sb.append(new SelectorPath(node.toPath())); sb.append("\n"); } })
/** * Get the remaining path after the given path to get this path * * @param from * @return the remaining path having remove the matching elements from the given path */ public SelectorPath from(SelectorPath from) { int i = 0; List<SelectorPart> remaining = new ArrayList<>(path); while (!remaining.isEmpty() && from.getDepth() > i && from.path.get(i).equals(remaining.get(0))) { i++; remaining.remove(0); } return new SelectorPath(remaining); }
@Test public void testGenerateNested() { Section section = new Section(jCas); section.setBegin(0); section.setDepth(1); section.setEnd(TEXT.length()); section.addToIndexes(); Paragraph paragraph = new Paragraph(jCas); paragraph.setBegin(0); paragraph.setDepth(2); paragraph.setEnd(TEXT.length()); paragraph.addToIndexes(); ItemHierarchy<Structure> structureHierarchy = StructureHierarchy.build(jCas, structuralClasses); SelectorPath path1 = structureHierarchy.getSelectorPath(paragraph); assertEquals("Section:nth-of-type(1) > Paragraph:nth-of-type(1)", path1.toString()); }
@Test public void testCanRepeatParagraph() throws InvalidParameterException { SelectorPath minimal = SelectorPath.parse("Document > Paragraph:nth-of-type(1)"); RepeatSearch repeatUnit = new RepeatSearch(ImmutableList.of(minimal), minimal); Optional<Structure> structure = recordStructureManager.select("Document > Heading"); Optional<Structure> repeat1 = recordStructureManager.repeatRecord(structure, repeatUnit, true); assertTrue(repeat1.isPresent()); assertEquals(paragraph1, repeat1.get()); Optional<Structure> repeat2 = recordStructureManager.repeatRecord(repeat1, repeatUnit, false); assertTrue(repeat2.isPresent()); assertEquals(paragraph2, repeat2.get()); Optional<Structure> repeat3 = recordStructureManager.repeatRecord(repeat2, repeatUnit, false); assertTrue(repeat3.isPresent()); assertEquals(paragraph3, repeat3.get()); Optional<Structure> repeat4 = recordStructureManager.repeatRecord(repeat3, repeatUnit, false); assertTrue(repeat4.isPresent()); assertEquals(paragraph4, repeat4.get()); Optional<Structure> repeat5 = recordStructureManager.repeatRecord(repeat4, repeatUnit, false); assertFalse(repeat5.isPresent()); }
/** * Get the selector path of the given item * * @param a the item * @return the selector path in this hierarchy for the given item */ public SelectorPath getSelectorPath(T a, Class<? extends T> type) { Node<T> node = getIndex().get(a); if (node == null) { return null; } return new SelectorPath(node.toPath(type)); }
/** * Get the remaining path after the given path to get this path * * @param from * @return the remaining path having remove the matching elements from the given path */ public SelectorPath from(SelectorPath from) { int i = 0; List<SelectorPart> remaining = new ArrayList<>(path); while (!remaining.isEmpty() && from.getDepth() > i && from.path.get(i).equals(remaining.get(0))) { i++; remaining.remove(0); } return new SelectorPath(remaining); }