blob: 9f6dff1cc8e3d99f89110bbf65855f0366ea61e9 [file] [log] [blame]
/*
* 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.directmemory.lightning.internal.marshaller;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.apache.directmemory.lightning.Marshaller;
import org.apache.directmemory.lightning.SerializationContext;
import org.apache.directmemory.lightning.Source;
import org.apache.directmemory.lightning.Target;
import org.apache.directmemory.lightning.TypeBindableMarshaller;
import org.apache.directmemory.lightning.base.AbstractMarshaller;
import org.apache.directmemory.lightning.exceptions.SerializerExecutionException;
import org.apache.directmemory.lightning.internal.CheatPropertyDescriptor;
import org.apache.directmemory.lightning.internal.util.TypeUtil;
import org.apache.directmemory.lightning.metadata.ClassDefinition;
import org.apache.directmemory.lightning.metadata.PropertyDescriptor;
public class ListMarshaller
extends AbstractMarshaller
implements TypeBindableMarshaller
{
private final Type listType;
private Marshaller listTypeMarshaller;
public ListMarshaller()
{
this( null );
}
private ListMarshaller( Type listType )
{
this.listType = listType;
}
@Override
public boolean acceptType( Class<?> type )
{
return List.class.isAssignableFrom( type );
}
@Override
public void marshall( Object value, PropertyDescriptor propertyDescriptor, Target target,
SerializationContext serializationContext )
throws IOException
{
if ( writePossibleNull( value, target ) )
{
List<?> list = (List<?>) value;
target.writeInt( list.size() );
Marshaller marshaller = null;
ClassDefinition classDefinition = null;
PropertyDescriptor pd = null;
if ( listType != null )
{
ensureMarshallerInitialized( serializationContext );
marshaller = listTypeMarshaller;
Class<?> baseType = TypeUtil.getBaseType( listType );
classDefinition =
serializationContext.getClassDefinitionContainer().getClassDefinitionByType( baseType );
pd = new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "List", baseType, marshaller );
}
for ( Object entry : list )
{
if ( writePossibleNull( entry, target ) )
{
if ( listType == null )
{
marshaller = serializationContext.findMarshaller( entry.getClass() );
classDefinition =
serializationContext.getClassDefinitionContainer().getClassDefinitionByType( entry.getClass() );
pd =
new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "List",
entry.getClass(), marshaller );
}
if ( classDefinition == null )
{
throw new SerializerExecutionException( "No ClassDefinition found for type " + entry.getClass() );
}
target.writeLong( classDefinition.getId() );
marshaller.marshall( entry, pd, target, serializationContext );
}
}
}
}
@Override
@SuppressWarnings( { "rawtypes", "unchecked" } )
public <V> V unmarshall( PropertyDescriptor propertyDescriptor, Source source,
SerializationContext serializationContext )
throws IOException
{
if ( isNull( source ) )
{
return null;
}
int size = source.readInt();
List list = new ArrayList( size );
if ( size > 0 )
{
for ( int i = 0; i < size; i++ )
{
if ( isNull( source ) )
{
list.add( null );
}
else
{
long classId = source.readLong();
ClassDefinition classDefinition =
serializationContext.getClassDefinitionContainer().getClassDefinitionById( classId );
Marshaller marshaller;
if ( listType != null )
{
ensureMarshallerInitialized( serializationContext );
marshaller = listTypeMarshaller;
}
else
{
marshaller = serializationContext.findMarshaller( classDefinition.getType() );
}
PropertyDescriptor pd =
new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "List",
classDefinition.getType(), marshaller );
list.add( marshaller.unmarshall( pd, source, serializationContext ) );
}
}
}
return (V) list;
}
@Override
public Marshaller bindType( Type... bindingTypes )
{
if ( bindingTypes == null || bindingTypes.length == 0 )
{
return new ListMarshaller();
}
if ( bindingTypes.length != 1 )
{
throw new SerializerExecutionException( "List type binding has no single generic: "
+ Arrays.toString( bindingTypes ) );
}
Type listType = bindingTypes[0];
return new ListMarshaller( listType );
}
private void ensureMarshallerInitialized( SerializationContext serializationContext )
{
if ( listTypeMarshaller != null )
{
return;
}
listTypeMarshaller = serializationContext.findMarshaller( listType );
}
}