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