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
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 }