/**************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved. *
* http://esper.codehaus.org *
* 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.ExprNode;
import com.espertech.esper.view.CloneableView;
import com.espertech.esper.view.View;
import com.espertech.esper.view.ViewSupport;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Iterator;
/**
* 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 ArrayDeque<View> parentViews = new ArrayDeque<View>();
private final ExprNode[] groupFieldNames;
private final EventType eventType;
/**
* Constructor.
* @param groupCriteria is the fields from which to pull the value to group by
* @param resultEventType is passed by the factory as the factory adds the merged fields to an event type
*/
public MergeView(AgentInstanceViewFactoryChainContext agentInstanceContext, ExprNode[] groupCriteria, EventType resultEventType)
{
this.agentInstanceContext = agentInstanceContext;
this.groupFieldNames = groupCriteria;
this.eventType = resultEventType;
}
public View cloneView()
{
return new MergeView(agentInstanceContext, groupFieldNames, eventType);
}
/**
* 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(AddPropertyValueView 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);
}
public final String toString()
{
return this.getClass().getName() + " groupFieldName=" + Arrays.toString(groupFieldNames);
}
public void removeParentView(View view)
{
parentViews.remove(view);
}
private static final Log log = LogFactory.getLog(MergeView.class);
}