1 package com.atlassian.plugins.rest.doclet.generators.schema;
2
3 import com.google.common.base.Function;
4 import com.google.common.base.Joiner;
5 import com.google.common.base.Objects;
6 import com.google.common.base.Splitter;
7 import com.google.common.collect.ImmutableList;
8 import com.google.common.collect.Iterables;
9 import com.google.common.collect.Lists;
10 import com.google.common.collect.Maps;
11 import org.codehaus.jackson.annotate.JsonAutoDetect;
12 import org.codehaus.jackson.annotate.JsonProperty;
13
14 import java.util.Arrays;
15 import java.util.List;
16 import java.util.Map;
17
18 @JsonAutoDetect
19 public class Schema
20 {
21 public enum Type
22 {
23 Any, Object, Array, Number, Integer, Boolean, String, Uri("string", "uri");
24
25 private final String name;
26 private final String format;
27
28 Type(final java.lang.String name, final java.lang.String format)
29 {
30 this.name = name;
31 this.format = format;
32 }
33
34 Type()
35 {
36 this(null, null);
37 }
38
39 @Override
40 public String toString()
41 {
42 return Objects.firstNonNull(name, this.name().toLowerCase());
43 }
44
45 public java.lang.String format()
46 {
47 return format;
48 }
49 }
50
51 private final String $ref;
52 private final String id;
53 private final String title;
54 private final String description;
55 private final String type;
56 private final String format;
57 private final Map<String, Schema> properties;
58 private final Schema items;
59 @JsonProperty ("enum")
60 private final List<String> _enum;
61 private final Map<String, Schema> patternProperties;
62 private final List<Schema> anyOf;
63 private final Map<String, Schema> definitions;
64 private Boolean additionalProperties;
65 private final List<String> required;
66
67 private Schema(final String $ref, final String id, String title, String description, Type type, Map<String, Schema> properties, Schema items, Iterable<String> _enum, Iterable<String> required, Map<String, Schema> patternProperties, final Map<String, Schema> definitions, final List<Schema> anyOf)
68 {
69 this.$ref = $ref;
70 this.id = id;
71 this.title = title;
72 this.description = description;
73 this.type = type != null && type != Type.Any ? type.toString() : null;
74 this.format = this.type != null ? type.format() : null;
75 this.anyOf = anyOf != null && anyOf.size() > 0 ? ImmutableList.copyOf(anyOf) : null;
76 this.properties = properties != null && properties.size() > 0 ? Maps.newLinkedHashMap(properties) : null;
77 this.items = items;
78 this._enum = _enum != null && Iterables.size(_enum) > 0 ? ImmutableList.copyOf(_enum) : null;
79 this.required = required != null && Iterables.size(required) > 0 ? ImmutableList.copyOf(required) : null;
80 this.patternProperties = patternProperties != null && patternProperties.size() > 0 ? Maps.newLinkedHashMap(patternProperties) : null;
81 this.definitions = definitions != null && definitions.size() > 0 ? definitions : null;
82 this.additionalProperties = type != null && type == Type.Object &&
83 (this.properties != null || this.patternProperties != null) ? false : null;
84 }
85
86 public static Schema ref(String title)
87 {
88 return new Schema("#/definitions/" + titleToId(title), null, null, null, null, null, null, null, null, null, null, null);
89 }
90
91 public static String titleToId(final String title)
92 {
93 return title != null ? Joiner.on("-").join(Splitter.on(" ").split(title)).toLowerCase() : null;
94 }
95
96 public String get$ref()
97 {
98 return $ref;
99 }
100
101 public String getId()
102 {
103 return id;
104 }
105
106 public String getTitle()
107 {
108 return title;
109 }
110
111 public String getDescription()
112 {
113 return description;
114 }
115
116 public String getType()
117 {
118 return type;
119 }
120
121 public String getFormat()
122 {
123 return format;
124 }
125
126 public Map<String, Schema> getProperties()
127 {
128 return properties;
129 }
130
131 public Schema getItems()
132 {
133 return items;
134 }
135
136 public List<String> get_enum()
137 {
138 return _enum;
139 }
140
141 public Map<String, Schema> getPatternProperties()
142 {
143 return patternProperties;
144 }
145
146 public List<Schema> getAnyOf()
147 {
148 return anyOf;
149 }
150
151 public Map<String, Schema> getDefinitions()
152 {
153 return definitions;
154 }
155
156 public Boolean getAdditionalProperties()
157 {
158 return additionalProperties;
159 }
160
161 public List<String> getRequired()
162 {
163 return required;
164 }
165
166 public static Builder builder()
167 {
168 return new Builder();
169 }
170
171 @Override
172 public boolean equals(Object o)
173 {
174 if (this == o) { return true; }
175 if (o == null || getClass() != o.getClass()) { return false; }
176
177 Schema that = (Schema) o;
178
179 return Objects.equal(this.title, that.title) &&
180 Objects.equal(this.description, that.description) &&
181 Objects.equal(this.type, that.type) &&
182 Objects.equal(this.properties, that.properties) &&
183 Objects.equal(this.items, that.items) &&
184 Objects.equal(this._enum, that._enum) &&
185 Objects.equal(this.required, that.required);
186 }
187
188 @Override
189 public int hashCode()
190 {
191 return Objects.hashCode(title, description, type, properties, items, _enum, required);
192 }
193
194 @Override
195 public String toString()
196 {
197 return Objects.toStringHelper(this)
198 .add("title", title)
199 .add("description", description)
200 .add("type", type)
201 .add("properties", properties)
202 .add("items", items)
203 .add("enum", _enum)
204 .add("required", required)
205 .toString();
206 }
207
208 public static final class Builder
209 {
210 private String id;
211 private String title;
212 private String description;
213 private Type type;
214 private Map<String, Schema> properties = Maps.newLinkedHashMap();
215 private Map<String, Schema> patternProperties = Maps.newLinkedHashMap();
216 private Schema items;
217 private List<String> _enum = Lists.newArrayList();
218 private List<String> required = Lists.newArrayList();
219 private Map<String, Schema> definitions = Maps.newTreeMap();
220 private List<Schema> anyOf = Lists.newArrayList();
221
222 private Builder() {}
223
224 public Builder setId(String id)
225 {
226 this.id = id;
227 return this;
228 }
229
230 public Builder setTitle(String title)
231 {
232 this.title = title;
233 return this;
234 }
235
236 public Builder setDescription(String description)
237 {
238 this.description = description;
239 return this;
240 }
241
242 public Builder setType(Type type)
243 {
244 this.type = type;
245 return this;
246 }
247
248 public Builder setProperties(Map<String, Schema> properties)
249 {
250 this.properties = properties;
251 return this;
252 }
253
254 public Builder addProperty(String propertyName, Schema propertySchema)
255 {
256 this.properties.put(propertyName, propertySchema);
257 return this;
258 }
259
260 public Builder addPatternProperty(String pattern, Schema schema)
261 {
262 this.patternProperties.put(pattern, schema);
263 return this;
264 }
265
266 public Builder setItems(Schema items)
267 {
268 this.items = items;
269 return this;
270 }
271
272 public <T extends Enum<T>> Builder setEnum(Class<T> enumType)
273 {
274 this._enum = ImmutableList.copyOf(Iterables.transform(Arrays.asList(enumType.getEnumConstants()), new Function<T, String>()
275 {
276 @Override
277 public String apply(final T input)
278 {
279 return input.toString();
280 }
281 }));
282 return this;
283 }
284
285 public Builder setRequired(List<String> required)
286 {
287 this.required = required;
288 return this;
289 }
290
291 public Builder addRequired(String required)
292 {
293 this.required.add(required);
294 return this;
295 }
296
297 public Builder addDefinition(Schema schema)
298 {
299 this.definitions.put(titleToId(schema.getTitle()), schema);
300 return this;
301 }
302
303 public Builder addAnyOf(Schema schema)
304 {
305 this.anyOf.add(schema);
306 return this;
307 }
308
309 public Schema build()
310 {
311 return new Schema(null, id, title, description, type, properties, items, _enum, required, patternProperties, definitions, anyOf);
312 }
313 }
314 }