sg.atom.utils._beta.functional.BaseSequence.java Source code

Java tutorial

Introduction

Here is the source code for sg.atom.utils._beta.functional.BaseSequence.java

Source

/*
 * 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);
    }
}