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

com.topologi.diffx.algorithm.ElementState Maven / Gradle / Ivy

Go to download

docx4j is a library which helps you to work with the Office Open XML file format as used in docx documents, pptx presentations, and xlsx spreadsheets.

There is a newer version: 6.1.2
Show newest version
package com.topologi.diffx.algorithm;

import com.topologi.diffx.event.DiffXEvent;
import com.topologi.diffx.event.CloseElementEvent;
import com.topologi.diffx.event.OpenElementEvent;

/**
 * Maintains the state of open and closed elements during the processing the Diff-X
 * algorithm.
 *
 * 

This class has two purposes, firstly to provide an object that is more specialised * than the generic lists and stack for use by the DiffX algorithms. Second, to deleguate * some of the complexity of algorithm. * *

This class has several methods that are similar to List interface * but does not implement it. * *

This class is not synchronised and is not meant to be serialisable. * * @author Christophe Lauret * @version 7 April 2005 */ final class ElementState { /** * The stack of open elements. */ private transient OpenElementEvent[] openElements; /** * The stack open elements changes. */ private transient char[] openChanges; /** * The size of both lists (the number of elements they contains). */ private transient int size; /** * Constructs an stack of elements with the specified initial capacity. * * @param initialCapacity The initial capacity of the list. * @throws IllegalArgumentException if the specified initial capacity is negative. */ public ElementState(int initialCapacity) throws IllegalArgumentException { if (initialCapacity < 0) throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity); this.openElements = new OpenElementEvent[initialCapacity]; this.openChanges = new char[initialCapacity]; } /** * Constructs an empty stack with an initial capacity of 12. */ public ElementState() { this(12); } /** * Increases the capacity of this class instance, if necessary, to ensure * that it can hold at least the number of elements specified by the * minimum capacity argument. * * @param minCapacity The desired minimum capacity. */ public void ensureCapacity(int minCapacity) { int oldCapacity = openElements.length; if (minCapacity > oldCapacity) { // make a copy of the old arrays. OpenElementEvent[] oldElements = this.openElements; char[] oldChanges = this.openChanges; int newCapacity = (oldCapacity * 3) / 2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; // create new arrays this.openElements = new OpenElementEvent[newCapacity]; this.openChanges = new char[newCapacity]; // copy the values of the old arrays into the new ones System.arraycopy(oldElements, 0, this.openElements, 0, this.size); System.arraycopy(oldChanges, 0, this.openChanges, 0, this.size); } } /** * Returns the number of elements in this stack. * * @return the number of elements in this stack. */ public int size() { return this.size; } /** * Tests if this list has no elements. * * @return true if this list has no elements; * false otherwise. */ public boolean isEmpty() { return size == 0; } /** * Returns true if this list contains the specified element. * * @param element Element whose presence is to be tested. * * @return true if the specified element is present; * false otherwise. */ public boolean contains(OpenElementEvent element) { return indexOf(element) >= 0; } /** * Searches for the first occurrence of the given argument, testing * for equality using the equals method. * * @param element The open elemnt to find. * * @return The index of the first occurrence of the argument in this list; * returns -1= 0; i--) if (this.openElements[i] == null) return i; } else { for (int i = this.size - 1; i >= 0; i--) if (element.equals(this.openElements[i])) return i; } return -1; } // Maintenance methods ------------------------------------------------------------------------ /** * Returns the current open element. * * @return The current open element; or null if none. */ public OpenElementEvent current() { if (!isEmpty()) return this.openElements[size - 1]; else return null; } /** * Returns the change of the current open element. * * @return The change of the current open element; or ' ' if none. */ public char currentChange() { if (!isEmpty()) return this.openChanges[size - 1]; else return ' '; } /** * Indicates whether the specified event is a close element that * matches the name and URI of the current open element. * * @param e The event to check. * * @return true if it matches the current element; * false otherwise. */ public boolean matchCurrent(DiffXEvent e) { // cannot match if empty if (isEmpty()) return false; // cannot match if not a close element event if (!(e instanceof CloseElementEvent)) return false; // check if they match return ((CloseElementEvent)e).match(current()); } /** * Updates the state from the inserted event. * * @param e The inserted event. */ public void insert(DiffXEvent e) { if (e instanceof OpenElementEvent) push((OpenElementEvent)e, '+'); else if (e instanceof CloseElementEvent) pop(); } /** * Updates the state from the formatted event. * * @param e The formatted event. */ public void format(DiffXEvent e) { if (e instanceof OpenElementEvent) push((OpenElementEvent)e, '='); else if (e instanceof CloseElementEvent) pop(); } /** * Updates the state from the deleted event. * * @param e The deleted event. */ public void delete(DiffXEvent e) { if (e instanceof OpenElementEvent) push((OpenElementEvent)e, '-'); else if (e instanceof CloseElementEvent) pop(); } /** * Indicates whether the specified event is a close element that * matches the name and URI of the current open element. * * @param e The event to check. * * @return true if it matches the current element; * false otherwise. */ public boolean okFormat(DiffXEvent e) { // cannot match if not a close element event if (!(e instanceof CloseElementEvent)) return true; // cannot match if empty if (isEmpty()) return false; // check if they match return ((CloseElementEvent)e).match(current()) && openChanges[size - 1] == '='; } /** * Indicates whether the specified event is a close element that * matches the name and URI of the current open element. * * @param e The event to check. * * @return true if it matches the current element; * false otherwise. */ public boolean okInsert(DiffXEvent e) { // cannot match if not a close element event if (!(e instanceof CloseElementEvent)) return true; // cannot match if empty if (isEmpty()) return false; // check if they match return ((CloseElementEvent)e).match(current()) && openChanges[size - 1] == '+'; } /** * Indicates whether the specified event is a close element that * matches the name and URI of the current open element. * * @param e The event to check. * * @return true if it matches the current element; * false otherwise. */ public boolean okDelete(DiffXEvent e) { // cannot match if not a close element event if (!(e instanceof CloseElementEvent)) return true; // cannot match if empty if (isEmpty()) return false; // check if they match return ((CloseElementEvent)e).match(current()) && openChanges[size - 1] == '-'; } // Stack methods ------------------------------------------------------------------------ /** * Push the specified open element and flags it with the specified change. * * @param e The open element to push. * @param c The character corresponding to change. */ private void push(OpenElementEvent e, char c) { ensureCapacity(size + 1); this.openElements[size] = e; this.openChanges[size] = c; size++; } /** * Removes the last element from the top of the stack. * * @return The last element from the top of the stack. */ public OpenElementEvent pop() { if (size > 0) { this.size--; return this.openElements[size]; } return null; } // Positional Access Operations --------------------------------------------------------- /** * Returns the open element at the specified position in this list. * * @param index index of element to return. * * @return The element at the specified position in this list. * * @throws IndexOutOfBoundsException if index is out of range * (index < 0 || index >= size()). */ public OpenElementEvent get(int index) throws IndexOutOfBoundsException { checkRange(index); return openElements[index]; } /** * Appends the specified element to the end of this list. * * @param o element to be appended to this list. * @return true (as per the general contract of Collection.add). */ private boolean add(OpenElementEvent o) { ensureCapacity(size + 1); openElements[size++] = o; return true; } /** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). * * @param index The index of the element to removed. * * @return The element that was removed from the list. * * @throws IndexOutOfBoundsException if index is out of range * (index < 0 || index >= size()). */ public OpenElementEvent remove(int index) throws IndexOutOfBoundsException { checkRange(index); OpenElementEvent oldValue = this.openElements[index]; int numMoved = size - index - 1; if (numMoved > 0) System.arraycopy(this.openElements, index+1, this.openElements, index, numMoved); this.openElements[--size] = null; // Let gc do its work return oldValue; } /** * Removes all of the elements from this list. The list will * be empty after this call returns. */ public void clear() { // Let gc do its work for (int i = 0; i < size; i++) openElements[i] = null; size = 0; } /** * Checks if the given index is in range. If not, throw an appropriate * runtime exception. This method does *not* check if the index is * negative: It is always used immediately prior to an array access, * which throws an ArrayIndexOutOfBoundsException if index is negative. * * @param index The index to check. * * @throws IndexOutOfBoundsException if index is out of range * (index < 0 || index >= size()). */ private void checkRange(int index) throws IndexOutOfBoundsException { if (index >= this.size) throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy