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

io.siddhi.core.event.ComplexEventChunk Maven / Gradle / Ivy

/*
 * Copyright (c) 2016, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you 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 io.siddhi.core.event;

import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.Serializable;
import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * Collection used to group and manage chunk or ComplexEvents
 *
 * @param  sub types of ComplexEvent such as StreamEvent and StateEvent
 */
public class ComplexEventChunk implements Iterator, Serializable {

    private static final Logger log = LogManager.getLogger(ComplexEventChunk.class);

    private static final long serialVersionUID = 3185987841726255019L;
    protected E first;
    protected E previousToLastReturned;
    protected E lastReturned;
    protected E last;

    //Only to maintain backward compatibility
    @Deprecated
    public ComplexEventChunk(boolean isBatch) {
    }

    public ComplexEventChunk() {
    }

    public ComplexEventChunk(E first, E last) {
        this.first = first;
        this.last = last;
    }

    //Only to maintain backward compatibility
    @Deprecated
    public ComplexEventChunk(E first, E last, boolean isBatch) {
        this.first = first;
        this.last = last;
    }

    public void insertBeforeCurrent(E events) {

        if (lastReturned == null) {
            throw new IllegalStateException();
        }

        E currentEvent = getLastEvent(events);

        if (previousToLastReturned != null) {
            previousToLastReturned.setNext(events);
        } else {
            first = events;
        }
        previousToLastReturned = currentEvent;

        currentEvent.setNext(lastReturned);
    }


    public void insertAfterCurrent(E streamEvents) {

        if (lastReturned == null) {
            throw new IllegalStateException();
        }

        E currentEvent = getLastEvent(streamEvents);

        ComplexEvent nextEvent = lastReturned.getNext();
        lastReturned.setNext(streamEvents);
        currentEvent.setNext(nextEvent);

    }

    public void add(E complexEvents) {
        if (first == null) {
            first = complexEvents;
        } else {
            last.setNext(complexEvents);
        }
        last = getLastEvent(complexEvents);

    }

    public void addAll(ComplexEventChunk complexEventChunk) {
        if (complexEventChunk.first != null) {
            if (first == null) {
                first = complexEventChunk.first;
            } else {
                last.setNext(complexEventChunk.first);
            }
            last = complexEventChunk.last;
        }
    }

    private E getLastEvent(E complexEvents) {
        E lastEvent = complexEvents;
        while (lastEvent != null && lastEvent.getNext() != null
                && lastEvent.getNext() != complexEvents) {
            lastEvent = (E) lastEvent.getNext();
        }
        if (lastEvent != null && lastEvent.getNext() == complexEvents) {
            //to detach the loop
            lastEvent.setNext(null);
            if (Level.WARN.isMoreSpecificThan(log.getLevel())) {
                //To help finding the root cause of the event loop, such that it can be fixed.
                //if this is an legitimate usecase increase the log level to ERROR for class ComplexEventChunk
                Exception exception = new RuntimeException("Unexpected event loop found!");
                log.warn(exception.getMessage() + " If the usecase is legitimate, increase the log " +
                        "level to ERROR for class: " + this.getClass().getName(), exception);
            }
        }
        return lastEvent;
    }

    /**
     * Returns true if the iteration has more elements. (In other
     * words, returns true if next would return an element
     * rather than throwing an exception.)
     *
     * @return true if the iterator has more elements.
     */
    public boolean hasNext() {
        if (lastReturned != null) {
            return lastReturned.getNext() != null;
        } else if (previousToLastReturned != null) {
            return previousToLastReturned.getNext() != null;
        } else {
            return first != null;
        }
    }

    /**
     * Returns the next element in the iteration.
     *
     * @return the next element in the iteration.
     * @throws java.util.NoSuchElementException iteration has no more elements.
     */
    public E next() {
        E returnEvent;
        if (lastReturned != null) {
            returnEvent = (E) lastReturned.getNext();
            previousToLastReturned = lastReturned;
        } else if (previousToLastReturned != null) {
            returnEvent = (E) previousToLastReturned.getNext();
        } else {
            returnEvent = first;
        }
        if (returnEvent == null) {
            throw new NoSuchElementException();
        }
        lastReturned = returnEvent;
        return returnEvent;
    }

    /**
     * Removes from the underlying collection the last element returned by the
     * iterator (optional operation).  This method can be called only once per
     * call to next.  The behavior of an iterator is unspecified if
     * the underlying collection is modified while the iteration is in
     * progress in any way other than by calling this method.
     *
     * @throws UnsupportedOperationException if the remove
     *                                       operation is not supported by this Iterator.
     * @throws IllegalStateException         if the next method has not
     *                                       yet been called, or the remove method has already
     *                                       been called after the last call to the next
     *                                       method.
     */
    public void remove() {
        if (lastReturned == null) {
            throw new IllegalStateException();
        }
        if (previousToLastReturned != null) {
            previousToLastReturned.setNext(lastReturned.getNext());
        } else {
            first = (E) lastReturned.getNext();
            if (first == null) {
                last = null;
            }
        }
        lastReturned.setNext(null);
        lastReturned = null;
    }

    public void detach() {
        if (lastReturned == null) {
            throw new IllegalStateException();
        }
        if (previousToLastReturned != null) {
            previousToLastReturned.setNext(null);
        } else {
            clear();
        }
        lastReturned = null;
    }

    public E detachAllBeforeCurrent() {

        if (lastReturned == null) {
            throw new IllegalStateException();
        }

        E firstEvent = null;
        if (previousToLastReturned != null) {
            previousToLastReturned.setNext(null);
            firstEvent = first;
            first = lastReturned;
            previousToLastReturned = null;
        }
        return firstEvent;
    }

    public void clear() {
        previousToLastReturned = null;
        lastReturned = null;
        first = null;
        last = null;
    }

    public void reset() {
        previousToLastReturned = null;
        lastReturned = null;
    }

    public E getFirst() {
        return first;
    }

    public E getLast() {
        return last;
    }

    public E poll() {
        if (first != null) {
            E firstEvent = first;
            first = (E) first.getNext();
            firstEvent.setNext(null);
            return firstEvent;
        } else {
            return null;
        }
    }

    //Only to maintain backward compatibility
    @Deprecated
    public boolean isBatch() {
        return true;
    }

    //Only to maintain backward compatibility
    @Deprecated
    public void setBatch(boolean batch) {
    }

    @Override
    public String toString() {
        return "EventChunk{" +
                "first=" + first +
                '}';
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy