All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fluxtion.ext.futext.api.util.CharEventStreamer Maven / Gradle / Ivy

The newest version!
package com.fluxtion.ext.futext.api.util;


import com.fluxtion.api.lifecycle.EventHandler;
import com.fluxtion.api.lifecycle.Lifecycle;
import com.fluxtion.ext.futext.api.event.CharEvent;
import com.fluxtion.ext.futext.api.event.EofEvent;
import com.fluxtion.ext.futext.api.util.AsciiCharEventFileStreamer.CharSink;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author gregp
 */
public class CharEventStreamer {

    private int chunkSize = 4 * 256 * 1024;
    final Exchanger exchanger = new Exchanger();
    final Exchanger charExchanger = new Exchanger();
    private ExecutorService threadPool = Executors.newSingleThreadExecutor();

    public int getChunkSize() {
        return chunkSize;
    }

    public void setChunkSize(int chunkSize) {
        this.chunkSize = chunkSize;
    }

    public void streamFromReader(final Reader reader, EventHandler eventHandler) throws FileNotFoundException, IOException, InterruptedException {
        CharEventStreamer.this.streamFromReader(reader, eventHandler, true);
    }

    public void streamFromReader(final Reader reader, EventHandler eventHandler, boolean callLifeCycleMethods) throws FileNotFoundException, IOException, InterruptedException {
        boolean isCharSink = eventHandler instanceof AsciiCharEventFileStreamer.CharSink;
        CharSink charSink = null;
        if (isCharSink) {
            charSink = (CharSink) eventHandler;
        }
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    CharChunk writeChunk = new CharChunk(chunkSize);
                    int numCharsRead;
                    while ((numCharsRead = reader.read(writeChunk.data, 0, writeChunk.data.length)) != -1) {
                        if (numCharsRead == chunkSize) {
                            writeChunk.full();
                        } else if (numCharsRead > 0) {
                            writeChunk.eof(numCharsRead);
                        }
                        writeChunk = charExchanger.exchange(writeChunk);
                    }
                } catch (Exception ex) {
                    Logger.getLogger(CharEventStreamer.class.getName()).log(Level.SEVERE, null, ex);
                } finally {
                    shutDown();
                }
            }
        });

        if (isCharSink) {
            pushCharChunkToHandler(charSink, callLifeCycleMethods);
        } else {
            pushCharChunkToHandler(eventHandler, callLifeCycleMethods);
        }

    }

    public void streamFromFile(final File file, EventHandler eventHandler) throws FileNotFoundException, IOException, InterruptedException {
        streamFromFile(file, eventHandler, true);
    }

    public void streamFromFile(final File file, EventHandler eventHandler, boolean callLifeCycleMethods) throws FileNotFoundException, IOException, InterruptedException {
        boolean isCharSink = eventHandler instanceof AsciiCharEventFileStreamer.CharSink;
        CharSink charSink = null;
        if (isCharSink) {
            charSink = (CharSink) eventHandler;
        }
        threadPool.submit(new Runnable() {
            @Override
            public void run() {
                try {
                    FileChannel fileChannel = new FileInputStream(file).getChannel();
                    long size = file.length();
                    MappedByteBuffer buffer = fileChannel.map(
                            FileChannel.MapMode.READ_ONLY, 0, size);
                    ByteChunk writeChunk = new ByteChunk(chunkSize);
                    while (buffer.hasRemaining()) {
                        if (buffer.remaining() > chunkSize) {
                            buffer.get(writeChunk.data);
                            writeChunk.full();
                        } else {
                            //eof
                            writeChunk.eof(buffer.remaining());
                            buffer.get(writeChunk.data, 0, writeChunk.limit);
                        }
                        writeChunk = exchanger.exchange(writeChunk);
                    }

                } catch (Exception ex) {
                    Logger.getLogger(CharEventStreamer.class.getName()).log(Level.SEVERE, null, ex);
                } finally {
                    shutDown();
                }
            }
        });
        try {
            if (isCharSink) {
                pushToHandler(charSink, callLifeCycleMethods);
            } else {
                pushToHandler(eventHandler, callLifeCycleMethods);
            }
        } catch (Exception e) {
            threadPool.shutdownNow();
        }
    }

    public void shutDown() {
        threadPool.shutdown();
    }

    private void pushCharChunkToHandler(EventHandler eventHandler, boolean callLifeCycleMethods) throws InterruptedException {
        if (callLifeCycleMethods) {
            initSep(eventHandler);
        }
        CharChunk readChunk = new CharChunk(chunkSize);
        CharEvent charEvent = new CharEvent(' ');
        while (!readChunk.eofChunk) {
            readChunk = charExchanger.exchange(readChunk);
            for (int i = 0; i < readChunk.limit; i++) {
                charEvent.setCharacter(readChunk.data[i]);
                eventHandler.onEvent(charEvent);
            }
        }
        eventHandler.onEvent(new EofEvent());
        if (callLifeCycleMethods) {
            tearDownSep(eventHandler);
        }
    }

    private void pushCharChunkToHandler(CharSink charSink, boolean callLifeCycleMethods) throws InterruptedException {
        if (callLifeCycleMethods) {
            initSep((EventHandler) charSink);
        }
        CharChunk readChunk = new CharChunk(chunkSize);
        CharEvent charEvent = new CharEvent(' ');
        while (!readChunk.eofChunk) {
            readChunk = charExchanger.exchange(readChunk);
            for (int i = 0; i < readChunk.limit; i++) {
                charEvent.setCharacter(readChunk.data[i]);
                charSink.handleCharEvent(charEvent);
            }
        }
        charSink.handleEofEvent(new EofEvent());
        if (callLifeCycleMethods) {
            tearDownSep((EventHandler) charSink);
        }
    }

    private void pushToHandler(EventHandler eventHandler, boolean callLifeCycleMethods) throws InterruptedException {
        if (callLifeCycleMethods) {
            initSep(eventHandler);
        }
        ByteChunk readChunk = new ByteChunk(chunkSize);
        CharEvent charEvent = new CharEvent(' ');
        while (!readChunk.eofChunk) {
            readChunk = exchanger.exchange(readChunk);
            for (int i = 0; i < readChunk.limit; i++) {
                charEvent.setCharacter((char) readChunk.data[i]);
                eventHandler.onEvent(charEvent);
            }
        }
        eventHandler.onEvent(new EofEvent());
        if (callLifeCycleMethods) {
            tearDownSep(eventHandler);
        }
    }

    private void pushToHandler(CharSink charSink, boolean callLifeCycleMethods) throws InterruptedException {
        if (callLifeCycleMethods) {
            initSep((EventHandler) charSink);
        }
        ByteChunk readChunk = new ByteChunk(chunkSize);
        CharEvent charEvent = new CharEvent(' ');
        while (!readChunk.eofChunk) {
            readChunk = exchanger.exchange(readChunk);
            for (int i = 0; i < readChunk.limit; i++) {
                charEvent.setCharacter((char) readChunk.data[i]);
                charSink.handleCharEvent(charEvent);
            }
        }
        
        ((EventHandler)charSink).onEvent(new EofEvent());
        if (callLifeCycleMethods) {
            tearDownSep((EventHandler) charSink);
        }
    }

    private static void initSep(EventHandler sep) {
        if (sep instanceof Lifecycle) {
            ((Lifecycle) sep).init();
        }
    }

    private static void tearDownSep(EventHandler sep) {
        if (sep instanceof Lifecycle) {
            ((Lifecycle) sep).tearDown();
        }
    }

    private static class ByteChunk {

        final byte[] data;
        boolean eofChunk = false;
        int limit;

        public ByteChunk(int size) {
            data = new byte[size];
        }

        void reset() {
            limit = 0;
            eofChunk = false;
        }

        void full() {
            limit = data.length;
            eofChunk = false;
        }

        void eof(int limit) {
            this.limit = limit;
            eofChunk = true;
        }

    }

    private static class CharChunk {

        final char[] data;
        boolean eofChunk = false;
        int limit;

        public CharChunk(int size) {
            data = new char[size];
        }

        void reset() {
            limit = 0;
            eofChunk = false;
        }

        void full() {
            limit = data.length;
            eofChunk = false;
        }

        void eof(int limit) {
            this.limit = limit;
            eofChunk = true;
        }

    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy