001/*
002 * JGrapes Event Driven Framework
003 * Copyright (C) 2016-2018 Michael N. Lipp
004 * 
005 * This program is free software; you can redistribute it and/or modify it 
006 * under the terms of the GNU Affero General Public License as published by 
007 * the Free Software Foundation; either version 3 of the License, or 
008 * (at your option) any later version.
009 * 
010 * This program is distributed in the hope that it will be useful, but 
011 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
012 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License 
013 * for more details.
014 * 
015 * You should have received a copy of the GNU Affero General Public License along 
016 * with this program; if not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jgrapes.io.events;
020
021import java.nio.Buffer;
022import java.util.Optional;
023import org.jgrapes.core.Channel;
024import org.jgrapes.core.Components;
025import org.jgrapes.core.Event;
026import org.jgrapes.io.util.ManagedBuffer;
027
028/**
029 * Events of this type signal that a new chunk of data is available
030 * for processing. From a consumer's point of view, the data is
031 * kept in a NIO {@link Buffer}. However, when creating the event
032 * the data has to be provided as a {@link ManagedBuffer}. 
033 * This buffer is returned to the pool upon successful processing 
034 * of the event.
035 * 
036 * As a convenience, the class provides the methods known
037 * from {@link Buffer} as short-cuts for invoking
038 * `data().`*method()*.
039 * 
040 * @param <T> the type of data used in this event
041 */
042public abstract class IOEvent<T extends Buffer> extends Event<Void> {
043
044    private ManagedBuffer<T> buffer;
045    private final boolean eor;
046
047    /**
048     * Instantiates a new IO event.
049     *
050     * @param buffer the buffer
051     * @param endOfRecord the end of record
052     */
053    protected IOEvent(ManagedBuffer<T> buffer, boolean endOfRecord) {
054        this.buffer = buffer;
055        this.eor = endOfRecord;
056    }
057
058    /**
059     * Get the managed buffer with the data from this event.
060     * 
061     * @return the buffer
062     */
063    public ManagedBuffer<T> buffer() {
064        return buffer;
065    }
066
067    /**
068     * Return the data associated with this event 
069     * as {@link Buffer}. This is short for
070     * `buffer().backingBuffer()`.
071     *
072     * @return the data
073     */
074    public T data() {
075        return buffer.backingBuffer();
076    }
077
078    /**
079     * Return the end of record flag passed to the constructor.
080     * The precise interpretation of a record depends on the data
081     * handled. 
082     * 
083     * @return the end of record flag
084     */
085    public boolean isEndOfRecord() {
086        return eor;
087    }
088
089    /*
090     * (non-Javadoc)
091     * 
092     * @see org.jgrapes.core.internal.EventBase#stopped()
093     */
094    @Override
095    protected void handled() {
096        buffer.unlockBuffer();
097        buffer = null;
098    }
099
100    /*
101     * (non-Javadoc)
102     * 
103     * @see java.lang.Object#toString()
104     */
105    @Override
106    public String toString() {
107        StringBuilder builder = new StringBuilder(50);
108        builder.append(Components.objectName(this))
109            .append(" [");
110        if (channels().length > 0) {
111            builder.append("channels=");
112            builder.append(Channel.toString(channels()));
113        }
114        builder.append(",size=")
115            .append(Optional.ofNullable(buffer).map(
116                bng -> bng.backingBuffer().remaining()).orElse(0))
117            .append(",eor=")
118            .append(eor)
119            .append(']');
120        return builder.toString();
121    }
122
123    /**
124     * @return the result
125     * @see java.nio.Buffer#hasRemaining()
126     */
127    public final boolean hasRemaining() {
128        return buffer.hasRemaining();
129    }
130
131    /**
132     * @return the result
133     * @see java.nio.Buffer#remaining()
134     */
135    public final int remaining() {
136        return buffer.remaining();
137    }
138}