Mega Code Archive

 
Categories / Java / Collections Data Structure
 

A class for you to extend when you want object to maintain a doubly linked list

/**    * Licensed to the Apache Software Foundation (ASF) under one or more  * contributor license agreements.  See the NOTICE file distributed with  * this work for additional information regarding copyright ownership.  * The ASF licenses this file to You under the Apache License, Version 2.0  * (the "License"); you may not use this file except in compliance with  * the License.  You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ /**  * Provides a base class for you to extend when you want object to maintain a  * doubly linked list to other objects without using a collection class.  *   * @author chirino  */ public class LinkedNode {     protected LinkedNode next = this;     protected LinkedNode prev = this;     protected boolean tail = true;     public LinkedNode getHeadNode() {         if (isHeadNode()) {             return this;         }         if (isTailNode()) {             return next;         }         LinkedNode rc = prev;         while (!rc.isHeadNode()) {             rc = rc.prev;         }         return rc;     }     public LinkedNode getTailNode() {         if (isTailNode()) {             return this;         }         if (isHeadNode()) {             return prev;         }         LinkedNode rc = next;         while (!rc.isTailNode()) {             rc = rc.next;         }         return rc;     }     public LinkedNode getNext() {         return tail ? null : next;     }     public LinkedNode getPrevious() {         return prev.tail ? null : prev;     }     public boolean isHeadNode() {         return prev.isTailNode();     }     public boolean isTailNode() {         return tail;     }     /**      * @param rightHead the node to link after this node.      * @return this      */     public LinkedNode linkAfter(LinkedNode rightHead) {         if (rightHead == this) {             throw new IllegalArgumentException("You cannot link to yourself");         }         if (!rightHead.isHeadNode()) {             throw new IllegalArgumentException("You only insert nodes that are the first in a list");         }         LinkedNode rightTail = rightHead.prev;         if (tail) {             tail = false;         } else {             rightTail.tail = false;         }         rightHead.prev = this; // link the head of the right side.         rightTail.next = next; // link the tail of the right side         next.prev = rightTail; // link the head of the left side         next = rightHead; // link the tail of the left side.         return this;     }     /**      * @param leftHead the node to link after this node.      * @return      * @return this      */     public LinkedNode linkBefore(LinkedNode leftHead) {         if (leftHead == this) {             throw new IllegalArgumentException("You cannot link to yourself");         }         if (!leftHead.isHeadNode()) {             throw new IllegalArgumentException("You only insert nodes that are the first in a list");         }         // The left side is no longer going to be a tail..         LinkedNode leftTail = leftHead.prev;         leftTail.tail = false;         leftTail.next = this; // link the tail of the left side.         leftHead.prev = prev; // link the head of the left side.         prev.next = leftHead; // link the tail of the right side.         prev = leftTail; // link the head of the right side.         return leftHead;     }     /**      * Removes this node out of the linked list it is chained in.      */     public void unlink() {         // If we are allready unlinked...         if (prev == this) {             reset();             return;         }         if (tail) {             prev.tail = true;         }         // Update the peers links..         next.prev = prev;         prev.next = next;         // Update our links..         reset();     }          public void reset() {         next = this;         prev = this;         tail = true;     } } ///////////////////////////////////// /**  * Licensed to the Apache Software Foundation (ASF) under one or more  * contributor license agreements.  See the NOTICE file distributed with  * this work for additional information regarding copyright ownership.  * The ASF licenses this file to You under the Apache License, Version 2.0  * (the "License"); you may not use this file except in compliance with  * the License.  You may obtain a copy of the License at  *  *      http://www.apache.org/licenses/LICENSE-2.0  *  * Unless required by applicable law or agreed to in writing, software  * distributed under the License is distributed on an "AS IS" BASIS,  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  * See the License for the specific language governing permissions and  * limitations under the License.  */ package org.apache.activemq.util; import junit.framework.TestCase; /**  * @author chirino  */ public class LinkedNodeTest extends TestCase {     static class IntLinkedNode extends LinkedNode {         public final int v;         public IntLinkedNode(int v) {             this.v = v;         };         @Override         public String toString() {             return "" + v;         }     }     IntLinkedNode i1 = new IntLinkedNode(1);     IntLinkedNode i2 = new IntLinkedNode(2);     IntLinkedNode i3 = new IntLinkedNode(3);     IntLinkedNode i4 = new IntLinkedNode(4);     IntLinkedNode i5 = new IntLinkedNode(5);     IntLinkedNode i6 = new IntLinkedNode(6);     public void testLinkAfter() {         i1.linkAfter(i2.linkAfter(i3));         // Order should be 1,2,3         assertTrue(i1.getNext() == i2);         assertTrue(i1.getNext().getNext() == i3);         assertNull(i1.getNext().getNext().getNext());         assertTrue(i3.getPrevious() == i2);         assertTrue(i3.getPrevious().getPrevious() == i1);         assertNull(i3.getPrevious().getPrevious().getPrevious());         assertTrue(i1.isHeadNode());         assertFalse(i1.isTailNode());         assertFalse(i2.isHeadNode());         assertFalse(i2.isTailNode());         assertTrue(i3.isTailNode());         assertFalse(i3.isHeadNode());         i1.linkAfter(i4.linkAfter(i5));         // Order should be 1,4,5,2,3         assertTrue(i1.getNext() == i4);         assertTrue(i1.getNext().getNext() == i5);         assertTrue(i1.getNext().getNext().getNext() == i2);         assertTrue(i1.getNext().getNext().getNext().getNext() == i3);         assertNull(i1.getNext().getNext().getNext().getNext().getNext());         assertTrue(i3.getPrevious() == i2);         assertTrue(i3.getPrevious().getPrevious() == i5);         assertTrue(i3.getPrevious().getPrevious().getPrevious() == i4);         assertTrue(i3.getPrevious().getPrevious().getPrevious().getPrevious() == i1);         assertNull(i3.getPrevious().getPrevious().getPrevious().getPrevious().getPrevious());         assertTrue(i1.isHeadNode());         assertFalse(i1.isTailNode());         assertFalse(i4.isHeadNode());         assertFalse(i4.isTailNode());         assertFalse(i5.isHeadNode());         assertFalse(i5.isTailNode());         assertFalse(i2.isHeadNode());         assertFalse(i2.isTailNode());         assertTrue(i3.isTailNode());         assertFalse(i3.isHeadNode());     }     public void testLinkBefore() {         i3.linkBefore(i2.linkBefore(i1));         assertTrue(i1.getNext() == i2);         assertTrue(i1.getNext().getNext() == i3);         assertNull(i1.getNext().getNext().getNext());         assertTrue(i3.getPrevious() == i2);         assertTrue(i3.getPrevious().getPrevious() == i1);         assertNull(i3.getPrevious().getPrevious().getPrevious());         assertTrue(i1.isHeadNode());         assertFalse(i1.isTailNode());         assertFalse(i2.isHeadNode());         assertFalse(i2.isTailNode());         assertTrue(i3.isTailNode());         assertFalse(i3.isHeadNode());         i2.linkBefore(i5.linkBefore(i4));         // Order should be 1,4,5,2,3         assertTrue(i1.getNext() == i4);         assertTrue(i1.getNext().getNext() == i5);         assertTrue(i1.getNext().getNext().getNext() == i2);         assertTrue(i1.getNext().getNext().getNext().getNext() == i3);         assertNull(i1.getNext().getNext().getNext().getNext().getNext());         assertTrue(i3.getPrevious() == i2);         assertTrue(i3.getPrevious().getPrevious() == i5);         assertTrue(i3.getPrevious().getPrevious().getPrevious() == i4);         assertTrue(i3.getPrevious().getPrevious().getPrevious().getPrevious() == i1);         assertNull(i3.getPrevious().getPrevious().getPrevious().getPrevious().getPrevious());         assertTrue(i1.isHeadNode());         assertFalse(i1.isTailNode());         assertFalse(i4.isHeadNode());         assertFalse(i4.isTailNode());         assertFalse(i5.isHeadNode());         assertFalse(i5.isTailNode());         assertFalse(i2.isHeadNode());         assertFalse(i2.isTailNode());         assertTrue(i3.isTailNode());         assertFalse(i3.isHeadNode());     }     public void testUnlink() {         i1.linkAfter(i2.linkAfter(i3));         i3.linkAfter(i4);         i1.linkBefore(i5);         i1.linkAfter(i6);         // Order should be 5,1,6,2,3,4         i4.unlink();         i5.unlink();         i6.unlink();         // Order should be 1,2,3         assertTrue(i1.getNext() == i2);         assertTrue(i1.getNext().getNext() == i3);         assertNull(i1.getNext().getNext().getNext());         assertTrue(i3.getPrevious() == i2);         assertTrue(i3.getPrevious().getPrevious() == i1);         assertNull(i3.getPrevious().getPrevious().getPrevious());         assertTrue(i1.isHeadNode());         assertFalse(i1.isTailNode());         assertFalse(i2.isHeadNode());         assertFalse(i2.isTailNode());         assertTrue(i3.isTailNode());         assertFalse(i3.isHeadNode());     } }