| package de.ids_mannheim.korap.response.match; |
| |
| import de.ids_mannheim.korap.response.Match; |
| import de.ids_mannheim.korap.response.match.HighlightCombinatorElement; |
| import java.util.*; |
| import java.io.*; |
| |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /* |
| Public class for combining highlighting elements |
| */ |
| public class HighlightCombinator { |
| |
| // Logger (use the Match class) |
| private final static Logger log = LoggerFactory.getLogger(Match.class); |
| |
| // This advices the java compiler to ignore all loggings |
| public static final boolean DEBUG = false; |
| |
| private LinkedList<HighlightCombinatorElement> combine; |
| private Stack<Integer> balanceStack = new Stack<>(); |
| private Stack<Integer> tempStack = new Stack<>(); |
| |
| |
| // Empty constructor |
| public HighlightCombinator () { |
| this.combine = new LinkedList<>(); |
| }; |
| |
| |
| // Return the combination list |
| public LinkedList<HighlightCombinatorElement> list () { |
| return this.combine; |
| }; |
| |
| |
| // get the first element (without removing) |
| public HighlightCombinatorElement getFirst () { |
| return this.combine.getFirst(); |
| }; |
| |
| |
| // get the last element (without removing) |
| public HighlightCombinatorElement getLast () { |
| return this.combine.getLast(); |
| }; |
| |
| |
| // get an element by index (without removing) |
| public HighlightCombinatorElement get (int index) { |
| return this.combine.get(index); |
| }; |
| |
| |
| // Get the size of the combinator stack |
| public short size () { |
| return (short) this.combine.size(); |
| }; |
| |
| |
| // Add primary data to the stack |
| public void addString (String characters) { |
| this.combine.add(new HighlightCombinatorElement(characters)); |
| if (DEBUG) { |
| log.trace("Add string \"{}\" to stack", characters); |
| }; |
| }; |
| |
| |
| // Add opening highlight combinator to the stack |
| public void addOpen (int number) { |
| this.combine.add(new HighlightCombinatorElement((byte) 1, number)); |
| this.balanceStack.push(number); |
| if (DEBUG) |
| log.trace("Add opening {} to stack", number); |
| }; |
| |
| |
| // Add empty highlight to the stack |
| public void addEmpty (int pagenumber) { |
| this.combine.add(new HighlightCombinatorElement((byte) 3, pagenumber)); |
| }; |
| |
| |
| // Add closing highlight combinator to the stack |
| public void addClose (int number) { |
| HighlightCombinatorElement lastComb; |
| |
| // Clean up temporary stack |
| this.tempStack.clear(); |
| |
| // Check if there is an opening tag at least |
| if (this.balanceStack.empty()) { |
| if (DEBUG) |
| log.trace("The balance stack is empty"); |
| return; |
| }; |
| |
| // Just some debug information |
| if (DEBUG) { |
| StringBuilder sb = new StringBuilder( |
| "Stack for checking with number "); |
| sb.append(number).append(" is "); |
| for (int s : this.balanceStack) { |
| sb.append('[').append(s).append(']'); |
| }; |
| log.trace(sb.toString()); |
| }; |
| |
| // class number of the last element |
| // It's already ensured the stack is not empty |
| int eold = this.balanceStack.pop(); |
| |
| // the closing element is not balanced, i.e. the last element differs |
| while (eold != number) { |
| |
| // Retrieve last combinator on stack |
| lastComb = this.combine.peekLast(); |
| |
| if (DEBUG) |
| log.trace( |
| "Closing element is unbalanced - {} " |
| + "!= {} with lastComb {}|{}|{}", |
| eold, |
| number, |
| lastComb.type, |
| lastComb.number, |
| lastComb.characters); |
| |
| // combinator is opening and the number is not equal to the last |
| // element on the balanceStack |
| if (lastComb.type == 1 && lastComb.number == eold) { |
| |
| // Remove the last element - it's empty and uninteresting! |
| this.combine.removeLast(); |
| } |
| |
| // Last element is empty |
| else if (lastComb.type == 3) { |
| log.error( |
| "The last element was empty -- and this is not correctly handled yet" |
| ); |
| } |
| |
| // combinator is either closing (??) or another opener |
| else { |
| |
| if (DEBUG) |
| log.trace("close element a) {}", eold); |
| |
| // Add a closer for the old element (this has following elements) |
| this.combine.add( |
| new HighlightCombinatorElement((byte) 2, eold, false)); |
| }; |
| |
| // add this element number temporarily on the stack |
| tempStack.push(eold); |
| |
| // There are no more elements on the balance stack |
| if (this.balanceStack.empty()) |
| break; |
| |
| // Check next element |
| eold = this.balanceStack.pop(); |
| }; |
| |
| // Get last combinator on the stack |
| lastComb = this.combine.peekLast(); |
| |
| if (DEBUG) { |
| log.trace("Stack for checking 2: {}|{}|{}|{}", lastComb.type, |
| lastComb.number, lastComb.characters, number); |
| }; |
| |
| if (lastComb.type == 1 && lastComb.number == number) { |
| while (lastComb.type == 1 && lastComb.number == number) { |
| // Remove the damn thing - It's empty and uninteresting! |
| this.combine.removeLast(); |
| lastComb = this.combine.peekLast(); |
| }; |
| } |
| else if (lastComb.type == 3) { |
| System.err.println("öööööööööööööööööööööööö"); |
| } |
| else { |
| if (DEBUG) |
| log.trace("close element b) {}", number); |
| |
| // Add a closer |
| this.combine.add(new HighlightCombinatorElement((byte) 2, number)); |
| }; |
| |
| // Fetch everything from the tempstack and reopen it |
| for (int e : tempStack) { |
| if (DEBUG) |
| log.trace("Reopen element {}", e); |
| combine.add(new HighlightCombinatorElement((byte) 1, e)); |
| balanceStack.push(e); |
| }; |
| }; |
| |
| |
| // Get all combined elements as a string |
| public String toString () { |
| StringBuilder sb = new StringBuilder(); |
| for (HighlightCombinatorElement e : combine) { |
| sb.append(e.toString()).append("\n"); |
| }; |
| return sb.toString(); |
| }; |
| }; |