/** * Returns a newly-created {@link Entry} of a JSON file. * * @param revision the revision of the JSON file * @param path the path of the JSON file * @param content the content of the JSON file * * @throws JsonParseException if the {@code content} is not a valid JSON */ public static Entry<JsonNode> ofJson(Revision revision, String path, String content) throws JsonParseException { return ofJson(revision, path, Jackson.readTree(content)); }
/** * Applies the specified {@link Query} to the {@link Entry#content()} of the specified {@link Entry} and * returns the query result. * * @throws IllegalStateException if the specified {@link Entry} is a directory * @throws QuerySyntaxException if the syntax of specified {@link Query} is invalid * @throws QueryExecutionException if an {@link Exception} is raised while applying the specified * {@link Query} to the {@link Entry#content()} */ static <T> Entry<T> applyQuery(Entry<T> entry, Query<T> query) { requireNonNull(query, "query"); entry.content(); // Ensure that content is not null. final EntryType entryType = entry.type(); final QueryType queryType = query.type(); if (!queryType.supportedEntryTypes().contains(entryType)) { throw new QueryExecutionException("Unsupported entry type: " + entryType + " (query: " + query + ')'); } if (queryType == IDENTITY) { return entry; } else if (queryType == JSON_PATH) { return Entry.of(entry.revision(), query.path(), entryType, query.apply(entry.content())); } else { throw new QueryExecutionException("Unsupported entry type: " + entryType + " (query: " + query + ')'); } }
@Override int weigh(Map<String, Entry<?>> value) { int weight = 0; weight += pathPattern.length(); weight += options.size(); for (Entry<?> e : value.values()) { weight += e.path().length(); if (e.hasContent()) { weight += e.contentAsText().length(); } } return weight; }
/** * Returns the JSON representation of {@link #content()}. * * @return the {@link JsonNode} parsed from the {@link #content()} * * @throws IllegalStateException if this {@link Entry} is a directory * @throws JsonParseException if failed to parse the {@link #content()} as JSON */ public JsonNode contentAsJson() throws JsonParseException { final T content = content(); if (content instanceof JsonNode) { return (JsonNode) content; } return Jackson.readTree(contentAsText()); }
public static com.linecorp.centraldogma.common.Entry<?> convert( com.linecorp.centraldogma.common.Revision revision, Entry entry) { switch (entry.getType()) { case JSON: try { final JsonNode value = Jackson.readTree(entry.getContent()); return com.linecorp.centraldogma.common.Entry.ofJson(revision, entry.getPath(), value); } catch (IOException e) { throw new UncheckedIOException(e); } case TEXT: return com.linecorp.centraldogma.common.Entry.ofText(revision, entry.getPath(), entry.getContent()); case DIRECTORY: return com.linecorp.centraldogma.common.Entry.ofDirectory(revision, entry.getPath()); default: throw new IllegalArgumentException("unsupported entry type: " + entry.getType()); } }
@Test public void ofJson() throws Exception { final Entry<JsonNode> e = Entry.ofJson(new Revision(1), "/a.json", "{ \"foo\": \"bar\" }"); assertThat(e.revision()).isEqualTo(new Revision(1)); assertThat(e.hasContent()).isTrue(); e.ifHasContent(content -> assertThatJson(content).isEqualTo("{ \"foo\": \"bar\" }")); assertThatJson(e.content()).isEqualTo("{ \"foo\": \"bar\" }"); assertThat(e.contentAsText()).isEqualTo("{\"foo\":\"bar\"}"); assertThat(e.contentAsPrettyText()).isEqualTo("{\n \"foo\": \"bar\"\n}"); assertThat(e.content()).isSameAs(e.contentAsJson()); assertThat(e.content()).isEqualTo(e.contentAsJson(JsonNode.class)); // JSON file vs. JSON file final Entry<JsonNode> e2 = Entry.ofJson(new Revision(1), "/a.json", "{ \"foo\": \"bar\" }"); assertThat(e).isEqualTo(e2); assertThat(e.hashCode()).isEqualTo(e2.hashCode()); assertThat(e).isNotEqualTo(Entry.ofJson(new Revision(2), "/a.json", "{ \"foo\": \"bar\" }")); assertThat(e).isNotEqualTo(Entry.ofJson(new Revision(1), "/b.json", "{ \"foo\": \"bar\" }")); assertThat(e).isNotEqualTo(Entry.ofJson(new Revision(1), "/a.json", "null")); // JSON file vs. text file final Entry<String> e3 = Entry.ofText(new Revision(1), "/a.json", "{\"foo\":\"bar\"}"); assertThat(e).isNotEqualTo(e3); assertThat(e.hashCode()).isNotEqualTo(e3.hashCode()); // JSON file vs. directory final Entry<Void> e4 = Entry.ofDirectory(new Revision(1), "/foo"); assertThat(e).isNotEqualTo(e4); assertThat(e.hashCode()).isNotEqualTo(e4.hashCode()); }
@Test public void ofDirectory() throws Exception { final Entry<Void> e = Entry.ofDirectory(new Revision(1), "/"); assertThat(e.revision()).isEqualTo(new Revision(1)); assertThat(e.hasContent()).isFalse(); e.ifHasContent(unused -> fail()); assertThatThrownBy(e::content).isInstanceOf(IllegalStateException.class); assertThatThrownBy(e::contentAsJson).isInstanceOf(IllegalStateException.class); assertThatThrownBy(e::contentAsText).isInstanceOf(IllegalStateException.class); assertThatThrownBy(e::contentAsPrettyText).isInstanceOf(IllegalStateException.class); assertThatThrownBy(() -> e.contentAsJson(JsonNode.class)).isInstanceOf(IllegalStateException.class); // directory vs. directory final Entry<Void> e2 = Entry.ofDirectory(new Revision(1), "/"); assertThat(e).isEqualTo(e2); assertThat(e.hashCode()).isEqualTo(e2.hashCode()); assertThat(e).isNotEqualTo(Entry.ofDirectory(new Revision(2), "/")); assertThat(e).isNotEqualTo(Entry.ofDirectory(new Revision(1), "/foo")); // directory vs. text file final Entry<String> e3 = Entry.ofText(new Revision(1), "/a.txt", "foo"); assertThat(e).isNotEqualTo(e3); assertThat(e.hashCode()).isNotEqualTo(e3.hashCode()); // directory vs. JSON file final Entry<JsonNode> e4 = Entry.ofJson(new Revision(1), "/a.json", "{ \"foo\": \"bar\" }"); assertThat(e).isNotEqualTo(e4); assertThat(e.hashCode()).isNotEqualTo(e4.hashCode()); }
static EntryDto convert(Entry<?> entry) { final EntryDto dto = new EntryDto(); dto.setRevision(entry.revision().text()); dto.setPath(entry.path()); dto.setType(entry.type().name()); dto.setContent(entry.contentAsText()); return dto; }
@Test(timeout = 10000) public void testWatchWithIdentityQuery() throws Exception { final Revision rev1 = repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, textUpserts[0]).join(); final CompletableFuture<Entry<String>> f = repo.watch(rev1, Query.ofText(textPaths[0])); final Revision rev2 = repo.commit(HEAD, 0L, Author.UNKNOWN, SUMMARY, textPatches[1]).join(); final Entry<String> res = f.get(3, TimeUnit.SECONDS); assertThat(res.revision()).isEqualTo(rev2); assertThat(res.type()).isEqualTo(EntryType.TEXT); // Text must be sanitized so that the last line ends with \n. assertThat(res.content()).isEqualTo(textUpserts[1].content() + '\n'); }
private static void handleWatchFileResult( CompletableFuture<com.linecorp.centraldogma.common.Entry<Object>> future, AsyncMethodCallback resultHandler) { future.handle((res, cause) -> { if (cause == null) { final WatchFileResult wfr = new WatchFileResult(); wfr.setRevision(convert(res.revision())); wfr.setType(convert(res.type())); wfr.setContent(res.contentAsText()); resultHandler.onComplete(wfr); } else if (cause instanceof CancellationException) { resultHandler.onComplete(CentralDogmaConstants.EMPTY_WATCH_FILE_RESULT); } else { logAndInvokeOnError("watchFile", resultHandler, cause); } return null; }); }
@Override protected CompletableFuture<Latest<T>> doWatch(CentralDogma client, String projectName, String repositoryName, Revision lastKnownRevision, long timeoutMillis) { return client.watchFile(projectName, repositoryName, lastKnownRevision, query, timeoutMillis) .thenApply(result -> { if (result == null) { return null; } return new Latest<>(result.revision(), function.apply(result.content())); }); } }
@SuppressWarnings("unchecked") static <T> T convertWithJackson(Entry<?> entry, Class<T> clazz) { requireNonNull(entry, "entry"); requireNonNull(clazz, "clazz"); try { return Jackson.treeToValue(((Entry<JsonNode>) entry).content(), clazz); } catch (Throwable cause) { return Exceptions.throwUnsafely(cause); } } }
public static Entry convert(com.linecorp.centraldogma.common.Entry<?> entry) { final Entry file = new Entry(entry.path(), convertEntryType(entry.type())); switch (entry.type()) { case JSON: // FIXME(trustin): Inefficiency try { file.setContent(Jackson.writeValueAsString(entry.content())); } catch (JsonProcessingException e) { throw new UncheckedIOException(e); } break; case TEXT: file.setContent((String) entry.content()); break; case DIRECTORY: break; default: throw new IllegalArgumentException("unsupported entry type: " + entry.type()); } return file; }
@Override public T content() { if (content == null) { throw new IllegalStateException(type() + " does not have content"); } return content; }
@Test public void getFile() throws Exception { doAnswer(invocation -> { final AsyncMethodCallback<com.linecorp.centraldogma.internal.thrift.Revision> callback = invocation.getArgument(3); callback.onComplete(new com.linecorp.centraldogma.internal.thrift.Revision(1, 0)); return null; }).when(iface).normalizeRevision(any(), any(), any(), any()); doAnswer(invocation -> { final AsyncMethodCallback<GetFileResult> callback = invocation.getArgument(4); callback.onComplete(new GetFileResult(TEntryType.TEXT, "content")); return null; }).when(iface).getFile(any(), any(), any(), any(), any()); assertThat(client.getFile("project", "repo", new Revision(1), Query.ofText("/a.txt")).get()) .isEqualTo(Entry.ofText(new Revision(1), "/a.txt", "content")); verify(iface).getFile(eq("project"), eq("repo"), any(), any(), any()); }
@Override public void getFile(String projectName, String repositoryName, Revision revision, Query query, AsyncMethodCallback resultHandler) { handle(projectManager.get(projectName).repos().get(repositoryName) .get(convert(revision), convert(query)) .thenApply(res -> new GetFileResult(convert(res.type()), res.contentAsText())), resultHandler); }
assertThat(client.getFiles(projName, REPO_FOO, rev2, "/target/**").join().values()) .containsExactlyInAnyOrder(expectedSecondMirrorState, Entry.ofDirectory(rev2, "/target/first"), Entry.ofText(rev2, "/target/first/light.txt", "26-Aug-2014\n"));
@Override int weigh(Entry<?> value) { int weight = 0; weight += query.path().length(); for (String e : query.expressions()) { weight += e.length(); } if (value != null && value.hasContent()) { weight += value.contentAsText().length(); } return weight; }