/*
***************************************************************************************
* 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.epl.expression.ops;
import com.espertech.esper.client.EventBean;
import com.espertech.esper.epl.expression.core.*;
import com.espertech.esper.metrics.instrumentation.InstrumentationHelper;
import com.espertech.esper.util.JavaClassHelper;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* Represents the "new {...}" operator in an expression tree.
*/
public class ExprNewStructNode extends ExprNodeBase implements ExprEvaluatorTypableReturn {
private static final long serialVersionUID = -210293632565665600L;
private final String[] columnNames;
private transient LinkedHashMap<String, Object> eventType;
private transient ExprEvaluator[] evaluators;
private boolean isAllConstants;
public ExprNewStructNode(String[] columnNames) {
this.columnNames = columnNames;
}
public ExprEvaluator getExprEvaluator() {
return this;
}
public ExprNode validate(ExprValidationContext validationContext) throws ExprValidationException {
eventType = new LinkedHashMap<String, Object>();
evaluators = ExprNodeUtility.getEvaluators(this.getChildNodes());
for (int i = 0; i < columnNames.length; i++) {
isAllConstants = isAllConstants && this.getChildNodes()[i].isConstantResult();
if (eventType.containsKey(columnNames[i])) {
throw new ExprValidationException("Failed to validate new-keyword property names, property '" + columnNames[i] + "' has already been declared");
}
Map<String, Object> eventTypeResult = null;
if (evaluators[i] instanceof ExprEvaluatorTypableReturn) {
eventTypeResult = ((ExprEvaluatorTypableReturn) evaluators[i]).getRowProperties();
}
if (eventTypeResult != null) {
eventType.put(columnNames[i], eventTypeResult);
} else {
Class classResult = JavaClassHelper.getBoxedType(evaluators[i].getType());
eventType.put(columnNames[i], classResult);
}
}
return null;
}
public String[] getColumnNames() {
return columnNames;
}
public boolean isConstantResult() {
return isAllConstants;
}
public Class getType() {
return Map.class;
}
public LinkedHashMap<String, Object> getRowProperties() throws ExprValidationException {
return eventType;
}
public Object evaluate(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext) {
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().qExprNew(this);
}
Map<String, Object> props = new HashMap<String, Object>();
for (int i = 0; i < evaluators.length; i++) {
props.put(columnNames[i], evaluators[i].evaluate(eventsPerStream, isNewData, exprEvaluatorContext));
}
if (InstrumentationHelper.ENABLED) {
InstrumentationHelper.get().aExprNew(props);
}
return props;
}
public Boolean isMultirow() {
return false; // New itself can only return a single row
}
public Object[] evaluateTypableSingle(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext context) {
Object[] rows = new Object[columnNames.length];
for (int i = 0; i < columnNames.length; i++) {
rows[i] = evaluators[i].evaluate(eventsPerStream, isNewData, context);
}
return rows;
}
public Object[][] evaluateTypableMulti(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext context) {
return null;
}
public boolean equalsNode(ExprNode node, boolean ignoreStreamPrefix) {
if (!(node instanceof ExprNewStructNode)) {
return false;
}
ExprNewStructNode other = (ExprNewStructNode) node;
return Arrays.deepEquals(other.columnNames, columnNames);
}
public void toPrecedenceFreeEPL(StringWriter writer) {
writer.write("new{");
String delimiter = "";
for (int i = 0; i < this.getChildNodes().length; i++) {
writer.append(delimiter);
writer.append(columnNames[i]);
ExprNode expr = this.getChildNodes()[i];
boolean outputexpr = true;
if (expr instanceof ExprIdentNode) {
ExprIdentNode prop = (ExprIdentNode) expr;
if (prop.getResolvedPropertyName().equals(columnNames[i])) {
outputexpr = false;
}
}
if (outputexpr) {
writer.append("=");
expr.toEPL(writer, ExprPrecedenceEnum.MINIMUM);
}
delimiter = ",";
}
writer.write("}");
}
public ExprPrecedenceEnum getPrecedence() {
return ExprPrecedenceEnum.UNARY;
}
}