001package org.kuali.common.util.bind.test; 002 003import static com.google.common.base.Preconditions.checkNotNull; 004 005import java.lang.annotation.Annotation; 006import java.lang.reflect.Field; 007import java.util.Collections; 008import java.util.Comparator; 009import java.util.List; 010 011import org.kuali.common.util.ReflectionUtils; 012import org.kuali.common.util.tree.ImmutableNode; 013import org.kuali.common.util.tree.MutableNode; 014import org.kuali.common.util.tree.Node; 015 016import com.google.common.collect.ImmutableList; 017import com.google.common.collect.Lists; 018 019public final class AnnotatedFieldAssembler implements Assembler<List<Node<Field>>> { 020 021 private final Class<? extends Annotation> annotation; 022 private final Class<?> type; 023 private final Comparator<Field> comparator; 024 025 @Override 026 public List<Node<Field>> assemble() { 027 List<MutableNode<Field>> assembled = assemble(type); 028 List<Node<Field>> list = Lists.newArrayList(); 029 for (Node<Field> element : assembled) { 030 list.add(ImmutableNode.copyOf(element)); 031 } 032 return ImmutableList.copyOf(list); 033 } 034 035 protected List<MutableNode<Field>> assemble(Class<?> type) { 036 List<Field> fields = getSortedFields(type); 037 List<MutableNode<Field>> list = Lists.newArrayList(); 038 for (Field field : fields) { 039 list.add(getNode(field)); 040 } 041 return list; 042 } 043 044 protected MutableNode<Field> getNode(Field field) { 045 MutableNode<Field> node = new MutableNode<Field>(field); 046 if (field.isAnnotationPresent(annotation)) { 047 node.add(assemble(field.getType())); 048 } 049 return node; 050 } 051 052 protected List<Field> getSortedFields(Class<?> type) { 053 List<Field> fields = Lists.newArrayList(ReflectionUtils.getAllFields(type)); 054 Collections.sort(fields, comparator); 055 return fields; 056 } 057 058 private AnnotatedFieldAssembler(Builder builder) { 059 this.annotation = builder.annotation; 060 this.type = builder.type; 061 this.comparator = builder.comparator; 062 } 063 064 public static AnnotatedFieldAssembler create(Class<?> type, Class<? extends Annotation> annotation) { 065 return builder(type, annotation).build(); 066 } 067 068 public static Builder builder(Class<?> type, Class<? extends Annotation> annotation) { 069 return new Builder(type, annotation); 070 } 071 072 public static class Builder implements org.apache.commons.lang3.builder.Builder<AnnotatedFieldAssembler> { 073 074 // Required 075 private final Class<?> type; 076 private final Class<? extends Annotation> annotation; 077 078 // Optional 079 private Comparator<Field> comparator = FieldNameComparator.INSTANCE; 080 081 public Builder(Class<?> type, Class<? extends Annotation> annotation) { 082 this.type = type; 083 this.annotation = annotation; 084 } 085 086 public Builder comparator(Comparator<Field> comparator) { 087 this.comparator = comparator; 088 return this; 089 } 090 091 @Override 092 public AnnotatedFieldAssembler build() { 093 AnnotatedFieldAssembler instance = new AnnotatedFieldAssembler(this); 094 validate(instance); 095 return instance; 096 } 097 098 private static void validate(AnnotatedFieldAssembler instance) { 099 checkNotNull(instance.annotation, "'annotation' cannot be null"); 100 checkNotNull(instance.type, "'type' cannot be null"); 101 checkNotNull(instance.comparator, "'comparator' cannot be null"); 102 } 103 104 public Comparator<Field> getComparator() { 105 return comparator; 106 } 107 108 public void setComparator(Comparator<Field> comparator) { 109 this.comparator = comparator; 110 } 111 112 public Class<? extends Annotation> getAnnotation() { 113 return annotation; 114 } 115 116 public Class<?> getType() { 117 return type; 118 } 119 } 120 121 public Class<? extends Annotation> getAnnotation() { 122 return annotation; 123 } 124 125 public Class<?> getType() { 126 return type; 127 } 128 129 public Comparator<Field> getComparator() { 130 return comparator; 131 } 132 133}