blob: f817102832753c2f6fd3fdf774935e0345b263db [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.Arrays;
import java.util.HashSet;
import java.util.Set;
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 SetMarshaller
extends AbstractMarshaller
implements TypeBindableMarshaller
{
private final Type setType;
private Marshaller setTypeMarshaller;
public SetMarshaller()
{
this( null );
}
private SetMarshaller( Type setType )
{
this.setType = setType;
}
@Override
public boolean acceptType( Class<?> type )
{
return Set.class.isAssignableFrom( type );
}
@Override
public void marshall( Object value, PropertyDescriptor propertyDescriptor, Target target,
SerializationContext serializationContext )
throws IOException
{
if ( writePossibleNull( value, target ) )
{
Set<?> set = (Set<?>) value;
target.writeInt( set.size() );
Marshaller marshaller = null;
ClassDefinition classDefinition = null;
PropertyDescriptor pd = null;
if ( setType != null )
{
ensureMarshallerInitialized( serializationContext );
marshaller = setTypeMarshaller;
Class<?> baseType = TypeUtil.getBaseType( setType );
classDefinition =
serializationContext.getClassDefinitionContainer().getClassDefinitionByType( baseType );
pd = new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Set", baseType, marshaller );
}
for ( Object entry : set )
{
if ( writePossibleNull( entry, target ) )
{
if ( setType == null )
{
marshaller = serializationContext.findMarshaller( entry.getClass() );
classDefinition =
serializationContext.getClassDefinitionContainer().getClassDefinitionByType( entry.getClass() );
pd =
new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Set",
entry.getClass(), marshaller );
}
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();
Set set = new HashSet( size );
if ( size > 0 )
{
for ( int i = 0; i < size; i++ )
{
if ( isNull( source ) )
{
set.add( null );
}
else
{
long classId = source.readLong();
ClassDefinition classDefinition =
serializationContext.getClassDefinitionContainer().getClassDefinitionById( classId );
Marshaller marshaller;
if ( setType != null )
{
ensureMarshallerInitialized( serializationContext );
marshaller = setTypeMarshaller;
}
else
{
marshaller = serializationContext.findMarshaller( classDefinition.getType() );
}
PropertyDescriptor pd =
new CheatPropertyDescriptor( propertyDescriptor.getPropertyName() + "Set",
classDefinition.getType(), marshaller );
set.add( marshaller.unmarshall( pd, source, serializationContext ) );
}
}
}
return (V) set;
}
@Override
public Marshaller bindType( Type... bindingTypes )
{
if ( bindingTypes == null || bindingTypes.length == 0 )
{
return new SetMarshaller();
}
if ( bindingTypes.length != 1 )
{
throw new SerializerExecutionException( "Set type binding has no single generic: "
+ Arrays.toString( bindingTypes ) );
}
Type setType = bindingTypes[0];
return new SetMarshaller( setType );
}
private void ensureMarshallerInitialized( SerializationContext serializationContext )
{
if ( setTypeMarshaller != null )
{
return;
}
setTypeMarshaller = serializationContext.findMarshaller( setType );
}
}