1   package com.atlassian.plugins.rest.common.expand.resolver;
2   
3   import com.atlassian.plugins.rest.common.expand.EntityCrawler;
4   import com.atlassian.plugins.rest.common.expand.EntityExpander;
5   import com.atlassian.plugins.rest.common.expand.ExpandContext;
6   import com.atlassian.plugins.rest.common.expand.entity.ListWrapper;
7   import static com.atlassian.plugins.rest.common.util.ReflectionUtils.setFieldValue;
8   import com.google.common.base.Preconditions;
9   import com.google.common.collect.Sets;
10  
11  import java.lang.reflect.Field;
12  import java.util.Collection;
13  import java.util.Set;
14  
15  /**
16   * An {@link EntityExpanderResolver entity expander resolver} that can create a {@link EntityExpander entity expander} for {@link ListWrapper list wrappers}
17   */
18  public class ListWrapperEntityExpanderResolver implements EntityExpanderResolver
19  {
20      static final ListWrapperEntityExpander EXPANDER = new ListWrapperEntityExpander();
21  
22      public boolean hasExpander(Class<?> type)
23      {
24          return ListWrapper.class.isAssignableFrom(Preconditions.checkNotNull(type));
25      }
26  
27      public <T> EntityExpander<T> getExpander(Class<? extends T> type)
28      {
29          return ListWrapper.class.isAssignableFrom(type) ? (EntityExpander<T>) EXPANDER : null;
30      }
31  
32      private static class ListWrapperEntityExpander implements EntityExpander<ListWrapper<?>>
33      {
34          public ListWrapper<?> expand(ExpandContext<ListWrapper<?>> context, EntityExpanderResolver expanderResolver, EntityCrawler entityCrawler)
35          {
36              final ListWrapper<?> entity = context.getEntity();
37  
38              final Set<Field> collectionFields = Sets.newHashSet();
39              final Field[] fields = entity.getClass().getDeclaredFields();
40              for (Field field : fields)
41              {
42                  if (Collection.class.isAssignableFrom(field.getType()))
43                  {
44                      collectionFields.add(field);
45                  }
46              }
47              if (collectionFields.isEmpty())
48              {
49                  throw new RuntimeException("Entity " + entity.getClass() + " has no collection field, cannot expand.");
50              }
51              if (collectionFields.size() > 1)
52              {
53                  throw new RuntimeException("Entity " + entity.getClass() + " has more than one collection field, cannot determine which collection to expand.");
54              }
55  
56              setFieldValue(collectionFields.iterator().next(), entity, entity.getCallback().getItems(context.getEntityExpandParameter().getIndexes(context.getExpandable())));
57  
58              entityCrawler.crawl(entity, context.getEntityExpandParameter().getExpandParameter(context.getExpandable()), expanderResolver);
59              return entity;
60          }
61      }
62  }