http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorArray.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorArray.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorArray.java new file mode 100644 index 0000000..ee45935 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorArray.java @@ -0,0 +1,92 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; + +/** Iterator over a Java base array */ +public final class IteratorArray<T> implements Iterator<T> +{ + /** Iterator over all the array elements */ + public static <T> IteratorArray<T> create(T[] array) + { return new IteratorArray<>(array, 0, array.length) ; } + + /** Iterator over array elements from start (inclusive) to finish (exclusive) */ + public static <T> IteratorArray<T> create(T[] array, int start, int finish) + { return new IteratorArray<>(array, start, finish) ; } + + private int idx ; + private int finishIdx ; + private T[] array ; + + private IteratorArray(T[] array, int start, int finish) + { + if ( start < 0 ) + throw new IllegalArgumentException("Start: "+start) ; + + if ( start > finish ) + throw new IllegalArgumentException("Start >= finish: "+start+" >= "+finish) ; + +// Instead: truncate to array length +// if ( finish > array.length ) +// throw new IllegalArgumentException("Finish outside array") ; +// +// Instead: immediate end iterator +// if ( start >= array.length ) +// throw new IllegalArgumentException("Start outside array") ; + + this.array = array ; + idx = start ; + finishIdx = finish ; + if ( idx < 0 ) + idx = 0 ; + if ( finishIdx > array.length ) + finishIdx = array.length ; + } + + @Override + public boolean hasNext() + { +// if ( idx < 0 ) +// return false ; + if ( idx >= finishIdx ) + return false ; + return true ; + } + + public T current() + { + if ( idx >= finishIdx ) + throw new NoSuchElementException() ; + return array[idx] ; + } + + @Override + public T next() + { + if ( ! hasNext() ) + throw new NoSuchElementException() ; + return array[idx++] ; + } + + @Override + public void remove() + { throw new UnsupportedOperationException("ArrayIterator") ; } +}
http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorBlockingQueue.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorBlockingQueue.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorBlockingQueue.java new file mode 100644 index 0000000..c11b262 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorBlockingQueue.java @@ -0,0 +1,73 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; +import java.util.concurrent.BlockingQueue ; + +/** Iterator over a blocking queue until queue end seen */ + +public class IteratorBlockingQueue<T> implements Iterator<T> +{ + private BlockingQueue<T> queue ; + private boolean finished = false ; + private T slot = null ; + private T endMarker ; + + public IteratorBlockingQueue(BlockingQueue<T> queue, T endMarker) { this.queue = queue ; this.endMarker = endMarker ; } + + @Override + public boolean hasNext() + { + if ( finished ) return false ; + if ( slot != null ) return true ; + try + { + slot = queue.take() ; + if ( slot == endMarker ) + { + finished = true ; + slot = null ; + return false ; + } + return true ; + + } catch (InterruptedException ex) + { + ex.printStackTrace(); + + } + return false ; + } + + @Override + public T next() + { + if ( ! hasNext() ) + throw new NoSuchElementException() ; + T item = slot ; + slot = null ; + return item ; + } + + @Override + public void remove() + { throw new UnsupportedOperationException() ; } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorConcat.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorConcat.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorConcat.java new file mode 100644 index 0000000..65e6430 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorConcat.java @@ -0,0 +1,104 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.List ; +import java.util.NoSuchElementException ; + +import org.apache.jena.atlas.lib.DS ; + +/** Iterator of Iterators + * IteratorConcat is better when there are lots of iterators to be joined. + * IteratorCons is slightly better for two iterators. + */ + +public class IteratorConcat<T> implements Iterator<T> +{ + private List<Iterator<T>> iterators = DS.list(); + int idx = -1 ; + private Iterator<T> current = null ; + private Iterator<T> removeFrom = null ; + boolean finished = false ; + + /** + * Usually, it is better to create an IteratorConcat explicitly and add iterator if there are going to be many. + * @param iter1 + * @param iter2 + * @return Iterator + * @see IteratorCons + */ + public static <T> Iterator<T> concat(Iterator<T> iter1, Iterator<T> iter2) + { + if (iter2 == null) return iter1 ; + if (iter1 == null) return iter2 ; + IteratorConcat<T> c = new IteratorConcat<>() ; + c.add(iter1) ; + c.add(iter2) ; + return c ; + } + + public IteratorConcat() {} + + + public void add(Iterator<T> iter) { iterators.add(iter) ; } + + @Override + public boolean hasNext() + { + if ( finished ) + return false ; + + if ( current != null && current.hasNext() ) + return true ; + + while ( idx < iterators.size()-1 ) + { + idx++ ; + current = iterators.get(idx) ; + if ( current.hasNext() ) + return true ; + // Nothing here - move on. + current = null ; + } + // idx has run off the end. + return false ; + } + + @Override + public T next() + { + if ( ! hasNext() ) + throw new NoSuchElementException() ; + removeFrom = current ; + return current.next(); + } + + @Override + public void remove() + { + if ( null == removeFrom ) + throw new IllegalStateException("no calls to next() since last call to remove()") ; + + removeFrom.remove() ; + removeFrom = null ; + + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorCons.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorCons.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorCons.java new file mode 100644 index 0000000..c6cfd61 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorCons.java @@ -0,0 +1,122 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; + +/** IteratorCons : the concatenation of two iterators. + * See also {@link IteratorConcat}. + * If there potentially many iterators to be joined, it is better to + * create an IteratorConcat explicitly and add each iterator. + * IteratorCons is slightly better in the two iterator case. + */ +public class IteratorCons<T> implements Iterator<T>, Iterable<T> +{ + // No - we don't really need IteratorCons and IteratorConcat + // Historical - IteratorCons came first. + // IteratorConcat is nearly as good as IteratorCons in the small when it + // it is hard to see when it woudl matter much. + + private Iterator<? extends T> iter1 ; + private Iterator<? extends T> iter2 ; + private Iterator<? extends T> removeFrom ; + + public static <X> Iterator<X> create(Iterator<? extends X> iter1, Iterator<? extends X> iter2) + { + if ( iter1 == null && iter2 == null ) + return Iter.nullIterator() ; + + // The casts are safe because an iterator can only return X, and does not take an X an an assignment. + if ( iter1 == null ) + { + @SuppressWarnings("unchecked") + Iterator<X> x = (Iterator<X>)iter2 ; + return x ; + } + + if ( iter2 == null ) + { + @SuppressWarnings("unchecked") + Iterator<X> x = (Iterator<X>)iter1 ; + return x ; + } + + return new IteratorCons<>(iter1, iter2) ; + } + + private IteratorCons(Iterator<? extends T> iter1, Iterator<? extends T> iter2) + { + this.iter1 = iter1 ; + this.iter2 = iter2 ; + } + + @Override + public boolean hasNext() + { + if ( iter1 != null ) + { + if ( iter1.hasNext() ) return true ; + // Iter1 ends + iter1 = null ; + } + + if ( iter2 != null ) + { + if ( iter2.hasNext() ) return true ; + // Iter2 ends + iter2 = null ; + } + return false ; + } + + @Override + public T next() + { + if ( ! hasNext() ) + throw new NoSuchElementException("Iterator2.next") ; + if ( iter1 != null ) + { + removeFrom = iter1 ; + return iter1.next(); + } + if ( iter2 != null ) + { + removeFrom = iter2 ; + return iter2.next(); + } + throw new Error("Iterator2.next") ; + } + + @Override + public void remove() + { + if ( null == removeFrom ) + throw new IllegalStateException("no calls to next() since last call to remove()") ; + + removeFrom.remove() ; + removeFrom = null ; + } + + @Override + public Iterator<T> iterator() + { + return this ; + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDelayedInitialization.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDelayedInitialization.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDelayedInitialization.java new file mode 100644 index 0000000..807105e --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorDelayedInitialization.java @@ -0,0 +1,78 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; + +import org.apache.jena.atlas.lib.Closeable ; + +/** Class to delay the initialization of an iterator until first call of an Iterator operation. */ + +public abstract class IteratorDelayedInitialization<T> implements Iterator<T>, Closeable +{ + private boolean initialized = false ; + private Iterator<T> iterator ; + + public IteratorDelayedInitialization() {} + + private void init() + { + if ( ! initialized ) + { + initialized = true ; + iterator = initializeIterator() ; + } + } + + // Called exactly once + protected abstract Iterator<T> initializeIterator() ; + + @Override + public boolean hasNext() + { + init() ; + boolean b = iterator.hasNext() ; + if ( ! b ) + close() ; + return b ; + } + + @Override + public T next() + { + init() ; + try { return iterator.next() ; } + catch (NoSuchElementException ex) { close() ; throw(ex) ; } + } + + @Override + public void remove() + { + init() ; + iterator.remove() ; + } + + @Override + public void close() + { + Iter.close(iterator) ; + iterator = null ; + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorInteger.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorInteger.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorInteger.java new file mode 100644 index 0000000..6fff27c --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorInteger.java @@ -0,0 +1,61 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; + +public class IteratorInteger implements Iterator<Long> +{ + private final long start ; + private final long finish ; + private long current ; + + public static IteratorInteger range(long start, long finish) + { + return new IteratorInteger(start, finish) ; + } + + + /** [start, finish) */ + public IteratorInteger(long start, long finish) + { + this.start = start ; + this.finish = finish ; + this.current = start ; + } + + @Override + public boolean hasNext() + { + return ( current < finish ) ; + } + + @Override + public Long next() + { + Long v = current; + current++ ; + return v ; + } + + @Override + public void remove() + { throw new UnsupportedOperationException() ; } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorResourceClosing.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorResourceClosing.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorResourceClosing.java new file mode 100644 index 0000000..89a54aa --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorResourceClosing.java @@ -0,0 +1,107 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator; + +import org.apache.jena.atlas.AtlasException ; +import org.apache.jena.atlas.io.IO ; +import org.apache.jena.atlas.lib.Closeable ; + +/** + * This iterator will automatically close a {@link org.apache.jena.atlas.lib.Closeable} or {@link java.io.Closeable} + * resource when the iterator is exhausted. Alternatively, the resource will be closed when {@link #close()} is + * called. An {@link AtlasException} will be thrown if access is attempted after {@link #close()} has been called. + */ +public class IteratorResourceClosing<T> implements Iterator<T>, Closeable +{ + private final Iterator<T> iter ; + private final Object resource ; + private boolean finished; + + public IteratorResourceClosing(Iterator<T> iter, Closeable resource) + { + this.iter = iter; + this.resource = resource; + this.finished = false; + } + + public IteratorResourceClosing(Iterator<T> iter, java.io.Closeable resource) + { + this.iter = iter; + this.resource = resource ; + this.finished = false; + } + + private void checkFinished() + { + if (finished) throw new AtlasException("IteratorResourceClosing is closed, no further operations can be performed on it.") ; + } + + @Override + public boolean hasNext() + { + if (finished) + return false; + + boolean toReturn = iter.hasNext(); + + // Clean up if we are done + if (!toReturn) + { + close(); + } + return toReturn ; + } + + @Override + public T next() + { + checkFinished(); + return iter.next() ; + } + + @Override + public void remove() + { + checkFinished(); + iter.remove() ; + } + + @Override + public void close() + { + if (!finished) + { + Iter.close(iter) ; + if (null != resource) + { + if (resource instanceof Closeable) + { + ((Closeable)resource).close() ; + } + else + { + IO.close((java.io.Closeable)resource) ; + } + } + finished = true; + } + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorSlotted.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorSlotted.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorSlotted.java new file mode 100644 index 0000000..fd846dc --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorSlotted.java @@ -0,0 +1,117 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; + +import org.apache.jena.atlas.lib.Lib ; + +/** An Iterator with a one slot lookahead. */ +public abstract class IteratorSlotted<T> implements Iterator<T> +{ + private boolean finished = false ; + private boolean slotIsSet = false ; + private T slot = null ; + + protected IteratorSlotted() { } + + // -------- The contract with the subclasses + + /** Implement this, not next() or nextBinding() */ + protected abstract T moveToNext() ; + + /** Can return true here then null from moveToNext() to indicate end. */ + protected abstract boolean hasMore() ; + // alter add a flag to say if null is a legal value. + + /** Close the iterator. */ + protected void closeIterator() { } + + // -------- The contract with the subclasses + + protected boolean isFinished() { return finished ; } + + @Override + public final boolean hasNext() + { + if ( finished ) + return false ; + if ( slotIsSet ) + return true ; + + boolean r = hasMore() ; + if ( ! r ) + { + close() ; + return false ; + } + + slot = moveToNext() ; + if ( slot == null ) { + close() ; + return false ; + } + + slotIsSet = true ; + return true ; + } + + /** final - autoclose and registration relies on it - implement moveToNextBinding() */ + @Override + public final T next() + { + if ( ! hasNext() ) throw new NoSuchElementException(Lib.className(this)) ; + + T obj = slot ; + slot = null ; + slotIsSet = false ; + return obj ; + } + + /** Look at the next element - returns null when there is no element */ + public final T peek() + { + return peek(null) ; + } + + /** Look at the next element - returns dft when there is no element */ + public final T peek(T dft) + { + hasNext() ; + if ( ! slotIsSet ) return dft ; + return slot ; + } + + @Override + public final void remove() + { + throw new UnsupportedOperationException(Lib.className(this)+".remove") ; + } + + public final void close() + { + if ( finished ) + return ; + closeIterator() ; + slotIsSet = false ; + slot = null ; + finished = true ; + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorTruncate.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorTruncate.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorTruncate.java new file mode 100644 index 0000000..86ef52e --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorTruncate.java @@ -0,0 +1,79 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; + +/** Iterate while a condition return true, then stop */ +public class IteratorTruncate<T> implements Iterator<T> +{ + static public interface Test { boolean accept(Object object) ; } + private Test test ; + private T slot = null ; + private boolean active = true ; + private Iterator<T> iter ; + + public IteratorTruncate (Test test, Iterator<T> iter) + { this.test = test ; this.iter = iter ; } + + @Override + public boolean hasNext() + { + if ( ! active ) return false ; + if ( slot != null ) + return true ; + + if ( ! iter.hasNext() ) + { + active = false ; + return false ; + } + + slot = iter.next() ; + if ( test.accept(slot) ) + return true ; + // Once the test goes false, no longer yield anything. + Iter.close(iter) ; + active = false ; + iter = null ; + slot = null ; + return false ; + } + + @Override + public T next() + { + if ( ! hasNext() ) + throw new NoSuchElementException("IteratorTruncate.next") ; + T x = slot ; + slot = null ; + return x ; + } + + @Override + public void remove() + { throw new UnsupportedOperationException("IteratorTruncate.remove"); } + + public void close() { + if ( iter != null ) + Iter.close(iter) ; + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithBuffer.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithBuffer.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithBuffer.java new file mode 100644 index 0000000..7af9ac8 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithBuffer.java @@ -0,0 +1,132 @@ +/* + * 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.jena.atlas.iterator ; + +import java.util.ArrayList ; +import java.util.Iterator ; +import java.util.List ; +import java.util.NoSuchElementException ; + +/** + * Iterator that delays output by N slots so you can react to the output before + * it's yielded. See also {@link PeekIterator} (which predates this code). See also + * {@link IteratorWithHistory} for an iterator that remembers what it has yielded. + * + * @see PeekIterator + * @see PushbackIterator + * @see IteratorWithHistory + */ +public class IteratorWithBuffer<T> implements Iterator<T> { + private List<T> lookahead ; + private Iterator<T> iter ; + private int capacity ; + private boolean innerHasEnded = false ; + + public IteratorWithBuffer(Iterator<T> iter, int N) { + if ( N < 0 ) + throw new IllegalArgumentException("Buffering size < 0") ; + this.iter = iter ; + this.lookahead = new ArrayList<>(N) ; + this.capacity = N ; + // Fill the lookahead. + for ( int i = 0 ; i < N ; i++ ) { + if ( !iter.hasNext() ) { + atEndInner() ; + break ; + } + T nextItem = iter.next() ; + // System.out.println("Fill: "+nextItem) ; + lookahead.add(nextItem) ; + } + } + + @Override + public boolean hasNext() { + return lookahead.size() > 0 ; + } + + @Override + public T next() { + if ( !hasNext() ) + throw new NoSuchElementException(this.getClass().getName()) ; + + if ( !iter.hasNext() ) + atEndInner() ; + + T item = lookahead.remove(0) ; + // System.out.println("remove: "+item) ; + if ( iter.hasNext() ) { + // Should not throw NoSuchElementException. + T nextItem = iter.next() ; + // System.out.println("add : "+nextItem) ; + lookahead.add(nextItem) ; + } + return item ; + } + + @Override + public void remove() { + throw new UnsupportedOperationException("remove") ; + } + + /** + * Look at elements that will be returned by a subsequnet call of .next(). + * The next element is index 0, then index 1 etc. This operation is valid + * immediately after the constructor returns. Returns null for no such + * element (underlying iterator didn't yeild enough elements). Throws + * IndexOutOfBoundsException if an attempt i smade to go beyond the + * buffering window. + */ + public T peek(int idx) { + if ( idx < 0 || idx >= capacity ) + throw new IndexOutOfBoundsException("Index: " + idx) ; + if ( idx >= lookahead.size() ) + return null ; + return lookahead.get(idx) ; + } + + /** + * Return the current size of the lookahead. This can be used to tell the + * difference between an iterator returning null and an iterator that is + * just short. + */ + public int currentSize() { + return lookahead.size() ; + } + + /** + * Set the element to be returned by a subsequent .next(). Use with care. + * The original element to be returned at this position is lost. + */ + public void set(int idx, T item) { + lookahead.set(idx, item) ; + } + + /** Called when the underlying iterator ends */ + private void atEndInner() { + if ( !innerHasEnded ) { + innerHasEnded = true ; + endReachedInner() ; + } + } + + /** Called, once, at the end of the wrapped iterator. */ + protected void endReachedInner() {} + +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithHistory.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithHistory.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithHistory.java new file mode 100644 index 0000000..b5b800a --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWithHistory.java @@ -0,0 +1,109 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.ArrayList ; +import java.util.Iterator ; +import java.util.List ; +import java.util.NoSuchElementException ; + +/** Remembers the last N yields. + * See also {@link IteratorWithBuffer}, for an iterator that looks ahead to what it will yield. + * @see IteratorWithBuffer + * @see PeekIterator + * @see PushbackIterator + */ +public class IteratorWithHistory<T> implements Iterator<T> +{ + private List<T> history ; + private Iterator<T> iter ; + private int capacity ; + private boolean hasEnded = false ; + + public IteratorWithHistory(Iterator<T> iter, int N) { + this.iter = iter ; + this.history = new ArrayList<>(N) ; + this.capacity = N ; + } + + @Override + public boolean hasNext() { + boolean b = iter.hasNext() ; + if ( !b ) + atEnd() ; + return b ; + } + + @Override + public T next() { + T item = null ; + try { + item = iter.next() ; + } + catch (NoSuchElementException ex) { + atEnd() ; + } + // Shuffle up, add at bottom. + if ( history.size() >= capacity ) + history.remove(history.size() - 1) ; + history.add(0, item) ; + return item ; + } + + @Override + public void remove() + { throw new UnsupportedOperationException("remove") ; } + + /** + * return the previous i'th element returned by next(). 0 means last call of + * next. History is retained after the end of iteration. + * + * @return Element or null for no such element (that is for haven't yielded + * that many elements). + * @throws IndexOutOfBoundsException + * if index is negative. + */ + public T getPrevious(int idx) { + if ( idx >= capacity || idx < 0 ) + throw new IndexOutOfBoundsException("Index: " + idx) ; + if ( idx >= history.size() ) + return null ; + return history.get(idx) ; + } + + /** + * Return the current size of the histiory. This can be used to tell the + * difference between an iterator returning null and an iterator that is + * just short. + */ + public int currentSize() { + return history.size() ; + } + + /** Called when the underlying iterator ends */ + protected void atEnd() { + if ( !hasEnded ) { + hasEnded = true ; + endReached() ; + } + } + + /** Called, once, at the end */ + protected void endReached() { } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWrapper.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWrapper.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWrapper.java new file mode 100644 index 0000000..83901f2 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/IteratorWrapper.java @@ -0,0 +1,41 @@ +/** + * 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.jena.atlas.iterator; + +import java.util.Iterator ; + +public class IteratorWrapper<T> implements Iterator<T> +{ + protected final Iterator<T> iterator ; + + public IteratorWrapper(Iterator<T> iterator) + { + this.iterator = iterator ; + } + + @Override + public boolean hasNext() { return iterator.hasNext() ; } + + @Override + public T next() { return iterator.next() ; } + + @Override + public void remove() { iterator.remove() ; } +} + http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/MapUtils.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/MapUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/MapUtils.java new file mode 100644 index 0000000..3c6492e --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/MapUtils.java @@ -0,0 +1,36 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Map ; + +import org.apache.jena.atlas.lib.ActionKeyValue ; + + + +public class MapUtils +{ + // Map specific operations + + public static <K, V> void apply(Map<K, V> map, ActionKeyValue<K, V> action) + { + for ( Map.Entry<K,V> entry : map.entrySet() ) + action.apply(entry.getKey(), entry.getValue()) ; + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/NullIterator.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/NullIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/NullIterator.java new file mode 100644 index 0000000..ff2b2f1 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/NullIterator.java @@ -0,0 +1,49 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; + +/** Null Iterator - also guaranteed sharable and immutable */ +public class NullIterator<T> implements Iterator<T>, Iterable<T> +{ + @Override + public boolean hasNext() + { + return false ; + } + + @Override + public T next() + { + throw new NoSuchElementException("NullIterator.next") ; + } + + @Override + public void remove() + { throw new NoSuchElementException("NullIterator.remove") ;} + + @Override + public Iterator<T> iterator() + { + return this ; + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/PeekIterator.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/PeekIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/PeekIterator.java new file mode 100644 index 0000000..d9c0d2e --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/PeekIterator.java @@ -0,0 +1,100 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; +import java.util.Queue ; + +/** PeekIterator - is one slot ahead from the wrapped iterator */ +public class PeekIterator<T> implements Iterator<T> +{ + private final Iterator<T> iter ; + private boolean finished = false ; + // Slot always full when iterator active. Null is a a valid element. + private T slot ; + + public static <T> PeekIterator<T> create(PeekIterator<T> iter) { return iter ; } + public static <T> PeekIterator<T> create(Iterator<T> iter) + { + if ( iter instanceof PeekIterator<?> ) + return (PeekIterator<T>)iter ; + return new PeekIterator<>(iter) ; + } + + public PeekIterator(Iterator<T> iter) + { + this.iter = iter ; + fill() ; + } + + private void fill() + { + if ( finished ) return ; + if ( iter.hasNext() ) + slot = iter.next(); + else + { + finished = true ; + slot = null ; + } + } + + @Override + public boolean hasNext() + { + if ( finished ) + return false ; + return true ; + } + + /** Peek the next element or return null + * @see Queue#peek + */ + public T peek() + { + if ( finished ) + return null ; + return slot ; + } + + /** Peek the next element or throw NoSuchElementException */ + public T element() + { + if ( finished ) + throw new NoSuchElementException() ; + return slot ; + } + + @Override + public T next() + { + if ( finished ) + throw new NoSuchElementException() ; + T x = slot ; + // Move on now so the slot is loaded for peek. + fill() ; + return x ; + } + + @Override + public void remove() + { throw new UnsupportedOperationException() ; } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/PushbackIterator.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/PushbackIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/PushbackIterator.java new file mode 100644 index 0000000..355c563 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/PushbackIterator.java @@ -0,0 +1,62 @@ +/* + * 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.jena.atlas.iterator ; + +import java.util.ArrayDeque ; +import java.util.Deque ; +import java.util.Iterator ; + +/** An iterator where you can push items backinto the iterator, to be yielded (LIFO) next time. + * @see PeekIterator + */ +public class PushbackIterator<T> implements Iterator<T> { + private Deque<T> items = new ArrayDeque<>() ; + private Iterator<T> iter ; + + public PushbackIterator(Iterator<T> iter) { + if ( iter == null ) + throw new IllegalArgumentException("Wrapped iterator can't be null") ; + this.iter = iter ; + } + + public void pushback(T item) { + items.push(item) ; + } + + @Override + public boolean hasNext() { + if ( !items.isEmpty() ) + return true ; + return iter.hasNext() ; + } + + @Override + public T next() { + if ( !items.isEmpty() ) + return items.pop() ; + return iter.next() ; + } + + @Override + public void remove() { + // Need to track if last next() was from the stack or not. + throw new UnsupportedOperationException() ; + } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/RepeatApplyIterator.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/RepeatApplyIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/RepeatApplyIterator.java new file mode 100644 index 0000000..e504265 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/RepeatApplyIterator.java @@ -0,0 +1,86 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; + +import org.apache.jena.atlas.lib.Closeable ; +import org.apache.jena.atlas.lib.Lib ; + +public abstract class RepeatApplyIterator<T> implements Iterator<T>, Closeable +{ + private Iterator<T> input ; + private boolean finished = false ; + private Iterator<T> currentStage = null ; + + protected RepeatApplyIterator(Iterator<T> input) + { + this.input = input ; + } + + @Override + public boolean hasNext() + { + if ( finished ) + return false ; + for ( ;; ) + { + if ( currentStage == null && input.hasNext() ) + { + T nextItem = input.next(); + currentStage = makeNextStage(nextItem) ; + } + + if ( currentStage == null ) + { + hasFinished() ; + finished = true ; + return false ; + } + + if ( currentStage.hasNext() ) + return true ; + + currentStage = null ; + } + } + + protected abstract Iterator<T> makeNextStage(T t) ; + + protected void hasFinished() {} + + @Override + public T next() + { + if ( ! hasNext() ) + throw new NoSuchElementException(Lib.className(this)+".next()/finished") ; + return currentStage.next() ; + } + + @Override + public final void remove() + { throw new UnsupportedOperationException() ; } + + @Override + public void close() + { + Iter.close(input) ; + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/SingletonIterator.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/SingletonIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/SingletonIterator.java new file mode 100644 index 0000000..9c49e48 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/SingletonIterator.java @@ -0,0 +1,51 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; +import java.util.NoSuchElementException ; + +public class SingletonIterator<T> implements Iterator<T> +{ + private T thing = null ; + private boolean yielded = false ; + + public static <T> SingletonIterator<T> create(T thing) { return new SingletonIterator<>(thing) ; } + + public SingletonIterator(T thing) { this.thing = thing ; } + + @Override + public boolean hasNext() + { + return ! yielded ; + } + + @Override + public T next() + { + if ( yielded ) + throw new NoSuchElementException("SingletonIterator.next") ; + yielded = true ; + return thing ; + } + + @Override + public void remove() + { throw new NoSuchElementException("SingletonIterator.remove") ;} +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/Transform.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/Transform.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Transform.java new file mode 100644 index 0000000..d5d6a0a --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/Transform.java @@ -0,0 +1,21 @@ +/* + * 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.jena.atlas.iterator; + +public interface Transform <T, R> { R convert(T item) ; } http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/iterator/WrapperIterator.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/iterator/WrapperIterator.java b/jena-base/src/main/java/org/apache/jena/atlas/iterator/WrapperIterator.java new file mode 100644 index 0000000..0a8a0b0 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/iterator/WrapperIterator.java @@ -0,0 +1,45 @@ +/* + * 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.jena.atlas.iterator; + +import java.util.Iterator ; + +public class WrapperIterator<T> implements Iterator<T> +{ + private final Iterator<T> iter ; + + public WrapperIterator(Iterator<T> iter) { this.iter = iter ; } + + @Override + public boolean hasNext() + { + return iter.hasNext() ; + } + + @Override + public T next() + { + return iter.next() ; + } + + @Override + public void remove() + { iter.remove() ; } + +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/ActionKeyValue.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/ActionKeyValue.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/ActionKeyValue.java new file mode 100644 index 0000000..894107a --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ActionKeyValue.java @@ -0,0 +1,24 @@ +/* + * 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.jena.atlas.lib; + +public interface ActionKeyValue<KeyType, ValueType> +{ + public void apply(KeyType key, ValueType value) ; +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/AlarmClock.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/AlarmClock.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/AlarmClock.java new file mode 100644 index 0000000..6210bf1 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/AlarmClock.java @@ -0,0 +1,69 @@ +/* + * 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.jena.atlas.lib ; + +import java.util.concurrent.ScheduledThreadPoolExecutor ; +import java.util.concurrent.TimeUnit ; + +/** + * An AlarmClock is an object that will make a callback (with a value) at a + * preset time. Simple abstraction of add/reset/cancel of a Runnable. Currently, + * backed by {@link ScheduledThreadPoolExecutor} + */ +public class AlarmClock { + private ScheduledThreadPoolExecutor timer = new ScheduledThreadPoolExecutor(1) ; + + /* package */AlarmClock() {} + + static private AlarmClock singleton = new AlarmClock() ; + + /** Global singleton for general use */ + static public AlarmClock get() { + return singleton ; + } + + /** Add a task to be called after a delay (in milliseconds) */ + public void add(Runnable task, long delay) { + if ( task == null ) + throw new IllegalArgumentException("Task is null") ; + timer.schedule(task, delay, TimeUnit.MILLISECONDS) ; + } + + /** Reschedule a task to now run after a different delay from now (in milliseconds) */ + public void reset(Runnable task, long delay) { + if ( task == null ) + throw new IllegalArgumentException("Task is null") ; + cancel(task) ; + add(task, delay) ; + } + + /** Cancel a task */ + public void cancel(Runnable task) { + if ( task == null ) + throw new IllegalArgumentException("Task is null") ; + timer.remove(task) ; + } + + // public int getCount() { return timer.getQueue().size(); } + + /** Clean up */ + public void release() { + timer.shutdownNow() ; + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Alg.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Alg.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Alg.java new file mode 100644 index 0000000..3a3dacb --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Alg.java @@ -0,0 +1,239 @@ +/* + * 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.jena.atlas.lib; + +import java.nio.IntBuffer ; +import java.util.Comparator ; +import java.util.List ; + +public class Alg +{ + // Linear search is really there to test binary search. + static int linearSearch(IntBuffer buff, int key) + { + return linearSearch(buff, 0, buff.limit(), key) ; + } + + static int linearSearch(IntBuffer buff, int low, int high, int key) + { + int len = buff.limit(); // In int units. + check(len, low, high) ; + for ( int i = low ; i < high ; i++ ) + { + int k2 = buff.get(i) ; + if ( k2 == key ) + return i ; + if ( k2 > key ) + return encodeIndex(i) ; + } + return encodeIndex(high) ; + } + + // The encoded offset (insertion point) when not found. + public static final int encodeIndex(int i) { return -(i+1) ; } + public static final int decodeIndex(int i) { return -(i+1) ; } + + + /* Both Arrays and Collections have a binary search implementation. + * Arrays searches Object[] arrays, and Collections searches List<T> + * + * But sometime things are not so easy, and it isn't neat as to + * what is being searched, like a slice of an NIO Buffer + * + * http://en.wikipedia.org/wiki/Binary_search + */ + + public static int binarySearch(IntBuffer buff, int value) + { + return binarySearch(buff, 0, buff.limit(), value) ; + } + + public static int binarySearch(IntBuffer buff, int low, int high, int value) + { + // Low is inclusive, high is exclusive. + check(buff.limit(), low, high) ; + high -- ; // Convert high to inclusive. + + // Non-tail-recursive form, because tail-recursion removal + // is not required by java (unlike scheme). + + while (low <= high) + { + int mid = (low + high) >>> 1 ; // int divide by 2 : better: mid = low + ((high - low) / 2) + int k = buff.get(mid) ; + + // Two comparisons : see wikipedia for one comparison version. + if (k < value) + low = mid + 1 ; + else if ( k > value) + high = mid - 1 ; + else + return mid ; + } + // On exit, when not finding, low is the least value + // above, including off the end of the array. + return encodeIndex(low) ; + } + + // Alt form - no early termination. +// public static int binarySearch2(IntBuffer buff, int value, int low, int high) +// { +// // Low is inclusive, high is exclusive +// check(buff.limit(), low, high) ; +// int N = high ; +// +// // Uses high as exclusive index +// while (low < high) +// { +// int mid = (low + high) >>> 1 ; // int divide by 2 : better: mid = low + ((high - low) / 2) +// int k = buff.get(mid) ; +// +// // Two comparisons : see wikipedia for one comparison version. +// if ( k < value) +// low = mid + 1 ; +// else +// //can't be high = mid-1: here A[mid] >= value, +// //so high can't be < mid if A[mid] == value +// high = mid; +// } +// if (low < N && buff.get(low) == value ) +// return low ; +// else +// return enc(low) ; +// } + + private static void check(int len, int low, int high) + { + if ( low > high ) + throw new IllegalArgumentException("Low index ("+low+") is not less than high index ("+high+")") ; + if ( low < 0 ) + throw new ArrayIndexOutOfBoundsException("Low index is negative: "+low) ; + if ( high > len ) + throw new ArrayIndexOutOfBoundsException("High index is too large: "+high) ; + } + + // Why isn't this in the java RT? + public static <T> int binarySearch( List<T> array, int low, int high, T value, Comparator<T> comparator ) + { + check(array.size(), low, high) ; + high -- ; + + while( low <= high ) + { + int mid = ( low + high ) >>> 1 ; + + T k = array.get(mid) ; + + int x = comparator.compare(k, value) ; + if ( x < 0 ) + low = mid + 1 ; + else if ( x > 0 ) + high = mid - 1 ; + else + return mid ; + } + return encodeIndex(low) ; + } + + // Why isn't this in the java RT? + public static <T extends Comparable<? super T>> + int binarySearch(T[] array, int low, int high, T value) + { + check(array.length, low, high) ; + high -- ; + + while( low <= high ) + { + int mid = ( low + high ) >>> 1 ; + + T k = array[mid] ; + + int x = k.compareTo(value) ; // comparator.compare(k, value) ; + if ( x < 0 ) + low = mid + 1 ; + else if ( x > 0 ) + high = mid - 1 ; + else + return mid ; + } + return encodeIndex(low) ; + } + + + // Use Arrays.binarySearch functions + +// public static int binarySearch(int buff[], int value) +// { return binarySearch(buff, value, 0, buff.length) ; } +// +// public static int binarySearch(int buff[], int low, int high, int value) +// { +// check(buff.length, low, high) ; +// // Low is inclusive, high is exclusive. +// high -- ; // Convert high to inclusive. +// +// // Non-tail-recursive form, because tail-recursion removal +// // is not required by java (unlike scheme). +// +// while (low <= high) +// { +// int mid = (low + high) >>> 1 ; // int divide by 2 +// int k = buff[mid] ; +// +// if (k < value) +// low = mid + 1 ; +// else if ( k > value) +// high = mid - 1 ; +// else +// return mid ; +// } +// // On exit, when not finding, low is the least value +// // above, including off the end of the array. +// return encodeIndex(low) ; +// } +// +// +// public static int binarySearch(long buff[], int value) +// { return binarySearch(buff, value, 0, buff.length) ; } +// +// public static int binarySearch(long buff[], int low, int high, long value) +// { +// check(buff.length, low, high) ; +// // Low is inclusive, high is exclusive. +// high -- ; // Convert high to inclusive. +// +// // Non-tail-recursive form, because tail-recursion removal +// // is not required by java (unlike scheme). +// +// while (low <= high) +// { +// int mid = (low + high) >>> 1 ; // int divide by 2 +// long k = buff[mid] ; +// +// if (k < value) +// low = mid + 1 ; +// else if ( k > value) +// high = mid - 1 ; +// else +// return mid ; +// } +// // On exit, when not finding, low is the least value +// // above, including off the end of the array. +// return encodeIndex(low) ; +// } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/Allocator.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/Allocator.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/Allocator.java new file mode 100644 index 0000000..84005de --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/Allocator.java @@ -0,0 +1,28 @@ +/* + * 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.jena.atlas.lib; + +public interface Allocator<T> +{ + /** Allocate a new T, different from others allocated */ + public T create() ; + +// /** Reset the process of allocation - may cause equivalent objects to be created from before the reset */ +// public void reset() ; +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/ArrayUtils.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/ArrayUtils.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/ArrayUtils.java new file mode 100644 index 0000000..d45a107 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/ArrayUtils.java @@ -0,0 +1,64 @@ +/* + * 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.jena.atlas.lib; + +import java.lang.reflect.Array ; +import java.util.Arrays ; + +/** Collection of array-related operations */ +public class ArrayUtils +{ + private ArrayUtils() {} + + /** Allocate an array of generic type T (initialized to null) */ + @SuppressWarnings("unchecked") + public static <T> T[] alloc(Class<T> cls, int n) + { + return (T[])Array.newInstance(cls, n) ; + } + + // Compiles but fails at runtime (class cast exception if the reuls is assigned or accessed) +// @SuppressWarnings("unchecked") +// T[] array = (T[])new Object[n] ; +// or is T known +// @SuppressWarnings("unchecked") +// Set<T> x[] = new Set[length] ; +// return array ; + + /** Allocation space and copy */ + public static <T> T[] copy(T[] array) + { + return copy(array, 0, array.length) ; + } + + /** Allocation space and copy */ + public static <T> T[] copy(T[] array, int start, int finish) + { + return Arrays.copyOfRange(array, start, finish) ; + +// // Java5. +// // Fails for arrays of length 0; +// if ( array.length <= start ) +// throw new IllegalArgumentException("Zero length array not supported") ; +// @SuppressWarnings("unchecked") +// T[] array2 = (T[])Array.newInstance(array[start].getClass(), finish-start) ; +// System.arraycopy(array, start, array2, 0, finish-start) ; +// return array2 ; + } +} http://git-wip-us.apache.org/repos/asf/jena/blob/1320f8db/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsInt.java ---------------------------------------------------------------------- diff --git a/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsInt.java b/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsInt.java new file mode 100644 index 0000000..1e112a0 --- /dev/null +++ b/jena-base/src/main/java/org/apache/jena/atlas/lib/BitsInt.java @@ -0,0 +1,309 @@ +/* + * 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.jena.atlas.lib; + +// NB shifting is "mod 32" -- <<32 is a no-op (not a clear). +// http://mindprod.com/jgloss/masking.html + +/** Utilities for manipulating a bit pattern which are held in a 32 bit int. + * @see BitsLong + */ +public final class BitsInt +{ + private BitsInt() {} + + private static int IntLen = Integer.SIZE ; + + /** Extract the value packed into bits start (inclusive) and finish (exclusive). + * The value is returned in the low part of the returned int. + * The low bit is bit zero. + * @param bits + * @param start + * @param finish + * @return int + */ + + public static final + int unpack(int bits, int start, int finish) + { + check(start, finish) ; + if ( finish == 0 ) return 0 ; + // Remove top bits by moving up. Clear bottom bits by them moving down. + return (bits<<(IntLen-finish)) >>> ((IntLen-finish)+start) ; + } + + /** Place the value into the bit pattern between start and finish + * and returns the new int. + * @param bits + * @param value + * @param start + * @param finish + * @return int + */ + public static final + int pack(int bits, int value, int start, int finish) + { + check(start, finish) ; + bits = clear$(bits, start, finish) ; + bits = bits | (value<<start) ; + return bits ; + } + + /** Get bits from a hex string. + * + * @param str + * @param startChar Index of first character (counted from the left, string style). + * @param finishChar Index after the last character (counted from the left, string style). + * @return int + */ + + public static final + int unpack(String str, int startChar, int finishChar) + { + String s = str.substring(startChar, finishChar) ; + return Integer.parseInt(s, 16) ; + } + + /** Set the bits specificied. + * + * @param bits Pattern + * @param bitIndex + * @return Modified pattern + */ + public static final + int set(int bits, int bitIndex) + { + check(bitIndex) ; + return set$(bits, bitIndex) ; + } + + /** Set the bits from start (inc) to finish (exc) to one + * + * @param bits Pattern + * @param start start (inclusive) + * @param finish finish (exclusive) + * @return Modified pattern + */ + public static final + int set(int bits, int start, int finish) + { + check(start, finish) ; + return set$(bits, start, finish) ; + } + + /** Test whether a bit is the same as isSet + * @param bits Pattern + * @param isSet Test whether is set or not. + * @param bitIndex Bit index + * @return Boolean + */ + public static final + boolean test(int bits, boolean isSet, int bitIndex) + { + check(bitIndex) ; + return test$(bits, isSet, bitIndex) ; + } + + /** Test whether a bit is set + * @param bits Pattern + * @param bitIndex Bit index + * @return Boolean + */ + public static final + boolean isSet(int bits, int bitIndex) + { + check(bitIndex) ; + return test$(bits, true, bitIndex) ; + } + + /** Test whether a range has a specific value or not + * @param bits Pattern + * @param value Value to test for + * @param start start (inclusive) + * @param finish finish (exclusive) + * @return Boolean + */ + public static final + boolean test(int bits, int value, int start, int finish) + { + check(start, finish) ; + return test$(bits, value, start, finish) ; + } + + /** Get the bits from start (inclusive) to finish (exclusive), + * leaving them aligned in the int. See also unpack, returns + * the value found at that place. + * @see #unpack(int, int, int) + * @param bits + * @param start + * @param finish + * @return int + */ + + public static final + int access(int bits, int start, int finish) + { + check(start, finish) ; + return access$(bits, start, finish) ; + } + + /** + * Clear the bits specified. + * @param bits + * @param start + * @param finish + * @return int + */ + public static final + int clear(int bits, int start, int finish) + { + check(start, finish) ; + return clear$(bits, start, finish) ; + } + + /** + * Create a mask that has ones between bit positions start (inc) and finish (exc), + * and zeros elsewhere. + * @param start + * @param finish + * @return int + */ + public static final + int mask(int start, int finish) + { + check(start, finish) ; + return mask$(start, finish) ; + } + + /** + * Create a mask that has zeros between bit positions start (inc) and finish (exc), + * and ones elsewhere + * @param start + * @param finish + * @return int + */ + public static final + int maskZero(int start, int finish) + { + check(start, finish) ; + return maskZero$(start, finish) ; + } + + private static final + int clear$(int bits, int start, int finish) + { + int mask = maskZero$(start, finish) ; + bits = bits & mask ; + return bits ; + } + + private static final + int set$(int bits, int bitIndex) + { + int mask = mask$(bitIndex) ; + return bits | mask ; + } + + private static final + int set$(int bits, int start, int finish) + { + int mask = mask$(start, finish) ; + return bits | mask ; + } + + private static + boolean test$(int bits, boolean isSet, int bitIndex) + { + return isSet == access$(bits, bitIndex) ; + } + + private static + boolean test$(int bits, int value, int start, int finish) + { + int v = access$(bits, start, finish) ; + return v == value ; + } + + + + private static final + boolean access$(int bits, int bitIndex) + { + int mask = mask$(bitIndex) ; + return (bits & mask) != 0L ; + } + + private static final + int access$(int bits, int start, int finish) + { + // Two ways: +// int mask = mask$(start, finish) ; +// return bits & mask ; + + return ( (bits<<(IntLen-finish)) >>> (IntLen-finish+start) ) << start ; + } + + + private static final + int mask$(int bitIndex) + { + return 1 << bitIndex ; + } + + private static final + int mask$(int start, int finish) + { + // int mask = 0 ; + // if ( finish == int.SIZE ) + // // <<int.SIZE is a no-op + // mask = -1 ; + // else + // mask = (1L<<finish)-1 ; + if ( finish == 0 ) + // So start is zero and so the mask is zero. + return 0 ; + + + int mask = -1 ; +// mask = mask << (IntLen-finish) >>> (intLen-finish) ; // Clear the top bits +// return mask >>> start << start ; // Clear the bottom bits + return mask << (IntLen-finish) >>> (IntLen-finish+start) << start ; + } + + private static final + int maskZero$(int start, int finish) + { + return ~mask$(start, finish) ; + } + + private static final + void check(int bitIndex) + { + if ( bitIndex < 0 || bitIndex >= IntLen ) throw new IllegalArgumentException("Illegal bit index: "+bitIndex) ; + } + + private static final + void check(int start, int finish) + { + if ( start < 0 || start >= IntLen ) throw new IllegalArgumentException("Illegal start: "+start) ; + if ( finish < 0 || finish > IntLen ) throw new IllegalArgumentException("Illegal finish: "+finish) ; + if ( start > finish ) throw new IllegalArgumentException("Illegal range: ("+start+", "+finish+")") ; + } + +}
