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      private DefaultExpandParameter() {
37          parameters = Maps.newHashMap();
38      }
39  
40      public DefaultExpandParameter(Collection<String> expands) {
41          parameters = parse(expands != null ? expands : Collections.<String>emptyList());
42      }
43  
44      public boolean shouldExpand(Expandable expandable) {
45          return parameters.containsKey(WILDCARD) || parameters.containsKey(Preconditions.checkNotNull(expandable).value());
46      }
47  
48      public Indexes getIndexes(Expandable expandable) {
49          final ExpandInformation expandInformation = parameters.get(Preconditions.checkNotNull(expandable).value());
50          return expandInformation != null ? expandInformation.getIndexes() : IndexParser.EMPTY;
51      }
52  
53      public ExpandParameter getExpandParameter(Expandable expandable) {
54          final ExpandInformation wildcardExpandInformation = parameters.get(WILDCARD);
55          final ExpandInformation valueExpandInformation = parameters.get(Preconditions.checkNotNull(expandable).value());
56  
57          return new ChainingExpandParameter(
58                  wildcardExpandInformation != null ? wildcardExpandInformation.getExpandParameter() : EMPTY_EXPAND_PARAMETER,
59                  valueExpandInformation != null ? valueExpandInformation.getExpandParameter() : EMPTY_EXPAND_PARAMETER);
60      }
61  
62      public boolean isEmpty() {
63          return parameters.isEmpty();
64      }
65  
66      private static void appendParam(Map<String, ExpandInformation> parameters, String expand) {
67          final ExpandKey key = ExpandKey.from(StringUtils.substringBefore(expand, DOT));
68          String newParameter = StringUtils.substringAfter(expand, DOT);
69          DefaultExpandParameter existingParameter = null;
70          if (parameters.containsKey(key.getName())) {
71              existingParameter = parameters.get(key.getName()).getExpandParameter();
72          } else {
73              existingParameter = new DefaultExpandParameter();
74              parameters.put(key.getName(), new ExpandInformation(key.getIndexes(), existingParameter));
75          }
76  
77          if (StringUtils.isNotBlank(newParameter)) {
78              appendParam(existingParameter.parameters, newParameter);
79          }
80      }
81  
82      private static Map<String, ExpandInformation> parse(Collection<String> expands) {
83          final Map<String, ExpandInformation> parameters = Maps.newHashMap();
84          for (String expand : preProcess(expands)) {
85              if (StringUtils.isNotEmpty(expand)) {
86                  appendParam(parameters, expand);
87              }
88          }
89          return parameters;
90      }
91  
92      private static Collection<String> preProcess(Collection<String> expands) {
93          final Collection<String> preProcessed = new HashSet<String>();
94          for (String expand : expands) {
95              preProcessed.addAll(Sets.newHashSet(expand.split(COMMA)));
96          }
97          return preProcessed;
98      }
99  
100     private static class ExpandKey {
101         private static final Pattern KEY_PATTERN = Pattern.compile("(\\w+|\\*)(?:\\[([\\d:\\-\\|]+)\\])?");
102 
103         private final String name;
104         private final Indexes indexes;
105 
106         ExpandKey(String name, Indexes indexes) {
107             this.name = name;
108             this.indexes = indexes;
109         }
110 
111         public String getName() {
112             return name;
113         }
114 
115         public Indexes getIndexes() {
116             return indexes;
117         }
118 
119         private static ExpandKey from(String key) {
120             final Matcher keyMatcher = KEY_PATTERN.matcher(key);
121             if (!keyMatcher.matches()) {
122                 throw new RuntimeException("key <" + key + "> doesn't match pattern");
123             }
124 
125             final String name = keyMatcher.group(1);
126             final String indexesString = keyMatcher.group(2);
127             return new ExpandKey(name, IndexParser.parse(indexesString));
128         }
129     }
130 
131     private static class ExpandInformation {
132         private final Indexes indexes;
133         private final DefaultExpandParameter expandParameter;
134 
135         public ExpandInformation(Indexes indexes, DefaultExpandParameter expandParameter) {
136             this.indexes = Preconditions.checkNotNull(indexes);
137             this.expandParameter = Preconditions.checkNotNull(expandParameter);
138         }
139 
140         public Indexes getIndexes() {
141             return indexes;
142         }
143 
144         public DefaultExpandParameter getExpandParameter() {
145             return expandParameter;
146         }
147     }
148 }