/*
* JBoss, Home of Professional Open Source.
* See the COPYRIGHT.txt file distributed with this work for information
* regarding copyright ownership. Some portions may be licensed
* to Red Hat, Inc. under one or more contributor license agreements.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301 USA.
*/
package org.teiid.query.sql.lang;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.teiid.designer.query.sql.lang.ISPParameter;
import org.teiid.query.parser.TeiidNodeFactory;
import org.teiid.query.parser.TeiidNodeFactory.ASTNodes;
import org.teiid.designer.runtime.version.spi.ITeiidServerVersion;
import org.teiid.query.sql.symbol.ElementSymbol;
import org.teiid.query.sql.symbol.Expression;
import org.teiid.runtime.client.Messages;
/**
* Represents a StoredProcedure's parameter for encapsulation in the Query framework
* This is basically a holder object set from the Server's implementation of
* a stored procedure.
* The connector will utilize this class to set the appropriate values at the
* datasource layer.
*/
public class SPParameter implements ISPParameter<ElementSymbol> {
/** Constant identifying an IN parameter */
public static final int IN = ParameterInfo.IN.index();
/** Constant identifying an OUT parameter */
public static final int OUT = ParameterInfo.OUT.index();
/** Constant identifying an INOUT parameter */
public static final int INOUT = ParameterInfo.INOUT.index();
/** Constant identifying a RETURN parameter */
public static final int RETURN_VALUE = ParameterInfo.RETURN_VALUE.index();
/** Constant identifying a RESULT SET parameter */
public static final int RESULT_SET = ParameterInfo.RESULT_SET.index();
// Basic state
private int parameterType = ParameterInfo.IN.index();
private Expression expression;
private int index;
private List<ElementSymbol> resultSetColumns; //contains List of columns if it is result set
private List<Object> resultSetIDs; // contains List of metadataIDs for each column in the result set
private boolean usingDefault;
private boolean varArg;
private ElementSymbol parameterSymbol;
private ITeiidServerVersion teiidVersion;
/**
* Constructor used when constructing a parameter during execution. In this case we
* know what the parameter is being filled with but no metadata about the parameter.
*
* @param teiidVersion
* @param index the positional index of this parameter
* @param expression
*/
public SPParameter(ITeiidServerVersion teiidVersion, int index, Expression expression) {
this.teiidVersion = teiidVersion;
setIndex(index);
setExpression(expression);
this.parameterSymbol = createASTNode(ASTNodes.ELEMENT_SYMBOL);
}
/**
* Constructor used when constructing a parameter from metadata.
* In this case we specify the description of the parameter but
* no notion of what it is being filled with.
*
* @param teiidVersion
* @param index Parameter index
* @param parameterType Type of parameter based on class constant - IN, OUT, etc
* @param name Full name of parameter (including proc name)
*/
public SPParameter(ITeiidServerVersion teiidVersion, int index, int parameterType, String name) {
this.teiidVersion = teiidVersion;
setIndex(index);
setParameterType(parameterType);
setName(name);
}
private <T extends LanguageObject> T createASTNode(ASTNodes nodeType) {
return TeiidNodeFactory.getInstance().create(teiidVersion, nodeType);
}
private ElementSymbol createElementSymbol(String name) {
ElementSymbol symbol = createASTNode(ASTNodes.ELEMENT_SYMBOL);
symbol.setName(name);
return symbol;
}
/**
* Get full parameter name,. If unknown, null is returned.
* @return Parameter name
*/
@Override
public String getName() {
return this.parameterSymbol.getName();
}
/**
* Set full parameter name
* @param name Parameter name
*/
@Override
public void setName(String name) {
if (parameterSymbol == null) {
this.parameterSymbol = createElementSymbol(name);
} else {
ElementSymbol es = createElementSymbol(name);
es.setMetadataID(parameterSymbol.getMetadataID());
es.setType(parameterSymbol.getType());
this.parameterSymbol = es;
}
}
/**
* @param parameterInfo
*/
@Override
public void setParameterType(ParameterInfo parameterInfo) {
this.parameterType = parameterInfo.index();
}
/**
* Set parameter type according to class constants.
* @param parameterType Type to set
*/
public void setParameterType(int parameterType){
// validate against above types
if(parameterType < ParameterInfo.IN.index() || parameterType > ParameterInfo.RESULT_SET.index()) {
throw new IllegalArgumentException(Messages.getString(Messages.ERR.ERR_015_010_0006, parameterType));
}
this.parameterType = parameterType;
}
/**
* Get type of parameter according to class constants.
* @return Parameter type
*/
@Override
public int getParameterType(){
return this.parameterType;
}
/**
* Set class type - MetaMatrix runtime types.
* @param classType
* for types
*/
@Override
public void setClassType(Class<?> classType){
this.parameterSymbol.setType(classType);
}
/**
* Get class type - MetaMatrix runtime types.
* @return MetaMatrix runtime type description
*/
@Override
public Class<?> getClassType(){
return this.parameterSymbol.getType();
}
/**
* Set the expression defining this parameter
* @param expression The expression defining this parameter's value
*/
public void setExpression(Expression expression){
this.expression = expression;
}
/**
* Return the expression defining the value of this parameter
* @return Expression defining the value of this parameter
*/
public Expression getExpression(){
return this.expression;
}
/**
* Set the positional index of this parameter
* @param index The positional index of this parameter
*/
public void setIndex(int index){
this.index = index;
}
/**
* Return the index of this parameter
* @return The index
*/
public int getIndex(){
return this.index;
}
/**
* Add a result set column if this parameter is a return
* result set.
* @param colName Name of column
* @param type Type of column
* @param id Object Id
*/
@Override
public void addResultSetColumn(String colName, Class<?> type, Object id) {
if(resultSetColumns == null){
resultSetColumns = new ArrayList<ElementSymbol>();
resultSetIDs = new ArrayList<Object>();
}
ElementSymbol rsColumn = createElementSymbol(colName);
rsColumn.setType(type);
rsColumn.setMetadataID(id);
resultSetColumns.add(rsColumn);
resultSetIDs.add(id);
}
/**
* Get the result set columns. If none exist, return empty list.
* @return List of ElementSymbol representing result set columns
*/
public List<ElementSymbol> getResultSetColumns(){
if(resultSetColumns == null){
return Collections.emptyList();
}
return resultSetColumns;
}
/**
* Get the result set metadata IDs. If none exist, return empty list.
* @return List of Object representing result set metadata IDs
*/
public List<Object> getResultSetIDs() {
if(resultSetIDs == null) {
return Collections.emptyList();
}
return this.resultSetIDs;
}
/**
* Get a particular result set column at the specified position.
* @param position Position of the result set column
* @return Element symbol representing the result set column at position
* @throws IllegalArgumentException If column doesn't exist
*/
public ElementSymbol getResultSetColumn(int position){
if(resultSetColumns == null){
throw new IllegalArgumentException(Messages.getString(Messages.ERR.ERR_015_010_0009));
}
//position is 1 based
position--;
if(position >= 0 && position < resultSetColumns.size()) {
return resultSetColumns.get(position);
}
throw new IllegalArgumentException(Messages.getString(Messages.ERR.ERR_015_010_0010, new Integer(position + 1)));
}
/**
* Get actual metadataID for this parameter
* @return Actual metadata ID for this parameter
*/
@Override
public Object getMetadataID() {
return this.parameterSymbol.getMetadataID();
}
/**
* Set actual metadataID for this parameter
* @param metadataID Actual metadataID
*/
@Override
public void setMetadataID(Object metadataID) {
this.parameterSymbol.setMetadataID(metadataID);
}
/**
* Get element symbol representing this parameter. The symbol will have the
* same name and type as the parameter.
* @return Element symbol representing the parameter
*/
@Override
public ElementSymbol getParameterSymbol() {
return parameterSymbol;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
SPParameter other = (SPParameter)obj;
if (this.expression == null) {
if (other.expression != null) return false;
} else if (!this.expression.equals(other.expression)) return false;
if (this.index != other.index) return false;
if (this.teiidVersion == null) {
if (other.teiidVersion != null) return false;
} else if (!this.teiidVersion.equals(other.teiidVersion)) return false;
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.expression == null) ? 0 : this.expression.hashCode());
result = prime * result + this.index;
result = prime * result + ((this.teiidVersion == null) ? 0 : this.teiidVersion.hashCode());
return result;
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
if(this.expression != null) {
return this.expression.toString();
}
return "?"; //$NON-NLS-1$
}
/**
* @return usingDefault
*/
public boolean isUsingDefault() {
return usingDefault;
}
/**
* @param usingDefault
*/
public void setUsingDefault(boolean usingDefault) {
this.usingDefault = usingDefault;
}
/**
* @param varArg
*/
public void setVarArg(boolean varArg) {
this.varArg = varArg;
}
/**
* @return varArg
*/
public boolean isVarArg() {
return varArg;
}
@Override
public SPParameter clone() {
SPParameter clone = new SPParameter(this.teiidVersion, getIndex(), getExpression());
clone.setParameterType(getParameterType());
if (this.parameterSymbol != null)
clone.parameterSymbol = this.parameterSymbol.clone();
if(getExpression() != null) {
clone.setExpression(getExpression().clone());
}
if(this.resultSetColumns != null) {
Iterator<ElementSymbol> iter = this.resultSetColumns.iterator();
Iterator<Object> idIter = this.resultSetIDs.iterator();
while(iter.hasNext()) {
ElementSymbol column = iter.next();
clone.addResultSetColumn(column.getName(), column.getType(), idIter.next());
}
}
clone.setUsingDefault(isUsingDefault());
clone.setVarArg(isVarArg());
return clone;
}
}