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