com.chm.converter.protostuff.codec.factory.CollectionCodecFactory Maven / Gradle / Ivy
package com.chm.converter.protostuff.codec.factory;
import com.chm.converter.core.reflect.ConverterTypes;
import com.chm.converter.core.reflect.TypeToken;
import com.chm.converter.core.universal.UniversalFactory;
import com.chm.converter.core.universal.UniversalGenerate;
import com.chm.converter.protostuff.codec.ProtostuffCodec;
import com.chm.converter.protostuff.codec.RuntimeTypeCodec;
import io.protostuff.Input;
import io.protostuff.Output;
import io.protostuff.ProtostuffException;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Collection;
/**
* 集合类编解码
*
* @author caihongming
* @version v1.0
* @date 2021-11-30
**/
public class CollectionCodecFactory implements UniversalFactory {
public static final String FIELD_NAME_VALUE = "v";
@Override
public ProtostuffCodec create(UniversalGenerate generate, TypeToken> typeToken) {
Class> rawTypeOfSrc = typeToken.getRawType();
if (!Collection.class.isAssignableFrom(rawTypeOfSrc)) {
return null;
}
Type type = typeToken.getType();
Type elementType = ConverterTypes.getCollectionElementType(type, rawTypeOfSrc);
ProtostuffCodec elementCodec = new RuntimeTypeCodec(generate, generate.get(elementType), elementType);
return new CollectionCodec(typeToken, elementCodec);
}
public static class CollectionCodec extends ProtostuffCodec> {
private final ProtostuffCodec elementCodec;
protected CollectionCodec(TypeToken> typeToken, ProtostuffCodec elementCodec) {
super(typeToken);
this.elementCodec = elementCodec;
}
@Override
public String getFieldName(int number) {
return number == 1 ? FIELD_NAME_VALUE : null;
}
@Override
public int getFieldNumber(String name) {
return name.length() == 1 && name.charAt(0) == 'v' ? 1 : 0;
}
@Override
public void writeTo(Output output, Collection message) throws IOException {
for (V value : message) {
// null values not serialized.
if (value != null) {
output.writeObject(1, value, elementCodec, true);
}
}
}
@Override
public Collection mergeFrom(Input input) throws IOException {
Collection collection = constructor.construct();
for (int number = input.readFieldNumber(this); ; number = input.readFieldNumber(this)) {
switch (number) {
case 0:
return collection;
case 1:
collection.add(input.mergeObject(null, elementCodec));
break;
default:
throw new ProtostuffException("The collection was incorrectly " +
"serialized.");
}
}
}
@Override
public CollectionCodec newInstance() {
return new CollectionCodec<>(this.typeToken, this.elementCodec);
}
}
}