/*


    ========== licence begin GPL
    Copyright (C) 2002-2003 SAP AG

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.

    This program 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 General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
    ========== licence end


*/
package com.sap.dbtech.jdbc;

import java.util.ArrayList;


/**
 * Information about structure and layout of a database procedure parameter.
 */
public class DBProcParameterInfo {
	
	public static final int ABAPTABLE  = 1;
	public static final int STRUCTURE  = 2;

	private int       type;
	private String    typeName;
	private String    sqlTypeName;
	private String    baseTypeName;
	private int       length;
	private int       precision;
	private ArrayList typeElements;
	
	/**
	 * Creates a new DB procedure parameter info.
	 * @param datatype The data type as read from DBPROCPARAMINFO.
	 * @param len The length information from DBPROCPARAMINFO.
	 * @param dec The precision information from DBPROCPARAMINFO.
	 */
	public DBProcParameterInfo(String datatype, int len, int dec) {
		
		this.typeName  = datatype;
		this.length    = len;
		this.precision = dec;	
		if(datatype.equals("ABAPTABLE")) {
			this.type = ABAPTABLE;
			this.typeElements = new ArrayList();
		} else if(datatype.equals("STRUCTURE")) {
			this.type = STRUCTURE;
			this.typeElements = new ArrayList();
		} 
	}
	
	public void addStructureElement(String typeName,
		String codeType,
		int length,
		int precision,
		int offset,
		int asciiOffset,
		int unicodeOffset) {
		if(this.typeElements == null) {
			return;		
		} else {
			this.typeElements.add(new StructureElement(typeName, codeType, 
				length, precision, offset, asciiOffset, unicodeOffset));
		}
	}
	
	public static class StructureElement {
		
		StructureElement(String typeName, String codeType, int length, 
		    int precision, int offset, int asciiOffset, int unicodeOffset) {
		 	this.typeName      = typeName;
		 	this.codeType      = codeType;
		 	this.length        = length;
		 	this.precision     = precision;
		 	this.offset        = offset;
			this.asciiOffset   = asciiOffset;
			this.unicodeOffset = unicodeOffset;  		   	
		 }
		 
		public String typeName;
		public String codeType;
		public int    length;
		public int    precision;
		public int    offset;
		public int    asciiOffset;
		public int    unicodeOffset;
		
		public String getSQLTypeName() {
			if(typeName.equals("CHAR")) {
				return typeName + "(" + length + ") " + codeType;
			} else if(typeName.equals("FIXED")) {
				return typeName + "(" + length + ", " + precision +")";
			} else if(typeName.equals("BOOLEAN")) {
				return typeName;
			} else {
				return typeName + "(" + length + ")";
			}
		}
	}

	public int getMemberCount() {
		return this.typeElements.size();
	}
	
	
	public int getType() {
		return this.type;
	}

	public StructureElement getMember(int index) {
		return (StructureElement) this.typeElements.get(index);
	}

	public String getSQLTypeName() {
		if(this.sqlTypeName == null) {
			StringBuffer typeBuffer = new StringBuffer();
			StringBuffer baseType   = new StringBuffer();
			String       close = ")";
			if(type == ABAPTABLE) {
				if(this.typeElements.size()==1) {
					StructureElement el = (StructureElement) this.typeElements.get(0);
					if(el.typeName.equals("CHAR")) {
						if(el.codeType.equals("ASCII")) {
							this.sqlTypeName = "CHARACTER STREAM";
						} else if(el.codeType.equals("BYTE")) {
							this.sqlTypeName = "BYTE STREAM";
						}
					} else if(el.typeName.equals("WYDE")) {
						this.sqlTypeName = "CHARACTER STREAM";
					}
					typeBuffer.append("STREAM(");
				} else {
					typeBuffer.append("STREAM(STRUCTURE(");
					close="))";
				}
			} else {
				typeBuffer.append("STRUCTURE(");
			}
			for(int i=0; i<this.typeElements.size(); ++i) {
				if(i!=0) {
					baseType.append(", ");
					typeBuffer.append(", ");
				}
				StructureElement el = (StructureElement) (this.typeElements.get(i));
				typeBuffer.append(el.getSQLTypeName());
				baseType.append(el.getSQLTypeName());
			}
			typeBuffer.append(close);
			this.sqlTypeName = typeBuffer.toString();
			this.baseTypeName = baseType.toString();
		}
		
		return this.sqlTypeName;
	}

	public String getBaseTypeName() {
		return this.baseTypeName;
	}
}
