001: // ============================================================================
002: // $Id: FindMismatch.java,v 1.17 2006/12/05 04:52:38 davidahall Exp $
003: // Copyright (c) 2003-2005 David A. Hall
004: // ============================================================================
005: // The contents of this file are subject to the Common Development and
006: // Distribution License (CDDL), Version 1.0 (the License); you may not use this
007: // file except in compliance with the License. You should have received a copy
008: // of the the License along with this file: if not, a copy of the License is
009: // available from Sun Microsystems, Inc.
010: //
011: // http://www.sun.com/cddl/cddl.html
012: //
013: // From time to time, the license steward (initially Sun Microsystems, Inc.) may
014: // publish revised and/or new versions of the License. You may not use,
015: // distribute, or otherwise make this file available under subsequent versions
016: // of the License.
017: //
018: // Alternatively, the contents of this file may be used under the terms of the
019: // GNU Lesser General Public License Version 2.1 or later (the "LGPL"), in which
020: // case the provisions of the LGPL are applicable instead of those above. If you
021: // wish to allow use of your version of this file only under the terms of the
022: // LGPL, and not to allow others to use your version of this file under the
023: // terms of the CDDL, indicate your decision by deleting the provisions above
024: // and replace them with the notice and other provisions required by the LGPL.
025: // If you do not delete the provisions above, a recipient may use your version
026: // of this file under the terms of either the CDDL or the LGPL.
027: //
028: // This library is distributed in the hope that it will be useful,
029: // but WITHOUT ANY WARRANTY; without even the implied warranty of
030: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
031: // ============================================================================
032:
033: package net.sf.jga.fn.algorithm;
034:
035: import java.util.Collection;
036: import java.util.Collections;
037: import java.util.Vector;
038: import net.sf.jga.fn.BinaryFunctor;
039: import net.sf.jga.fn.UnaryFunctor;
040: import net.sf.jga.fn.comparison.NotEqualTo;
041: import net.sf.jga.util.EmptyIterator;
042: import net.sf.jga.util.FindIterator;
043: import net.sf.jga.util.LookAheadIterator;
044: import java.util.Iterator;
045:
046: /**
047: * Locates the next element in an iteration that is not equal to the
048: * corresponding element in a given collection.
049: * <p>
050: * To Serialize a FindMismatch, the generic parameter T must be serializable.
051: * <p>
052: * Copyright © 2003-2005 David A. Hall
053: *
054: * @author <a href="mailto:davidahall@users.sourceforge.net">David A. Hall</a>
055: * @deprecated
056: **/
057:
058: public class FindMismatch<T> extends LookAheadFunctor<T> {
059:
060: static final long serialVersionUID = -5406536818520367561L;
061:
062: // The collection of elements against which an iteration will be compared
063: private Collection<? extends T> _elements;
064:
065: // functor used to compare an element in the iteration and the collection
066: private BinaryFunctor<T, T, Boolean> _bf;
067:
068: // The iterator used for a given call to fn
069: private LookAheadIterator<T> _elemIter;
070:
071: // The element that was not matched
072: private T _mismatch;
073:
074: /**
075: * Builds a FindMismatch functor that uses !equals() to compare elements.
076: * If the collection is null, an empty collection will be used for
077: * comparison.
078: */
079: public FindMismatch(Collection<? extends T> elements) {
080: this (elements, new NotEqualTo<T>());
081: }
082:
083: /**
084: * Builds a FindMismatch functor that uses the given functor to compare
085: * elements. The functor is expected to compare two arguments and return
086: * TRUE if they are <b>not</b> equal. If the collection is null, an empty
087: * collection will be used for comparison.
088: */
089: public FindMismatch(Collection<? extends T> elements,
090: BinaryFunctor<T, T, Boolean> neq) {
091: _elements = (elements == null) ? new Vector<T>() : elements;
092: _bf = neq;
093: }
094:
095: /**
096: * Builds one-time use FindMismatch finder that will test against the
097: * contents of an iteration rather than a collection. The functor is
098: * expected to compare two arguments and return TRUE if they are <b>not</b>
099: * equal.
100: * <p>
101: * A FindMismatch built this way cannot be used more than once as the
102: * contents of the iteration will be consumed in the first execution.
103: */
104: public FindMismatch(Iterator<? extends T> iter,
105: BinaryFunctor<T, T, Boolean> neq) {
106: if (iter == null)
107: iter = new EmptyIterator<T>();
108:
109: _elemIter = new LookAheadIterator<T>(iter);
110: _bf = neq;
111: }
112:
113: /**
114: * Returns the collection against which the argument will be compared. When
115: * called on a FindMismatch built with an iteration rather than a collection,
116: * this method will return null
117: */
118: public Collection<? extends T> getElements() {
119: return (_elements == null) ? null : Collections
120: .unmodifiableCollection(_elements);
121: }
122:
123: /**
124: * Returns the functor that is used to test matching elements
125: */
126:
127: public BinaryFunctor<T, T, Boolean> getComparisonFn() {
128: return _bf;
129: }
130:
131: /**
132: * Returns the mismatched element in the given collection/iteration on the
133: * last call to fn(). If the iterator passed to the last call to fn() had
134: * no mismatch for the length of the collection, then this method returns
135: * null.
136: * @throws IllegalStateException if called before a call to fn.
137: */
138:
139: // NOTE: the signature changed to fix bug 919269. The old signature was
140: // public LookAheadIterator<T> getMismatchedElement
141: public T getMismatchedElement() {
142: if (_elemIter == null)
143: throw new IllegalStateException();
144:
145: return _mismatch;
146: }
147:
148: // UnaryFunctor Interface
149:
150: /**
151: * Locates the first/next element in an iteration that is not the same as
152: * the corresponding element in the given collection/iteration.
153: * @return an iterator whose next() [if it hasNext()] points to the next
154: * element in the iteration that does not match the corresponding element in
155: * the given collection. If no such element exists and the iteration is
156: * longer than the the given collection, then the returned iterator's next()
157: * points to the first element that does not exist in the given collection.
158: * If no mismatched element exists and the collection is at least as long as
159: * the iteration, then the returned iterator's hasNext() will be false.
160: */
161: public LookAheadIterator<T> fn(Iterator<? extends T> iterator) {
162: if (_elemIter == null)
163: _elemIter = new LookAheadIterator<T>(_elements.iterator());
164:
165: LookAheadIterator<T> lai = wrap(iterator, 1);
166: while (lai.hasNextPlus(1) && _elemIter.hasNextPlus(1)) {
167: T arg1 = lai.peek(1);
168: T arg2 = _elemIter.peek(1);
169: if (_bf.fn(arg1, arg2)) {
170: _mismatch = _elemIter.next();
171: return lai;
172: }
173: lai.next();
174: _elemIter.next();
175: }
176:
177: return lai;
178: }
179:
180: /**
181: * Calls the Visitor's <code>visit(FindMismatch)</code> method, if it
182: * implements the nested Visitor interface.
183: */
184: public void accept(net.sf.jga.fn.Visitor v) {
185: if (v instanceof FindMismatch.Visitor)
186: ((FindMismatch.Visitor) v).visit(this );
187: else
188: v.visit(this );
189: }
190:
191: // Object overrides
192:
193: public String toString() {
194: return "FindMismatch";
195: }
196:
197: // AcyclicVisitor
198:
199: /**
200: * Interface for classes that may interpret a <b>FindMismatch</b>
201: * functor
202: */
203: public interface Visitor extends net.sf.jga.fn.Visitor {
204: public void visit(FindMismatch host);
205: }
206:
207: }
|