package jeffaschenk.commons.touchpoint.model.threads; /** * CircularObjectStack.java * Provides a Stack Accessible from Multiple Threads by * Synchronizing access methods for the Stack. * <p/> * Created on September 29, 2005, 7:16 PM * * @author jeff.schenk */ public class CircularObjectStack { private CircularObjectStackNode head_stacknode = null; private CircularObjectStackNode tail_stacknode = null; // ************************** // Constants for Switch. private static final int STACK_PUSH_OPERATION = 1; private static final int STACK_POP_OPERATION = 2; private static final int STACK_INSERT_OPERATION = 3; private static final int STACK_GETNEXT_OPERATION = 4; /** * Creates a new instance of CircularObjectStack */ public CircularObjectStack() { } /** * push, Will Insert an Object Reference to the Bottom of the Stack. */ public synchronized void push(Object o) { this.stackOperation(o, STACK_PUSH_OPERATION); } // End of push Method. /** * insert, Will Insert an Object Reference to the Top of the Stack. */ public synchronized void insert(Object o) { this.stackOperation(o, STACK_INSERT_OPERATION); } // End of insert Method. /** * locate, Will locate an Object in the Stack. */ public synchronized Object locate(Object o) { if (this.head_stacknode == null) { return null; } // ******************************** // Iterate to Find Object In Stack. CircularObjectStackNode stacknode = this.head_stacknode; do { if (stacknode.object == o) { return stacknode.object; } stacknode = stacknode.next_object; } while (stacknode != this.head_stacknode); // *************************************** // Return Null for a Not Found Condition. return null; } // End of locate Method. /** * showsStack in String Form. */ public synchronized String showStack() { StringBuffer sb = new StringBuffer(); if (this.head_stacknode == null) { return null; } // ******************************** // Iterate to show Objects In Stack. CircularObjectStackNode stacknode = this.head_stacknode; sb.append("["); do { sb.append(" -> "); sb.append(stacknode.object.toString()); stacknode = stacknode.next_object; } while (stacknode != this.head_stacknode); // *************************************** // Return String sb.append("]"); return sb.toString(); } // End of showStack Method. /** * showsStack in String Form. */ public synchronized String showReverseStack() { StringBuffer sb = new StringBuffer(); if (this.tail_stacknode == null) { return null; } // ******************************** // Iterate to show Objects In Stack. CircularObjectStackNode stacknode = this.tail_stacknode; sb.append("["); do { sb.append(" <- "); sb.append(stacknode.object.toString()); stacknode = stacknode.previous_object; } while (stacknode != this.tail_stacknode); // *************************************** // Return String sb.append("]"); return sb.toString(); } // End of showStack Method. /** * getNext, Will Obtain Next Object from the Stack. * Will continue Circular Path Never Ending, until * Stack is Empty. */ public synchronized Object getNext() { return this.stackOperation(null, STACK_GETNEXT_OPERATION); } // End of getNext Method. /** * pop, Will Obtain Last Object from the Stack. * Will continue Circular Path Never Ending, unit * Stack is Empty. */ public synchronized Object pop() { return this.stackOperation(null, STACK_POP_OPERATION); } // End of pop Method. /** * hasModeNodes provides an indication if * we in fact at this time have more Nodes in the * Stack. * If this is true and you perform a getNext/pull or * pop and you can receive a null object. This indicates * that another thread has already taken the last * object from the stack. */ public synchronized boolean hasMoreNodes() { if (this.head_stacknode == null) { return false; } return true; } // End of hasMoreNodes Method. /** * Size Method to obtian number of objects * in the Node Stack. */ public synchronized int size() { int size = 0; if (this.head_stacknode == null) { return size; } // ******************************** // Iterate to Find Object In Stack. CircularObjectStackNode stacknode = this.head_stacknode; do { size++; stacknode = stacknode.next_object; } while (stacknode != this.head_stacknode); // *************************************** // Return Null for a Not Found Condition. return size; } // End of size Method. // ************************************ // PRIVATE COMMON METHODS. // ************************************ /** * Private Method to perform a Find of an Object in the Stack. */ private synchronized CircularObjectStackNode find(Object o) { if (this.head_stacknode == null) { return null; } // ******************************** // Iterate to Find Object In Stack. CircularObjectStackNode stacknode = this.head_stacknode; do { if (stacknode.object == o) { return stacknode; } stacknode = stacknode.next_object; } while (stacknode != this.head_stacknode); // *************************************** // Return Null for a Not Found Condition. return null; } // End of find Method. /** * stackOperation, Will provide common private method to synchronize Insert * Push, POP, GetNext behavior to/from the Object Stack. */ private synchronized Object stackOperation(Object o, int operation) { // ************************** // Initialize. boolean push = false; Object robject = null; // ***************************** // Switch based Upon Operation. switch (operation) { // ********************************* // Perform PUSH or INSERT to place // Entry onto the Stack. case STACK_PUSH_OPERATION: push = true; case STACK_INSERT_OPERATION: CircularObjectStackNode stacknode = new CircularObjectStackNode(); stacknode.object = o; if (this.head_stacknode == null) { stacknode.next_object = stacknode.previous_object = stacknode; this.head_stacknode = this.tail_stacknode = stacknode; } // End of If check for First Insertion. else if (push) { stacknode.previous_object = this.tail_stacknode; stacknode.next_object = this.head_stacknode; this.tail_stacknode.next_object = stacknode; this.head_stacknode.previous_object = stacknode; this.tail_stacknode = stacknode; } // End of Push to Bottom of Stack. else { stacknode.next_object = this.head_stacknode; stacknode.previous_object = this.tail_stacknode; this.head_stacknode.previous_object = stacknode; this.tail_stacknode.next_object = stacknode; this.head_stacknode = stacknode; } // End of Insert to Top of Stack. break; // ********************************* // Perform Getnext, final processing // will deleted this object from the // stack. case STACK_GETNEXT_OPERATION: if (this.head_stacknode != null) { robject = this.head_stacknode.object; this.removeHead(robject); } // End of Check for Nothing in Stack. break; // ********************************* // Perform POP, final processing // will deleted this object from the // stack. case STACK_POP_OPERATION: if (this.tail_stacknode != null) { robject = this.tail_stacknode.object; this.removeTail(robject); } // End of Check for Nothing in Stack. break; // ********************************* // Default do Nothing. default: } // End of Switch statement. // *************************** // Return Object, could // be "NULL" depending upon // Operation. return robject; } // End of stackOperation Common synchronized Private Method. /** * Private Remove Method to remove a reference from the top of the stack. */ private synchronized void removeHead(Object o) { //System.out.println("++ Removing Current Head Object:"+o.toString()); // ****************************** // Check for Last Node in the // Stack. if (this.head_stacknode == this.tail_stacknode) { this.head_stacknode = this.tail_stacknode = null; return; } // End of Check for Last Node in Stack. // ************************************ // Remove Reference and Join Together. this.head_stacknode = this.head_stacknode.next_object; this.head_stacknode.previous_object = this.tail_stacknode; this.tail_stacknode.next_object = this.head_stacknode; } // End of deleteHead Method. /** * Private Remove Method to remove a reference from the bottom of the stack. */ private synchronized void removeTail(Object o) { //System.out.println("++ Removing Current Tail Object:"+o.toString()); // ****************************** // Check for Last Node in the // Stack. if (this.head_stacknode == this.tail_stacknode) { this.head_stacknode = this.tail_stacknode = null; return; } // End of Check for Last Node in Stack. // ************************************ // Remove Reference and Join Together. this.tail_stacknode = this.tail_stacknode.previous_object; this.tail_stacknode.next_object = this.head_stacknode; this.head_stacknode.previous_object = this.tail_stacknode; } // End of deleteTail Method. } ///:~ End of CircularObjectStack Class.