blob: b6610bc8e5fa79ad5bee1069f1cb140bf38b239a [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.
*/
package org.apache.etch.bindings.java.transport.fmt;
import java.lang.reflect.Array;
import org.apache.etch.bindings.java.msg.ComboValidator;
import org.apache.etch.bindings.java.msg.StructValue;
import org.apache.etch.bindings.java.msg.Type;
import org.apache.etch.bindings.java.msg.Validator;
import org.apache.etch.bindings.java.msg.ValueFactory;
import org.apache.etch.bindings.java.support.Validator_StructValue;
import org.apache.etch.bindings.java.transport.ArrayValue;
/**
* Common interface for various types of tagged data input and output.
*/
abstract public class TaggedData
{
/**
* Constructs the TaggedData.
*
* @param vf
*/
public TaggedData( ValueFactory vf )
{
this.vf = vf;
}
/**
* The value factory to use for tagged input and output.
*/
protected final ValueFactory vf;
/**
* @return the value factory to use for tagged input and output.
*/
public ValueFactory getValueFactory()
{
return vf;
}
/**
* @param value
* @param v
* @return an ArrayValue which models the given array.
*/
@SuppressWarnings("deprecation")
protected ArrayValue toArrayValue( Object value, Validator v )
{
Class<?> c = value.getClass();
// System.out.printf( "toArrayValue: class is %s\n", c );
int dim = 0;
while (c.isArray())
{
dim++;
c = c.getComponentType();
}
// System.out.printf( "toArrayValue: base class is %s dim %d\n", c, dim );
// now we want the type code for c, and if the type code is custom,
// we'll also want the struct type code.
byte typeCode = getNativeTypeCode( c );
Type customStructType;
if (typeCode == TypeCode.CUSTOM || typeCode == TypeCode.STRUCT)
{
customStructType = getCustomStructType( c );
if (customStructType == null && c == StructValue.class)
{
Validator_StructValue x = findStructValueValidator( v );
if (x != null)
customStructType = x.getType();
}
if (customStructType == null )
throw new IllegalArgumentException( "customStructType == null" );
}
else
customStructType = null;
// System.out.printf( "toArrayValue: type %d customStructType %d dim %d\n", type, customStructType, dim );
return new ArrayValue( value, typeCode, customStructType, dim );
}
private Validator_StructValue findStructValueValidator( Validator v )
{
if (v instanceof Validator_StructValue)
return (Validator_StructValue) v;
if (v instanceof ComboValidator)
{
ComboValidator x = (ComboValidator) v;
Validator_StructValue y = findStructValueValidator( x.a() );
if (y != null)
return y;
return findStructValueValidator( x.b() );
}
return null;
}
/**
* @param av
* @return a native array converted from an array value.
*/
protected Object fromArrayValue( ArrayValue av )
{
return av.getArray();
}
/**
* @param typeCode
* @param customStructType
* @param dim
* @param length
* @return the allocated array value.
*/
protected Object allocArrayValue( byte typeCode, Type customStructType,
int dim, int length )
{
Class<?> clss = getComponentType( typeCode, customStructType, dim-1 );
if (clss == null)
throw new IllegalArgumentException( String.format(
"could not get array for %s, %s, %d",
typeCode, customStructType, dim-1 ) );
return Array.newInstance( clss, length );
}
@SuppressWarnings("deprecation")
private Class<?> getComponentType( byte typeCode, Type customStructType,
int dim )
{
Class<?> c;
if (typeCode == TypeCode.CUSTOM || typeCode == TypeCode.STRUCT)
{
c = customStructType.getComponentType();
if (c == null)
c = StructValue.class;
}
else
{
c = getNativeType( typeCode );
}
// System.out.printf( "getComponentType class %s\n", c );
if (c == null)
return null;
if (dim == 0)
return c;
// TODO is there a better way to get the class of a multi-dimensional array?
int[] dims = new int[dim];
Object o = Array.newInstance( c, dims );
// System.out.printf( "object = %s\n", o );
c = o.getClass();
// System.out.printf( "class = %s\n", c );
return c;
}
/**
* @param value
* @return return a type code for the specified value.
*/
abstract public byte checkValue( Object value );
/**
* 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.
* @param c
* @return a type code for the specified class.
*/
abstract public byte getNativeTypeCode( Class<?> c );
/**
* @param c
* @return a struct type for the specified custom class.
*/
abstract public Type getCustomStructType( Class<?> c );
/**
* @param type
* @return the class for a specified (native) type code.
*/
abstract public Class<?> getNativeType( byte type );
}