1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package com.linecorp.centraldogma.common;
18
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static java.util.Objects.requireNonNull;
21
22 import java.util.Objects;
23 import java.util.function.Consumer;
24
25 import javax.annotation.Nullable;
26
27 import com.fasterxml.jackson.core.JsonParseException;
28 import com.fasterxml.jackson.databind.JsonNode;
29 import com.google.common.base.MoreObjects;
30
31 import com.linecorp.centraldogma.internal.Jackson;
32
33
34
35
36
37
38 public final class Entry<T> implements ContentHolder<T> {
39
40
41
42
43
44
45
46 public static Entry<Void> ofDirectory(Revision revision, String path) {
47 return new Entry<>(revision, path, EntryType.DIRECTORY, null);
48 }
49
50
51
52
53
54
55
56
57 public static Entry<JsonNode> ofJson(Revision revision, String path, JsonNode content) {
58 return new Entry<>(revision, path, EntryType.JSON, content);
59 }
60
61
62
63
64
65
66
67
68
69
70 public static Entry<JsonNode> ofJson(Revision revision, String path, String content)
71 throws JsonParseException {
72 return ofJson(revision, path, Jackson.readTree(content));
73 }
74
75
76
77
78
79
80
81
82 public static Entry<String> ofText(Revision revision, String path, String content) {
83 return new Entry<>(revision, path, EntryType.TEXT, content);
84 }
85
86
87
88
89
90
91
92
93
94
95 public static <T> Entry<T> of(Revision revision, String path, EntryType type, @Nullable T content) {
96 return new Entry<>(revision, path, type, content);
97 }
98
99 private final Revision revision;
100 private final String path;
101 @Nullable
102 private final T content;
103 private final EntryType type;
104 @Nullable
105 private String contentAsText;
106 @Nullable
107 private String contentAsPrettyText;
108
109
110
111
112
113
114
115
116
117 private Entry(Revision revision, String path, EntryType type, @Nullable T content) {
118 requireNonNull(revision, "revision");
119 checkArgument(!revision.isRelative(), "revision: %s (expected: absolute revision)", revision);
120 this.revision = revision;
121 this.path = requireNonNull(path, "path");
122 this.type = requireNonNull(type, "type");
123
124 final Class<?> entryContentType = type.type();
125
126 if (entryContentType == Void.class) {
127 checkArgument(content == null, "content: %s (expected: null)", content);
128 this.content = null;
129 } else {
130 @SuppressWarnings("unchecked")
131 final T castContent = (T) entryContentType.cast(requireNonNull(content, "content"));
132 this.content = castContent;
133 }
134 }
135
136
137
138
139 public Revision revision() {
140 return revision;
141 }
142
143
144
145
146 public String path() {
147 return path;
148 }
149
150
151
152
153 public boolean hasContent() {
154 return content != null;
155 }
156
157
158
159
160 public void ifHasContent(Consumer<? super T> consumer) {
161 requireNonNull(consumer, "consumer");
162 if (content != null) {
163 consumer.accept(content);
164 }
165 }
166
167 @Override
168 public EntryType type() {
169 return type;
170 }
171
172 @Override
173 public T content() {
174 if (content == null) {
175 throw new EntryNoContentException(type, revision, path);
176 }
177 return content;
178 }
179
180 @Override
181 public String contentAsText() {
182 if (contentAsText == null) {
183 contentAsText = ContentHolder.super.contentAsText();
184 }
185 return contentAsText;
186 }
187
188 @Override
189 public String contentAsPrettyText() {
190 if (contentAsPrettyText == null) {
191 contentAsPrettyText = ContentHolder.super.contentAsPrettyText();
192 }
193 return contentAsPrettyText;
194 }
195
196 @Override
197 public int hashCode() {
198 return (revision.hashCode() * 31 + type.hashCode()) * 31 + path.hashCode();
199 }
200
201 @Override
202 public boolean equals(Object o) {
203 if (this == o) {
204 return true;
205 }
206 if (!(o instanceof Entry)) {
207 return false;
208 }
209
210 @SuppressWarnings("unchecked")
211 final Entry<T> that = (Entry<T>) o;
212
213 return type == that.type && revision.equals(that.revision) && path.equals(that.path) &&
214 Objects.equals(content, that.content);
215 }
216
217 @Override
218 public String toString() {
219 return MoreObjects.toStringHelper(this).omitNullValues()
220 .add("revision", revision.text())
221 .add("path", path)
222 .add("type", type)
223 .add("content", hasContent() ? contentAsText() : null)
224 .toString();
225 }
226 }