Files
redkale/src/main/java/org/redkale/convert/ArrayEncoder.java
2022-05-27 10:39:58 +08:00

138 lines
4.4 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.redkale.convert;
import java.lang.reflect.*;
/**
* 数组的序列化操作类 <br>
* 对象数组的序列化不包含int[]、long[]这样的primitive class数组。 <br>
* 支持一定程度的泛型。 <br>
*
* <p>
* 详情见: https://redkale.org
*
* @author zhangjx
* @param <T> 序列化的数组元素类型
*/
@SuppressWarnings("unchecked")
public class ArrayEncoder<T> implements Encodeable<Writer, T[]> {
protected final Type type;
protected final Type componentType;
protected final Encodeable anyEncoder;
protected final Encodeable<Writer, Object> componentEncoder;
protected final boolean subTypeFinal;
protected volatile boolean inited = false;
protected final Object lock = new Object();
public ArrayEncoder(final ConvertFactory factory, final Type type) {
this.type = type;
try {
if (type instanceof GenericArrayType) {
Type t = ((GenericArrayType) type).getGenericComponentType();
this.componentType = t instanceof TypeVariable ? Object.class : t;
} else if ((type instanceof Class) && ((Class) type).isArray()) {
this.componentType = ((Class) type).getComponentType();
} else {
throw new ConvertException("(" + type + ") is not a array type");
}
factory.register(type, this);
this.componentEncoder = factory.loadEncoder(this.componentType);
this.anyEncoder = factory.getAnyEncoder();
this.subTypeFinal = (this.componentType instanceof Class) && Modifier.isFinal(((Class) this.componentType).getModifiers());
} finally {
inited = true;
synchronized (lock) {
lock.notifyAll();
}
}
}
@Override
public void convertTo(Writer out, T[] value) {
convertTo(out, null, value);
}
public void convertTo(Writer out, EnMember member, T[] value) {
if (value == null) {
out.writeNull();
return;
}
int iMax = value.length - 1;
if (iMax == -1) {
out.writeArrayB(0, this, componentEncoder, value);
out.writeArrayE();
return;
}
Encodeable<Writer, Object> itemEncoder = this.componentEncoder;
if (itemEncoder == null) {
if (!this.inited) {
synchronized (lock) {
try {
lock.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
if (subTypeFinal) {
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
for (int i = 0;; i++) {
writeMemberValue(out, member, itemEncoder, value[i], i);
if (i == iMax) break;
out.writeArrayMark();
}
}
} else {
if (out.writeArrayB(value.length, this, itemEncoder, value) < 0) {
final Type comp = this.componentType;
for (int i = 0;; i++) {
Object v = value[i];
writeMemberValue(out, member, ((v != null && (v.getClass() == comp || out.specify() == comp)) ? itemEncoder : anyEncoder), v, i);
if (i == iMax) break;
out.writeArrayMark();
}
}
}
out.writeArrayE();
}
protected void writeMemberValue(Writer out, EnMember member, Encodeable<Writer, Object> encoder, Object value, int index) {
encoder.convertTo(out, value);
}
@Override
public String toString() {
return this.getClass().getSimpleName() + "{componentType:" + this.componentType + ", encoder:" + this.componentEncoder + "}";
}
@Override
public Type getType() {
return type;
}
@Override
public boolean specifyable() {
return false;
}
public Type getComponentType() {
return componentType;
}
public Encodeable<Writer, Object> getComponentEncoder() {
return componentEncoder;
}
}