View Javadoc

1   package com.atlassian.plugins.rest.common.expand.parameter;
2   
3   import com.atlassian.annotations.tenancy.TenantAware;
4   import com.atlassian.plugins.rest.common.expand.Expandable;
5   import com.google.common.base.Preconditions;
6   import com.google.common.collect.Maps;
7   import com.google.common.collect.Sets;
8   import org.apache.commons.lang.StringUtils;
9   
10  import java.util.Collection;
11  import java.util.Collections;
12  import java.util.HashSet;
13  import java.util.Map;
14  import java.util.regex.Matcher;
15  import java.util.regex.Pattern;
16  
17  import static com.atlassian.annotations.tenancy.TenancyScope.SUPPRESS;
18  
19  /**
20   * Parses and allow easy retrieval of information of expansion parameter.
21   */
22  public final class DefaultExpandParameter implements ExpandParameter {
23      private static final String DOT = ".";
24      private static final String COMMA = ",";
25      private static final String WILDCARD = "*";
26  
27      private static final ExpandParameter EMPTY_EXPAND_PARAMETER = new DefaultExpandParameter((String) null);
28  
29      @TenantAware(SUPPRESS)
30      private final Map<String, ExpandInformation> parameters;
31  
32      private DefaultExpandParameter(String expand) {
33          this(StringUtils.isNotBlank(expand) ? Collections.singleton(expand) : Collections.<String>emptyList());
34      }
35  
36      public DefaultExpandParameter(Collection<String> expands) {
37          parameters = parse(expands != null ? expands : Collections.<String>emptyList());
38      }
39  
40      public boolean shouldExpand(Expandable expandable) {
41          return parameters.containsKey(WILDCARD) || parameters.containsKey(Preconditions.checkNotNull(expandable).value());
42      }
43  
44      public Indexes getIndexes(Expandable expandable) {
45          final ExpandInformation expandInformation = parameters.get(Preconditions.checkNotNull(expandable).value());
46          return expandInformation != null ? expandInformation.getIndexes() : IndexParser.EMPTY;
47      }
48  
49      public ExpandParameter getExpandParameter(Expandable expandable) {
50          final ExpandInformation wildcardExpandInformation = parameters.get(WILDCARD);
51          final ExpandInformation valueExpandInformation = parameters.get(Preconditions.checkNotNull(expandable).value());
52  
53          return new ChainingExpandParameter(
54                  wildcardExpandInformation != null ? wildcardExpandInformation.getExpandParameter() : EMPTY_EXPAND_PARAMETER,
55                  valueExpandInformation != null ? valueExpandInformation.getExpandParameter() : EMPTY_EXPAND_PARAMETER);
56      }
57  
58      public boolean isEmpty() {
59          return parameters.isEmpty();
60      }
61  
62      private static Map<String, ExpandInformation> parse(Collection<String> expands) {
63          final Map<String, ExpandInformation> parameters = Maps.newHashMap();
64          for (String expand : preProcess(expands)) {
65              if (StringUtils.isNotEmpty(expand)) {
66                  final ExpandKey key = ExpandKey.from(StringUtils.substringBefore(expand, DOT));
67  
68                  DefaultExpandParameter newParameter = new DefaultExpandParameter(StringUtils.substringAfter(expand, DOT));
69                  if (parameters.containsKey(key.getName())) {
70                      DefaultExpandParameter existingParameter = parameters.get(key.getName()).getExpandParameter();
71                      newParameter.parameters.putAll(existingParameter.parameters);
72                  }
73                  parameters.put(key.getName(), new ExpandInformation(key.getIndexes(), newParameter));
74              }
75          }
76          return parameters;
77      }
78  
79      private static Collection<String> preProcess(Collection<String> expands) {
80          final Collection<String> preProcessed = new HashSet<String>();
81          for (String expand : expands) {
82              preProcessed.addAll(Sets.newHashSet(expand.split(COMMA)));
83          }
84          return preProcessed;
85      }
86  
87      private static class ExpandKey {
88          private static final Pattern KEY_PATTERN = Pattern.compile("(\\w+|\\*)(?:\\[([\\d:\\-\\|]+)\\])?");
89  
90          private final String name;
91          private final Indexes indexes;
92  
93          ExpandKey(String name, Indexes indexes) {
94              this.name = name;
95              this.indexes = indexes;
96          }
97  
98          public String getName() {
99              return name;
100         }
101 
102         public Indexes getIndexes() {
103             return indexes;
104         }
105 
106         private static ExpandKey from(String key) {
107             final Matcher keyMatcher = KEY_PATTERN.matcher(key);
108             if (!keyMatcher.matches()) {
109                 throw new RuntimeException("key <" + key + "> doesn't match pattern");
110             }
111 
112             final String name = keyMatcher.group(1);
113             final String indexesString = keyMatcher.group(2);
114             return new ExpandKey(name, IndexParser.parse(indexesString));
115         }
116     }
117 
118     private static class ExpandInformation {
119         private final Indexes indexes;
120         private final DefaultExpandParameter expandParameter;
121 
122         public ExpandInformation(Indexes indexes, DefaultExpandParameter expandParameter) {
123             this.indexes = Preconditions.checkNotNull(indexes);
124             this.expandParameter = Preconditions.checkNotNull(expandParameter);
125         }
126 
127         public Indexes getIndexes() {
128             return indexes;
129         }
130 
131         public DefaultExpandParameter getExpandParameter() {
132             return expandParameter;
133         }
134     }
135 }