#region Disclaimer / License
// Copyright (C) 2009, Kenneth Skovhede
// http://www.hexad.dk, opensource@hexad.dk
//
// 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
//
#endregion
using System;
using System.IO;
using System.Xml;
using Topology.Geometries;
using System.Data;
using System.Collections.Generic;
namespace OSGeo.MapGuide.MaestroAPI
{
///
/// Represents a set of results from a query
///
public abstract class FeatureSetReader : IDisposable, IDataReader, IEnumerable
{
protected FeatureSetColumn[] m_columns;
protected FeatureSetRow m_row;
protected Dictionary _nameOrdinalMap;
protected FeatureSetReader() { }
///
/// Initializes the column array for this reader. Must be called before
/// any reading operations commence.
///
///
protected void InitColumns(FeatureSetColumn[] cols)
{
m_columns = cols;
_nameOrdinalMap = new Dictionary();
for (int i = 0; i < m_columns.Length; i++)
{
_nameOrdinalMap.Add(m_columns[i].Name, i);
}
}
public FeatureSetColumn[] Columns
{
get { return m_columns; }
}
public bool Read()
{
m_row = null;
bool next = ReadInternal();
if (next)
{
m_row = ProcessFeatureRow();
}
return next;
}
protected abstract bool ReadInternal();
protected abstract FeatureSetRow ProcessFeatureRow();
public FeatureSetRow Row
{
get { return m_row; }
}
public virtual void Dispose() { }
public void Close()
{
CloseInternal();
this.IsClosed = true;
}
protected abstract void CloseInternal();
public abstract int Depth { get; }
public abstract DataTable GetSchemaTable();
public bool IsClosed { get; private set; }
public bool NextResult()
{
return Read();
}
public abstract int RecordsAffected { get; }
public int FieldCount
{
get { return m_columns.Length; }
}
public virtual bool GetBoolean(int i)
{
return (bool)m_row[GetName(i)];
}
public virtual byte GetByte(int i)
{
return (byte)m_row[GetName(i)];
}
public virtual long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
throw new NotImplementedException();
}
public virtual char GetChar(int i)
{
return (char)m_row[GetName(i)];
}
public virtual long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
{
throw new NotImplementedException();
}
public virtual IDataReader GetData(int i)
{
return (IDataReader)m_row[GetName(i)];
}
public virtual string GetDataTypeName(int i)
{
return m_columns[i].Type.Name;
}
public virtual DateTime GetDateTime(int i)
{
return (DateTime)m_row[GetName(i)];
}
public virtual decimal GetDecimal(int i)
{
return (decimal)m_row[GetName(i)];
}
public virtual double GetDouble(int i)
{
return (double)m_row[GetName(i)];
}
public virtual Type GetFieldType(int i)
{
return m_columns[i].Type;
}
public float GetFloat(int i)
{
return (float)m_row[GetName(i)];
}
public virtual Guid GetGuid(int i)
{
return (Guid)m_row[GetName(i)];
}
public short GetInt16(int i)
{
return (short)m_row[GetName(i)];
}
public int GetInt32(int i)
{
return (int)m_row[GetName(i)];
}
public long GetInt64(int i)
{
return (long)m_row[GetName(i)];
}
public string GetName(int i)
{
return m_columns[i].Name;
}
public int GetOrdinal(string name)
{
return _nameOrdinalMap[name];
}
public string GetString(int i)
{
return (string)m_row[GetName(i)];
}
public object GetValue(int i)
{
return m_row[GetName(i)];
}
public int GetValues(object[] values)
{
throw new NotImplementedException();
}
public bool IsDBNull(int i)
{
return m_row.IsValueNull(i);
}
public object this[string name]
{
get { return m_row[name]; }
}
public object this[int i]
{
get { return m_row[GetName(i)]; }
}
internal class FeatureSetRowEnumerator : IEnumerator
{
private FeatureSetReader _parent;
public FeatureSetRowEnumerator(FeatureSetReader parent)
{
_parent = parent;
}
public IDataRecord Current
{
get { return _parent.Row; }
}
public void Dispose() { }
object System.Collections.IEnumerator.Current
{
get { return _parent.Row; }
}
public bool MoveNext()
{
return _parent.Read();
}
public void Reset()
{
throw new NotSupportedException();
}
}
public IEnumerator GetEnumerator()
{
return new FeatureSetRowEnumerator(this);
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new FeatureSetRowEnumerator(this);
}
}
public abstract class FeatureSetColumn
{
protected System.Collections.Hashtable m_metadata = new System.Collections.Hashtable();
protected string m_name;
protected Type m_type;
protected bool m_allowNull;
public string Name { get { return m_name; } }
public Type Type { get { return m_type; } }
public System.Collections.ICollection MetadataKeys { get { return m_metadata.Keys; } }
public object GetMetadata(string key)
{
return m_metadata[key];
}
public void SetMetadata(string key, object value)
{
m_metadata[key] = value;
}
}
public abstract class FeatureSetRow : IDataRecord
{
private Topology.IO.WKTReader m_reader = null;
protected Topology.IO.WKTReader Reader
{
get
{
if (m_reader == null)
m_reader = new Topology.IO.WKTReader();
return m_reader;
}
}
protected FeatureSetReader m_parent;
protected object[] m_items;
protected bool[] m_nulls;
protected bool[] m_lazyloadGeometry;
protected FeatureSetRow(FeatureSetReader parent)
{
m_parent = parent;
m_items = new object[parent.Columns.Length];
m_nulls = new bool[parent.Columns.Length];
m_lazyloadGeometry = new bool[parent.Columns.Length];
for(int i = 0;i < m_nulls.Length; i++)
{
m_nulls[i] = true;
m_lazyloadGeometry[i] = false;
}
}
[Obsolete("This will be gone in a future release. Use IsDBNull(int i) instead. To get the index use GetOrdinal(string name)")]
public bool IsValueNull(string name)
{
return IsValueNull(GetOrdinal(name));
}
[Obsolete("This will be gone in a future release. Use IsDBNull(int i) instead")]
public bool IsValueNull(int index)
{
if (index >= m_nulls.Length)
throw new InvalidOperationException("Index " + index.ToString() + ", was out of bounds");
else
return m_nulls[index];
}
public int GetOrdinal(string name)
{
if (name == null)
throw new ArgumentNullException("name");
if (name == "")
throw new Exception("The name parameter must not be empty");
name = name.Trim();
for(int i = 0; i < m_parent.Columns.Length; i++)
if (m_parent.Columns[i].Name.Equals(name))
return i;
for(int i = 0; i < m_parent.Columns.Length; i++)
if (m_parent.Columns[i].Name.ToLower().Equals(name.ToLower()))
return i;
string[] t = new string[m_parent.Columns.Length];
for(int i = 0; i < m_parent.Columns.Length; i++)
t[i] = m_parent.Columns[i].Name;
throw new InvalidOperationException("Column name: " + name + ", was not found\nColumn names (" + m_parent.Columns.Length.ToString() + "): " + string.Join(", ", t));
}
public object this[string name]
{
get
{
return this[GetOrdinal(name)];
}
}
public int FieldCount
{
get { return m_parent.Columns.Length; }
}
public bool GetBoolean(int i)
{
return (bool)m_items[i];
}
public byte GetByte(int i)
{
return (byte)m_items[i];
}
public long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferoffset, int length)
{
throw new NotImplementedException();
}
public char GetChar(int i)
{
return (char)m_items[i];
}
public long GetChars(int i, long fieldoffset, char[] buffer, int bufferoffset, int length)
{
throw new NotImplementedException();
}
public IDataReader GetData(int i)
{
return (IDataReader)m_items[i];
}
public string GetDataTypeName(int i)
{
return m_parent.Columns[i].Type.Name;
}
public DateTime GetDateTime(int i)
{
return (DateTime)m_items[i];
}
public decimal GetDecimal(int i)
{
return (decimal)m_items[i];
}
public double GetDouble(int i)
{
return (double)m_items[i];
}
public Type GetFieldType(int i)
{
return m_parent.Columns[i].Type;
}
public float GetFloat(int i)
{
return (float)m_items[i];
}
public Guid GetGuid(int i)
{
return (Guid)m_items[i];
}
public short GetInt16(int i)
{
return (short)m_items[i];
}
public int GetInt32(int i)
{
return (int)m_items[i];
}
public long GetInt64(int i)
{
return (long)m_items[i];
}
public string GetName(int i)
{
return m_parent.GetName(i);
}
public string GetString(int i)
{
return (string)m_items[i];
}
public object GetValue(int i)
{
return m_items[i];
}
public int GetValues(object[] values)
{
throw new NotImplementedException();
}
public bool IsDBNull(int index)
{
if (index >= m_nulls.Length)
throw new InvalidOperationException("Index " + index.ToString() + ", was out of bounds");
else
return m_nulls[index];
}
public object this[int i]
{
get
{
if (i >= m_items.Length)
{
throw new InvalidOperationException("Index " + i.ToString() + ", was out of bounds");
}
else
{
if (m_lazyloadGeometry[i] && !m_nulls[i])
{
m_items[i] = this.Reader.Read((string)m_items[i]);
m_lazyloadGeometry[i] = false;
}
return m_items[i];
}
}
}
}
}