/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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.drools.core.util.index; import org.drools.core.common.InternalFactHandle; import org.drools.core.reteoo.TupleMemory; import org.drools.core.spi.Tuple; import org.drools.core.util.Entry; import org.drools.core.util.FastIterator; import org.drools.core.util.Iterator; import org.drools.core.util.LinkedList; public class TupleList implements TupleMemory, Entry<TupleList> { public static final long serialVersionUID = 510l; private TupleList next; private Tuple first; private Tuple last; private TupleHashTableIterator iterator; private int size; public TupleList() { } public TupleList( Tuple first, Tuple last, int size ) { this.first = first; this.last = last; this.size = size; } public boolean isEmpty() { return size == 0; } public Tuple getFirst(Tuple rightTuple) { return this.first; } public Tuple getFirst() { return this.first; } public Tuple getLast() { return this.last; } public void clear() { this.first = null; this.last = null; size = 0; } public void removeAdd(Tuple tuple) { remove(tuple); add(tuple); } public void add(final Tuple tuple) { if ( this.last != null ) { this.last.setNext( tuple ); tuple.setPrevious( this.last ); this.last = tuple; } else { this.first = tuple; this.last = tuple; } tuple.setMemory( this ); this.size++; } public void remove(final Tuple tuple) { Tuple previous = tuple.getPrevious(); Tuple next = tuple.getNext(); if ( previous != null && next != null ) { // remove from middle previous.setNext( next ); next.setPrevious( previous ); } else if ( next != null ) { // remove from first this.first = next; next.setPrevious( null ); } else if ( previous != null ) { // remove from end this.last = previous; previous.setNext( null ); } else { // remove everything this.last = null; this.first = null; } tuple.clear(); this.size--; } public Tuple removeFirst() { Tuple tuple = this.first; if ( this.last == tuple ) { this.last = null; this.first = null; } else { this.first = tuple.getNext(); if ( this.first != null ) { this.first.setPrevious(null); } } tuple.clear(); this.size--; return tuple; } public boolean contains(final Tuple tuple) { return get( tuple ) != null; } public Tuple get(final Tuple tuple) { Tuple current = this.first; while ( current != null ) { if ( tuple.equals( current ) ) { return current; } current = current.getNext(); } return null; } public Tuple get(final InternalFactHandle handle) { Tuple current = this.first; while ( current != null ) { if ( handle == current.getFactHandle() ) { return current; } current = current.getNext(); } return null; } public int size() { return this.size; } public Tuple[] toArray() { Tuple[] tuples = new Tuple[this.size]; Tuple current = first; for ( int i = 0; i < this.size; i++ ) { tuples[i] = current; current = current.getNext(); } return tuples; } @Override public IndexType getIndexType() { return TupleMemory.IndexType.NONE; } public FastIterator fastIterator() { return LinkedList.fastIterator; // contains no state, so ok to be static } public FastIterator fullFastIterator() { return LinkedList.fastIterator; // contains no state, so ok to be static } public FastIterator fullFastIterator(Tuple tuple) { return LinkedList.fastIterator; // contains no state, so ok to be static } public Iterator<Tuple> iterator() { if ( this.iterator == null ) { this.iterator = new TupleHashTableIterator(); } this.iterator.reset( this.first ); return this.iterator; } public static class TupleHashTableIterator implements Iterator<Tuple> { private Tuple current; public void reset(Tuple first) { this.current = first; } public Tuple next() { if ( this.current != null ) { Tuple returnValue = this.current; this.current = current.getNext(); return returnValue; } else { return null; } } public void remove() { // do nothing } } public boolean isIndexed() { return false; } public TupleList getNext() { return this.next; } public void setNext(final TupleList next) { this.next = next; } public String toString() { StringBuilder builder = new StringBuilder(); Iterator it = iterator(); for ( Tuple tuple = (Tuple) it.next(); tuple != null; tuple = (Tuple) it.next() ) { builder.append(tuple).append("\n"); } return builder.toString(); } protected void copyStateInto(TupleList other) { other.next = next; other.first = first; other.last = last; other.iterator = iterator; other.size = size; for ( Tuple current = first; current != null; current = current.getNext() ) { current.setMemory(other); } } }