in hollow/src/main/java/com/netflix/hollow/core/write/objectmapper/HollowObjectTypeMapper.java [63:144]
public HollowObjectTypeMapper(HollowObjectMapper parentMapper, Class<?> clazz, String declaredTypeName, Set<Type> visited) {
this.parentMapper = parentMapper;
this.clazz = clazz;
this.typeName = declaredTypeName != null ? declaredTypeName : getDefaultTypeName(clazz);
this.mappedFields = new ArrayList<MappedField>();
boolean hasAssignedOrdinalField = false;
long assignedOrdinalFieldOffset = -1;
if(clazz == String.class) {
try {
mappedFields.add(new MappedField(clazz.getDeclaredField("value")));
} catch (Exception e) {
throw new RuntimeException(e);
}
} else if(clazz == Date.class) {
try {
mappedFields.add(new MappedField(MappedFieldType.DATE_TIME));
} catch(Exception e) {
throw new RuntimeException(e);
}
} else {
/// gather fields from type hierarchy
Class<?> currentClass = clazz;
while(currentClass != Object.class && currentClass != Enum.class) {
if(currentClass.isInterface()) {
throw new IllegalArgumentException("Unexpected interface " + currentClass.getSimpleName() + " passed as field.");
} if (currentClass.isArray()) {
throw new IllegalArgumentException("Unexpected array " + currentClass.getSimpleName() + " passed as field. Consider using collections or marking as transient.");
}
Field[] declaredFields = currentClass.getDeclaredFields();
for(int i=0;i<declaredFields.length;i++) {
Field declaredField = declaredFields[i];
int modifiers = declaredField.getModifiers();
if(!Modifier.isTransient(modifiers) && !Modifier.isStatic(modifiers) &&
!"__assigned_ordinal".equals(declaredField.getName()) &&
!declaredField.isAnnotationPresent(HollowTransient.class)) {
mappedFields.add(new MappedField(declaredField, visited));
} else if("__assigned_ordinal".equals(declaredField.getName()) &&
currentClass == clazz) {
// If there is a field of name __assigned_ordinal on clazz
if(declaredField.getType() == long.class) {
assignedOrdinalFieldOffset = unsafe.objectFieldOffset(declaredField);
hasAssignedOrdinalField = true;;
}
}
}
if(currentClass.isEnum())
mappedFields.add(new MappedField(MappedFieldType.ENUM_NAME));
currentClass = currentClass.getSuperclass();
}
}
this.schema = new HollowObjectSchema(typeName, mappedFields.size(), getKeyFieldPaths(clazz));
Set<String> fieldNamesSeen = new HashSet<>();
for(MappedField field : mappedFields) {
if(!fieldNamesSeen.add(field.getFieldName()))
throw new IllegalArgumentException("Duplicate field name '" + field.getFieldName() + "' found in class hierarchy for class " + clazz.getName());
if(field.getFieldType() == MappedFieldType.REFERENCE) {
schema.addField(field.getFieldName(), field.getFieldType().getSchemaFieldType(), field.getReferencedTypeName());
} else {
schema.addField(field.getFieldName(), field.getFieldType().getSchemaFieldType());
}
}
HollowObjectTypeWriteState existingWriteState = (HollowObjectTypeWriteState) parentMapper.getStateEngine().getTypeState(typeName);
if (existingWriteState != null) {
this.writeState = existingWriteState;
} else {
int numShardsByAnnotation = getNumShardsByAnnotation(clazz);
this.writeState = new HollowObjectTypeWriteState(schema, numShardsByAnnotation);
}
this.assignedOrdinalFieldOffset = assignedOrdinalFieldOffset;
this.hasAssignedOrdinalField = hasAssignedOrdinalField;
}