package com.appmetr.hercules.metadata; import com.appmetr.hercules.annotations.*; import com.appmetr.hercules.partition.NoPartitionProvider; import com.appmetr.hercules.partition.PartitionProvider; import com.appmetr.hercules.serializers.AbstractHerculesSerializer; import java.lang.reflect.Field; public class WideEntityMetadataExtractor { public WideEntityMetadata extract(Class<?> clazz) { WideEntityMetadata metadata = new WideEntityMetadata(); EntityAnnotationsValidator.isClassWideEntity(clazz); EntityAnnotationsValidator.validateWideEntitySerializer(clazz); parseClassLevelMetadata(clazz, metadata); parseFieldLevelMetadata(clazz, metadata); return metadata; } private void parseClassLevelMetadata(Class<?> clazz, WideEntityMetadata metadata) { metadata.setEntityClass(clazz); WideEntity wideEntityAnnotation = clazz.getAnnotation(WideEntity.class); metadata.setColumnFamily(wideEntityAnnotation.columnFamily().length() == 0 ? clazz.getSimpleName() : wideEntityAnnotation.columnFamily()); MetadataExtractorUtils.setEntityComparatorType(clazz, metadata, wideEntityAnnotation.comparatorType()); MetadataExtractorUtils.setEntitySerializer(clazz, metadata); MetadataExtractorUtils.setEntityTTL(clazz, metadata); if (metadata.getEntitySerializer() == null) { throw new RuntimeException("Wide entity " + clazz.getSimpleName() + " should contain " + Serializer.class.getSimpleName()); } metadata.setListenerMetadata(MetadataExtractorUtils.getListenerMetadata(clazz)); if (metadata.getListenerMetadata().getPreLoadMethod() != null) { throw new RuntimeException("Wide entity " + clazz.getSimpleName() + " shouldn't contain PreLoad method listener"); } if (metadata.getListenerMetadata().getPreDeleteMethod() != null) { throw new RuntimeException("Wide entity " + clazz.getSimpleName() + " shouldn't contain PreDelete method listener"); } if (metadata.getListenerMetadata().getPostDeleteMethod() != null) { throw new RuntimeException("Wide entity " + clazz.getSimpleName() + " shouldn't contain PostDelete method listener"); } Class<? extends PartitionProvider> providerClass = null; if (clazz.isAnnotationPresent(Partitioned.class)) { Partitioned partitionedAnnotation = clazz.getAnnotation(Partitioned.class); if (!partitionedAnnotation.value().equals(NoPartitionProvider.class)) { providerClass = partitionedAnnotation.value(); } } if (providerClass == null) { providerClass = NoPartitionProvider.class; } metadata.setPartitionProviderClass(providerClass); //Row key metadata if (clazz.isAnnotationPresent(RowKey.class)) { RowKey rowKeyAnnotation = clazz.getAnnotation(RowKey.class); KeyMetadata rowKeyMetadata = new KeyMetadata(); if (rowKeyAnnotation.keyClass().equals(Object.class)) { throw new RuntimeException("Class level " + RowKey.class.getSimpleName() + " annotation for class " + clazz.getSimpleName() + " should contain keyClass field"); } Class rowKeyClass = rowKeyAnnotation.keyClass(); rowKeyMetadata.setKeyClass(rowKeyClass); if (!rowKeyAnnotation.serializer().equals(AbstractHerculesSerializer.class)) { rowKeyMetadata.setSerializer(rowKeyAnnotation.serializer()); } else if (rowKeyClass.isAnnotationPresent(Serializer.class)) { rowKeyMetadata.setSerializer(((Serializer) rowKeyClass.getAnnotation(Serializer.class)).value()); } metadata.setRowKeyMetadata(rowKeyMetadata); } //Top key metadata if (clazz.isAnnotationPresent(TopKey.class)) { TopKey topKeyAnnotation = clazz.getAnnotation(TopKey.class); KeyMetadata topKeyMetadata = new KeyMetadata(); if (topKeyAnnotation.keyClass().equals(Object.class)) { throw new RuntimeException("Class level " + TopKey.class.getSimpleName() + " annotation for class " + clazz.getSimpleName() + " should contain keyClass field"); } Class topKeyClass = topKeyAnnotation.keyClass(); topKeyMetadata.setKeyClass(topKeyAnnotation.keyClass()); if (!topKeyAnnotation.serializer().equals(AbstractHerculesSerializer.class)) { topKeyMetadata.setSerializer(topKeyAnnotation.serializer()); } else if (topKeyClass.isAnnotationPresent(Serializer.class)) { topKeyMetadata.setSerializer(((Serializer) topKeyClass.getAnnotation(Serializer.class)).value()); } metadata.setTopKeyMetadata(topKeyMetadata); } } private void parseFieldLevelMetadata(Class<?> clazz, WideEntityMetadata metadata) { for (Field field : clazz.getDeclaredFields()) { //Row key metadata if (field.isAnnotationPresent(RowKey.class)) { field.setAccessible(true); if (metadata.getRowKeyMetadata() != null) { throw new RuntimeException(RowKey.class.getSimpleName() + " annotation " + clazz.getSimpleName() + "should be present only on field or class level"); } KeyMetadata rowKeyMetadata = new KeyMetadata(); Class rowKeyClass = field.getType(); rowKeyMetadata.setField(field); rowKeyMetadata.setKeyClass(rowKeyClass); RowKey rowKeyAnnotation = field.getAnnotation(RowKey.class); if (!rowKeyAnnotation.serializer().equals(AbstractHerculesSerializer.class)) { rowKeyMetadata.setSerializer(rowKeyAnnotation.serializer()); } else if (rowKeyClass.isAnnotationPresent(Serializer.class)) { rowKeyMetadata.setSerializer(((Serializer) rowKeyClass.getAnnotation(Serializer.class)).value()); } metadata.setRowKeyMetadata(rowKeyMetadata); } //Top key metadata if (field.isAnnotationPresent(TopKey.class)) { field.setAccessible(true); if (metadata.getTopKeyMetadata() != null) { throw new RuntimeException(TopKey.class.getSimpleName() + " annotation for class " + clazz.getSimpleName() + " should be present only on field or class level"); } KeyMetadata topKeyMetadata = new KeyMetadata(); Class topKeyClass = field.getType(); topKeyMetadata.setField(field); topKeyMetadata.setKeyClass(field.getType()); TopKey topKeyAnnotation = field.getAnnotation(TopKey.class); if (!topKeyAnnotation.serializer().equals(AbstractHerculesSerializer.class)) { topKeyMetadata.setSerializer(topKeyAnnotation.serializer()); } else if (topKeyClass.isAnnotationPresent(Serializer.class)) { topKeyMetadata.setSerializer(((Serializer) topKeyClass.getAnnotation(Serializer.class)).value()); } metadata.setTopKeyMetadata(topKeyMetadata); } } } }