blob: 85195d4f6d7a9b5f2a0dd68f27ef5063996289e8 [file] [log] [blame]
// $Id$
//
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
//
using System;
using Org.Apache.Etch.Bindings.Csharp.Msg;
using Org.Apache.Etch.Bindings.Csharp.Support;
namespace Org.Apache.Etch.Bindings.Csharp.Transport.Fmt
{
/// <summary>
/// Common interface for various types of tagged data input and output.
/// </summary>
abstract public class TaggedData
{
public TaggedData()
{
}
/// <summary>
/// Constructs the TaggedData.
/// </summary>
/// <param name="vf"></param>
public TaggedData( ValueFactory vf )
{
this.vf = vf;
}
/// <summary>
/// The value factory to use for tagged input and output.
/// </summary>
protected readonly ValueFactory vf;
/// <summary>
///
/// </summary>
/// <returns>the value factory to use for tagged input and output.</returns>
public ValueFactory GetValueFactory()
{
return vf;
}
protected ArrayValue ToArrayValue( Object value, Validator v )
{
Type c = value.GetType();
int dim = 0;
while ( c.IsArray )
{
dim++;
c = c.GetElementType();
}
// now we want the type code for c, and if the type code is custom,
// we'll also want the struct type code.
sbyte typeCode = GetNativeTypeCode( c );
XType customStructType;
if (typeCode == TypeCode.CUSTOM || typeCode == TypeCode.STRUCT)
{
customStructType = GetCustomStructType(c);
if (customStructType == null && c == typeof(StructValue))
{
Validator_StructValue x = FindStructValueValidator( v );
if (x != null)
customStructType = x.GetXType();
}
if (customStructType == null )
throw new ArgumentException(" In tagged Data" );
}
else
customStructType = null;
return new ArrayValue( value, typeCode, customStructType, dim );
}
private Validator_StructValue FindStructValueValidator( Validator v )
{
if (v is Validator_StructValue)
return (Validator_StructValue) v;
if (v is ComboValidator)
{
ComboValidator x = (ComboValidator) v;
Validator_StructValue y = FindStructValueValidator( x.A() );
if (y != null)
return y;
return FindStructValueValidator( x.B() );
}
return null;
}
protected Object FromArrayValue( ArrayValue av )
{
return av.GetArray();
}
protected Object AllocateArrayValue( sbyte typeCode, XType customStructType,
int dim, int length )
{
Type clss = GetComponentType( typeCode, customStructType, dim );
if ( clss == null )
throw new ArgumentException(String.Format(
"could not get array for {0}, {1}, {2}",
typeCode, customStructType, dim));
return Array.CreateInstance( clss, length );
}
private Type GetComponentType( sbyte typeCode, XType customStructType, int dim )
{
Type c;
if (typeCode == TypeCode.CUSTOM || typeCode == TypeCode.STRUCT)
{
// c = GetCustomType( customStructType );
c = customStructType.GetComponentType();
if (c == null)
c = typeof (StructValue);
}
else
c = GetNativeType(typeCode);
//Console.WriteLine( "c = " + c );
if ( c == null )
return null;
if ( dim == 0 )
return c;
int[] dims;
while ( dim > 0 )
{
dims = new int[ dim ];
if ( dim > 1 )
c = c.MakeArrayType();
dim--;
}
//Object o = Array.CreateInstance( c, 1 );
//c = ( ( Array ) o ).GetType();
//Console.WriteLine( "type= "+c );
return c;
}
/// <summary>
/// Returns the type code for the specified class. This
/// is needed when we have an array and we have determine
/// the base type and now we're fixing to serialize it.
/// We use the base type code to reconstitute it on the
/// other side. So we don't return a perfect code the way
/// checkValue does, but rather just something that let's
/// us recreate the appropriate array type on import.
/// </summary>
/// <param name="c"></param>
/// <returns>a type code for the specified class.</returns>
abstract public sbyte GetNativeTypeCode( Type c );
/// <summary>
///
/// </summary>
/// <param name="c"></param>
/// <returns>a struct type for the specified custom class.</returns>
abstract public XType GetCustomStructType( Type c );
/// <summary>
///
/// </summary>
/// <param name="type"></param>
/// <returns>the class for a specified (native) type code.</returns>
abstract public Type GetNativeType( sbyte type );
abstract public sbyte CheckValue( Object value );
}
}