Java tutorial
/* * Copyright 2011,2012 Metamarkets Group Inc. * * Licensed 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 sg.atom.utils._beta.functional; import com.google.common.base.Throwables; import com.google.common.io.Closeables; import java.io.Closeable; import java.io.IOException; import java.util.Iterator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** */ public class BaseSequence<T, IterType extends Iterator<T>> implements Sequence<T> { private static final Logger log = LoggerFactory.getLogger(BaseSequence.class); private final IteratorMaker<T, IterType> maker; public static <T> Sequence<T> simple(final Iterable<T> iterable) { return new BaseSequence<T, Iterator<T>>(new BaseSequence.IteratorMaker<T, Iterator<T>>() { @Override public Iterator<T> make() { return iterable.iterator(); } @Override public void cleanup(Iterator<T> iterFromMake) { } }); } public BaseSequence(IteratorMaker<T, IterType> maker) { this.maker = maker; } @Override public <OutType> OutType accumulate(OutType initValue, final Accumulator<OutType, T> fn) { Yielder<OutType> yielder = null; try { yielder = toYielder(initValue, YieldingAccumulators.fromAccumulator(fn)); return yielder.get(); } finally { try { Closeables.close(yielder, true); } catch (IOException ioe) { } } } @Override public <OutType> Yielder<OutType> toYielder(OutType initValue, YieldingAccumulator<OutType, T> accumulator) { final IterType iterator = maker.make(); try { return makeYielder(initValue, accumulator, iterator); } catch (Exception e) { // We caught an Exception instead of returning a really, real, live, real boy, errr, iterator // So we better try to close our stuff, 'cause the exception is what is making it out of here. try { maker.cleanup(iterator); } catch (RuntimeException e1) { log.error("Exception thrown when closing maker. Logging and ignoring.", e1); } throw Throwables.propagate(e); } } private <OutType> Yielder<OutType> makeYielder(OutType initValue, final YieldingAccumulator<OutType, T> accumulator, final IterType iter) { OutType retVal = initValue; while (!accumulator.yielded() && iter.hasNext()) { retVal = accumulator.accumulate(retVal, iter.next()); } if (!accumulator.yielded()) { return Yielders.done(retVal, new Closeable() { @Override public void close() throws IOException { maker.cleanup(iter); } }); } final OutType finalRetVal = retVal; return new Yielder<OutType>() { @Override public OutType get() { return finalRetVal; } @Override public Yielder<OutType> next(OutType initValue) { accumulator.reset(); try { return makeYielder(initValue, accumulator, iter); } catch (Exception e) { // We caught an Exception instead of returning a really, real, live, real boy, errr, iterator // So we better try to close our stuff, 'cause the exception is what is making it out of here. try { maker.cleanup(iter); } catch (RuntimeException e1) { log.error("Exception thrown when closing maker. Logging and ignoring.", e1); } throw Throwables.propagate(e); } } @Override public boolean isDone() { return false; } @Override public void close() throws IOException { maker.cleanup(iter); } }; } public static interface IteratorMaker<T, IterType extends Iterator<T>> { public IterType make(); public void cleanup(IterType iterFromMake); } }