private void reverseChangeLog() throws InvalidOperationException { Deque<Operation> operations = new LinkedList<>(this.changeLog); while (!operations.isEmpty()) { Operation operation = operations.pop(); if (!TokenHook.TokenType.Word.equals(operation.tokenType)) { Operation inverse = operation.getInverse(); Collection<Operation> c = new LinkedList<>(); c.add(inverse); this.applyOperations(c, false); } } }
protected void applyOperations(Collection<Operation> operations, boolean save) throws InvalidOperationException { if (this.compiled) { throw new IllegalStateException("XMLEditableString already compiled"); } for (Operation operation : operations) { int operationEndIndex = operation.startIndex + operation.length; operation.originalString = this.currentString.substring(operation.startIndex, operationEndIndex); int delta = operation.lengthNewString - operation.length; if (delta != 0) { for (TokenHook hook : this.tokens) { int hookLastEditedIndex = hook.startIndex + hook.length - 1; if (hook.startIndex >= operationEndIndex) { hook.startIndex += delta; } else if (hook.startIndex > operation.startIndex) { throw new InvalidOperationException(operation, hook); } else if (hook.startIndex == operation.startIndex && operation.length > hook.length) { throw new InvalidOperationException(operation, hook); } else if (hook.startIndex == operation.startIndex && operation.length < hook.length) { hook.length += delta; } else if (hook.startIndex == operation.startIndex) { hook.length = operation.lengthNewString; } else if (hookLastEditedIndex >= operationEndIndex) { hook.length += delta; } else if (hookLastEditedIndex >= operation.startIndex) { throw new InvalidOperationException(operation, hook); } else if (hookLastEditedIndex < operation.startIndex) { // Do nothing } else { throw new InvalidOperationException(operation, hook, "Unexpected situation"); } } } if (TokenHook.TokenType.XML.equals(operation.tokenType)) { for (TokenHook hook : this.xml) { int hookLastEditedIndex = hook.startIndex + hook.length - 1; if (hook.startIndex >= operationEndIndex) { hook.startIndex += delta; } else if (hook.startIndex > operation.startIndex) { throw new InvalidOperationException(operation, hook); } else if (hook.startIndex == operation.startIndex && operation.length > hook.length) { throw new InvalidOperationException(operation, hook); } else if (hook.startIndex == operation.startIndex && operation.length < hook.length) { hook.length += delta; } else if (hook.startIndex == operation.startIndex) { hook.length = operation.lengthNewString; } else if (hookLastEditedIndex >= operationEndIndex) { hook.length += delta; } else if (hookLastEditedIndex >= operation.startIndex) { throw new InvalidOperationException(operation, hook); } else if (hookLastEditedIndex < operation.startIndex) { // Do nothing } else { throw new InvalidOperationException(operation, hook, "Unexpected situation"); } } } if (!TokenHook.TokenType.Word.equals(operation.tokenType)) { this.currentString.replace(operation.startIndex, operationEndIndex, operation.newString); } if (save) { if (operation.tokenType != null) { if (TokenHook.TokenType.XML.equals(operation.tokenType)) { TokenHook hook = new TokenHook(operation.startIndex, operation.lengthNewString, operation.tokenType); this.xml.add(hook); } else { if (this.tokenMask == null) { this.tokenMask = new TokenMask(this.currentString.length()); } this.tokenMask.setToken(operation.startIndex, operation.lengthNewString); } } this.changeLog.push(operation); } } }