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;
023
024import org.jgrapes.core.Channel;
025import org.jgrapes.core.Components;
026import org.jgrapes.core.Event;
027import org.jgrapes.io.util.ManagedBuffer;
028
029/**
030 * Events of this type signal that a new chunk of data is available
031 * for processing. From a consumer's point of view, the data is
032 * kept in a NIO {@link Buffer}. However, when creating the event
033 * the data has to be provided as a {@link ManagedBuffer}. 
034 * This buffer is returned to the pool upon successful processing 
035 * of the event.
036 * 
037 * As a convenience, the class provides the methods known
038 * from {@link Buffer} as short-cuts for invoking
039 * `data().`*method()*.
040 * 
041 * @param <T> the type of data used in this event
042 */
043public abstract class IOEvent<T extends Buffer> extends Event<Void> {
044
045    private ManagedBuffer<T> buffer;
046    private final boolean eor;
047
048    /**
049     * Instantiates a new IO event.
050     *
051     * @param buffer the buffer
052     * @param endOfRecord the end of record
053     */
054    protected IOEvent(ManagedBuffer<T> buffer, boolean endOfRecord) {
055        this.buffer = buffer;
056        this.eor = endOfRecord;
057    }
058
059    /**
060     * Get the managed buffer with the data from this event.
061     * 
062     * @return the buffer
063     */
064    public ManagedBuffer<T> buffer() {
065        return buffer;
066    }
067
068    /**
069     * Return the data associated with this event 
070     * as {@link Buffer}. This is short for
071     * `buffer().backingBuffer()`.
072     *
073     * @return the data
074     */
075    public T data() {
076        return buffer.backingBuffer();
077    }
078
079    /**
080     * Return the end of record flag passed to the constructor.
081     * The precise interpretation of a record depends on the data
082     * handled. 
083     * 
084     * @return the end of record flag
085     */
086    public boolean isEndOfRecord() {
087        return eor;
088    }
089
090    /*
091     * (non-Javadoc)
092     * 
093     * @see org.jgrapes.core.internal.EventBase#stopped()
094     */
095    @Override
096    protected void handled() {
097        buffer.unlockBuffer();
098        buffer = null;
099    }
100
101    /*
102     * (non-Javadoc)
103     * 
104     * @see java.lang.Object#toString()
105     */
106    @Override
107    public String toString() {
108        StringBuilder builder = new StringBuilder();
109        builder.append(Components.objectName(this))
110            .append(" [");
111        if (channels().length > 0) {
112            builder.append("channels=");
113            builder.append(Channel.toString(channels()));
114        }
115        builder.append(",size=")
116            .append(Optional.ofNullable(buffer).map(
117                bng -> bng.backingBuffer().remaining()).orElse(0))
118            .append(",eor=")
119            .append(eor)
120            .append(']');
121        return builder.toString();
122    }
123
124    /**
125     * @return the result
126     * @see java.nio.Buffer#hasRemaining()
127     */
128    public final boolean hasRemaining() {
129        return buffer.hasRemaining();
130    }
131
132    /**
133     * @return the result
134     * @see java.nio.Buffer#remaining()
135     */
136    public final int remaining() {
137        return buffer.remaining();
138    }
139}