All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vladsch.flexmark.util.sequence.ReplacedTextMapper Maven / Gradle / Ivy

There is a newer version: 0.64.8
Show newest version
package com.vladsch.flexmark.util.sequence;

import java.util.ArrayList;

/**
 * Class which tracks text replacements to provide original offset from modified offset.
 * 

* This is needed when the original based sequence needs to be un-escaped but offsets to original escaped text * are needed. *

* These replacements can be nested so that you can track replacements of replaced text. * To add nested replacements use startNestedReplacement() *

* when isModified() returns true then the text mapper is already used and nested replacements need to be applied */ // REFACTOR: to use segment builder with ISegmentBuilder.F_INCLUDE_ANCHORS and use segment information to find original offsets public class ReplacedTextMapper { private ReplacedTextMapper parent; private BasedSequence original; private ArrayList regions = new ArrayList<>(); private ArrayList replacedSegments = new ArrayList<>(); private int replacedLength = 0; private BasedSequence replacedSequence = null; public ReplacedTextMapper(BasedSequence original) { this.original = original; this.parent = null; } private ReplacedTextMapper(ReplacedTextMapper other) { this.parent = other.parent; this.original = other.original; this.regions = other.regions; this.replacedSegments = other.replacedSegments; this.replacedLength = other.replacedLength; this.replacedSequence = other.getReplacedSequence(); } public void startNestedReplacement(BasedSequence sequence) { assert sequence.equals(this.getReplacedSequence()); // create parent from our data and re-initialize this.parent = new ReplacedTextMapper(this); this.original = sequence; this.regions = new ArrayList<>(); this.replacedSegments = new ArrayList<>(); this.replacedLength = 0; this.replacedSequence = null; } public boolean isModified() { return replacedLength > 0; } public boolean isFinalized() { return replacedSequence != null; } private void finalizeMods() { if (replacedSequence == null) { replacedSequence = replacedSegments.isEmpty() ? BasedSequence.NULL : SegmentedSequence.create(original, replacedSegments); } } public ReplacedTextMapper getParent() { return parent; } public void addReplacedText(int startIndex, int endIndex, BasedSequence replacedSequence) { if (isFinalized()) throw new IllegalStateException("Cannot modify finalized ReplacedTextMapper"); regions.add(new ReplacedTextRegion(original.subSequence(startIndex, endIndex).getSourceRange(), Range.of(startIndex, endIndex), Range.of(replacedLength, replacedLength + replacedSequence.length()))); replacedLength += replacedSequence.length(); replacedSegments.add(replacedSequence); } public void addOriginalText(int startIndex, int endIndex) { if (isFinalized()) throw new IllegalStateException("Cannot modify finalized ReplacedTextMapper"); if (startIndex < endIndex) { BasedSequence originalSegment = original.subSequence(startIndex, endIndex); regions.add(new ReplacedTextRegion(originalSegment.getSourceRange(), Range.of(startIndex, endIndex), Range.of(replacedLength, replacedLength + originalSegment.length()))); replacedLength += originalSegment.length(); replacedSegments.add(originalSegment); } } public ArrayList getRegions() { finalizeMods(); return regions; } public ArrayList getReplacedSegments() { finalizeMods(); return replacedSegments; } public BasedSequence getReplacedSequence() { finalizeMods(); return replacedSequence; } public int getReplacedLength() { finalizeMods(); return replacedLength; } private int parentOriginalOffset(int originalIndex) { return parent != null ? parent.originalOffset(originalIndex) : originalIndex; } public int originalOffset(int replacedIndex) { finalizeMods(); if (regions.isEmpty()) return parentOriginalOffset(replacedIndex); if (replacedIndex == replacedLength) return parentOriginalOffset(original.length()); int originalIndex = replacedIndex; for (ReplacedTextRegion region : regions) { if (region.containsReplacedIndex(replacedIndex)) { originalIndex = region.getOriginalRange().getStart() + replacedIndex - region.getReplacedRange().getStart(); if (originalIndex > region.getOriginalRange().getEnd()) { originalIndex = region.getOriginalRange().getEnd(); } break; } } return parentOriginalOffset(originalIndex); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy