/*
***************************************************************************************
* Copyright (C) 2006 EsperTech, Inc. All rights reserved. *
* http://www.espertech.com/esper *
* http://www.espertech.com *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license *
* a copy of which has been included with this distribution in the license.txt file. *
***************************************************************************************
*/
package com.espertech.esper.view.std;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.client.EventType;
import com.espertech.esper.collection.IterablesListIterator;
import com.espertech.esper.core.context.util.AgentInstanceViewFactoryChainContext;
import com.espertech.esper.epl.expression.core.ExprNode;
import com.espertech.esper.view.CloneableView;
import com.espertech.esper.view.View;
import com.espertech.esper.view.ViewSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* The merge view works together with a group view that splits the data in a stream to multiple subviews, based on
* a key index. Every group view requires a merge view to merge the many subviews back into a single view.
* Typically the last view in a chain containing a group view is a merge view.
* The merge view has no other responsibility then becoming the single last instance in the chain
* to which external listeners for updates can be attached to receive updates for the many subviews
* that have this merge view as common child views.
* The parent view of this view is generally the AddPropertyValueView that adds the grouped-by information
* back into the data.
*/
public final class MergeView extends ViewSupport implements CloneableView, MergeViewMarker {
private final AgentInstanceViewFactoryChainContext agentInstanceContext;
private final Collection<View> parentViews;
private final ExprNode[] groupFieldNames;
private final EventType eventType;
private final boolean removable;
public MergeView(AgentInstanceViewFactoryChainContext agentInstanceContext,
ExprNode[] groupCriteria,
EventType resultEventType,
boolean removable) {
this.removable = removable;
if (!removable) {
parentViews = new ArrayDeque<View>();
} else {
parentViews = new HashSet<View>();
}
this.agentInstanceContext = agentInstanceContext;
this.groupFieldNames = groupCriteria;
this.eventType = resultEventType;
}
public View cloneView() {
return new MergeView(agentInstanceContext, groupFieldNames, eventType, removable);
}
/**
* Returns the field name that contains the values to group by.
*
* @return field name providing group key value
*/
public final ExprNode[] getGroupFieldNames() {
return groupFieldNames;
}
/**
* Add a parent data merge view.
*
* @param parentView is the parent data merge view to add
*/
public final void addParentView(View parentView) {
parentViews.add(parentView);
}
public final EventType getEventType() {
// The schema is the parent view's type, or the type plus the added field(s)
return eventType;
}
public final void update(EventBean[] newData, EventBean[] oldData) {
updateChildren(newData, oldData);
}
public final Iterator<EventBean> iterator() {
// The merge data view has multiple parent views which are AddPropertyValueView
ArrayDeque<Iterable<EventBean>> iterables = new ArrayDeque<Iterable<EventBean>>();
for (View dataView : parentViews) {
iterables.add(dataView);
}
return new IterablesListIterator(iterables.iterator());
}
public final String toString() {
return this.getClass().getName() + " groupFieldName=" + Arrays.toString(groupFieldNames);
}
public void removeParentView(View view) {
parentViews.remove(view);
}
private static final Logger log = LoggerFactory.getLogger(MergeView.class);
}